Implement complete multi-language support with Romanian/English
- Added next-intl for internationalization with Romanian as default locale - Restructured app directory with [locale] routing (/ro, /en) - Created comprehensive translation files for both languages - Fixed Next.js 15 async params compatibility in layout components - Updated all components to use proper i18n hooks and translations - Configured middleware for locale routing and fallbacks - Fixed FloatingChat component translation array handling - Restored complete home page with internationalized content - Fixed Material-UI Slide component prop error (mountOnExit → unmountOnExit) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
55
app/[locale]/layout.tsx
Normal file
55
app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import '../globals.css'
|
||||
import type { Metadata } from 'next'
|
||||
import { NextIntlClientProvider } from 'next-intl'
|
||||
import { getMessages } from 'next-intl/server'
|
||||
import { notFound } from 'next/navigation'
|
||||
import { MuiThemeProvider } from '@/components/providers/theme-provider'
|
||||
import { Navigation } from '@/components/layout/navigation'
|
||||
import FloatingChat from '@/components/chat/floating-chat'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Ghid Biblic - Biblical Guide',
|
||||
description: 'A comprehensive Bible study application with AI chat capabilities',
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return [
|
||||
{ locale: 'ro' },
|
||||
{ locale: 'en' }
|
||||
]
|
||||
}
|
||||
|
||||
interface LocaleLayoutProps {
|
||||
children: React.ReactNode
|
||||
params: Promise<{ locale: string }>
|
||||
}
|
||||
|
||||
const locales = ['ro', 'en']
|
||||
|
||||
export default async function LocaleLayout({
|
||||
children,
|
||||
params
|
||||
}: LocaleLayoutProps) {
|
||||
const { locale } = await params
|
||||
|
||||
// Validate locale
|
||||
if (!locales.includes(locale)) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const messages = await getMessages()
|
||||
|
||||
return (
|
||||
<html lang={locale}>
|
||||
<body>
|
||||
<NextIntlClientProvider messages={messages} locale={locale}>
|
||||
<MuiThemeProvider>
|
||||
<Navigation />
|
||||
{children}
|
||||
<FloatingChat />
|
||||
</MuiThemeProvider>
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -18,38 +18,40 @@ import {
|
||||
AutoStories,
|
||||
Favorite,
|
||||
} from '@mui/icons-material'
|
||||
import { Navigation } from '@/components/layout/navigation'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useTranslations, useLocale } from 'next-intl'
|
||||
|
||||
export default function Home() {
|
||||
const theme = useTheme()
|
||||
const router = useRouter()
|
||||
const t = useTranslations('home')
|
||||
const locale = useLocale()
|
||||
|
||||
const features = [
|
||||
{
|
||||
title: 'Citește Biblia',
|
||||
description: 'Explorează Scriptura cu o interfață modernă și ușor de folosit',
|
||||
title: t('features.bible.title'),
|
||||
description: t('features.bible.description'),
|
||||
icon: <MenuBook sx={{ fontSize: 40, color: 'primary.main' }} />,
|
||||
path: '/bible',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
{
|
||||
title: 'Chat cu AI',
|
||||
description: 'Pune întrebări despre Scriptură și primește răspunsuri clare',
|
||||
title: t('features.chat.title'),
|
||||
description: t('features.chat.description'),
|
||||
icon: <Chat sx={{ fontSize: 40, color: 'secondary.main' }} />,
|
||||
path: '/chat',
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
{
|
||||
title: 'Rugăciuni',
|
||||
description: 'Partajează rugăciuni și roagă-te împreună cu comunitatea',
|
||||
title: t('features.prayers.title'),
|
||||
description: t('features.prayers.description'),
|
||||
icon: <Prayer sx={{ fontSize: 40, color: 'success.main' }} />,
|
||||
path: '/prayers',
|
||||
color: theme.palette.success.main,
|
||||
},
|
||||
{
|
||||
title: 'Căutare',
|
||||
description: 'Caută versete și pasaje din întreaga Scriptură',
|
||||
title: t('features.search.title'),
|
||||
description: t('features.search.description'),
|
||||
icon: <Search sx={{ fontSize: 40, color: 'info.main' }} />,
|
||||
path: '/search',
|
||||
color: theme.palette.info.main,
|
||||
@@ -58,8 +60,6 @@ export default function Home() {
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Navigation />
|
||||
|
||||
{/* Hero Section */}
|
||||
<Box
|
||||
sx={{
|
||||
@@ -73,15 +73,13 @@ export default function Home() {
|
||||
<Grid container spacing={4} alignItems="center">
|
||||
<Grid item xs={12} md={8}>
|
||||
<Typography variant="h2" component="h1" gutterBottom>
|
||||
Ghid Biblic
|
||||
{t('hero.title')}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="h2" sx={{ mb: 3, opacity: 0.9 }}>
|
||||
Explorează Scriptura cu ajutorul inteligenței artificiale
|
||||
{t('hero.subtitle')}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ mb: 4, opacity: 0.8, maxWidth: 600 }}>
|
||||
O platformă modernă pentru studiul Bibliei, cu chat AI inteligent,
|
||||
căutare avansată și o comunitate de rugăciune care te sprijină în
|
||||
călătoria ta spirituală.
|
||||
{t('hero.description')}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
|
||||
<Button
|
||||
@@ -92,9 +90,9 @@ export default function Home() {
|
||||
'&:hover': { bgcolor: 'secondary.dark' },
|
||||
}}
|
||||
startIcon={<AutoStories />}
|
||||
onClick={() => router.push('/bible')}
|
||||
onClick={() => router.push(`/${locale}/bible`)}
|
||||
>
|
||||
Începe să citești
|
||||
{t('hero.cta.readBible')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="outlined"
|
||||
@@ -108,9 +106,9 @@ export default function Home() {
|
||||
},
|
||||
}}
|
||||
startIcon={<Chat />}
|
||||
onClick={() => router.push('/chat')}
|
||||
onClick={() => router.push(`/${locale}/chat`)}
|
||||
>
|
||||
Întreabă AI
|
||||
{t('hero.cta.askAI')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Grid>
|
||||
@@ -126,7 +124,7 @@ export default function Home() {
|
||||
{/* Features Section */}
|
||||
<Container maxWidth="lg" sx={{ mb: 8 }}>
|
||||
<Typography variant="h3" component="h2" textAlign="center" sx={{ mb: 2 }}>
|
||||
Descoperă funcționalitățile
|
||||
{t('features.title')}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body1"
|
||||
@@ -134,7 +132,7 @@ export default function Home() {
|
||||
color="text.secondary"
|
||||
sx={{ mb: 6, maxWidth: 600, mx: 'auto' }}
|
||||
>
|
||||
Totul de ce ai nevoie pentru o experiență completă de studiu biblic
|
||||
{t('features.subtitle')}
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={4}>
|
||||
@@ -152,7 +150,7 @@ export default function Home() {
|
||||
boxShadow: 4,
|
||||
},
|
||||
}}
|
||||
onClick={() => router.push(feature.path)}
|
||||
onClick={() => router.push(`/${locale}${feature.path}`)}
|
||||
>
|
||||
<CardContent sx={{ flexGrow: 1, textAlign: 'center', p: 3 }}>
|
||||
<Box sx={{ mb: 2 }}>
|
||||
@@ -179,19 +177,19 @@ export default function Home() {
|
||||
<Typography variant="h3" color="primary.main" gutterBottom>
|
||||
66
|
||||
</Typography>
|
||||
<Typography variant="h6">Cărți biblice</Typography>
|
||||
<Typography variant="h6">{t('stats.books')}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Typography variant="h3" color="secondary.main" gutterBottom>
|
||||
31,000+
|
||||
</Typography>
|
||||
<Typography variant="h6">Versete</Typography>
|
||||
<Typography variant="h6">{t('stats.verses')}</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Typography variant="h3" color="success.main" gutterBottom>
|
||||
24/7
|
||||
</Typography>
|
||||
<Typography variant="h6">Chat AI disponibil</Typography>
|
||||
<Typography variant="h6">{t('stats.aiAvailable')}</Typography>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
@@ -200,19 +198,19 @@ export default function Home() {
|
||||
{/* CTA Section */}
|
||||
<Container maxWidth="sm" sx={{ textAlign: 'center', mb: 8 }}>
|
||||
<Typography variant="h4" component="h2" gutterBottom>
|
||||
Începe călătoria ta spirituală
|
||||
{t('cta.title')}
|
||||
</Typography>
|
||||
<Typography variant="body1" color="text.secondary" sx={{ mb: 4 }}>
|
||||
Alătură-te comunității noastre și descoperă înțelepciunea Scripturii
|
||||
{t('cta.description')}
|
||||
</Typography>
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
startIcon={<Favorite />}
|
||||
sx={{ mr: 2 }}
|
||||
onClick={() => router.push('/bible')}
|
||||
onClick={() => router.push(`/${locale}/bible`)}
|
||||
>
|
||||
Începe acum
|
||||
{t('cta.startNow')}
|
||||
</Button>
|
||||
</Container>
|
||||
</Box>
|
||||
@@ -4,6 +4,7 @@ import { searchBibleHybrid, BibleVerse } from '@/lib/vector-search'
|
||||
|
||||
const chatRequestSchema = z.object({
|
||||
message: z.string().min(1),
|
||||
locale: z.string().optional().default('ro'),
|
||||
history: z.array(z.object({
|
||||
id: z.string(),
|
||||
role: z.enum(['user', 'assistant']),
|
||||
@@ -15,11 +16,10 @@ const chatRequestSchema = z.object({
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { message, history } = chatRequestSchema.parse(body)
|
||||
const { message, locale, history } = chatRequestSchema.parse(body)
|
||||
|
||||
// For now, return a mock response
|
||||
// TODO: Integrate with Azure OpenAI when ready
|
||||
const response = await generateBiblicalResponse(message, history)
|
||||
// Generate response using Azure OpenAI with vector search
|
||||
const response = await generateBiblicalResponse(message, locale, history)
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
@@ -49,10 +49,10 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
async function generateBiblicalResponse(message: string, history: any[]): Promise<string> {
|
||||
async function generateBiblicalResponse(message: string, locale: string, history: any[]): Promise<string> {
|
||||
try {
|
||||
// Search for relevant Bible verses using vector search
|
||||
const relevantVerses = await searchBibleHybrid(message, 5)
|
||||
// Search for relevant Bible verses using vector search with language filtering
|
||||
const relevantVerses = await searchBibleHybrid(message, locale, 5)
|
||||
|
||||
// Create context from relevant verses
|
||||
const versesContext = relevantVerses
|
||||
@@ -65,8 +65,9 @@ async function generateBiblicalResponse(message: string, history: any[]): Promis
|
||||
.map(msg => `${msg.role}: ${msg.content}`)
|
||||
.join('\n')
|
||||
|
||||
// Construct prompt for Azure OpenAI
|
||||
const systemPrompt = `Ești un asistent AI pentru întrebări biblice în limba română. Răspunde pe baza Scripturii, fiind respectuos și înțelept.
|
||||
// Create language-specific system prompts
|
||||
const systemPrompts = {
|
||||
ro: `Ești un asistent AI pentru întrebări biblice în limba română. Răspunde pe baza Scripturii, fiind respectuos și înțelept.
|
||||
|
||||
Instrucțiuni:
|
||||
- Folosește versurile biblice relevante pentru a răspunde la întrebare
|
||||
@@ -81,7 +82,27 @@ ${versesContext}
|
||||
Conversația anterioară:
|
||||
${conversationHistory}
|
||||
|
||||
Întrebarea curentă: ${message}`
|
||||
Întrebarea curentă: ${message}`,
|
||||
|
||||
en: `You are an AI assistant for biblical questions in English. Answer based on Scripture, being respectful and wise.
|
||||
|
||||
Instructions:
|
||||
- Use the relevant Bible verses to answer the question
|
||||
- Always cite biblical references (e.g., John 3:16)
|
||||
- Respond in English
|
||||
- Be empathetic and encouraging
|
||||
- If unsure, encourage personal study and prayer
|
||||
|
||||
Relevant verses for this question:
|
||||
${versesContext}
|
||||
|
||||
Previous conversation:
|
||||
${conversationHistory}
|
||||
|
||||
Current question: ${message}`
|
||||
}
|
||||
|
||||
const systemPrompt = systemPrompts[locale as keyof typeof systemPrompts] || systemPrompts.en
|
||||
|
||||
// Call Azure OpenAI
|
||||
const response = await fetch(
|
||||
@@ -120,11 +141,21 @@ ${conversationHistory}
|
||||
} catch (error) {
|
||||
console.error('Error calling Azure OpenAI:', error)
|
||||
|
||||
// Fallback to simple response if AI fails
|
||||
return `Îmi pare rău, dar întâmpin o problemă tehnică în acest moment. Te încurajez să cercetezi acest subiect în Scripturi și să te rogi pentru înțelegere.
|
||||
// Language-specific fallback responses
|
||||
const fallbackResponses = {
|
||||
ro: `Îmi pare rău, dar întâmpin o problemă tehnică în acest moment. Te încurajez să cercetezi acest subiect în Scripturi și să te rogi pentru înțelegere.
|
||||
|
||||
"Cercetați Scripturile, pentru că socotiți că în ele aveți viața veșnică, și tocmai ele mărturisesc despre Mine" (Ioan 5:39).
|
||||
|
||||
"Dacă vreunul dintre voi duce lipsă de înțelepciune, să ceară de la Dumnezeu, care dă tuturor cu dărnicie și fără mustrare, și i se va da" (Iacov 1:5).`
|
||||
"Dacă vreunul dintre voi duce lipsă de înțelepciune, să ceară de la Dumnezeu, care dă tuturor cu dărnicie și fără mustrare, și i se va da" (Iacov 1:5).`,
|
||||
|
||||
en: `Sorry, I'm experiencing a technical issue at the moment. I encourage you to research this topic in Scripture and pray for understanding.
|
||||
|
||||
"You study the Scriptures diligently because you think that in them you have eternal life. These are the very Scriptures that testify about me" (John 5:39).
|
||||
|
||||
"If any of you lacks wisdom, you should ask God, who gives generously to all without finding fault, and it will be given to you" (James 1:5).`
|
||||
}
|
||||
|
||||
return fallbackResponses[locale as keyof typeof fallbackResponses] || fallbackResponses.en
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,7 @@
|
||||
import './globals.css'
|
||||
import type { Metadata } from 'next'
|
||||
import { MuiThemeProvider } from '@/components/providers/theme-provider'
|
||||
import FloatingChat from '@/components/chat/floating-chat'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Ghid Biblic - Biblical Guide',
|
||||
description: 'A comprehensive Bible study application with AI chat capabilities',
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="ro">
|
||||
<body>
|
||||
<MuiThemeProvider>
|
||||
{children}
|
||||
<FloatingChat />
|
||||
</MuiThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
return children
|
||||
}
|
||||
Reference in New Issue
Block a user