11 Commits

Author SHA1 Message Date
bc4e103cb8 Update src/components/LanguageSwitcher.tsx 2026-06-10 20:59:02 +00:00
c697bf6c68 Update src/components/LanguageSwitcher.tsx 2026-06-10 20:58:27 +00:00
fe494ff3eb Update src/app/page.tsx 2026-06-10 20:58:26 +00:00
ff7b22eaa9 Add src/middleware.ts 2026-06-10 20:57:32 +00:00
685a4c9be9 Add src/lib/i18nConfig.ts 2026-06-10 20:57:31 +00:00
42ee617a67 Add src/components/LanguageSwitcher.tsx 2026-06-10 20:57:31 +00:00
80d1b44fc3 Update src/app/page.tsx 2026-06-10 20:57:31 +00:00
22bd622a46 Update src/app/layout.tsx 2026-06-10 20:57:30 +00:00
e9828f8859 Add src/app/[locale]/page.tsx 2026-06-10 20:57:30 +00:00
bca33a9d74 Add src/app/[locale]/layout.tsx 2026-06-10 20:57:29 +00:00
e2e6ad56f7 Merge version_2 into main
Merge version_2 into main
2026-06-10 20:52:04 +00:00
7 changed files with 289 additions and 36 deletions

View File

@@ -0,0 +1,72 @@
"use client";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ReactLenis from "lenis/react";
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
import ProductCart from '@/components/ecommerce/cart/ProductCart';
import { useParams } from 'next/navigation';
import { LanguageSwitcher } from '@/components/LanguageSwitcher';
import { Locale } from '@/lib/i18nConfig';
export default function LocaleLayout({
children,
}: Readonly<{ children: React.ReactNode }>)
{
const params = useParams();
const locale = params.locale as Locale;
return (
<ThemeProvider
defaultButtonVariant="text-shift"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="medium"
sizing="largeSmallSizeMediumTitles"
background="blurBottom"
cardStyle="gradient-radial"
primaryButtonStyle="shadow"
secondaryButtonStyle="solid"
headingFontWeight="bold"
>
<ReactLenis root>
<div id="nav" data-section="nav">
<NavbarLayoutFloatingInline
navItems={[
{ name: "Home", id: `/${locale}` },
{ name: "Vision", id: `#about` },
{ name: "Services", id: `#product` },
{ name: "Portfolio", id: `#team` },
{ name: "Clients", id: `#testimonial` },
{ name: "Contact", id: `#contact` },
]}
brandName="Enkidu Soft"
button={{
text: "Get in Touch", href: `#contact`
}}
animateOnLoad={true}
>
<LanguageSwitcher currentLocale={locale} />
</NavbarLayoutFloatingInline>
</div>
{children}
{/* The ProductCart is a global component, typically rendered within a layout. Moved here. */}
<div id="ecommerce" data-section="ecommerce">
<ProductCart
isOpen={false}
onClose={() => {}}
items={[
{
id: "item1", name: "Sample Product", price: "99.99", quantity: 1,
imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Sample Product Image"
}
]}
total="99.99"
buttons={[
{ text: "Checkout", onClick: () => console.log("Checkout clicked") }
]}
/>
</div>
</ReactLenis>
</ThemeProvider>
);
}

74
src/app/[locale]/page.tsx Normal file
View File

@@ -0,0 +1,74 @@
"use client";
import SplitAbout from '@/components/sections/about/SplitAbout';
import ProductCardThree from '@/components/sections/product/ProductCardThree';
import TeamCardTwo from '@/components/sections/team/TeamCardTwo';
import TestimonialCardFifteen from '@/components/sections/testimonial/TestimonialCardFifteen';
export default function LocalizedLandingPage() {
return (
<>
<div id="about" data-section="about">
<SplitAbout
textboxLayout="default"
useInvertedBackground={false}
imageSrc="http://img.b2bpic.net/free-photo/network-connections_1048-7667.jpg"
imageAlt="Network connections"
title="Our Story & Mission"
description="We are a company dedicated to innovation and excellence, striving to deliver cutting-edge solutions for our clients."
bulletPoints={[
{ title: "Innovation driven", description: "Driving innovation across all our solutions." },
{ title: "Client-focused", description: "Prioritizing client needs and delivering tailored results." },
{ title: "Excellence in execution", description: "Committing to high-quality execution in every project." }
]}
/>
</div>
<div id="product" data-section="product">
<ProductCardThree
animationType="slide-up"
textboxLayout="default"
gridVariant="uniform-all-items-equal"
useInvertedBackground={false}
title="Our Featured Products"
description="Explore our range of innovative products designed to meet your needs."
/>
</div>
<div id="team" data-section="team">
<TeamCardTwo
animationType="slide-up"
textboxLayout="default"
gridVariant="uniform-all-items-equal"
useInvertedBackground={false}
title="Meet Our Team"
description="A dedicated group of professionals passionate about technology and innovation."
members={[
{
id: "john-doe", name: "John Doe", role: "CEO", imageSrc: "http://img.b2bpic.net/free-photo/focused-woman-working-with-ai-chatbot-her-desktop-computer_482257-120813.jpg", imageAlt: "John Doe, CEO", description: "Leading our company with vision and expertise."
},
{
id: "jane-smith", name: "Jane Smith", role: "CTO", imageSrc: "http://img.b2bpic.net/free-photo/african-american-software-developer-does-visual-coding-creating-software_482257-127024.jpg", imageAlt: "Jane Smith, CTO", description: "Pioneering our technological advancements."
}
]}
/>
</div>
<div id="testimonial" data-section="testimonial">
<TestimonialCardFifteen
useInvertedBackground={false}
testimonial="Working with this team has been a game-changer for our business. Their expertise and dedication are unmatched."
rating={5}
ratingAnimation="slide-up"
author="Alice Johnson"
avatars={[
{
src: "http://img.b2bpic.net/free-photo/focused-woman-working-with-ai-chatbot-her-desktop-computer_482257-120813.jpg", alt: "Alice Johnson"
}
]}
avatarsAnimation="slide-up"
/>
</div>
</>
);
}

View File

@@ -1,36 +1,25 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import { Halant } from "next/font/google"; import { Public_Sans } from "next/font/google";
import { Inter } from "next/font/google";
import "./globals.css"; import "./globals.css";
import "@/lib/gsap-setup"; import "@/lib/gsap-setup";
import { ServiceWrapper } from "@/components/ServiceWrapper"; import { ServiceWrapper } from "@/components/ServiceWrapper";
import Tag from "@/tag/Tag"; import Tag from "@/tag/Tag";
import { getVisualEditScript } from "@/utils/visual-edit-script"; import { getVisualEditScript } from "@/utils/visual-edit-script";
import { Public_Sans } from "next/font/google"; import { i18n } from '@/lib/i18nConfig'; // New import
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Enkidu Soft - Engineering Excellence', title: 'Enkidu Soft - Engineering Excellence',
description: 'Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.', description: 'Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.',
openGraph: { openGraph: {
"title": "Enkidu Soft - Engineering Excellence", "title": "Enkidu Soft - Engineering Excellence", "description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.", "url": "https://www.enkidusoft.com/en", "siteName": "Enkidu Soft", "images": [
"description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.",
"url": "https://www.enkidusoft.com/en",
"siteName": "Enkidu Soft",
"images": [
{ {
"url": "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg", "url": "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg", "alt": "Abstract data flow and secure connections"
"alt": "Abstract data flow and secure connections"
} }
], ],
"type": "website" "type": "website"
}, },
twitter: { twitter: {
"card": "summary_large_image", "card": "summary_large_image", "title": "Enkidu Soft - Engineering Excellence", "description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.", "images": [
"title": "Enkidu Soft - Engineering Excellence",
"description": "Enkidu Soft partners with enterprise leaders to architect, build, and scale transformative software solutions with rigorous engineering and deep market insight.",
"images": [
"http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg" "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg"
] ]
}, },
@@ -41,17 +30,23 @@ export const metadata: Metadata = {
}; };
const publicSans = Public_Sans({ const publicSans = Public_Sans({
variable: "--font-public-sans", variable: "--font-public-sans", subsets: ["latin"],
subsets: ["latin"],
}); });
// Generate static params for all locales
export function generateStaticParams() {
return i18n.locales.map((locale) => ({ locale }));
}
export default function RootLayout({ export default function RootLayout({
children, children,
params: { locale }, // Accept locale from the URL
}: Readonly<{ }: Readonly<{
children: React.ReactNode; children: React.ReactNode;
params: { locale: string }; // Type definition for params
}>) { }>) {
return ( return (
<html lang="en" suppressHydrationWarning> <html lang={locale} dir={locale === 'ar' ? 'rtl' : 'ltr'} suppressHydrationWarning>
<ServiceWrapper> <ServiceWrapper>
<body className={`${publicSans.variable} antialiased`}> <body className={`${publicSans.variable} antialiased`}>
<Tag /> <Tag />

View File

@@ -4,10 +4,11 @@ import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import ReactLenis from "lenis/react"; import ReactLenis from "lenis/react";
import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline'; import NavbarLayoutFloatingInline from '@/components/navbar/NavbarLayoutFloatingInline';
import ProductCardThree from '@/components/sections/product/ProductCardThree'; import ProductCardThree from '@/components/sections/product/ProductCardThree';
import ProductCart from '@/components/ecommerce/cart/ProductCart';
import SplitAbout from '@/components/sections/about/SplitAbout'; import SplitAbout from '@/components/sections/about/SplitAbout';
import TeamCardTwo from '@/components/sections/team/TeamCardTwo'; import TeamCardTwo from '@/components/sections/team/TeamCardTwo';
import TestimonialCardFifteen from '@/components/sections/testimonial/TestimonialCardFifteen'; import TestimonialCardFifteen from '@/components/sections/testimonial/TestimonialCardFifteen';
import SocialProofOne from '@/components/sections/socialProof/SocialProofOne';
import ContactSplitForm from '@/components/sections/contact/ContactSplitForm';
export default function LandingPage() { export default function LandingPage() {
return ( return (
@@ -63,14 +64,34 @@ export default function LandingPage() {
/> />
</div> </div>
<div id="product" data-section="product"> <div id="portfolio" data-section="portfolio">
<ProductCardThree <ProductCardThree
animationType="slide-up" animationType="slide-up"
textboxLayout="default" textboxLayout="default"
gridVariant="uniform-all-items-equal" gridVariant="bento-grid"
useInvertedBackground={false} useInvertedBackground={false}
title="Our Featured Products" title="Our Portfolio Showcase"
description="Explore our range of innovative products designed to meet your needs." description="Discover our diverse projects and the impact we've made."
products={[
{ id: "p1", name: "Enterprise CRM", price: "Software Development", imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Enterprise CRM project" },
{ id: "p2", name: "AI-Powered Analytics", price: "AI & Data Science", imageSrc: "http://img.b2bpic.net/free-photo/network-connections_1048-7667.jpg", imageAlt: "AI-Powered Analytics project" },
{ id: "p3", name: "Fintech Platform", price: "Fintech Solutions", imageSrc: "http://img.b2bpic.net/free-photo/geometric-abstract-background-technology-concept-connecting-dots-design_53876-153353.jpg", imageAlt: "Fintech Platform project" },
{ id: "p4", name: "Mobile E-commerce App", price: "Mobile Development", imageSrc: "http://img.b2bpic.net/free-photo/close-up-of-business-man-using-laptop_1048-18305.jpg", imageAlt: "Mobile E-commerce App project" }
]}
/>
</div>
<div id="clients" data-section="clients">
<SocialProofOne
textboxLayout="default"
useInvertedBackground={false}
title="Trusted by Industry Leaders"
description="We partner with leading organizations to drive innovation and growth."
names={[
"TechCorp", "Innovate Global", "Future Solutions", "Dynamic Systems", "Quantum Leap", "Synergy Corp", "Global Dynamics"
]}
showCard={false}
speed={30}
/> />
</div> </div>
@@ -108,19 +129,20 @@ export default function LandingPage() {
/> />
</div> </div>
<div id="ecommerce" data-section="ecommerce"> <div id="contact" data-section="contact">
<ProductCart <ContactSplitForm
isOpen={false} title="Partner with Us"
onClose={() => {}} description="Ready to transform your enterprise? Get in touch with our experts today."
items={[ inputs={[
{ { name: "name", type: "text", placeholder: "Your Name", required: true },
id: "item1", name: "Sample Product", price: "99.99", quantity: 1, { name: "email", type: "email", placeholder: "Your Email", required: true },
imageSrc: "http://img.b2bpic.net/free-photo/modern-equipped-computer-lab_23-2149241207.jpg", imageAlt: "Sample Product Image"} { name: "company", type: "text", placeholder: "Your Company" }
]}
total="99.99"
buttons={[
{ text: "Checkout", onClick: () => console.log("Checkout clicked") }
]} ]}
textarea={{ name: "message", placeholder: "Your message...", rows: 5, required: false }}
buttonText="Send Message"
imageSrc="http://img.b2bpic.net/free-photo/contact-us-customer-service-concept-man-using-laptop_23-2149454178.jpg"
imageAlt="Contact us"
useInvertedBackground={false}
/> />
</div> </div>
</ReactLenis> </ReactLenis>

View File

@@ -0,0 +1,46 @@
"use client";
import { useRouter, usePathname } from 'next/navigation';
import { i18n, Locale } from '@/lib/i18nConfig';
import { useState, useEffect } from 'react';
interface LanguageSwitcherProps {
currentLocale: Locale;
}
export function LanguageSwitcher({ currentLocale }: LanguageSwitcherProps) {
const router = useRouter();
const pathname = usePathname();
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
setIsMounted(true);
}, []);
if (!isMounted) {
return null; // Or a loading spinner
}
const onSelectChange = (newLocale: Locale) => {
// Replace the current locale in the pathname with the new one
const newPath = `/${newLocale}${pathname.substring(3)}`; // Assuming /en, /fr, /es are 3 chars
router.push(newPath);
// Set cookie for middleware to remember preferred locale
document.cookie = `NEXT_LOCALE=${newLocale}; path=/; max-age=31536000;`;
};
return (
<select
onChange={(e) => onSelectChange(e.target.value as Locale)}
value={currentLocale}
className="w-[100px] bg-background-accent text-foreground p-2 rounded-md border border-gray-300 dark:border-gray-700"
>
{i18n.locales.map((locale) => (
<option key={locale} value={locale}>
{locale.toUpperCase()}
</option>
))}
</select>
);
}

6
src/lib/i18nConfig.ts Normal file
View File

@@ -0,0 +1,6 @@
export const i18n = {
defaultLocale: 'en',
locales: ['en', 'fr', 'es'], // Define your supported locales
} as const;
export type Locale = (typeof i18n)['locales'][number];

38
src/middleware.ts Normal file
View File

@@ -0,0 +1,38 @@
import { NextRequest, NextResponse } from 'next/server';
import { i18n } from './lib/i18nConfig';
const PUBLIC_FILE_REGEX = /\.(.*)$/;
export function middleware(request: NextRequest) {
const locale = request.cookies.get('NEXT_LOCALE')?.value || i18n.defaultLocale;
const { pathname } = request.nextUrl;
// Skip internal Next.js paths and static files
if (
pathname.startsWith('/_next') ||
pathname.startsWith('/api') ||
PUBLIC_FILE_REGEX.test(pathname)
) {
return;
}
// Check if there is any supported locale in the pathname
const pathnameHasLocale = i18n.locales.some(
(loc) => pathname.startsWith(`/${loc}/`) || pathname === `/${loc}`
);
if (pathnameHasLocale) {
return NextResponse.next();
}
// Rewrite to include the default locale if no locale is present
request.nextUrl.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(request.nextUrl);
}
export const config = {
matcher: [
'/((?!api|_next/static|_next/image|favicon.ico).*)',
'/',
],
};