feat: implement bilingual English/Spanish toggle with lossless i18n translation engine across all pages

This commit is contained in:
2026-09-11 21:07:34 -07:00
parent 8cd0fbce52
commit 7b483b8020
17 changed files with 877 additions and 45 deletions
+17 -1
View File
@@ -64,7 +64,11 @@
<!-- CTA -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span>(661) 581-7278</span>
</a>
@@ -90,6 +94,17 @@
<a href="tumbleweed-removal.html" class="mobile-link">Tumbleweed Removal</a>
<a href="contact.html" class="mobile-link">Contact</a>
<div style="margin-top: 24px;">
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" style="width: 100%;" data-scope="Mobile Menu">Get Free Estimate</button>
</div>
</div>
@@ -287,6 +302,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -114,7 +114,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -135,6 +139,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Acton Landscaping" style="width: 100%; margin-top: 10px;">Request Acton Quote</button>
</div>
</header>
@@ -518,6 +533,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+13
View File
@@ -246,10 +246,23 @@ document.addEventListener('DOMContentLoaded', () => {
if (selectedSize === 'acreage' && !timeText.includes('Days')) {
timeText = '1 - 2 Days (Full Crew)';
}
if (document.documentElement.lang === 'es') {
timeText = timeText.replace(/Same Day/gi, 'Mismo Día')
.replace(/Same-Day/gi, 'Mismo Día')
.replace(/Hours/gi, 'Horas')
.replace(/Days/gi, 'Días')
.replace(/Routine/gi, 'Rutina')
.replace(/\(Full Crew\)/gi, '(Equipo Completo)');
}
timeDisplay.textContent = timeText;
}
}
// Listen for language changes to update localized calculator output
window.addEventListener('languageChanged', () => {
updateEstimate();
});
// Listen to all calculator radio buttons
const calcInputs = document.querySelectorAll('input[name="calc-service"], input[name="calc-size"], input[name="calc-condition"]');
calcInputs.forEach(input => {
+17 -1
View File
@@ -94,7 +94,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span>(661) 581-7278</span>
</a>
@@ -115,6 +119,17 @@
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="index.html#reviews" class="nav-link mobile-link">Customer Reviews</a>
<a href="contact.html" class="nav-link mobile-link" style="color: var(--neon-text-shade); font-weight: 800;">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" style="width: 100%; margin-top: 10px;">Request Instant Quote</button>
</div>
</header>
@@ -541,6 +556,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+49 -30
View File
@@ -28,7 +28,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@500;600;700;800;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="styles.css?v=4">
<!-- Structured Data: LocalBusiness Schema -->
<script type="application/ld+json">
@@ -78,8 +78,12 @@
<svg class="icon-svg" width="13" height="13" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round" style="margin-right: 5px;"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
High Desert Notice
</span>
<span>LA & Kern County Fire Clearance Deadlines Approaching! Fast 48-Hour Weed Abatement Available.</span>
<a href="#calculator" class="announcement-link">Get Instant Estimate &rarr;</a>
<span data-i18n="topbar.notice">LA & Kern County Fire Clearance Deadlines Approaching! Fast 48-Hour Weed Abatement Available.</span>
<a href="#calculator" class="announcement-link" data-i18n="topbar.cta">Get Instant Estimate &rarr;</a>
<div class="lang-switch" role="group" aria-label="Language selector" style="margin-left: 8px;">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
</aside>
@@ -98,22 +102,26 @@
<!-- Desktop Navigation -->
<nav class="nav-desktop" aria-label="Main Navigation">
<a href="#services" class="nav-link">Services</a>
<a href="#calculator" class="nav-link">Cost Calculator</a>
<a href="#transformation" class="nav-link">Before & After</a>
<a href="#projects" class="nav-link">Projects</a>
<a href="#areas" class="nav-link">Service Areas</a>
<a href="#reviews" class="nav-link">Reviews</a>
<a href="contact.html" class="nav-link">Contact</a>
<a href="#services" class="nav-link" data-i18n="nav.services">Services</a>
<a href="#calculator" class="nav-link" data-i18n="nav.calculator">Cost Calculator</a>
<a href="#transformation" class="nav-link" data-i18n="nav.transformation">Before & After</a>
<a href="#projects" class="nav-link" data-i18n="nav.projects">Projects</a>
<a href="#areas" class="nav-link" data-i18n="nav.areas">Service Areas</a>
<a href="#reviews" class="nav-link" data-i18n="nav.reviews">Reviews</a>
<a href="contact.html" class="nav-link" data-i18n="nav.contact">Contact</a>
</nav>
<!-- Header CTAs -->
<div class="header-cta-group">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
<button class="btn btn-primary open-quote-btn" id="header-quote-btn">
<button class="btn btn-primary open-quote-btn" id="header-quote-btn" data-i18n="nav.estimate">
Free Estimate
</button>
<button class="mobile-menu-btn" id="mobile-toggle" aria-label="Toggle navigation menu">
@@ -131,6 +139,16 @@
<a href="#areas" class="nav-link mobile-link">Service Areas</a>
<a href="#reviews" class="nav-link mobile-link">Customer Reviews</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" style="width: 100%; margin-top: 10px;">Request Instant Quote</button>
</div>
</header>
@@ -143,25 +161,25 @@
<div class="hero-badge-row">
<span class="badge">
<span class="badge-dot"></span>
Antelope Valley High-Desert Yard Specialists
<span data-i18n="hero.badge">Antelope Valley High-Desert Yard Specialists</span>
</span>
</div>
<h1 class="hero-title">
Rugged Desert. <br>
<span class="neon-text">Precision Lawns.</span><br>
Zero Compromise.
<span data-i18n="hero.title.1">Rugged Desert.</span> <br>
<span class="neon-text" data-i18n="hero.title.2">Precision Lawns.</span><br>
<span data-i18n="hero.title.3">Zero Compromise.</span>
</h1>
<p class="hero-subtitle">
<p class="hero-subtitle" data-i18n="hero.subtitle">
Tumbleweeds, unkempt desert brush, or high water bills? Next Gen transforms harsh Antelope Valley properties into pristine, fire-safe showpieces. Fast turnarounds across Palmdale, Lancaster, Quartz Hill, and surrounding desert communities.
</p>
<div class="hero-actions">
<a href="#calculator" class="btn btn-primary btn-lg">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
Calculate Your Estimate
<span data-i18n="hero.cta.calculate">Calculate Your Estimate</span>
</a>
<a href="tel:6615817278" class="btn btn-secondary btn-lg">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
Call (661) 581-7278
<span data-i18n="hero.cta.phone">Call (661) 581-7278</span>
</a>
</div>
@@ -251,7 +269,7 @@
</div>
<div>
<div class="stat-num">48<span>h</span></div>
<div class="stat-label">Emergency Storm Cleanups</div>
<div class="stat-label"><span data-i18n="stat.emergency.title">Emergency Storm Cleanups</span></div>
</div>
</div>
<div class="stat-item">
@@ -262,7 +280,7 @@
</div>
<div>
<div class="stat-num">75<span>%</span></div>
<div class="stat-label">Avg Water Bill Savings</div>
<div class="stat-label"><span data-i18n="stat.water.title">Avg Water Bill Savings</span></div>
</div>
</div>
</div>
@@ -274,7 +292,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Instant Estimation Engine</span></div>
<h2 class="section-title">Transparent Pricing for <span class="neon-text">High Desert Yards</span></h2>
<h2 class="section-title" data-i18n-html="calc.title">Transparent Pricing for <span class="neon-text">High Desert Yards</span></h2>
<p class="section-description">
Customize your property parameters below. Get an immediate ballpark estimate tailored for Antelope Valley parcel sizes, soil types, and fire safety codes.
</p>
@@ -448,7 +466,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Authentic High Desert Results</span></div>
<h2 class="section-title">See the <span class="neon-text">Same-Day Cleanup</span></h2>
<h2 class="section-title" data-i18n-html="ba.title">See the <span class="neon-text">Same-Day Cleanup</span></h2>
<p class="section-description">
Slide the divider to see the exact same property before and after our crew arrived: waist-high weeds, tumbleweeds, and yard trash completely cleared down to clean, raked, fire-safe ground.
</p>
@@ -481,7 +499,7 @@
<div class="ba-hint">
<span style="display: inline-flex; align-items: center; gap: 8px;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--neon-green)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m11 17-5-5 5-5"></path><path d="m18 17-5-5 5-5"></path></svg>
Drag the neon divider or tap anywhere to compare before &amp; after
<span data-i18n="ba.hint">Drag the neon divider or tap anywhere to compare before &amp; after</span>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--neon-green)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 17 5-5-5-5"></path><path d="m13 17 5-5-5-5"></path></svg>
</span>
</div>
@@ -521,7 +539,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Featured AV Installations</span></div>
<h2 class="section-title">Beyond Cleanouts: <span class="neon-text">Custom Desert Living</span></h2>
<h2 class="section-title" data-i18n-html="projects.title">Beyond Cleanouts: <span class="neon-text">Custom Desert Living</span></h2>
<p class="section-description">
Explore drought-tolerant xeriscaping, decorative river rockscapes, and synthetic turf installations engineered to withstand 105°F+ High Desert heat and heavy seasonal winds.
</p>
@@ -576,7 +594,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Built For Antelope Valley</span></div>
<h2 class="section-title">Complete Yard & Landscaping <span class="neon-text">Services</span></h2>
<h2 class="section-title" data-i18n-html="services.title">Complete Yard & Landscaping <span class="neon-text">Services</span></h2>
<p class="section-description">
We don't do cookie-cutter coastal landscaping. Our equipment, crews, and materials are engineered for High Desert caliche soil, seasonal windstorms, and California drought restrictions.
</p>
@@ -825,7 +843,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Local Territory Coverage</span></div>
<h2 class="section-title">Proudly Serving the Entire <span class="neon-text">Antelope Valley</span></h2>
<h2 class="section-title" data-i18n-html="areas.title">Proudly Serving the Entire <span class="neon-text">Antelope Valley</span></h2>
<p class="section-description">
Our crews live and work right here in the High Desert. We arrive equipped with commercial-grade trimmers, mowers, haul trailers, and hand tools suited for residential yards and neighborhood properties alike.
</p>
@@ -947,7 +965,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Real Antelope Valley Feedback</span></div>
<h2 class="section-title">What High Desert <span class="neon-text">Homeowners Say</span></h2>
<h2 class="section-title" data-i18n-html="reviews.title">What High Desert <span class="neon-text">Homeowners Say</span></h2>
<p class="section-description">
Don't just take our word for it. Here is how Next Gen has helped neighbors in Palmdale, Lancaster, and Quartz Hill regain control of their properties.
</p>
@@ -1028,7 +1046,7 @@
<div class="container">
<div class="section-header">
<div class="section-tag"><span class="badge">Common Questions</span></div>
<h2 class="section-title">Frequently Asked <span class="neon-text">Questions</span></h2>
<h2 class="section-title" data-i18n-html="faq.title">Frequently Asked <span class="neon-text">Questions</span></h2>
<p class="section-description">
Everything you need to know about our Antelope Valley yard care, county weed deadlines, and pricing.
</p>
@@ -1077,7 +1095,7 @@
<section class="cta-banner-section">
<div class="container">
<div class="cta-banner-card">
<h2>Ready To Reclaim Your <span class="neon-text">High Desert Yard?</span></h2>
<h2 data-i18n-html="cta.title">Ready To Reclaim Your <span class="neon-text">High Desert Yard?</span></h2>
<p>
Don't let windblown tumbleweeds and fire hazards take over. Get an honest, zero-pressure quote from the local Next Gen team that knows Antelope Valley soil inside and out.
</p>
@@ -1175,7 +1193,7 @@
</button>
<div class="modal-header">
<span class="badge" style="margin-bottom: 8px;">Quick Response Guarantee</span>
<h3 id="modal-title">Request Your <span class="neon-text">Free Estimate</span></h3>
<h3 id="modal-title" data-i18n-html="modal.title">Request Your <span class="neon-text">Free Estimate</span></h3>
<p>Fill out the form below or call us directly. Next Gen responds within 15 minutes during daylight hours.</p>
</div>
@@ -1276,6 +1294,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -110,7 +110,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -131,6 +135,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Lancaster Landscaping" style="width: 100%; margin-top: 10px;">Request Lancaster Quote</button>
</div>
</header>
@@ -514,6 +529,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -197,7 +197,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -218,6 +222,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="service-areas.html" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="All Service Areas" style="width: 100%; margin-top: 10px;">Get Free Estimate</button>
</div>
</header>
@@ -661,6 +676,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -110,7 +110,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -131,6 +135,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Palmdale Landscaping" style="width: 100%; margin-top: 10px;">Request Palmdale Quote</button>
</div>
</header>
@@ -514,6 +529,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -120,7 +120,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -141,6 +145,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="service-areas.html" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="General Inquiry" style="width: 100%; margin-top: 10px;">Get Free Estimate</button>
</div>
</header>
@@ -469,6 +484,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -109,7 +109,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -130,6 +134,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Quartz Hill Landscaping" style="width: 100%; margin-top: 10px;">Request Quartz Hill Quote</button>
</div>
</header>
@@ -513,6 +528,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -114,7 +114,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -135,6 +139,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Rosamond Landscaping" style="width: 100%; margin-top: 10px;">Request Rosamond Quote</button>
</div>
</header>
@@ -518,6 +533,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -197,7 +197,11 @@
<!-- Header CTAs -->
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span class="phone-text">(661) 581-7278</span>
</a>
@@ -218,6 +222,17 @@
<a href="index.html#projects" class="nav-link mobile-link">Featured Projects</a>
<a href="service-areas.html" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact Us</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="All Service Areas" style="width: 100%; margin-top: 10px;">Get Free Estimate</button>
</div>
</header>
@@ -661,6 +676,7 @@
</div>
<div id="toast" class="toast-notification"></div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+115 -2
View File
@@ -79,6 +79,7 @@ html {
scroll-behavior: smooth;
color-scheme: light;
font-size: 16px;
overflow-x: hidden;
}
body {
@@ -2116,6 +2117,11 @@ textarea.form-control {
font-size: 1.1rem;
}
.hero-title {
font-size: clamp(1.85rem, 7.5vw, 2.4rem);
word-break: break-word;
}
.logo-symbol {
width: 36px;
height: 36px;
@@ -2127,9 +2133,13 @@ textarea.form-control {
padding: 6px;
}
#header-quote-btn,
.header-cta-group .open-quote-btn {
padding: 7px 11px;
font-size: 0.78rem;
display: none !important;
}
.announcement-bar .lang-switch {
display: none !important;
}
.mobile-sticky-bar {
@@ -2200,6 +2210,21 @@ textarea.form-control {
}
}
/* Specific Smartphone Adjustments (<= 480px) */
@media (max-width: 480px) {
#header-quote-btn,
.header-cta-group .open-quote-btn {
display: none !important;
}
.announcement-bar .lang-switch {
display: none !important;
}
.announcement-bar {
padding: 8px 12px;
font-size: 0.74rem;
}
}
/* ==========================================================================
YARD CLEANUP SECTION & FEATURED PROJECTS SECTION (2-SECTION SPLIT)
========================================================================== */
@@ -2563,3 +2588,91 @@ section#projects {
}
}
/* ==========================================================================
LANGUAGE SWITCHER (EN / ES)
========================================================================== */
.lang-switch {
display: inline-flex;
align-items: center;
background: rgba(15, 23, 42, 0.06);
border: 1.5px solid rgba(15, 23, 42, 0.12);
border-radius: 20px;
padding: 3px;
gap: 2px;
user-select: none;
flex-shrink: 0;
transition: all var(--transition-fast);
}
.lang-switch:hover {
border-color: var(--neon-green);
box-shadow: 0 0 12px rgba(0, 230, 118, 0.3);
}
.lang-btn {
background: transparent;
border: none;
color: #64748b;
font-family: var(--font-body);
font-size: 0.74rem;
font-weight: 800;
letter-spacing: 0.06em;
padding: 5px 11px;
border-radius: 14px;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.16, 1, 0.3, 1);
display: inline-flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.lang-btn:hover {
color: #0f172a;
}
.lang-btn.active {
background: #0f172a;
color: var(--neon-lime);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2), 0 0 10px rgba(0, 230, 118, 0.45);
}
/* Top bar variant */
.top-bar .lang-switch {
background: rgba(255, 255, 255, 0.08);
border-color: rgba(255, 255, 255, 0.16);
}
.top-bar .lang-btn {
color: #94a3b8;
font-size: 0.7rem;
padding: 3px 8px;
}
.top-bar .lang-btn.active {
background: var(--neon-lime);
color: #05080b;
box-shadow: 0 0 10px rgba(0, 230, 118, 0.6);
}
/* Mobile drawer container */
.mobile-lang-wrap {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 18px;
background: rgba(255, 255, 255, 0.05);
border-radius: var(--radius-md);
margin-bottom: 20px;
border: 1px solid rgba(255, 255, 255, 0.08);
}
.mobile-lang-label {
font-size: 0.85rem;
font-weight: 700;
color: #cbd5e1;
display: flex;
align-items: center;
gap: 6px;
}
+17 -1
View File
@@ -69,7 +69,11 @@
</nav>
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span>(661) 581-7278</span>
</a>
@@ -94,6 +98,17 @@
<a href="tumbleweed-removal.html" class="mobile-link">Tumbleweed Removal</a>
<a href="contact.html" class="mobile-link">Contact</a>
<div style="margin-top: 24px;">
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" style="width: 100%;" data-scope="Mobile Menu">Get Free Estimate</button>
</div>
</div>
@@ -350,6 +365,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+479
View File
@@ -0,0 +1,479 @@
/**
* NEXT GEN LANDSCAPING & YARD CARE (AV YARD PRO)
* Enterprise-Grade Bilingual Internationalization (i18n) Engine
* Antelope Valley (Palmdale, Lancaster, Quartz Hill, Acton, Rosamond)
*/
(function() {
'use strict';
// Rich HTML translations for headings and highlights that contain styled neon spans
const htmlDictionary = {
"calc.title": {
en: 'Transparent Pricing for <span class="neon-text">High Desert Yards</span>',
es: 'Precios Transparentes para <span class="neon-text">Jardines del Alto Desierto</span>'
},
"ba.title": {
en: 'See the <span class="neon-text">Same-Day Cleanup</span>',
es: 'Vea la <span class="neon-text">Limpieza el Mismo Día</span>'
},
"projects.title": {
en: 'Beyond Cleanouts: <span class="neon-text">Custom Desert Living</span>',
es: 'Más Allá de Limpiezas: <span class="neon-text">Vida Desértica a Medida</span>'
},
"services.title": {
en: 'Complete Yard & Landscaping <span class="neon-text">Services</span>',
es: 'Servicios Completos de Jardinería y <span class="neon-text">Mantenimiento</span>'
},
"areas.title": {
en: 'Proudly Serving the Entire <span class="neon-text">Antelope Valley</span>',
es: 'Sirviendo con Orgullo a Todo <span class="neon-text">Antelope Valley</span>'
},
"reviews.title": {
en: 'What High Desert <span class="neon-text">Homeowners Say</span>',
es: 'Lo que Dicen los <span class="neon-text">Propietarios del Desierto</span>'
},
"faq.title": {
en: 'Frequently Asked <span class="neon-text">Questions</span>',
es: 'Preguntas <span class="neon-text">Frecuentes</span>'
},
"cta.title": {
en: 'Ready To Reclaim Your <span class="neon-text">High Desert Yard?</span>',
es: '¿Listo Para Recuperar Su <span class="neon-text">Jardín del Alto Desierto?</span>'
},
"modal.title": {
en: 'Request Your <span class="neon-text">Free Estimate</span>',
es: 'Solicite Su <span class="neon-text">Presupuesto Gratis</span>'
}
};
// Comprehensive plain text dictionary
const dictionary = {
// --- Top Announcement Bar ---
"High Desert Notice": "Aviso del Alto Desierto",
"LA & Kern County Fire Clearance Deadlines Approaching! Fast 48-Hour Weed Abatement Available.": "¡Se acercan los plazos de desbroce contra incendios de LA y Kern! Desbroce rápido en 48 horas.",
"Get Instant Estimate →": "Obtener Presupuesto Inmediato →",
"Get Instant Estimate &rarr;": "Obtener Presupuesto Inmediato →",
"Direct: (661) 581-7278": "Directo: (661) 581-7278",
"24-Hr Text Dispatch Available": "Despacho por Mensaje 24 Horas",
// --- Navigation Links ---
"Services": "Servicios",
"Cost Calculator": "Calculadora de Costos",
"Before & After": "Antes y Después",
"Projects": "Proyectos",
"Featured Projects": "Proyectos Destacados",
"Service Areas": "Zonas de Servicio",
"All Service Areas": "Todas las Zonas de Servicio",
"All Services": "Todos los Servicios",
"Reviews": "Opiniones",
"Customer Reviews": "Opiniones de Clientes",
"Contact": "Contacto",
"Contact Us": "Contáctenos",
"Free Estimate": "Presupuesto Gratis",
"Get Free Estimate": "Obtener Presupuesto Gratis",
"Request Instant Quote": "Solicitar Presupuesto Inmediato",
"Language / Idioma:": "Idioma / Lenguaje:",
"Home": "Inicio",
// --- Hero Section ---
"Antelope Valley High-Desert Yard Specialists": "Especialistas en Jardinería del Alto Desierto de Antelope Valley",
"Rugged Desert.": "Desierto Agreste.",
"Precision Lawns.": "Césped de Precisión.",
"Zero Compromise.": "Cero Compromisos.",
"Tumbleweeds, unkempt desert brush, or high water bills? Next Gen transforms harsh Antelope Valley properties into pristine, fire-safe showpieces. Fast turnarounds across Palmdale, Lancaster, Quartz Hill, and surrounding desert communities.": "¿Rodadoras, maleza desértica o altas facturas de agua? Next Gen transforma terrenos difíciles de Antelope Valley en propiedades impecables y seguras contra incendios. Servicio rápido en Palmdale, Lancaster, Quartz Hill y comunidades vecinas.",
"Calculate Your Estimate": "Calcular Su Presupuesto",
"Calculate Yard Cost": "Calcular Costo de Jardín",
"Call (661) 581-7278": "Llamar (661) 581-7278",
"Direct Call (661) 581-7278": "Llamar Directo (661) 581-7278",
// --- Stats Ticker ---
"Zero Tractor Damage": "Cero Daño de Tractor",
"Lightweight Walk-Behind Precision": "Precisión Manual Ligera",
"Walk-Behind Precision Only": "Solo Precisión Manual y Cortacésped",
"Emergency Storm Cleanups": "Limpiezas de Emergencia",
"24-48 Hr Fast Dispatch": "Despacho Rápido en 24-48 Horas",
"Avg Water Bill Savings": "Ahorro Promedio en Agua",
"Smart Drip & Turf Solutions": "Soluciones de Riego y Césped",
"Fire Code Compliance": "Cumplimiento contra Incendios",
"LA County Defensible Space": "Espacio Defensivo del Condado de LA",
// --- Calculator Section ---
"Instant Estimation Engine": "Calculadora de Estimación Inmediata",
"Transparent Pricing for High Desert Yards": "Precios Transparentes para Jardines del Alto Desierto",
"Customize your property parameters below. Get an immediate ballpark estimate tailored for Antelope Valley parcel sizes, soil types, and fire safety codes.": "Personalice los parámetros de su propiedad a continuación. Obtenga un presupuesto aproximado e inmediato adaptado a los tamaños de lote, tipos de suelo y normas contra incendios de Antelope Valley.",
"Select Primary Service Needed": "Seleccione el Servicio Principal",
"Select Yard or Parcel Footprint": "Seleccione el Tamaño del Terreno",
"Yard Condition / Growth Severity": "Condición del Terreno / Severidad",
// Calculator Service Options
"Tumbleweed & Cleanout": "Limpieza y Retiro de Rodadoras",
"Windstorm brush, trashout, deep haul": "Maleza de tormenta, basura y retiro profundo",
"Fire Hazard Clearance": "Desbroce contra Incendios",
"100ft defensible space, weed whacking, raking": "Espacio defensivo de 100 pies, desbroce y rastrillado",
"Artificial Turf / Putting Green": "Césped Sintético / Putting Green",
"Cool-blade UV turf, zero water maintenance": "Césped UV refrescante, cero agua",
"Desert Xeriscaping & Rock": "Jardinería Desértica (Xeriscape) y Rocas",
"DG, river stone, desert agaves & drip": "Granito, piedra de río, agaves y riego por goteo",
"Tree Trimming & Palms": "Poda de Árboles y Palmeras",
"Wind mitigation, skinning & pruning": "Prevención contra viento, afeitado y poda",
"Routine Yard Maintenance": "Mantenimiento Periódico de Jardín",
"Bi-weekly / monthly edging & detailing": "Orillado y detallado quincenal o mensual",
// Calculator Size Options
"Front Yard Only": "Solo Patio Delantero",
"Up to ~2,000 sq ft": "Hasta ~2,000 pies²",
"Standard Suburb Lot": "Lote Residencial Estándar",
"1/4 Acre (Front & Back)": "1/4 Acre (Delantero y Trasero)",
"Half-Acre Parcel": "Terreno de Medio Acre",
"~20,000 sq ft": "~20,000 pies²",
"Large Residential Parcel": "Terreno Residencial Grande",
"Comprehensive crew clearance": "Despeje integral con cuadrilla completa",
// Calculator Severity Options
"Light / Moderate": "Ligero / Moderado",
"Surface weeds, basic tidying": "Maleza superficial, limpieza básica",
"Heavy Overgrowth": "Crecimiento Denso / Pesado",
"Tall foxtails, tumbleweed build-up": "Pasto alto, colas de zorro y rodadoras",
"Severe / Jungle": "Severo / Muy Denso",
"Waist-high brush, debris & heavy hauling": "Maleza a la cintura, escombros y retiro pesado",
// Calculator Output Box
"Estimated Price Range": "Rango de Precio Estimado",
"*All-inclusive: labor, equipment, disposal & hauling.": "*Todo incluido: mano de obra, equipo, traslado y descarga.",
"Lock In This Estimate & Book": "Asegurar Este Presupuesto y Reservar",
"Free in-person confirmation walkthrough before any work begins.": "Recorrido de confirmación en persona gratis antes de comenzar cualquier trabajo.",
"Commercial Haul Included": "Transporte Comercial Incluido",
"County Defensible Space Compliant": "Cumplimiento de Espacio Defensivo del Condado",
// --- Before / After Section ---
"Authentic High Desert Results": "Resultados Auténticos del Alto Desierto",
"See the Same-Day Cleanup": "Vea la Limpieza el Mismo Día",
"Slide the divider to see the exact same property before and after our crew arrived: waist-high weeds, tumbleweeds, and yard trash completely cleared down to clean, raked, fire-safe ground.": "Deslice el divisor para ver la misma propiedad antes y después de nuestro equipo: maleza a la cintura, rodadoras y basura completamente despejadas hasta dejar el suelo limpio, rastrillado y seguro contra incendios.",
"Drag the neon divider or tap anywhere to compare before & after": "Deslice el divisor de neón o toque en cualquier parte para comparar el antes y después",
"Same-Day Crew Turnaround": "Entrega del Equipo el Mismo Día",
"100% Hand-Raked Ground Finish": "Acabado de Suelo Rastrillado a Mano al 100%",
"Fenceline & Pipe Safe (No Heavy Tractors)": "Seguro para Cercas y Tuberías (Sin Tractores)",
"Full Trailer Haul-Away Included": "Retiro Completo en Remolque Incluido",
"AFTER": "DESPUÉS",
": CLEANED YARD": ": TERRENO LIMPIO",
"BEFORE": "ANTES",
": OVERGROWN": ": CON MALEZA",
// --- Featured Projects ---
"Featured AV Installations": "Instalaciones Destacadas en AV",
"Beyond Cleanouts: Custom Desert Living": "Más Allá de Limpiezas: Vida Desértica a Medida",
"Explore drought-tolerant xeriscaping, decorative river rockscapes, and synthetic turf installations engineered to withstand 105°F+ High Desert heat and heavy seasonal winds.": "Explore jardines xeriscaping tolerantes a la sequía, rocas decorativas de río e instalaciones de césped sintético diseñadas para soportar más de 105°F y fuertes vientos.",
"Modern Xeriscape & River Rock": "Xeriscape Moderno y Roca de Río",
"Replaced weed-choked dirt with decomposed granite, decorative river boulders, and automated drip agave beds.": "Reemplazamos tierra con maleza por granito descompuesto, rocas decorativas de río y canteros de agave con riego por goteo.",
"Water Savings:": "Ahorro de Agua:",
"Turnaround:": "Tiempo de Ejecución:",
"3 Days": "3 Días",
"Luxury Turf & Yard Remodel": "Césped de Lujo y Remodelación de Patio",
"Triple-layer UV-rated artificial turf resilient against desert wind gusts and summer highs above 105°F.": "Césped artificial de triple capa resistente a los fuertes vientos del desierto y veranos de más de 105°F.",
"Request Similar Xeriscape Quote": "Solicitar Presupuesto de Xeriscape Similar",
"Request Similar Turf Quote": "Solicitar Presupuesto de Césped Similar",
"Warranty:": "Garantía:",
"15-Year": "15 Años",
"Maintenance:": "Mantenimiento:",
"Zero Mow": "Cero Corte",
"Fire Clearance Lot Trash-Out": "Desbroce de Lote y Retiro de Residuos",
"Cleared 1/2 acre of windblown Russian thistle tumbleweeds, dry sage, and debris to pass LA County fire inspection.": "Despejamos medio acre de rodadoras de cardo ruso, pasto seco y escombros para aprobar la inspección de bomberos.",
"County Status:": "Estado del Condado:",
"100% Passed": "100% Aprobado",
"Haul-Away:": "Retiro de Carga:",
"2 Full Trailers": "2 Remolques Llenos",
// --- Core Services ---
"Built For Antelope Valley": "Diseñado para Antelope Valley",
"Complete Yard & Landscaping Services": "Servicios Completos de Jardinería y Mantenimiento",
"We don't do cookie-cutter coastal landscaping. Our equipment, crews, and materials are engineered for High Desert caliche soil, seasonal windstorms, and California drought restrictions.": "No hacemos jardinería costera genérica. Nuestro equipo, cuadrillas y materiales están preparados para el suelo de caliche, tormentas de viento y restricciones de sequía de California.",
// Service 1
"LA County Weed Abatement": "Desbroce contra Incendios Condado de LA",
"Stay ahead of LA County and Kern County fire inspection notices. We cut, weed whack, rake, and clear properties to meet strict 100-foot defensible space requirements before deadlines hit.": "Anticípese a las inspecciones de incendios de LA y Kern. Cortamos, desbrozamos, rastrillamos y limpiamos su propiedad para cumplir con el espacio defensivo de 100 pies antes del plazo límite.",
"100-Foot Fire Defensible Perimeter": "Perímetro Defensivo contra Incendios de 100 Pies",
"High-Power Weed Whacking, Mowing & Raking": "Desbroce de Alta Potencia, Corte y Rastrillado",
"Guaranteed County Inspection Sign-Off": "Aprobación Garantizada de Inspección del Condado",
"Get Fire Clearance Quote": "Presupuesto de Desbroce contra Incendios",
"View Weed Abatement Details →": "Ver Detalles de Desbroce →",
// Service 2
"Tumbleweed & Windstorm Hauling": "Retiro de Rodadoras y Limpieza de Tormentas",
"When the Antelope Valley 60mph winds blow, tumbleweeds stack to the roofline against your fences and sheds. We eradicate the piles and haul everything to the transfer station.": "Cuando los vientos de 60 mph de Antelope Valley azotan, las rodadoras se apilan hasta los techos contra cercas y cobertizos. Erradicamos los montones y transportamos todo a los centros autorizados.",
"Fence Line & Rooftop Tumbleweed Removal": "Retiro de Rodadoras en Cercas y Techos",
"High-Capacity Hauling & Dump Trailers": "Remolques de Volteo y Carga Pesada de Gran Capacidad",
"Property Trash-Out & Lot Cleans": "Limpieza Integral de Terrenos y Residuos",
"Book Cleanout": "Reservar Limpieza",
"View Tumbleweed Details →": "Ver Detalles de Rodadoras →",
// Service 3
"Artificial Turf & Putting Greens": "Césped Sintético y Putting Greens",
"Enjoy an emerald green yard year-round without paying astronomical water rates. We install commercial-grade, anti-microbial turf with specialized heat-deflecting cooling infill.": "Disfrute de un jardín verde esmeralda todo el año sin pagar facturas de agua astronómicas. Instalamos césped comercial antimicrobiano con relleno refrigerante contra el calor.",
"UV-Stabilized (No Fade In Desert Sun)": "Protección UV (Sin Decoloración por Sol del Desierto)",
"Pet-Friendly with Rapid Drainage Base": "Apto para Mascotas con Base de Drenaje Rápido",
"Custom Backyard Putting Greens": "Putting Greens Personalizados para Patios",
"Get Turf Estimate": "Obtener Presupuesto de Césped",
// Service 4
"Desert Xeriscape & Rockscaping": "Jardinería Desértica (Xeriscape) y Rocas",
"Stunning architectural landscaping engineered to thrive in the High Desert. We blend decomposed granite, California gold river rock, decorative boulders, and water-wise agaves.": "Hermosa jardinería arquitectónica diseñada para prosperar en el Alto Desierto. Combinamos granito descompuesto, piedra de río dorada, rocas decorativas y agaves resistentes.",
"Decomposed Granite & Crushed Stone": "Granito Descompuesto y Piedra Triturada",
"Heavy-Duty Commercial Weed Barrier Fabric": "Malla Profesional de Alta Densidad contra Maleza",
"Architectural Desert Boulders & Succulents": "Rocas Arquitectónicas y Suculentas del Desierto",
"Explore Rockscaping": "Explorar Jardinería con Rocas",
// Service 5
"Tree Trimming & Palm Pruning": "Poda de Árboles y Palmeras",
"High winds in Palmdale and Lancaster topple untrimmed trees and dead palm fronds. We thin tree canopies for wind passage, skin palms, and grind dangerous stumps safely.": "Los fuertes vientos en Palmdale y Lancaster derriban árboles sin podar y palmas secas. Aclareamos copas para el paso del viento, afeitamos palmeras y trituramos tocones peligrosos.",
"Wind Mitigation Canopy Thinning": "Aclareo de Copas para Mitigar Vientos Fuertes",
"Palm Frond Skinning & Seed Removal": "Afeitado de Palmeras y Retiro de Semillas",
"Complete Stump Grinding & Root Extraction": "Trituración Completa de Tocones y Extracción de Raíces",
"Quote Tree Work": "Presupuesto de Trabajo en Árboles",
// Service 6
"Smart Irrigation & Drip Repair": "Reparación de Riego por Goteo Inteligente",
"Desert soil requires dialed-in watering. Leaky valves or broken lines skyrocket your utility bill. We diagnose underground leaks, replace cracked manifolds, and tune drip systems.": "El suelo desértico requiere riego exacto. Válvulas con fugas o líneas rotas disparan su factura. Diagnosticamos fugas subterráneas, reemplazamos colectores agrietados y calibramos goteo.",
"Subsurface Drip Line Conversions": "Conversión a Líneas de Riego por Goteo Subterráneo",
"Smart Wi-Fi Weather-Sensing Controllers": "Controladores Wi-Fi Inteligentes con Sensor de Clima",
"Anti-Siphon Valve & Backflow Replacement": "Reemplazo de Válvulas Anti-Sifón y Antirretorno",
"Schedule Irrigation Check": "Programar Revisión de Riego",
// --- Service Areas ---
"Local Territory Coverage": "Cobertura Territorial Local",
"Proudly Serving the Entire Antelope Valley": "Sirviendo con Orgullo a Todo Antelope Valley",
"Our crews live and work right here in the High Desert. We arrive equipped with commercial-grade trimmers, mowers, haul trailers, and hand tools suited for residential yards and neighborhood properties alike.": "Nuestras cuadrillas viven y trabajan aquí mismo en el Alto Desierto. Llegamos equipados con desbrozadoras comerciales, cortacéspedes, remolques y herramientas de mano aptas para cualquier propiedad.",
"West Palmdale": "Palmdale Oeste",
"East Palmdale": "Palmdale Este",
"Lancaster West": "Lancaster Oeste",
"Quartz Hill": "Quartz Hill",
"Rosamond & Mojave": "Rosamond y Mojave",
"Acton & Agua Dulce": "Acton y Agua Dulce",
"View All Antelope Valley Service Areas & Regulations →": "Ver Todas las Zonas de Servicio y Regulaciones de Antelope Valley →",
"View All Service Areas →": "Ver Todas las Zonas de Servicio →",
"All Service Areas →": "Todas las Zonas de Servicio →",
// --- Reviews Section ---
"Real Antelope Valley Feedback": "Opiniones Reales de Antelope Valley",
"What High Desert Homeowners Say": "Lo que Dicen los Propietarios del Desierto",
"Don't just take our word for it. Here is how Next Gen has helped neighbors in Palmdale, Lancaster, and Quartz Hill regain control of their properties.": "No solo se quede con nuestra palabra. Así es como Next Gen ha ayudado a vecinos en Palmdale, Lancaster y Quartz Hill a recuperar sus terrenos.",
"\"We received a weed abatement violation notice from LA County Fire with a 2-week deadline. Next Gen showed up the next morning with commercial weed trimmers and had our full half-acre cleared, raked, and hauled into their trailer before sundown. The inspector signed off with zero issues. Lifesavers!\"": "\"Recibimos un aviso de infracción por maleza de los Bomberos del Condado de LA con un plazo de 2 semanas. Next Gen llegó a la mañana siguiente con desbrozadoras comerciales y dejó nuestro medio acre despejado, rastrillado y cargado en su remolque antes de caer el sol. El inspector lo firmó sin un solo problema. ¡Nos salvaron!\"",
"\"After the winter windstorms, our backyard had tumbleweeds literally stacked 8 feet high against our vinyl fence. These guys had the proper heavy-duty trailers and cleared everything in 3 hours. Super polite, fair pricing, and they left the yard spotless.\"": "\"Después de las tormentas de viento invernales, nuestro patio trasero tenía rodadoras apiladas a 8 pies de altura contra nuestra cerca de vinilo. Estos chicos llegaron con remolques de carga pesada y despejaron todo en 3 horas. Súper amables, precio justo y dejaron el patio impecable.\"",
"\"We ditched our dead grass for artificial turf and desert rockscape. Our water bill dropped by over $220/month in the summer, and our dogs love the turf. The green is so vibrant and stays cool even when Palmdale hits 104 degrees. Highly recommend!\"": "\"Reemplazamos el pasto seco por césped artificial y rocas de desierto. Nuestra factura de agua bajó más de $220/mes en el verano y a nuestros perros les fascina. El verde es vibrante y se mantiene fresco incluso a 104 grados en Palmdale. ¡Muy recomendados!\"",
// --- FAQs Section ---
"Common Questions": "Preguntas Frecuentes",
"Frequently Asked Questions": "Preguntas Frecuentes",
"Everything you need to know about our Antelope Valley yard care, county weed deadlines, and pricing.": "Todo lo que necesita saber sobre el cuidado de jardines, plazos de maleza del condado y precios en Antelope Valley.",
"What are the LA County and Kern County weed abatement deadlines?": "¿Cuáles son los plazos de desbroce contra incendios de los condados de LA y Kern?",
"In the Antelope Valley, LA County Agricultural Commissioner and Fire Department inspections typically begin in mid-to-late spring and enforce 100-foot defensible space clearance around structures and 10-foot road buffers. Failure to clear can result in county-enforced contractor billing and heavy penalty fees. Next Gen guarantees work that passes county inspection on the first visit.": "En Antelope Valley, las inspecciones de bomberos del Condado de LA comienzan a mediados de primavera y exigen un espacio defensivo de 100 pies alrededor de estructuras y márgenes de 10 pies en caminos. No limpiar puede ocasionar multas severas y cobros del condado. Next Gen garantiza trabajos que aprueban la inspección en la primera visita.",
"How does artificial turf hold up in high Antelope Valley summer heat?": "¿Cómo resiste el césped sintético el intenso calor veraniego de Antelope Valley?",
"We exclusively install UV-stabilized commercial turf with special cooling infill designed to withstand 110°F+ desert temperatures without melting, fading, or discoloring. It also includes an engineered perforated backing that drains quickly during rare desert cloudbursts and prevents pet odor buildup.": "Instalamos exclusivamente césped comercial con protección UV y relleno refrigerante especial para soportar más de 110°F sin derretirse ni desteñirse. Además, cuenta con base perforada que drena rápidamente y previene la acumulación de olores de mascotas.",
"Do you haul away the debris, or do I need to rent a dumpster?": "¿Se llevan los escombros o necesito rentar un contenedor de basura?",
"We handle 100% of the hauling. Our fleet is equipped with high-capacity dump trailers and commercial trucks. All tumbleweeds, tree clippings, dead brush, and yard trash are loaded and legally disposed of at authorized local green-waste facilities in Palmdale and Lancaster.": "Nosotros nos encargamos del 100% del retiro y transporte. Nuestra flota cuenta con remolques de volteo de alta capacidad. Todas las rodadoras, ramas podadas y maleza seca se cargan y depositan legalmente en instalaciones de reciclaje verde autorizadas en Palmdale y Lancaster.",
"Can I get an estimate by texting photos of my yard?": "¿Puedo obtener un presupuesto enviando fotos de mi patio por mensaje?",
"Yes! You can text photos and your address directly to (661) 581-7278. We can often provide a same-hour ballpark estimate, followed by a quick in-person verification before any tools touch the ground.": "¡Sí! Puede enviar fotos y su dirección directamente al (661) 581-7278. A menudo entregamos un estimado en la misma hora, seguido de una confirmación rápida en persona antes de iniciar los trabajos.",
"What equipment do you use for yard cleanups and weed clearing?": "¿Qué herramientas y equipos usan para la limpieza de patios y desbroce?",
"We use commercial-grade walk-behind mowers, high-powered gas weed trimmers/whackers, heavy-duty landscape rakes, blowers, and our haul truck & trailer. We specialize in residential yards, standard lots, and parcels up to a half-acre—getting directly up against fences, walls, and corners that heavy machinery and tractors can't reach.": "Usamos cortacéspedes comerciales de empuje, desbrozadoras a gas de alta potencia, rastrillos reforzados, sopladoras y remolques de volteo. Nos especializamos en patios residenciales y terrenos de hasta medio acre, llegando directamente contra cercas y paredes donde los tractores pesados no pueden entrar sin causar daños.",
// --- Final CTA ---
"Ready To Reclaim Your High Desert Yard?": "¿Listo Para Recuperar Su Jardín del Alto Desierto?",
"Don't let windblown tumbleweeds and fire hazards take over. Get an honest, zero-pressure quote from the local Next Gen team that knows Antelope Valley soil inside and out.": "No permita que las rodadoras y los peligros de incendio se apoderen de su propiedad. Obtenga un presupuesto honesto del equipo local de Next Gen que conoce el terreno de Antelope Valley al detalle.",
"Request Free On-Site Quote": "Solicitar Presupuesto en el Lugar Gratis",
// --- Modal Form ---
"Quick Response Guarantee": "Garantía de Respuesta Rápida",
"Request Your Free Estimate": "Solicite Su Presupuesto Gratis",
"Fill out the form below or call us directly. Next Gen responds within 15 minutes during daylight hours.": "Complete el formulario a continuación o llámenos directamente. Next Gen responde en menos de 15 minutos en horas diurnas.",
"Full Name *": "Nombre Completo *",
"Mobile Phone (for quote text) *": "Teléfono Móvil (para texto de presupuesto) *",
"Property Address / City *": "Dirección de la Propiedad / Ciudad *",
"Service Needed": "Servicio Solicitado",
"Select a Service": "Seleccione un Servicio",
"Weed Abatement (Fire Clearance)": "Desbroce contra Incendios (Fire Clearance)",
"Tumbleweed Removal & Hauling": "Retiro y Transporte de Rodadoras",
"Synthetic Turf Installation": "Instalación de Césped Sintético",
"Desert Xeriscape & Rockscaping": "Jardinería Desértica (Xeriscape) y Rocas",
"Tree Trimming & Palm Pruning": "Poda de Árboles y Palmeras",
"Smart Irrigation & Drip Repair": "Reparación de Riego por Goteo",
"Complete Property Cleanup / Trash-Out": "Limpieza Completa de Propiedad / Desalojo",
"Notes / Yard Size": "Notas / Tamaño del Terreno",
"Submit for Fast Quote →": "Enviar Para Presupuesto Rápido →",
// --- Footer ---
"Antelope Valley's premier landscaping, fire hazard weed abatement, desert rockscaping, and synthetic turf contractor. Palmdale & Lancaster, California.": "El principal contratista de jardinería, desbroce contra incendios, rocas desérticas y césped sintético en Antelope Valley. Palmdale y Lancaster, California.",
"Working Hours": "Horario de Trabajo",
"Mon Fri: 6:30 AM 7:00 PM": "Lun Vie: 6:30 AM 7:00 PM",
"Saturday: 7:00 AM 6:00 PM": "Sábado: 7:00 AM 6:00 PM",
"Sunday: Emergency Storm Calls": "Domingo: Llamadas de Emergencia",
"24-Hr Antelope Valley Dispatch": "Despacho 24 Horas en Antelope Valley",
"Next Gen Landscaping & Yard Care. All rights reserved.": "Next Gen Landscaping & Yard Care. Todos los derechos reservados.",
"Privacy Policy (CCPA / CPRA)": "Política de Privacidad (CCPA / CPRA)",
"Terms of Service": "Términos de Servicio",
"Licensed, Bonded & Insured • High Desert Fire Hazard Compliant": "Licenciados, Asegurados y Afianzados • Cumplimiento contra Incendios del Alto Desierto",
"Licensed, Bonded & Insured • Residential Hand-Tool Precision": "Licenciados, Asegurados y Afianzados • Precisión Manual Residencial",
"Palmdale, CA (93550, 93551)": "Palmdale, CA (93550, 93551)",
"Lancaster, CA (93534, 93535)": "Lancaster, CA (93534, 93535)",
"Quartz Hill, CA (93536)": "Quartz Hill, CA (93536)",
"Acton & Agua Dulce": "Acton y Agua Dulce",
"Rosamond & Mojave": "Rosamond y Mojave",
// Subpage & Hub Pages
"Same-Day & 48-Hour On-Site Estimates Across All High Desert Zip Codes.": "Presupuestos en el sitio el mismo día y en 48 horas en todos los códigos postales del Alto Desierto.",
"All Antelope Valley Service Areas & Regulations": "Todas las Zonas de Servicio y Regulaciones de Antelope Valley",
"High Desert Landscaping & Weed Abatement Locations": "Ubicaciones de Jardinería y Desbroce en el Alto Desierto",
"Fast 24-48 hour response times for LA County Fire defensible space compliance, tumbleweed clearing, desert rockscaping, and water-saving synthetic turf throughout the Antelope Valley.": "Respuesta rápida de 24 a 48 horas para cumplimiento de espacio defensivo contra incendios del Condado de LA, retiro de rodadoras, jardinería xeriscape y césped sintético en todo Antelope Valley.",
"Palmdale Yard Care & Weed Abatement": "Cuidado de Jardines y Desbroce en Palmdale",
"Lancaster Yard Care & Weed Abatement": "Cuidado de Jardines y Desbroce en Lancaster",
"Quartz Hill Yard Care & Weed Abatement": "Cuidado de Jardines y Desbroce en Quartz Hill",
"Acton & Agua Dulce Yard Care": "Cuidado de Jardines en Acton y Agua Dulce",
"Rosamond & Mojave Yard Care": "Cuidado de Jardines en Rosamond y Mojave"
};
/**
* Set Application Language
* @param {'en'|'es'} lang
*/
function setLanguage(lang) {
if (lang !== 'es') lang = 'en';
// 1. Save state in localStorage
try {
localStorage.setItem('avyardpro_lang', lang);
} catch (e) {}
// 2. Set document language
document.documentElement.lang = lang;
// 3. Update all toggle button active classes
document.querySelectorAll('.lang-btn').forEach(btn => {
const btnLang = btn.getAttribute('data-lang');
if (btnLang === lang) {
btn.classList.add('active');
btn.setAttribute('aria-pressed', 'true');
} else {
btn.classList.remove('active');
btn.setAttribute('aria-pressed', 'false');
}
});
// 4. Update rich HTML elements with data-i18n-html
document.querySelectorAll('[data-i18n-html]').forEach(el => {
const key = el.getAttribute('data-i18n-html');
if (htmlDictionary[key] && htmlDictionary[key][lang]) {
el.innerHTML = htmlDictionary[key][lang];
}
});
// 5. Update text elements
const targets = document.querySelectorAll(
'h1, h2, h3, h4, h5, p, span, a, button, label, summary, div.stat-label, div.calc-option-title, div.calc-option-desc, div.faq-answer'
);
targets.forEach(el => {
// Don't overwrite elements handled by data-i18n-html
if (el.hasAttribute('data-i18n-html') || el.closest('[data-i18n-html]')) {
return;
}
// Skip elements that contain other complex children unless it's pure text or text + svg
if (el.children.length > 0 && !el.classList.contains('badge') && !el.classList.contains('btn') && !el.classList.contains('showcase-stat') && !el.classList.contains('announcement-link')) {
return;
}
// Store initial English text on first pass
if (typeof el._originalText === 'undefined') {
el._originalText = el.textContent.trim();
}
const original = el._originalText;
if (lang === 'es') {
if (dictionary[original]) {
const svg = el.querySelector('svg');
if (svg) {
const svgHtml = svg.outerHTML;
el.innerHTML = svgHtml + ' ' + dictionary[original];
} else {
el.textContent = dictionary[original];
}
}
} else {
// Restore original English text
const svg = el.querySelector('svg');
if (svg) {
const svgHtml = svg.outerHTML;
el.innerHTML = svgHtml + ' ' + original;
} else {
el.textContent = original;
}
}
});
// 6. Translate select options in forms
document.querySelectorAll('select option').forEach(opt => {
if (typeof opt._originalText === 'undefined') {
opt._originalText = opt.textContent.trim();
}
const orig = opt._originalText;
if (lang === 'es' && dictionary[orig]) {
opt.textContent = dictionary[orig];
} else if (lang === 'en') {
opt.textContent = orig;
}
});
// 7. Translate input & textarea placeholders
document.querySelectorAll('input[placeholder], textarea[placeholder]').forEach(input => {
if (typeof input._originalPlaceholder === 'undefined') {
input._originalPlaceholder = input.getAttribute('placeholder') || '';
}
const orig = input._originalPlaceholder;
if (lang === 'es' && dictionary[orig]) {
input.setAttribute('placeholder', dictionary[orig]);
} else if (lang === 'en') {
input.setAttribute('placeholder', orig);
}
});
// 8. Dispatch event for calculators, sliders, or other components
window.dispatchEvent(new CustomEvent('languageChanged', { detail: { lang } }));
}
// Expose globally
window.setAppLanguage = setLanguage;
// Initialize immediately or on DOMContentLoaded
function initLanguage() {
// Check URL query parameter: ?lang=es or ?lang=en
const urlParams = new URLSearchParams(window.location.search);
const urlLang = urlParams.get('lang');
let activeLang = 'en';
try {
activeLang = urlLang || localStorage.getItem('avyardpro_lang') || 'en';
} catch (e) {
activeLang = urlLang || 'en';
}
// Attach click listeners to all language switch buttons
document.querySelectorAll('.lang-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
e.preventDefault();
const target = btn.getAttribute('data-lang');
if (target) {
setLanguage(target);
}
});
});
// Apply active language
setLanguage(activeLang);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initLanguage);
} else {
initLanguage();
}
})();
+17 -1
View File
@@ -78,7 +78,11 @@
</nav>
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span>(661) 581-7278</span>
</a>
@@ -97,6 +101,17 @@
<a href="index.html#transformation" class="nav-link mobile-link">Before & After</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="Tumbleweed Removal & Cleanout" style="width: 100%; margin-top: 10px;">Request Tumbleweed Quote</button>
</div>
</header>
@@ -447,6 +462,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>
+17 -1
View File
@@ -78,7 +78,11 @@
</nav>
<div class="header-cta-group">
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
<a href="tel:6615817278" class="phone-direct" aria-label="Call Next Gen Landscaping">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"/></svg>
<span>(661) 581-7278</span>
</a>
@@ -97,6 +101,17 @@
<a href="index.html#transformation" class="nav-link mobile-link">Before & After</a>
<a href="index.html#areas" class="nav-link mobile-link">Service Areas</a>
<a href="contact.html" class="nav-link mobile-link">Contact</a>
<div class="mobile-lang-wrap">
<span class="mobile-lang-label">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1 4-10z"/></svg>
Language / Idioma:
</span>
<div class="lang-switch" role="group" aria-label="Language selector">
<button type="button" class="lang-btn active" data-lang="en">EN</button>
<button type="button" class="lang-btn" data-lang="es">ES</button>
</div>
</div>
<button class="btn btn-primary open-quote-btn" data-scope="LA County Weed Abatement" style="width: 100%; margin-top: 10px;">Request Weed Quote</button>
</div>
</header>
@@ -456,6 +471,7 @@
</div>
</div>
<script src="translations.js"></script>
<script src="app.js"></script>
</body>
</html>