From 8a57ccb1970fc79b564c8518a67251a55e94d6db Mon Sep 17 00:00:00 2001 From: RyloRiz <91710711+RyloRiz@users.noreply.github.com> Date: Tue, 7 Jul 2026 02:41:13 -0700 Subject: [PATCH] added i18n + changed routing --- app/[locale]/about/page.tsx | 28 ++--- app/[locale]/contact/layout.tsx | 28 ++--- app/[locale]/documents/layout.tsx | 28 ++--- app/[locale]/documents/page.tsx | 3 +- app/[locale]/fraud/layout.tsx | 28 ++--- app/[locale]/inspection/layout.tsx | 28 ++--- app/[locale]/inspection/page.tsx | 20 ++-- app/[locale]/layout.tsx | 48 ++------ app/[locale]/page.tsx | 11 +- app/[locale]/research/page.tsx | 28 ++--- app/[locale]/rights/page.tsx | 33 ++---- app/[locale]/team/page.tsx | 30 ++--- app/[locale]/volunteer/layout.tsx | 18 +++ app/[locale]/volunteer/page.tsx | 4 +- app/not-found.tsx | 9 +- app/sitemap.ts | 80 ++++++------- components/layout/Footer.tsx | 33 ++++-- components/layout/LanguageSwitcher.tsx | 9 +- components/layout/Nav.tsx | 51 ++++++--- lib/constants.ts | 2 +- lib/i18n/config.ts | 8 ++ lib/i18n/dictionaries/ar-EG.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/en.json | 89 ++++++++++++++- lib/i18n/dictionaries/es.json | 89 ++++++++++++++- lib/i18n/dictionaries/fa.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/hi.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/hy.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/ko.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/tl.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/vi.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionaries/zh-Hans.json | 152 ++++++++++++++++++++++++- lib/i18n/dictionary.ts | 84 ++++++++++++++ lib/i18n/get-dictionary.ts | 36 +++++- lib/i18n/home-dict.ts | 40 +------ lib/i18n/metadata.ts | 104 +++++++++++++++++ middleware.ts => proxy.ts | 20 ++-- 36 files changed, 1862 insertions(+), 343 deletions(-) create mode 100644 app/[locale]/volunteer/layout.tsx create mode 100644 lib/i18n/dictionary.ts create mode 100644 lib/i18n/metadata.ts rename middleware.ts => proxy.ts (60%) diff --git a/app/[locale]/about/page.tsx b/app/[locale]/about/page.tsx index f7bc620..560706c 100644 --- a/app/[locale]/about/page.tsx +++ b/app/[locale]/about/page.tsx @@ -1,4 +1,3 @@ -import type { Metadata } from "next"; import Image from "next/image"; import { PageHero, @@ -6,25 +5,16 @@ import { Divider, SectionTitle, } from "@/components/ui"; +import { getRouteMetadata } from "@/lib/i18n/metadata"; -export const metadata: Metadata = { - title: "About Us", - description: - "VINdicated was founded by Rana Darwich after experiencing dealership discrimination firsthand. Learn about our mission to educate, empower, and vindicate car buyers.", - openGraph: { - title: "About Us", - description: - "VINdicated was founded by Rana Darwich after experiencing dealership discrimination firsthand. Learn about our mission to educate, empower, and vindicate car buyers.", - url: "/about", - type: "website", - images: [{ url: "/illus-woman-dealership.png", alt: "VINdicated: About Us" }], - }, - twitter: { - title: "About Us", - description: - "VINdicated was founded by Rana Darwich after experiencing dealership discrimination firsthand. Learn about our mission to educate, empower, and vindicate car buyers.", - }, -}; +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + return getRouteMetadata(locale, "about", "/about"); +} export default function AboutPage() { return ( diff --git a/app/[locale]/contact/layout.tsx b/app/[locale]/contact/layout.tsx index c56f64b..c14286d 100644 --- a/app/[locale]/contact/layout.tsx +++ b/app/[locale]/contact/layout.tsx @@ -1,23 +1,13 @@ -import type { Metadata } from "next"; +import { getRouteMetadata } from "@/lib/i18n/metadata"; -export const metadata: Metadata = { - title: "Contact", - description: - "Get in touch with VINdicated: volunteer with our team, share your story, participate in research, or partner with us.", - openGraph: { - title: "Contact", - description: - "Get in touch with VINdicated: volunteer with our team, share your story, participate in research, or partner with us.", - url: "/contact", - type: "website", - images: [{ url: "/illus-woman-dealership.png", alt: "VINdicated: Contact" }], - }, - twitter: { - title: "Contact", - description: - "Get in touch with VINdicated: volunteer with our team, share your story, participate in research, or partner with us.", - }, -}; +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + return getRouteMetadata(locale, "contact", "/contact"); +} export default function ContactLayout({ children, diff --git a/app/[locale]/documents/layout.tsx b/app/[locale]/documents/layout.tsx index 9f8644e..7c4d3ad 100644 --- a/app/[locale]/documents/layout.tsx +++ b/app/[locale]/documents/layout.tsx @@ -1,23 +1,13 @@ -import type { Metadata } from "next"; +import { getRouteMetadata } from "@/lib/i18n/metadata"; -export const metadata: Metadata = { - title: "Documents Decoded", - description: - "Interactive guides to understanding car buying documents: the pink slip, Carfax reports, financing contracts, and more. Know what you're signing before you sign it.", - openGraph: { - title: "Documents Decoded", - description: - "Interactive guides to understanding car buying documents: the pink slip, Carfax reports, financing contracts, and more. Know what you're signing before you sign it.", - url: "/documents", - type: "website", - images: [{ url: "/illus-woman-dealership.png", alt: "VINdicated: Documents Decoded" }], - }, - twitter: { - title: "Documents Decoded", - description: - "Interactive guides to understanding car buying documents: the pink slip, Carfax reports, financing contracts, and more. Know what you're signing before you sign it.", - }, -}; +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + return getRouteMetadata(locale, "documents", "/documents"); +} export default function DocumentsLayout({ children, diff --git a/app/[locale]/documents/page.tsx b/app/[locale]/documents/page.tsx index 5b0f0a5..b9f596b 100644 --- a/app/[locale]/documents/page.tsx +++ b/app/[locale]/documents/page.tsx @@ -337,7 +337,8 @@ const bgItems = [ <>

A service contract (extended warranty) is optional and not free. The - word "available" means they want to sell it to you, but it doesn't necessarily mean you need + word "available" means they want to sell it to you, but it + doesn't necessarily mean you need it.

diff --git a/app/[locale]/fraud/layout.tsx b/app/[locale]/fraud/layout.tsx index ec20f78..fcf4087 100644 --- a/app/[locale]/fraud/layout.tsx +++ b/app/[locale]/fraud/layout.tsx @@ -1,23 +1,13 @@ -import type { Metadata } from "next"; +import { getRouteMetadata } from "@/lib/i18n/metadata"; -export const metadata: Metadata = { - title: "Fraud Prevention", - description: - "Learn to recognize and counter common dealer scams. Know the red flags, your legal rights under California and federal law, and what to do if you've been scammed.", - openGraph: { - title: "Fraud Prevention", - description: - "Learn to recognize and counter common dealer scams. Know the red flags, your legal rights under California and federal law, and what to do if you've been scammed.", - url: "/fraud", - type: "website", - images: [{ url: "/illus-woman-dealership.png", alt: "VINdicated: Fraud Prevention" }], - }, - twitter: { - title: "Fraud Prevention", - description: - "Learn to recognize and counter common dealer scams. Know the red flags, your legal rights under California and federal law, and what to do if you've been scammed.", - }, -}; +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + return getRouteMetadata(locale, "fraud", "/fraud"); +} export default function FraudLayout({ children, diff --git a/app/[locale]/inspection/layout.tsx b/app/[locale]/inspection/layout.tsx index 2651731..4e75fc5 100644 --- a/app/[locale]/inspection/layout.tsx +++ b/app/[locale]/inspection/layout.tsx @@ -1,23 +1,13 @@ -import type { Metadata } from "next"; +import { getRouteMetadata } from "@/lib/i18n/metadata"; -export const metadata: Metadata = { - title: "Inspection Guide", - description: - "A step-by-step guide to inspecting a used car before you buy. Know what to look for under the hood, on the lot, and in the paperwork.", - openGraph: { - title: "Inspection Guide", - description: - "A step-by-step guide to inspecting a used car before you buy. Know what to look for under the hood, on the lot, and in the paperwork.", - url: "/inspection", - type: "website", - images: [{ url: "/illus-woman-dealership.png", alt: "VINdicated: Inspection Guide" }], - }, - twitter: { - title: "Inspection Guide", - description: - "A step-by-step guide to inspecting a used car before you buy. Know what to look for under the hood, on the lot, and in the paperwork.", - }, -}; +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + return getRouteMetadata(locale, "inspection", "/inspection"); +} export default function InspectionLayout({ children, diff --git a/app/[locale]/inspection/page.tsx b/app/[locale]/inspection/page.tsx index 72eea0d..0f25e04 100644 --- a/app/[locale]/inspection/page.tsx +++ b/app/[locale]/inspection/page.tsx @@ -633,11 +633,11 @@ const inspectionAccordion = [
  • Check engine light codes: Even if the light - isn't on, a mechanic can pull stored codes. + isn't on, a mechanic can pull stored codes.
  • Compression test: Reveals internal engine wear - that visual inspection can't catch. + that visual inspection can't catch.
  • ), @@ -711,7 +711,7 @@ const inspectionAccordion = [ body: (

    - A Carfax report helps but isn't the whole picture. A physical + A Carfax report helps but isn't the whole picture. A physical inspection can catch: