Skip to content

Commit 230aa96

Browse files
Add English language support
- Add language toggle to the top banner. - Implement English and Spanish versions. - Set Spanish as the default language.
1 parent bb8b714 commit 230aa96

File tree

6 files changed

+312
-125
lines changed

6 files changed

+312
-125
lines changed

src/App.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Toaster as Sonner } from "@/components/ui/sonner";
44
import { TooltipProvider } from "@/components/ui/tooltip";
55
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
66
import { BrowserRouter, Routes, Route } from "react-router-dom";
7+
import { LanguageProvider } from "@/contexts/LanguageContext";
78
import Index from "./pages/Index";
89
import QuienesSomos from "./pages/QuienesSomos";
910
import Servicios from "./pages/Servicios";
@@ -15,20 +16,22 @@ const queryClient = new QueryClient();
1516

1617
const App = () => (
1718
<QueryClientProvider client={queryClient}>
18-
<TooltipProvider>
19-
<Toaster />
20-
<Sonner />
21-
<BrowserRouter>
22-
<Routes>
23-
<Route path="/" element={<Index />} />
24-
<Route path="/quienes-somos" element={<QuienesSomos />} />
25-
<Route path="/servicios" element={<Servicios />} />
26-
<Route path="/ambientes" element={<Ambientes />} />
27-
<Route path="/contacto" element={<Contacto />} />
28-
<Route path="*" element={<NotFound />} />
29-
</Routes>
30-
</BrowserRouter>
31-
</TooltipProvider>
19+
<LanguageProvider>
20+
<TooltipProvider>
21+
<Toaster />
22+
<Sonner />
23+
<BrowserRouter>
24+
<Routes>
25+
<Route path="/" element={<Index />} />
26+
<Route path="/quienes-somos" element={<QuienesSomos />} />
27+
<Route path="/servicios" element={<Servicios />} />
28+
<Route path="/ambientes" element={<Ambientes />} />
29+
<Route path="/contacto" element={<Contacto />} />
30+
<Route path="*" element={<NotFound />} />
31+
</Routes>
32+
</BrowserRouter>
33+
</TooltipProvider>
34+
</LanguageProvider>
3235
</QueryClientProvider>
3336
);
3437

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
import { Globe } from 'lucide-react';
3+
import { useLanguage } from '@/contexts/LanguageContext';
4+
5+
const LanguageSwitcher = () => {
6+
const { language, setLanguage } = useLanguage();
7+
8+
return (
9+
<div className="flex items-center space-x-2">
10+
<Globe className="h-4 w-4 text-gray-600" />
11+
<div className="flex items-center space-x-1">
12+
<button
13+
onClick={() => setLanguage('es')}
14+
className={`px-2 py-1 text-sm font-medium rounded transition-colors ${
15+
language === 'es'
16+
? 'bg-dental-600 text-white'
17+
: 'text-gray-600 hover:text-dental-600'
18+
}`}
19+
>
20+
ES
21+
</button>
22+
<span className="text-gray-400">|</span>
23+
<button
24+
onClick={() => setLanguage('en')}
25+
className={`px-2 py-1 text-sm font-medium rounded transition-colors ${
26+
language === 'en'
27+
? 'bg-dental-600 text-white'
28+
: 'text-gray-600 hover:text-dental-600'
29+
}`}
30+
>
31+
EN
32+
</button>
33+
</div>
34+
</div>
35+
);
36+
};
37+
38+
export default LanguageSwitcher;

src/components/Navbar.tsx

Lines changed: 102 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,144 +2,158 @@
22
import { useState } from 'react';
33
import { Link, useLocation } from 'react-router-dom';
44
import { Menu, X, Facebook, Instagram } from 'lucide-react';
5+
import { useLanguage } from '@/contexts/LanguageContext';
6+
import LanguageSwitcher from './LanguageSwitcher';
57

68
const Navbar = () => {
79
const [isOpen, setIsOpen] = useState(false);
810
const location = useLocation();
11+
const { t } = useLanguage();
912

1013
const navigation = [
11-
{ name: 'Inicio', href: '/' },
12-
{ name: 'Quiénes Somos', href: '/quienes-somos' },
13-
{ name: 'Servicios', href: '/servicios' },
14-
{ name: 'Ambientes', href: '/ambientes' },
15-
{ name: 'Contacto', href: '/contacto' },
14+
{ name: t('nav.home'), href: '/' },
15+
{ name: t('nav.about'), href: '/quienes-somos' },
16+
{ name: t('nav.services'), href: '/servicios' },
17+
{ name: t('nav.environments'), href: '/ambientes' },
18+
{ name: t('nav.contact'), href: '/contacto' },
1619
];
1720

1821
const isActive = (path: string) => location.pathname === path;
1922

2023
return (
21-
<nav className="bg-white shadow-lg sticky top-0 z-50">
22-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
23-
<div className="flex justify-between h-20">
24-
{/* Logo */}
25-
<div className="flex items-center">
26-
<Link to="/" className="flex items-center space-x-3">
27-
<img
28-
src="/images/7763065a-89ed-4786-a8c7-998e28bbf032.webp"
29-
alt="Dra. Liz Cheng"
30-
className="h-20 w-auto"
31-
/>
32-
</Link>
24+
<>
25+
{/* Top Language Bar */}
26+
<div className="bg-dental-50 border-b border-dental-100">
27+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
28+
<div className="flex justify-end py-2">
29+
<LanguageSwitcher />
3330
</div>
31+
</div>
32+
</div>
3433

35-
{/* Desktop Navigation */}
36-
<div className="hidden md:flex items-center space-x-8">
37-
{navigation.map((item) => (
38-
<Link
39-
key={item.name}
40-
to={item.href}
41-
className={`text-gray-700 hover:text-dental-600 px-3 py-2 text-sm font-medium transition-colors ${
42-
isActive(item.href) ? 'text-dental-600 border-b-2 border-dental-600' : ''
43-
}`}
44-
>
45-
{item.name}
34+
<nav className="bg-white shadow-lg sticky top-0 z-50">
35+
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
36+
<div className="flex justify-between h-20">
37+
{/* Logo */}
38+
<div className="flex items-center">
39+
<Link to="/" className="flex items-center space-x-3">
40+
<img
41+
src="/images/7763065a-89ed-4786-a8c7-998e28bbf032.webp"
42+
alt="Dra. Liz Cheng"
43+
className="h-20 w-auto"
44+
/>
4645
</Link>
47-
))}
48-
49-
{/* Social Media Links */}
50-
<div className="flex items-center space-x-3">
51-
<a
52-
href="https://www.facebook.com/dra.lizcheng"
53-
target="_blank"
54-
rel="noopener noreferrer"
55-
className="text-gray-700 hover:text-dental-600 transition-colors"
56-
>
57-
<Facebook className="h-5 w-5" />
58-
</a>
59-
<a
60-
href="https://www.instagram.com/dra.lizcheng/"
61-
target="_blank"
62-
rel="noopener noreferrer"
63-
className="text-gray-700 hover:text-dental-600 transition-colors"
64-
>
65-
<Instagram className="h-5 w-5" />
66-
</a>
6746
</div>
68-
69-
<a
70-
href="https://api.whatsapp.com/send/?phone=51987566993&text=Hola%21+Deseo+agendar+mi+cita%21&type=phone_number&app_absent=0"
71-
target="_blank"
72-
rel="noopener noreferrer"
73-
className="bg-dental-600 hover:bg-dental-700 text-white px-6 py-2 rounded-full text-sm font-medium transition-colors"
74-
>
75-
Agendar Cita
76-
</a>
77-
</div>
78-
79-
{/* Mobile menu button */}
80-
<div className="md:hidden flex items-center">
81-
<button
82-
onClick={() => setIsOpen(!isOpen)}
83-
className="text-gray-700 hover:text-dental-600 focus:outline-none"
84-
>
85-
{isOpen ? <X size={24} /> : <Menu size={24} />}
86-
</button>
87-
</div>
88-
</div>
8947

90-
{/* Mobile Navigation */}
91-
{isOpen && (
92-
<div className="md:hidden">
93-
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t">
48+
{/* Desktop Navigation */}
49+
<div className="hidden md:flex items-center space-x-8">
9450
{navigation.map((item) => (
9551
<Link
9652
key={item.name}
9753
to={item.href}
98-
className={`block px-3 py-2 text-base font-medium transition-colors ${
99-
isActive(item.href)
100-
? 'text-dental-600 bg-dental-50'
101-
: 'text-gray-700 hover:text-dental-600 hover:bg-dental-50'
54+
className={`text-gray-700 hover:text-dental-600 px-3 py-2 text-sm font-medium transition-colors ${
55+
isActive(item.href) ? 'text-dental-600 border-b-2 border-dental-600' : ''
10256
}`}
103-
onClick={() => setIsOpen(false)}
10457
>
10558
{item.name}
10659
</Link>
10760
))}
10861

109-
{/* Mobile Social Media Links */}
110-
<div className="flex items-center justify-center space-x-6 py-4">
62+
{/* Social Media Links */}
63+
<div className="flex items-center space-x-3">
11164
<a
11265
href="https://www.facebook.com/dra.lizcheng"
11366
target="_blank"
11467
rel="noopener noreferrer"
11568
className="text-gray-700 hover:text-dental-600 transition-colors"
11669
>
117-
<Facebook className="h-6 w-6" />
70+
<Facebook className="h-5 w-5" />
11871
</a>
11972
<a
12073
href="https://www.instagram.com/dra.lizcheng/"
12174
target="_blank"
12275
rel="noopener noreferrer"
12376
className="text-gray-700 hover:text-dental-600 transition-colors"
12477
>
125-
<Instagram className="h-6 w-6" />
78+
<Instagram className="h-5 w-5" />
12679
</a>
12780
</div>
12881

12982
<a
13083
href="https://api.whatsapp.com/send/?phone=51987566993&text=Hola%21+Deseo+agendar+mi+cita%21&type=phone_number&app_absent=0"
13184
target="_blank"
13285
rel="noopener noreferrer"
133-
className="block w-full text-center bg-dental-600 hover:bg-dental-700 text-white px-6 py-2 rounded-full text-sm font-medium transition-colors mt-4"
134-
onClick={() => setIsOpen(false)}
86+
className="bg-dental-600 hover:bg-dental-700 text-white px-6 py-2 rounded-full text-sm font-medium transition-colors"
13587
>
136-
Agendar Cita
88+
{t('nav.schedule')}
13789
</a>
13890
</div>
91+
92+
{/* Mobile menu button */}
93+
<div className="md:hidden flex items-center">
94+
<button
95+
onClick={() => setIsOpen(!isOpen)}
96+
className="text-gray-700 hover:text-dental-600 focus:outline-none"
97+
>
98+
{isOpen ? <X size={24} /> : <Menu size={24} />}
99+
</button>
100+
</div>
139101
</div>
140-
)}
141-
</div>
142-
</nav>
102+
103+
{/* Mobile Navigation */}
104+
{isOpen && (
105+
<div className="md:hidden">
106+
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t">
107+
{navigation.map((item) => (
108+
<Link
109+
key={item.name}
110+
to={item.href}
111+
className={`block px-3 py-2 text-base font-medium transition-colors ${
112+
isActive(item.href)
113+
? 'text-dental-600 bg-dental-50'
114+
: 'text-gray-700 hover:text-dental-600 hover:bg-dental-50'
115+
}`}
116+
onClick={() => setIsOpen(false)}
117+
>
118+
{item.name}
119+
</Link>
120+
))}
121+
122+
{/* Mobile Social Media Links */}
123+
<div className="flex items-center justify-center space-x-6 py-4">
124+
<a
125+
href="https://www.facebook.com/dra.lizcheng"
126+
target="_blank"
127+
rel="noopener noreferrer"
128+
className="text-gray-700 hover:text-dental-600 transition-colors"
129+
>
130+
<Facebook className="h-6 w-6" />
131+
</a>
132+
<a
133+
href="https://www.instagram.com/dra.lizcheng/"
134+
target="_blank"
135+
rel="noopener noreferrer"
136+
className="text-gray-700 hover:text-dental-600 transition-colors"
137+
>
138+
<Instagram className="h-6 w-6" />
139+
</a>
140+
</div>
141+
142+
<a
143+
href="https://api.whatsapp.com/send/?phone=51987566993&text=Hola%21+Deseo+agendar+mi+cita%21&type=phone_number&app_absent=0"
144+
target="_blank"
145+
rel="noopener noreferrer"
146+
className="block w-full text-center bg-dental-600 hover:bg-dental-700 text-white px-6 py-2 rounded-full text-sm font-medium transition-colors mt-4"
147+
onClick={() => setIsOpen(false)}
148+
>
149+
{t('nav.schedule')}
150+
</a>
151+
</div>
152+
</div>
153+
)}
154+
</div>
155+
</nav>
156+
</>
143157
);
144158
};
145159

0 commit comments

Comments
 (0)