feat(i18n): reconcile multilingual pages and shared forms

This commit is contained in:
DeCentN2Madness committed 2026-10-13 23:01:38 -07:00
1 parent b5bc95bc2b
commit 8e64d32209
22 files changed
+2866 -88

No files matched your search

+13 -8
View File
@@ -2,11 +2,16 @@
import Button from './Button.astro';
import ContactObfuscation from './ContactObfuscation.astro';
import { formMessages } from '../utils/form-messages';
interface Props {
lang?: string;
title?: string;
}
const { title = 'Contact AIA' } = Astro.props;
const { lang = 'en' } = Astro.props;
const text = formMessages(lang);
const title = Astro.props.title ?? text.contactHeading;
---
<form class="contact-form-card" method="post" action="">
@@ -14,13 +19,13 @@ const { title = 'Contact AIA' } = Astro.props;
<!-- TODO: Add spam protection before production launch. -->
<h3 class="contact-form-card__title">{title}</h3>
<div class="contact-form-card__fields">
<label>Parent or guardian name<input name="name" autocomplete="name" /></label>
<label>Email<input type="email" name="email" autocomplete="email" /></label>
<label>Phone<input type="tel" name="phone" autocomplete="tel" /></label>
<label>Service of interest<select name="service"><option>ABA Therapy</option><option>Autism Evaluation</option><option>Learner Social Club</option><option>Other</option></select></label>
<label>How can we help?<textarea name="message" rows="5"></textarea></label>
<Button type="submit" disabled aria-describedby="contact-form-note" class="contact-form-card__submit">Submit</Button>
<p id="contact-form-note" class="contact-form-card__note">Online submission is not yet connected. Please call <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</p>
<label>{text.name}<input name="name" autocomplete="name" /></label>
<label>{text.email}<input type="email" name="email" autocomplete="email" /></label>
<label>{text.phone}<input type="tel" name="phone" autocomplete="tel" /></label>
<label>{text.service}<select name="service">{text.options.map((label) => <option>{label}</option>)}</select></label>
<label>{text.message}<textarea name="message" rows="5"></textarea></label>
<Button type="submit" disabled aria-describedby="contact-form-note" class="contact-form-card__submit">{text.submit}</Button>
<p id="contact-form-note" class="contact-form-card__note">{text.disabled} <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</p>
</div>
</form>
+12 -9
View File
@@ -1,21 +1,24 @@
---
import Button from './Button.astro';
import ContactObfuscation from './ContactObfuscation.astro';
const { title = 'Schedule Your Free Consultation', showBackground = false } = Astro.props;
import { formMessages } from '../utils/form-messages';
const { lang = 'en', showBackground = false } = Astro.props;
const text = formMessages(lang);
const title = Astro.props.title ?? text.heading;
---
<section class:list={['form-section', { 'form-section-background': showBackground }]} aria-labelledby="form-title">
<div class="container form-grid">
<div><p class="eyebrow">Get started</p><h2 id="form-title">{title}</h2><p>Tell our client advocates how we can help. Submission is disabled until a production form backend is selected.</p></div>
<div><p class="eyebrow">{text.eyebrow}</p><h2 id="form-title">{title}</h2><p>{text.intro}</p></div>
<form class="form" method="post" action="">
<!-- TODO: Wire this form to Netlify Forms, a custom API endpoint, or another backend service. -->
<!-- TODO: Add spam protection before production launch. -->
<label>Parent or guardian name<input name="name" autocomplete="name" /></label>
<label>Email<input type="email" name="email" autocomplete="email" /></label>
<label>Phone<input type="tel" name="phone" autocomplete="tel" /></label>
<label>Service of interest<select name="service"><option>ABA Therapy</option><option>Autism Evaluation</option><option>Learner Social Club</option><option>Other</option></select></label>
<label>How can we help?<textarea name="message" rows="5"></textarea></label>
<Button type="submit" disabled aria-describedby="form-note">Submit</Button>
<p id="form-note" class="form-note">Online submission is not yet connected. Please call <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</p>
<label>{text.name}<input name="name" autocomplete="name" /></label>
<label>{text.email}<input type="email" name="email" autocomplete="email" /></label>
<label>{text.phone}<input type="tel" name="phone" autocomplete="tel" /></label>
<label>{text.service}<select name="service">{text.options.map((label) => <option>{label}</option>)}</select></label>
<label>{text.message}<textarea name="message" rows="5"></textarea></label>
<Button type="submit" disabled aria-describedby="form-note">{text.submit}</Button>
<p id="form-note" class="form-note">{text.disabled} <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />.</p>
</form>
</div>
</section>
+7 -7
View File
@@ -17,31 +17,31 @@ if (!slice?.items.length) throw new Error(`Empty author archive: ${author.archiv
const { Content } = await render(author.entry);
const prefix = locale === 'en' ? '' : `/${locale}`;
const text = {
en: { heading: 'The Library at AZ Institute for Autism', title: 'Library & News Room | Arizona Institute for Autism', page: 'Page' },
es: { heading: 'La Biblioteca en AZ Institute for Autism', title: 'Biblioteca y Noticias | Instituto de Autismo de Arizona', page: 'Página' },
ar: { heading: 'مكتبة معهد أريزونا للتوحد', title: 'المكتبة وغرفة الأخبار | معهد أريزونا للتوحد', page: 'الصفحة' }
en: { heading: 'The Library at AZ Institute for Autism', title: 'Library & News Room | Arizona Institute for Autism', page: 'Page', welcome: 'Welcome to', posts: 'All Post', popular: 'Popular Posts' },
es: { heading: 'La Biblioteca en AZ Institute for Autism', title: 'Biblioteca y Noticias | Instituto de Autismo de Arizona', page: 'Página', welcome: 'Bienvenido a', posts: 'Todas las publicaciones', popular: 'Publicaciones populares' },
ar: { heading: 'مكتبة معهد أريزونا للتوحد', title: 'المكتبة وغرفة الأخبار | معهد أريزونا للتوحد', page: 'الصفحة', welcome: 'مرحبًا بكم في', posts: 'جميع المقالات', popular: 'المقالات الشائعة' }
}[locale];
const title = `${text.title} | ${author.displayName}${currentPage > 1 ? ` | ${text.page} ${currentPage}` : ''}`;
// Use the existing catalog's latest-post treatment; no second article list.
const popular = catalog.slice(0, 5);
---
<BaseLayout title={title} description={author.description} image={author.avatar} lang={locale}>
<PageHero title={text.heading} image="/assets/images/hero-library-index.webp" eyebrow="Welcome to" constrain />
<PageHero title={text.heading} image="/assets/images/hero-library-index.webp" eyebrow={text.welcome} constrain />
<section class="author-profile" aria-labelledby="author-heading">
{author.avatar && <img class="author-profile__avatar" src={author.avatar} alt={author.displayName} width="176" height="176" />}
<div class="author-profile__content">
<h2 id="author-heading"><bdi>{author.displayName}</bdi></h2>
<h2 id="author-heading"><bdi>{locale === 'ar' ? author.displayName.split(/(BCBA|LBA)/).map((part) => /^(BCBA|LBA)$/.test(part) ? <bdi dir="ltr" lang="en">{part}</bdi> : part) : author.displayName}</bdi></h2>
<div class="author-biography"><Content /></div>
</div>
</section>
<div class="author-listing container">
<section aria-labelledby="author-posts-heading">
<h2 id="author-posts-heading" class="author-posts-heading"><a href={libraryRootRoute(locale)}>All Post</a></h2>
<h2 id="author-posts-heading" class="author-posts-heading"><a href={libraryRootRoute(locale)}>{text.posts}</a></h2>
<div class="blog-list">{slice.items.map(({ entry }) => <BlogCard post={entry} prefix={prefix} />)}</div>
<LibraryPagination locale={locale} page={slice} authorRoot={author.archiveRoute} />
</section>
<aside class="author-sidebar" aria-labelledby="author-popular-heading">
<h2 id="author-popular-heading">Popular Posts</h2>
<h2 id="author-popular-heading">{text.popular}</h2>
<ul>{popular.map(({ entry, route }) => <li><a href={route}>{entry.data.title}</a></li>)}</ul>
</aside>
</div>
+11 -7
View File
@@ -1,11 +1,14 @@
---
import ContactForm from '../ContactForm.astro';
import { formMessages } from '../../utils/form-messages';
interface Props {
title: string;
lang: string;
}
const { title } = Astro.props;
const { title, lang } = Astro.props;
const text = formMessages(lang);
---
<section class="contact-page">
@@ -13,12 +16,12 @@ const { title } = Astro.props;
<div class="contact-page__copy">
<slot />
</div>
<ContactForm title={title} />
<ContactForm title={title} lang={lang} />
</div>
</section>
<section class="contact-map-section" aria-label="Map showing Arizona Institute for Autism in Scottsdale">
<div id="aia-contact-map" class="contact-map"></div>
<section class="contact-map-section" aria-label={text.map}>
<div id="aia-contact-map" class="contact-map" data-tile-alt={text.tile} data-zoom-in={text.zoomIn} data-zoom-out={text.zoomOut} data-marker-label={text.marker}></div>
</section>
<script is:inline src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
@@ -28,7 +31,8 @@ const { title } = Astro.props;
if (!mapElement || !window.L) return;
const map = window.L.map(mapElement).setView([33.63, -111.88756], 12);
const map = window.L.map(mapElement, { zoomControl: false }).setView([33.63, -111.88756], 12);
window.L.control.zoom({ zoomInTitle: mapElement.dataset.zoomIn, zoomOutTitle: mapElement.dataset.zoomOut }).addTo(map);
const tiles = window.L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
maxZoom: 19
@@ -36,13 +40,13 @@ const { title } = Astro.props;
tiles.on('tileload', (event) => {
if (event.tile && !event.tile.alt) {
event.tile.alt = 'OpenStreetMap tile showing area around Arizona Institute for Autism in Scottsdale, AZ';
event.tile.alt = mapElement.dataset.tileAlt;
}
});
tiles.addTo(map);
window.L.marker([33.617746, -111.88756]).addTo(map).bindPopup(`
window.L.marker([33.617746, -111.88756], { alt: mapElement.dataset.markerLabel, title: mapElement.dataset.markerLabel }).addTo(map).bindPopup(`
<span style="display:block;text-align:center">
<b>Arizona Institute for Autism</b><br>
<img class="contact-map__logo" alt="Arizona Institute for Autism" src="/assets/images/aia-logo.svg" width="94">
@@ -45,7 +45,7 @@ El refuerzo positivo ocurre cuando una consecuencia deseable sigue inmediatament
- **Mejora la regulación emocional.** Las recompensas ayudan a los niños a asociar sentimientos positivos con el autocontrol.
⚙️ **Tip:** Reinforcement is more effective when it feels genuine. Use specific praise like "I love how you put your shoes away!" instead of a generic "Good job!"
⚙️ **Consejo:** El refuerzo es más eficaz cuando se percibe como sincero. Use elogios específicos como «¡Me encanta cómo guardaste tus zapatos!» en lugar de un «¡Buen trabajo!» genérico.
## Beneficios clave para niños con autismo
+101
View File
@@ -0,0 +1,101 @@
---
title: "Política de privacidad | Arizona Institute for Autism"
description: "Descubra cómo Arizona Institute for Autism protege sus datos. Nuestra política de privacidad detalla la recopilación, el uso y la seguridad de su información."
displayH1: "Política de privacidad"
slug: "privacy-policy"
canonical: "https://www.azinstitute4autism.com/es/privacy-policy"
lang: "es"
translationKey: "privacy-policy"
draft: false
---
import ContactObfuscation from '../../../components/ContactObfuscation.astro';
Última actualización: **19 de febrero de 2025**
## Introducción
En el Instituto de Autismo de Arizona, nos dedicamos a proteger la privacidad y seguridad de los visitantes de nuestro sitio web, clientes y sus familias. Esta política explica cómo recopilamos, usamos y protegemos su información personal.
Como proveedores de atención médica, cumplimos estrictamente con la **[HIPAA](https://www.hhs.gov/hipaa/for-professionals/privacy/laws-regulations/index.html)** (Ley de Portabilidad y Responsabilidad del Seguro Médico), la **[COPPA](https://www.ecfr.gov/current/title-16/chapter-I/subchapter-C/part-312)** (Ley de Protección de la Privacidad en Línea de los Niños) y todas las regulaciones federales y estatales aplicables que rigen la privacidad y seguridad de la **[PHI](https://cphs.berkeley.edu/hipaa/hipaa18.html)** (Información de Salud Protegida). Podemos recopilar los siguientes tipos de información:
* **Información de identificación personal:** Su nombre, dirección, número de teléfono, dirección de correo electrónico y otros datos de contacto.
* **Información de salud:** Diagnósticos, planes de tratamiento, historial médico y otra información relacionada con la salud necesaria para proporcionar servicios de tratamiento para el autismo.
* **Datos de uso del sitio web:** Información como direcciones IP, tipo de navegador, tipo de dispositivo, sistema operativo y páginas visitadas. Estos datos se recopilan de forma agregada y no identificable con fines analíticos.
* **Información de pago:** Números de tarjetas de crédito, fechas de vencimiento y otros detalles de pago necesarios para procesar las transacciones de forma segura.
## Cómo Usamos Su Información
Utilizamos la información recopilada para los siguientes fines:
* **Prestación de servicios:** Para brindar servicios de tratamiento para el autismo, incluyendo la terapia de Análisis de Comportamiento Aplicado (ABA) y programas relacionados.
* **Comunicación:** Para responder a consultas, enviar boletines informativos y proporcionar actualizaciones sobre nuestros servicios.
* **Marketing (No Personalizado y Cumpliendo con HIPAA):**
* Utilizamos datos agregados y anonimizados para analizar tendencias y mejorar nuestros esfuerzos de divulgación.
* **No utilizamos ningún dato relacionado con la salud para publicidad dirigida o remarketing.**
* La información de salud protegida (PHI) nunca se comparte con comercializadores externos, anunciantes o plataformas de análisis.
* **Investigación y Desarrollo:** Para mejorar nuestros servicios, optimizar la funcionalidad del sitio web y apoyar la investigación en el tratamiento del autismo.
* **Cumplimiento Legal:** Para cumplir con la HIPAA, la COPPA y otras leyes pertinentes, incluidos los requisitos legales y policiales.
## Cómo Protegemos Su Información
Implementamos medidas de seguridad sólidas para garantizar la confidencialidad e integridad de sus datos:
* **Cifrado:** Utilizamos protocolos de cifrado compatibles con HIPAA para proteger los datos durante la transmisión y el almacenamiento.
* **Controles de acceso:** Solo el personal autorizado, con las verificaciones de antecedentes adecuadas y capacitación en confidencialidad, puede acceder a su información.
* **Almacenamiento seguro de datos:** Todos los datos se almacenan en servidores seguros y compatibles con HIPAA, tanto física como electrónicamente.
* **Respuesta a incidentes:** Mantenemos un plan integral de respuesta a brechas de datos para abordar y mitigar rápidamente cualquier incidente de seguridad.
## Compartiendo su información
No vendemos, alquilamos ni compartimos información de salud protegida con anunciantes externos. La información solo podrá compartirse en las siguientes circunstancias necesarias y permitidas:
* **Proveedores de servicios:** Contratistas, proveedores y socios que nos ayudan a prestar nuestros servicios de manera compatible con la HIPAA.
* **Compañías de Seguros:** Para procesar reclamaciones y obtener el reembolso de los servicios.
* **Instituciones de investigación:** En un formato desidentificado para apoyar la investigación y el avance del tratamiento del autismo.
* **Obligaciones Legales:** Cuando lo exija la ley, la normativa o una orden judicial.
## Sus derechos
Tiene los siguientes derechos con respecto a su información personal y de salud:
* **Acceso:** Puede solicitar una copia de sus registros en cualquier momento.
* **Corrección:** Si alguna información es incorrecta o incompleta, puede solicitar correcciones.
* **Exclusión:** Puede optar por no recibir boletines informativos, correos electrónicos de marketing u otras comunicaciones no esenciales.
* **Eliminación:** Puede solicitar la eliminación de sus datos personales cuando sea legalmente permisible. Tenga en cuenta que algunos registros deben conservarse de acuerdo con las regulaciones de la HIPAA.
## Privacidad de los niños y cumplimiento de la COPPA
Cumplimos con la Ley de Protección de la Privacidad en Línea de los Niños. Esto significa:
* Obtenemos el consentimiento parental verificable antes de recopilar información personal de niños menores de 13 años.
* **No recopilamos información de niños a sabiendas sin la aprobación de los padres o tutores.**
* Cualquier dato recopilado de niños se utiliza únicamente para servicios de tratamiento del autismo y nunca se comparte con fines de marketing.
* Si cree que hemos recopilado datos de un niño inadvertidamente sin el consentimiento adecuado, póngase en contacto con nosotros inmediatamente para su eliminación.
## Acuerdos de Protección de Datos (APD)
Hemos establecido Acuerdos de Protección de Datos con nuestros proveedores de servicios y contratistas. Estos acuerdos exigen que:
* Su información se procese de acuerdo con la HIPAA y todas las leyes de protección de datos aplicables.
* **No se utilizan datos personales de salud para publicidad, seguimiento analítico o fines de marketing. La información de salud protegida (PHI) nunca se comparte con plataformas de marketing de terceros.**
## Seguimiento de terceros y datos de uso del sitio web
Nuestro sitio web utiliza análisis anónimos para mejorar la funcionalidad. Específicamente:
* **No rastreamos a los visitantes del sitio web para publicidad personalizada relacionada con la salud.**
* **No utilizamos cookies de publicidad de terceros para recopilar datos relacionados con la salud. No realizamos seguimiento del comportamiento que se dirige a los usuarios en función de sus condiciones de salud. Estas prácticas están diseñadas para garantizar el cumplimiento de las políticas de atención médica e información confidencial.**
## Cambios a esta política
Podemos actualizar esta política de privacidad periódicamente. Todos los cambios se publicarán en esta página con una fecha de **Última actualización** actualizada. Su uso continuo de nuestro sitio web y servicios después de dichos cambios significa su aceptación de los términos revisados.
## Contáctenos
Si tiene alguna pregunta o inquietud sobre esta política de privacidad o desea ejercer sus derechos de privacidad, contáctenos en:
* **Correo electrónico:** <ContactObfuscation email="info@azinstitute4autism.com" obfuscatedText="info [at] azinstitute4autism [dot] com" />
* **Dirección:** 8901 E. Raintree Drive, Suite #160 Scottsdale Arizona 85260
* **Teléfono:** <ContactObfuscation phone="(480) 687-7099" hrefValue="+14806877099" obfuscatedText="9907-786 (084)" />
Al utilizar nuestro sitio web y servicios, usted confirma que ha leído, comprendido y acepta los términos descritos en esta política de privacidad.
+2 -2
View File
@@ -76,8 +76,8 @@ if (entry.data.slug === 'team' && entry.data.lang === 'en' && !entry.data.team)
: entry.data.slug === 'donate-autism-giveback' && entry.data.lang === 'en'
? <slot />
: entry.data.slug === 'contact'
? <ContactPage title={bannerTitle}><slot /></ContactPage>
? <ContactPage title={bannerTitle} lang={entry.data.lang}><slot /></ContactPage>
: <article class:list={['prose', 'source-page', 'container', { 'service-page': isService }]}><slot /></article>}
{isService && entry.data.lang === 'en' && <ServiceInquiryDrawer service={entry.data.slug} />}
{showForm && <FormShell title={bannerTitle} showBackground={entry.data.slug === 'client-consultation'} />}
{showForm && <FormShell lang={entry.data.lang} title={bannerTitle} showBackground={entry.data.slug === 'client-consultation'} />}
</BaseLayout>
+30
View File
@@ -0,0 +1,30 @@
/** Existing published form locales only; adding another locale requires reviewed copy. */
const messages = {
en: {
heading: 'Schedule Your Free Consultation', eyebrow: 'Get started',
intro: 'Tell our client advocates how we can help. Submission is disabled until a production form backend is selected.',
contactHeading: 'Contact AIA', name: 'Parent or guardian name', email: 'Email', phone: 'Phone',
service: 'Service of interest', options: ['ABA Therapy', 'Autism Evaluation', 'Learner Social Club', 'Other'],
message: 'How can we help?', submit: 'Submit',
disabled: 'Online submission is not yet connected. Please call',
map: 'Map showing Arizona Institute for Autism in Scottsdale',
tile: 'OpenStreetMap tile showing area around Arizona Institute for Autism in Scottsdale, AZ',
zoomIn: 'Zoom in', zoomOut: 'Zoom out', marker: 'Arizona Institute for Autism'
},
es: {
heading: 'Programe su consulta gratuita', eyebrow: 'Comience aquí',
intro: 'Cuéntenos cómo pueden ayudarle nuestros defensores de clientes. El envío está deshabilitado hasta que se seleccione un sistema para recibir los formularios.',
contactHeading: 'Contactar a AIA', name: 'Nombre del padre, la madre o el tutor', email: 'Correo electrónico', phone: 'Teléfono',
service: 'Servicio de interés', options: ['Terapia ABA', 'Evaluación de autismo', 'Learner Social Club', 'Otro'],
message: '¿Cómo podemos ayudarle?', submit: 'Enviar',
disabled: 'El envío en línea aún no está habilitado. Llame al',
map: 'Mapa de la ubicación de Arizona Institute for Autism en Scottsdale',
tile: 'Mapa de OpenStreetMap de los alrededores de Arizona Institute for Autism en Scottsdale, Arizona',
zoomIn: 'Acercar', zoomOut: 'Alejar', marker: 'Arizona Institute for Autism'
}
};
export function formMessages(locale: string) {
if (locale !== 'en' && locale !== 'es') throw new Error(`No reviewed form copy for locale: ${locale}`);
return messages[locale];
}