From 2acca5b6413024054a64634411e2aa117503957e Mon Sep 17 00:00:00 2001 From: Rachele Morino Date: Fri, 6 Mar 2026 13:20:12 -0500 Subject: [PATCH 1/6] Final copy updates --- .../public/locales/en/translation.json | 25 +++++++++++++---- .../public/locales/es/translation.json | 27 ++++++++++++++----- .../public/locales/zh/translation.json | 27 ++++++++++++------- .../src/components/EditFiltersModal.tsx | 4 ++- .../NeighborhoodCard/NeighborhoodCard.tsx | 14 ++++++---- .../NeighborhoodsList/NeighborhoodsList.tsx | 13 +++++---- .../src/components/base/Meter/Meter.tsx | 12 +++++++-- .../src/components/base/Range/Range.tsx | 10 ++++--- src/frontend/src/pages/Components.tsx | 2 +- 9 files changed, 95 insertions(+), 39 deletions(-) diff --git a/src/frontend/public/locales/en/translation.json b/src/frontend/public/locales/en/translation.json index b2131aaa..01a5096e 100644 --- a/src/frontend/public/locales/en/translation.json +++ b/src/frontend/public/locales/en/translation.json @@ -41,7 +41,13 @@ "otherTitle": "Other recommended neighborhoods", "otherTitleLegend": "Other", "tooFarTitle": "Not a match", - "tooFarDisclaimer": "These neighborhoods are out of reach with your selected transit option, meaning commute times exceeding 1 hour" + "tooFarDisclaimer": "These neighborhoods are excluded by the filters set in your profile", + "groupedCountZipCodes": "zip codes", + "groupedLoadMore": "Load more", + "eccBenefits": "ECC Benefits", + "commute": "Commute", + "min": "min", + "over2Hours": "Over 2 hr" }, "photoCredit": "Photo by {{artist}}. ", "photoSource": "Source.", @@ -63,7 +69,12 @@ "schoolsSafetyCard": { "header": "Schools & Safety", "schoolsLabel": "Schools", - "safetyLabel": "Safety" + "safetyLabel": "Safety", + "high": "High", + "above": "Above Avg", + "average": "Average", + "below": "Below Avg", + "low": "Low" }, "findUnitsLink": "Go to Find Units to learn more", "aboutAreaSection": { @@ -136,7 +147,7 @@ "header": "Your Profile", "stepBedroom": { "question": "How many bedrooms does your voucher have?", - "description": "Reach out to your BHA Housing Coordinator if you're unsure." + "description": "Reach out to your BHA Housing Specialist if you're unsure." }, "stepImportance": { "question": "What is important to you?", @@ -188,7 +199,10 @@ "bodyText": "Edit your settings and add filters using the buttons at the top", "showMyRecommendations": "Show my recommendations", "listNeighborhoods": "List all neighborhoods", - "showTopTen": "Show Top 10" + "showTopTen": "Show Top 10", + "next": "Next", + "details": "Details", + "prev": "Prev" }, "filterModal": { "dialogHeading": "Filter recommendations", @@ -201,7 +215,8 @@ "regionMapCaption": "Based on a map by", "echoLink": "Learn more about ECHO", "regionsFilterLabel": "Filter by region selections", - "eccFilter": "Only recommend Expanded Choice Communities (ECC)" + "eccFilter": "Only recommend Expanded Choice Communities (ECC)", + "eccFilterDescription": "Moving to an ECC area could qualify you for financial assistance to help with your security deposit, broker fees, and moving expenses." }, "editTripsModal": { "dialogHeading": "Choose a trip", diff --git a/src/frontend/public/locales/es/translation.json b/src/frontend/public/locales/es/translation.json index 5f4def88..475ec9e0 100644 --- a/src/frontend/public/locales/es/translation.json +++ b/src/frontend/public/locales/es/translation.json @@ -39,9 +39,13 @@ "bestRecTitle": "Highest-ranked recommendations", "recTitle": "Recommended", "otherTitle": "Other recommended neighborhoods", - "otherTitleLegend": "Other", - "tooFarTitle": "Not a match", - "tooFarDisclaimer": "These neighborhoods are out of reach with your selected transit option, meaning commute times exceeding 1 hour" + "tooFarDisclaimer": "These neighborhoods are excluded by the filters set in your profile", + "groupedCountZipCodes": "zip codes", + "groupedLoadMore": "Load more", + "eccBenefits": "ECC Benefits", + "commute": "Commute", + "min": "min", + "over2Hours": "Over 2 hr" }, "photoCredit": "Photo by {{artist}}. ", "photoSource": "Source.", @@ -63,7 +67,12 @@ "schoolsSafetyCard": { "header": "Schools & Safety", "schoolsLabel": "Schools", - "safetyLabel": "Safety" + "safetyLabel": "Safety", + "high": "High", + "above": "Above Avg", + "average": "Average", + "below": "Below Avg", + "low": "Low" }, "findUnitsLink": "Go to Find Units to learn more", "aboutAreaSection": { @@ -136,7 +145,7 @@ "header": "¡Tu perfil", "stepBedroom": { "question": "How many bedrooms does your voucher have?", - "description": "Reach out to your BHA Housing Coordinator if you're unsure." + "description": "Reach out to your BHA Housing Specialist if you're unsure." }, "stepImportance": { "question": "What is important to you?", @@ -188,7 +197,10 @@ "bodyText": "Edit your settings and add filters using the buttons at the top", "showMyRecommendations": "Show my recommendations", "listNeighborhoods": "List all neighborhoods", - "showTopTen": "Show Top 10" + "showTopTen": "Show Top 10", + "next": "Next", + "details": "Details", + "prev": "Prev" }, "filterModal": { "dialogHeading": "Filter recommendations", @@ -201,7 +213,8 @@ "regionMapCaption": "Based on a map by", "echoLink": "Learn more about ECHO", "regionsFilterLabel": "Filter by region selections", - "eccFilter": "Only recommend Expanded Choice Communities (ECC)" + "eccFilter": "Only recommend Expanded Choice Communities (ECC)", + "eccFilterDescription": "Moving to an ECC area could qualify you for financial assistance to help with your security deposit, broker fees, and moving expenses." }, "editTripsModal": { "dialogHeading": "Choose a trip", diff --git a/src/frontend/public/locales/zh/translation.json b/src/frontend/public/locales/zh/translation.json index 416eef1e..6d8944a6 100644 --- a/src/frontend/public/locales/zh/translation.json +++ b/src/frontend/public/locales/zh/translation.json @@ -41,7 +41,13 @@ "otherTitle": "Other recommended neighborhoods", "otherTitleLegend": "Other", "tooFarTitle": "Not a match", - "tooFarDisclaimer": "These neighborhoods are out of reach with your selected transit option, meaning commute times exceeding 1 hour" + "tooFarDisclaimer": "These neighborhoods are excluded by the filters set in your profile", + "groupedCountZipCodes": "zip codes", + "groupedLoadMore": "Load more", + "eccBenefits": "ECC Benefits", + "commute": "Commute", + "min": "min", + "over2Hours": "Over 2 hr" }, "photoCredit": "Photo by {{artist}}. ", "photoSource": "Source.", @@ -63,7 +69,12 @@ "schoolsSafetyCard": { "header": "Schools & Safety", "schoolsLabel": "Schools", - "safetyLabel": "Safety" + "safetyLabel": "Safety", + "high": "High", + "above": "Above Avg", + "average": "Average", + "below": "Below Avg", + "low": "Low" }, "findUnitsLink": "Go to Find Units to learn more", "aboutAreaSection": { @@ -183,12 +194,9 @@ } }, "top10Tour": { - "header": "Discover Neighborhoods", - "subHeader": "Recommendations are based on your profile and selected trip.", - "bodyText": "Edit your settings and add filters using the buttons at the top", - "showMyRecommendations": "Show my recommendations", - "listNeighborhoods": "List all neighborhoods", - "showTopTen": "Show Top 10" + "next": "Next", + "details": "Details", + "prev": "Prev" }, "filterModal": { "dialogHeading": "Filter recommendations", @@ -201,7 +209,8 @@ "regionMapCaption": "Based on a map by", "echoLink": "Learn more about ECHO", "regionsFilterLabel": "Filter by region selections", - "eccFilter": "Only recommend Expanded Choice Communities (ECC)" + "eccFilter": "Only recommend Expanded Choice Communities (ECC)", + "eccFilterDescription": "Moving to an ECC area could qualify you for financial assistance to help with your security deposit, broker fees, and moving expenses." }, "editTripsModal": { "dialogHeading": "Choose a trip", diff --git a/src/frontend/src/components/EditFiltersModal.tsx b/src/frontend/src/components/EditFiltersModal.tsx index b34dbd41..74368563 100644 --- a/src/frontend/src/components/EditFiltersModal.tsx +++ b/src/frontend/src/components/EditFiltersModal.tsx @@ -213,7 +213,9 @@ const EditFiltersModal = ({ isMobile = false }) => { ecc: isSelected, }) } - description={`Select to only recommend neighborhoods that are Expanded Choice Communities (ECC)`} + description={t( + "filterModal.eccFilterDescription" + )} footer={ - Top 10 + {t("discoverNeighborhoods.topTen")} )} {hasECC && (
- ECC Benefits + + {t("discoverNeighborhoods.eccBenefits")} +
)} @@ -142,7 +146,7 @@ const NeighborhoodCard = ({ } > - Prev + {t("top10Tour.prev")} )} {onDetails && ( @@ -151,7 +155,7 @@ const NeighborhoodCard = ({ className="flex-1" onPress={onDetails} > - Details + {t("top10Tour.details")} )} {onNext && ( @@ -163,7 +167,7 @@ const NeighborhoodCard = ({ } > - Next + {t("top10Tour.next")} )} diff --git a/src/frontend/src/components/NeighborhoodsList/NeighborhoodsList.tsx b/src/frontend/src/components/NeighborhoodsList/NeighborhoodsList.tsx index e3f9df7a..0de107bc 100644 --- a/src/frontend/src/components/NeighborhoodsList/NeighborhoodsList.tsx +++ b/src/frontend/src/components/NeighborhoodsList/NeighborhoodsList.tsx @@ -1,11 +1,12 @@ import { useState } from "react"; -import type { NeighborhoodDetails } from "reducers/neighborhoods/types"; -import formatNeighborhoodDataByViewType from "libs/formatNeighborhoodDataByCard"; import Button from "components/base/Button/Button"; +import formatNeighborhoodDataByViewType from "libs/formatNeighborhoodDataByCard"; +import type { NeighborhoodDetails } from "reducers/neighborhoods/types"; -import { listStyles } from "./NeighborhoodsList.styles"; +import { useTranslation } from "react-i18next"; import ClickableNeighborhoodCard from "../NeighborhoodCard/ClickableNeighborhoodCard"; +import { listStyles } from "./NeighborhoodsList.styles"; interface Props { neighborhoodDetailsMap: NeighborhoodDetails; @@ -34,6 +35,7 @@ const NeighborhoodList = ({ groupCount, button, } = listStyles({ isMobile: isMobile, isGroup: isGroup }); + const { t } = useTranslation(); // Display 10 Neighborhood cards per page. // If it's a grouped-by-neighborhood-name list, @@ -58,7 +60,8 @@ const NeighborhoodList = ({

{groupName}

- {neighborhoodList.length} zip codes + {neighborhoodList.length}{" "} + {t("discoverNeighborhoods.groupedCountZipCodes")}

)} @@ -99,7 +102,7 @@ const NeighborhoodList = ({ className={button()} onClick={handleLoadMore} > - Load More + {t("discoverNeighborhoods.groupedLoadMore")} )} diff --git a/src/frontend/src/components/base/Meter/Meter.tsx b/src/frontend/src/components/base/Meter/Meter.tsx index 84f01e74..e105bbb4 100644 --- a/src/frontend/src/components/base/Meter/Meter.tsx +++ b/src/frontend/src/components/base/Meter/Meter.tsx @@ -1,9 +1,10 @@ import { - Meter as AriaMeter, Label as AriaLabel, + Meter as AriaMeter, type MeterProps as AriaMeterProps, } from "react-aria-components"; +import { useTranslation } from "react-i18next"; import { meterStyles } from "./Meter.styles"; type MeterStatus = "Low" | "Below Avg" | "Average" | "Above Avg" | "High"; @@ -22,10 +23,13 @@ const getStatusFromValue = (value: number): MeterStatus => { }; const Meter = ({ label, showCategory = false, ...props }: MeterProps) => { + const { t } = useTranslation(); const status = getStatusFromValue(props.value ?? 0); const { root, labelContainer, mainLabel, valueLabel, track, fill, thumb } = meterStyles({ status }); + const translatableLabelKey = status.split(" ")[0].toLowerCase(); + return ( {({ percentage }) => ( @@ -34,7 +38,11 @@ const Meter = ({ label, showCategory = false, ...props }: MeterProps) => { {label} {showCategory && ( - {status} + {t([ + "neighborhoodDetail." + + "schoolsSafetyCard." + + translatableLabelKey, + ])} )} diff --git a/src/frontend/src/components/base/Range/Range.tsx b/src/frontend/src/components/base/Range/Range.tsx index b656445c..635bc288 100644 --- a/src/frontend/src/components/base/Range/Range.tsx +++ b/src/frontend/src/components/base/Range/Range.tsx @@ -1,6 +1,7 @@ +import DotIcon from "assets/icons/dots.svg?react"; import { useMemo } from "react"; +import { useTranslation } from "react-i18next"; import { rangeStyles } from "./Range.styles"; -import DotIcon from "assets/icons/dots.svg?react"; const MIN_DEFAULT = 0; const MAX_DEFAULT = 120; @@ -22,6 +23,7 @@ const Range = ({ min = MIN_DEFAULT, max = MAX_DEFAULT, }: RangeProps) => { + const { t } = useTranslation(); const { root, labelContainer, mainLabel, rangeLabel, track, fill, dots } = rangeStyles(); @@ -32,9 +34,9 @@ const Range = ({ ((Math.min(end, MAX_DEFAULT) - start) / totalRange) * 100 || 8; const rangeText = useMemo(() => { - if (start >= MAX_DEFAULT) return "Over 2 hr"; - if (isPoint) return `${start} min`; - return `${start}-${end > MAX_DEFAULT ? `${MAX_DEFAULT}+` : end} min`; + if (start >= MAX_DEFAULT) return t("discoverNeighborhoods.over2Hours"); + if (isPoint) return `${start} ${t("discoverNeighborhoods.min")}`; + return `${start}-${end > MAX_DEFAULT ? `${MAX_DEFAULT}+` : end} ${t("discoverNeighborhoods.min")}`; }, [start, end]); return ( diff --git a/src/frontend/src/pages/Components.tsx b/src/frontend/src/pages/Components.tsx index 25a3a746..f0df9779 100644 --- a/src/frontend/src/pages/Components.tsx +++ b/src/frontend/src/pages/Components.tsx @@ -583,7 +583,7 @@ const Components = () => { {/* Each direct child is treated as a step */} Date: Mon, 9 Mar 2026 17:13:05 -0400 Subject: [PATCH 2/6] Add Spanish translations --- .../public/locales/es/translation.json | 280 +++++++++--------- 1 file changed, 141 insertions(+), 139 deletions(-) diff --git a/src/frontend/public/locales/es/translation.json b/src/frontend/public/locales/es/translation.json index 475ec9e0..e07de313 100644 --- a/src/frontend/public/locales/es/translation.json +++ b/src/frontend/public/locales/es/translation.json @@ -1,235 +1,237 @@ { "discover": "Descubrir", "compare": "Comparar", - "favorites": "Favorites", + "favorites": "Favoritos", "logout": "Cerrar sesión", - "filtersButton": "Profile", + "filtersButton": "Perfil", "transitModesSimple": { - "peak": "express public transit", - "offPeak": "express public transit", - "peakNoExpress": "public transit", - "offPeakNoExpress": "public transit", - "car": "car" + "peak": "autobús/tren exprés", + "offPeak": "autobús/tren exprés", + "peakNoExpress": "autobús/tren", + "offPeakNoExpress": "autobús/tren", + "car": "automóvil" }, - "map": "Map", - "list": "List", + "map": "Mapa", + "list": "Lista", "destinationPurposes": { - "Work": "Work", - "School": "School", - "Daycare": "Daycare", - "Friends/Family": "Friends/Family", + "Work": "Trabajo", + "School": "Escuela", + "Daycare": "Guardería", + "Friends/Family": "Amigos/Familia", "Doctor": "Doctor", - "Other": "Other" + "Other": "Otro" }, "signInPage": { - "signIn": "Iniciar sesión", - "signInModalSubtitle": "Debes ser participante del <0>programa BHA ECHO para utilizar esta herramienta.", - "signInPageCaption": "Encuentre vecindarios que funcionen para usted y su familia", + "signIn": "Inicio de sesión", + "signInModalSubtitle": "Debes ser participante del <0>programa ECHO de BHA para usar esta herramienta.", + "signInPageCaption": "Encuentra los vecindarios que funcionan para ti y tu familia", "signInWithEmail": "Inicia sesión con tu correo electrónico", "emailAddressInvalid": "La dirección de correo electrónico no es válida", "checkYourEmail": "Revisa tu correo electrónico", - "goBack": "Volver", - "signInConfirm": "Enviamos un correo electrónico con un enlace de inicio de sesión a {{email}}. Haga clic en el enlace para iniciar sesión en ECHO.", - "enterEmailAddress": "Introduce tu dirección de correo electrónico" + "goBack": "Regresar", + "signInConfirm": "Enviamos un correo electrónico con un enlace de inicio de sesión a {{email}}. Haz clic en el enlace para iniciar sesión en ECHO.", + "enterEmailAddress": "Ingresa tu correo electrónico" }, "discoverNeighborhoods": { - "title": "Discover Neighborhoods", - "subtitle": "Recommendations are based on your profile and selected trip", - "topTen": "Top 10", - "bestRecTitle": "Highest-ranked recommendations", + "title": "Descubrir vecindarios", + "subtitle": "Las recomendaciones se basan en tu perfil y el viaje seleccionado.", + "topTen": "10 Mejores", + "bestRecTitle": "Recomendaciones mejor valoradas", "recTitle": "Recommended", "otherTitle": "Other recommended neighborhoods", + "otherTitleLegend": "Otro", + "tooFarTitle": "No coincide", "tooFarDisclaimer": "These neighborhoods are excluded by the filters set in your profile", - "groupedCountZipCodes": "zip codes", - "groupedLoadMore": "Load more", - "eccBenefits": "ECC Benefits", - "commute": "Commute", - "min": "min", + "groupedCountZipCodes": "códigos postales", + "groupedLoadMore": "Mostrar más", + "eccBenefits": "Beneficios ECC", + "commute": "Transporte", + "min": "minutos", "over2Hours": "Over 2 hr" }, "photoCredit": "Photo by {{artist}}. ", "photoSource": "Source.", "neighborhoodDetail": { - "addToFavorites": "Add to favorites", + "addToFavorites": "Agregar a favoritos", "moveCountText": "¡{{count}} titulares de vales ya se mudaron aquí!", - "infoToggleLabel": "Info", - "unitsToggleLabel": "Find units", - "eccYes": "Yes", + "infoToggleLabel": "Información", + "unitsToggleLabel": "Encontrar unidades", + "eccYes": "Sí", "affordableCard": { - "header": "Affordable", - "bodyText": "La mayoría de las familias pagan no más del 30% de sus ingresos en alquiler." + "header": "Asequible", + "bodyText": "La mayoría de las familias no pagan más del 30% de sus ingresos en alquiler." }, "echoBenefitsCard": { - "header": "ECHO Benefits", - "bodyText": "Receive financial assistance for Security Deposit, Broker’s Fees, Moving Expenses and more." + "header": "Beneficios de ECHO", + "bodyText": "Asistencia financiera para el depósito de seguridad, tarifas del agente, gastos de mudanza y más." }, "schoolChoice": "School choice options", "schoolsSafetyCard": { - "header": "Schools & Safety", - "schoolsLabel": "Schools", - "safetyLabel": "Safety", - "high": "High", - "above": "Above Avg", - "average": "Average", - "below": "Below Avg", - "low": "Low" + "header": "Escuelas y Seguridad", + "schoolsLabel": "Escuelas", + "safetyLabel": "Seguridad", + "high": "Alto", + "above": "Por encima del Promedio", + "average": "Promedio", + "below": "Por debajo del Promedio", + "low": "Bajo" }, - "findUnitsLink": "Go to Find Units to learn more", + "findUnitsLink": "Ve a Encontrar unidades para obtener más información", "aboutAreaSection": { - "header": "About this area", - "readMoreButton": "READ MORE" + "header": "Acerca de esta área", + "readMoreButton": "Leer más" }, "learnMoreSection": { - "subheader": "Learn more", - "websiteLink": "Website", + "subheader": "Aprender más", + "websiteLink": "Página web", "wikipediaLink": "Wikipedia", "googleLink": "Google" }, "unitsContent": { "step1": { - "stepNumber": "STEP 1", - "header": "Check your Budget", - "voucherCovers": "Your vouchers covers units up to", - "perMonth": "/ month", - "whatYouPay": "What you pay", - "yourPaymentDetail": "In most cases you pay no more than 30% of your income, plus utilities.", - "learnVouchersLink": "Learn more about vouchers", - "echoBenefits": "Your ECHO benefits", - "sdBrokerFee": "Security deposit and/or Broker’s Fee", - "movingExpenses": "Moving expenses", - "landlordIncentive": "Landlord incentive", - "learnEchoLink": "Learn more about ECHO" + "stepNumber": "PASO 1", + "header": "Revisa tu presupuesto", + "voucherCovers": "Tu vale cubre unidades hasta", + "perMonth": "/ mes", + "whatYouPay": "Lo que pagas", + "yourPaymentDetail": "En la mayoría de los casos, pagas no más del 30% de tus ingresos, más los servicios.", + "learnVouchersLink": "Aprende más sobre los vales", + "echoBenefits": "Tus beneficios ECHO", + "sdBrokerFee": "Depósito de seguridad y/o tarifas del agente", + "movingExpenses": "Gastos de mudanza", + "landlordIncentive": "Incentivo al arrendador", + "learnEchoLink": "Aprende más sobre ECHO" }, "step2": { - "stepNumber": "STEP 2", - "header": "Find units you like", - "affordabilityCalculator": "Use the Affordability Calculator to check if a unit fits your budget", - "linkSubtext": "{{town}} {{zipcode}}, {{brCount}}br" + "stepNumber": "PASO 2", + "header": "Encuentra las unidades que te gusten", + "affordabilityCalculator": "Utiliza la Calculadora de Asequibilidad para comprobar si una unidad está dentro de su presupuesto.", + "linkSubtext": "{{town}} {{zipcode}}, {{brCount}} dormitorios" }, "step3": { - "stepNumber": "STEP 3", + "stepNumber": "PASO 3", "header": "Found a unit? Use the Affordability Calculator to check if it’s in budget", "bodyText": "All Calculations are subject to a final BHA determination.", "linkSubtext": "Open Affordability Calculator" }, "step4": { - "stepNumber": "STEP 4", - "header": "Schedule a viewing and reach out to your ECHO Coordinator", + "stepNumber": "PASO 4", + "header": "Agenda una visita y contacta a tu Coordinador de ECHO", "bodyText": "Please have the unit address and Property Owner’s information ready.", - "coordinatorLink": "Contact your coordinator" + "coordinatorLink": "Contacta a tu coordinador" }, "unitsModal": { - "header": "will open in a new tab.", - "affordLinkTitle": "What can I afford?", - "affordLinkSubtitle": "See how much rent BHA will cover and learn about additional benefits", - "calculatorLinkTitle": "Can I afford this unit?", - "calculatorLinkSubtitle": "The BHA Affordability Calculator helps you estimate your copay." + "header": "se abrirá en una nueva pestaña.", + "affordLinkTitle": "¿Qué puedo pagar?", + "affordLinkSubtitle": "Ve cuánto alquiler cubrirá BHA y aprende sobre beneficios adicionales", + "calculatorLinkTitle": "¿Puedo pagar esta unidad?", + "calculatorLinkSubtitle": "La Calculadora de Asequibilidad de BHA te ayuda a estimar tu copago." } } }, "yourTrips": { - "heading": "Your Trips", + "heading": "Sus viajes", "subheading": "Commute times are estimates. Your actual commute times may vary based on your new address.", - "busAndTrain": "Bus & Train", - "car": "Car", - "touchPrompt": "Select a trip to see directions on a map", - "editTrips": "Edit your trips", + "busAndTrain": "Autobús/Tren", + "car": "Automóvil", + "touchPrompt": "Selecciona un viaje para ver direcciones en el mapa", + "editTrips": "Edite sus destinos", "openInGoogle": "Abierto en Google Maps" }, "userProfile": { - "title": "¡Descubra los barrios", - "description": "Start by creating a profile to help us recommend neighborhoods to you", - "actionButton": "Create your profile", - "caption": "Takes just 5 minutes!", + "title": "Descubrir vecindarios", + "description": "Comienza creando un perfil para ayudarnos a recomendarte vecindarios.", + "actionButton": "Crea tu perfil", + "caption": "¡Solo toma 5 minutos!", "wizard": { - "header": "¡Tu perfil", + "header": "Tu perfil", "stepBedroom": { - "question": "How many bedrooms does your voucher have?", - "description": "Reach out to your BHA Housing Specialist if you're unsure." + "question": "¿De Cuántos dormitorios es su vale?", + "description": "Comuníquese con su Coordinador de Vivienda de BHA si no está seguro(a)." }, "stepImportance": { - "question": "What is important to you?", - "commuteTime": "Commute time", - "schoolQuality": "School Quality", - "publicSafety": "Public safety", - "notImportant": "Not important", - "veryImportant": "Very important" + "question": "¿Qué es importante para usted?", + "commuteTime": "Tiempo de transporte", + "schoolQuality": "Calidad de las escuelas", + "publicSafety": "Seguridad pública", + "notImportant": "No es importante", + "veryImportant": "Muy importante" }, "stepTravelMode": { - "question": "How do you typically get around?", - "toggleCar": "Car", - "toggleTransit": "Bus/Train", - "checkboxDescription": "The Commuter rail and express bus allow us to recommend more neighborhoods, but they usually cost more than the subway or local bus.", - "checkboxLabel": "I'm willing to take the express bus or commuter rail" + "question": "¿Cómo se movilizas normalmente?", + "toggleCar": "Automóvil", + "toggleTransit": "Autobús/Tren", + "checkboxDescription": "El tren de cercanías (MBTA Commuter Rail) y el autobús exprés nos permiten recomendar más vecindarios, pero generalmente cuestan más que el tren o el autobús local.", + "checkboxLabel": "Estoy dispuesto(a) a tomar el autobús exprés o el tren de cercanías (MBTA Commuter Rail)" }, "button": { "continue": "Continuar", - "finish": "Finish" + "finish": "Finalizar" } } }, "userTrip": { "wizard": { - "header": "Your trip", + "header": "Sus viajes", "stepAddTrip": { - "question": "Which trips do you make frequently?", - "description": "We use this information to recommend neighborhoods near the places you visit often", - "addATrip": "Add a trip", - "addAnotherTrip": "Add another trip", + "question": "¿Qué viajes realiza con frecuencia?", + "description": "Usamos esta información para recomendar vecindarios cerca de los lugares que visita con frecuencia.", + "addATrip": "Agregar un viaje", + "addAnotherTrip": "Agregar otro viaje", "error": "You have destinations that are not valid, please remove and try again." }, "addNewTripModal": { "question": "Add new trip", - "purposeLabel": "What kind of place is it?", - "locationLabel": "Where is it?", - "locationPlaceholder": "Enter an address", + "purposeLabel": "¿Qué tipo de lugar es?", + "locationLabel": "¿Dónde?", + "locationPlaceholder": "Ingrese una dirección", "finish": "Add trip" }, "button": { "continue": "Continuar", - "finish": "Finish" + "finish": "Finalizar" } } }, "top10Tour": { - "header": "Discover Neighborhoods", - "subHeader": "Recommendations are based on your profile and selected trip.", - "bodyText": "Edit your settings and add filters using the buttons at the top", - "showMyRecommendations": "Show my recommendations", - "listNeighborhoods": "List all neighborhoods", - "showTopTen": "Show Top 10", - "next": "Next", - "details": "Details", - "prev": "Prev" + "header": "Descubrir vecindarios", + "subHeader": "Las recomendaciones se basan en tu perfil y el viaje seleccionado.", + "bodyText": "Edita tus configuraciones y añade filtros usando los botones en la parte superior.", + "showMyRecommendations": "Mostrar mis recomendaciones", + "listNeighborhoods": "Lista de todos los vecindarios", + "showTopTen": "Mostrar 10 mejores", + "next": "Siguiente", + "details": "Detalles", + "prev": "Anterior" }, "filterModal": { - "dialogHeading": "Filter recommendations", - "profileEditHeading": "Your Profile", - "bedroom": "Bedroom", - "edit": "Edit", - "regionsFilterHeading": "Filter by region", - "regionsFilterSubHeading": "Select all regions you are interested in", - "otherFilterHeading": "Other filters", + "dialogHeading": "Filtrar recomendaciones", + "profileEditHeading": "Tu perfil", + "bedroom": "Habitaciones", + "edit": "Edite", + "regionsFilterHeading": "Filtrar por región", + "regionsFilterSubHeading": "Selecciona todas las regiones de tu interés", + "otherFilterHeading": "Otros filtros", "regionMapCaption": "Based on a map by", - "echoLink": "Learn more about ECHO", - "regionsFilterLabel": "Filter by region selections", - "eccFilter": "Only recommend Expanded Choice Communities (ECC)", - "eccFilterDescription": "Moving to an ECC area could qualify you for financial assistance to help with your security deposit, broker fees, and moving expenses." + "echoLink": "Aprenda acerca de ECHO", + "regionsFilterLabel": "Filtrar por región", + "eccFilter": "Sólo se recomienda Expanded Choice Communities (Más Opciones de Comunidades) (ECC)", + "eccFilterDescription": "Mudarse a un área ECC puede cualificarle para asistencia financiera para ayudar con el depósito de seguridad, tarifa de agente y gastos de mudanza." }, "editTripsModal": { - "dialogHeading": "Choose a trip", - "dialogSubHeading": "We recommend neighborhoods that are conveniently located.", - "trafficHeading": "Choose traffic conditions", - "travelModeHeading": "How do you usually get around?", - "peak": "Peak", - "offPeak": "Off-peak" + "dialogHeading": "Escoja un destino", + "dialogSubHeading": "Recomendamos un vecindario que está localizado convenientemente.", + "trafficHeading": "Escoja situaciones de tráfico", + "travelModeHeading": "¿Cómo usted usualmente se moviliza?", + "peak": "Mucho tráfico", + "offPeak": "Poco tráfico" }, - "searchModal": "Search the map", - "searchModalDescription": "Type a neighborhood name to find it on the map", - "searchModalPlaceholder": "Search neighborhoods", + "searchModal": "Busque en el mapa", + "searchModalDescription": "Escriba el nombre de un vecindario para encontrarlo en el mapa", + "searchModalPlaceholder": "Buscar vecindarios", "comparePage": { "title": "Favorite Neighborhoods", - "subtitle": "Your Favorites", - "introDescription": "Add neighborhoods to your favorites to make them show up in the comparison." + "subtitle": "Tus favoritos", + "introDescription": "Agrega vecindarios a tus favoritos para que aparezcan en la comparación." } } From 2446642dc72dbad62d8c50817415d1eae8b681c2 Mon Sep 17 00:00:00 2001 From: Rachele Morino Date: Tue, 10 Mar 2026 01:58:47 -0400 Subject: [PATCH 3/6] Add Chinese translations --- .../public/locales/zh/translation.json | 260 +++++++++--------- 1 file changed, 133 insertions(+), 127 deletions(-) diff --git a/src/frontend/public/locales/zh/translation.json b/src/frontend/public/locales/zh/translation.json index 6d8944a6..347ae411 100644 --- a/src/frontend/public/locales/zh/translation.json +++ b/src/frontend/public/locales/zh/translation.json @@ -9,182 +9,182 @@ "offPeak": "express public transit", "peakNoExpress": "public transit", "offPeakNoExpress": "public transit", - "car": "car" + "car": "汽車" }, - "map": "Map", - "list": "List", + "map": "地圖", + "list": "清單", "destinationPurposes": { - "Work": "Work", - "School": "School", - "Daycare": "Daycare", - "Friends/Family": "Friends/Family", - "Doctor": "Doctor", - "Other": "Other" + "Work": "工作", + "School": "學校", + "Daycare": "托兒所", + "Friends/Family": "朋友/家人", + "Doctor": "醫生", + "Other": "其他" }, "signInPage": { - "signIn": "登陆", - "signInModalSubtitle": "您需要成为<0>BHA ECHO项目的参与者才能使用此工具。", - "signInPageCaption": "寻找适合您和您的家人的社区", - "signInWithEmail": "使用您的电子邮箱登录", + "signIn": "登入", + "signInModalSubtitle": "您必須是 波房局<0>(BHA)擴大住房機會選擇 (ECHO) 計劃畫的參與者,才能使用此工具。", + "signInPageCaption": "尋找適合您和家人的社區", + "signInWithEmail": "使用您的電郵地址登入", "emailAddressInvalid": "电子邮箱地址无效", "checkYourEmail": "查看您的电子邮件", "goBack": "返回", - "signInConfirm": "我们已向{{email}}发送了一封包含登录链接的电子邮件。点击该链接即可登录ECHO。", - "enterEmailAddress": "输入您的电子邮箱地址" + "signInConfirm": "我們已將含有登入連結的電子郵件發送至{{email}}。請點擊該連結以登入ECHO。", + "enterEmailAddress": "請輸入您的電郵地址" }, "discoverNeighborhoods": { - "title": "Discover Neighborhoods", - "subtitle": "Recommendations are based on your profile and selected trip", - "topTen": "Top 10", - "bestRecTitle": "Highest-ranked recommendations", + "title": "探索社區", + "subtitle": "推薦是根據您的個人檔案和所選行程而提供。", + "topTen": "前 10 名", + "bestRecTitle": "最高排名的推薦", "recTitle": "Recommended", "otherTitle": "Other recommended neighborhoods", - "otherTitleLegend": "Other", - "tooFarTitle": "Not a match", + "otherTitleLegend": "其他", + "tooFarTitle": "沒有相符的", "tooFarDisclaimer": "These neighborhoods are excluded by the filters set in your profile", - "groupedCountZipCodes": "zip codes", - "groupedLoadMore": "Load more", - "eccBenefits": "ECC Benefits", - "commute": "Commute", - "min": "min", + "groupedCountZipCodes": "個郵政編", + "groupedLoadMore": "載入更多", + "eccBenefits": "擴大選擇社區(ECC)補助", + "commute": "通勤", + "min": "分鐘", "over2Hours": "Over 2 hr" }, "photoCredit": "Photo by {{artist}}. ", "photoSource": "Source.", "neighborhoodDetail": { - "addToFavorites": "Add to favorites", - "moveCountText": "已有 {{count}} 名代金券持有者搬到这里了!", - "infoToggleLabel": "Info", - "unitsToggleLabel": "Find units", - "eccYes": "Yes", + "addToFavorites": "加入收藏", + "moveCountText": "已有 {{count}} 名房屋租賃券持有者搬到這裡!", + "infoToggleLabel": "資訊", + "unitsToggleLabel": "尋找單位", + "eccYes": "是", "affordableCard": { - "header": "Affordable", - "bodyText": "大多数家庭支付的租金不超过其收入的30%。" + "header": "可負擔的", + "bodyText": "大多數家庭的租金不超過收入的30%。" }, "echoBenefitsCard": { - "header": "ECHO Benefits", - "bodyText": "Receive financial assistance for Security Deposit, Broker’s Fees, Moving Expenses and more." + "header": "ECHO 補助", + "bodyText": "經濟援助以支付保證金、仲介費、搬遷費用等。" }, "schoolChoice": "School choice options", "schoolsSafetyCard": { - "header": "Schools & Safety", - "schoolsLabel": "Schools", - "safetyLabel": "Safety", - "high": "High", - "above": "Above Avg", - "average": "Average", - "below": "Below Avg", - "low": "Low" + "header": "學校與安全", + "schoolsLabel": "學校", + "safetyLabel": "安全", + "high": "高", + "above": "高於平均", + "average": "平均", + "below": "低於平均", + "low": "低" }, - "findUnitsLink": "Go to Find Units to learn more", + "findUnitsLink": "前往 「尋找單位」 以了解更多資訊", "aboutAreaSection": { - "header": "About this area", - "readMoreButton": "READ MORE" + "header": "關於此區域", + "readMoreButton": "查看更多" }, "learnMoreSection": { - "subheader": "Learn more", - "websiteLink": "Website", + "subheader": "了解更多", + "websiteLink": "網站", "wikipediaLink": "Wikipedia", "googleLink": "Google" }, "unitsContent": { "step1": { - "stepNumber": "STEP 1", - "header": "Check your Budget", - "voucherCovers": "Your vouchers covers units up to", - "perMonth": "/ month", - "whatYouPay": "What you pay", - "yourPaymentDetail": "In most cases you pay no more than 30% of your income, plus utilities.", - "learnVouchersLink": "Learn more about vouchers", - "echoBenefits": "Your ECHO benefits", - "sdBrokerFee": "Security deposit and/or Broker’s Fee", - "movingExpenses": "Moving expenses", - "landlordIncentive": "Landlord incentive", - "learnEchoLink": "Learn more about ECHO" + "stepNumber": "步驟 1", + "header": "查看您的預算", + "voucherCovers": "您的房屋租賃券涵蓋單位的上限為", + "perMonth": "每月 ", + "whatYouPay": "您需支付", + "yourPaymentDetail": "在大多數情況下,您支付的金額不超過您收入的 30%,另加水電等公用事業費用。", + "learnVouchersLink": "了解更多關於房屋租賃券", + "echoBenefits": "您的 ECHO 補助", + "sdBrokerFee": "保證金和/或仲介費", + "movingExpenses": "搬遷費用", + "landlordIncentive": "房東獎勵金", + "learnEchoLink": "了解更多關於 ECHO 的資訊" }, "step2": { - "stepNumber": "STEP 2", - "header": "Find units you like", - "affordabilityCalculator": "Use the Affordability Calculator to check if a unit fits your budget", - "linkSubtext": "{{town}} {{zipcode}}, {{brCount}}br" + "stepNumber": "步驟 2", + "header": "尋找您喜歡的單位", + "affordabilityCalculator": "使用 可負擔能力計算器 查看該單位是否符合您的預算", + "linkSubtext": "{{town}} {{zipcode}}, {{brCount}}個臥室" }, "step3": { - "stepNumber": "STEP 3", + "stepNumber": "步驟 3", "header": "Found a unit? Use the Affordability Calculator to check if it’s in budget", "bodyText": "All Calculations are subject to a final BHA determination.", "linkSubtext": "Open Affordability Calculator" }, "step4": { - "stepNumber": "STEP 4", - "header": "Schedule a viewing and reach out to your ECHO Coordinator", + "stepNumber": "步驟 4", + "header": "安排參觀,並聯絡您的 ECHO 協調員", "bodyText": "Please have the unit address and Property Owner’s information ready.", - "coordinatorLink": "Contact your coordinator" + "coordinatorLink": "聯絡您的協調員" }, "unitsModal": { - "header": "will open in a new tab.", - "affordLinkTitle": "What can I afford?", - "affordLinkSubtitle": "See how much rent BHA will cover and learn about additional benefits", - "calculatorLinkTitle": "Can I afford this unit?", - "calculatorLinkSubtitle": "The BHA Affordability Calculator helps you estimate your copay." + "header": "將在新分頁中開啟。", + "affordLinkTitle": "我能負擔多少?", + "affordLinkSubtitle": "查看 波房局(BHA) 可補助的租金金額,並了解其他額外補助。", + "calculatorLinkTitle": "我能負擔這個單位嗎?", + "calculatorLinkSubtitle": "波房局(BHA) 可負擔能力計算器可 幫助您估算需自付的金額" } } }, "yourTrips": { - "heading": "Your Trips", + "heading": "您的行程", "subheading": "Commute times are estimates. Your actual commute times may vary based on your new address.", "busAndTrain": "Bus & Train", - "car": "Car", - "touchPrompt": "Select a trip to see directions on a map", - "editTrips": "Edit your trips", + "car": "汽車", + "touchPrompt": "選擇行程以在地圖上查看路線", + "editTrips": "編輯您的行程", "openInGoogle": "在谷歌地图中打开" }, "userProfile": { - "title": "发现社区", - "description": "创建个人资料,帮助我们向您推荐社区", + "title": "探索社區", + "description": "請先建立個人檔案,以便我們為您推薦合適的社區", "actionButton": "创建个人资料", "caption": "只要5分钟!", "wizard": { - "header": "您的资料", + "header": "您的個人檔案", "stepBedroom": { - "question": "How many bedrooms does your voucher have?", - "description": "如果您不确定,请联系BHA住房协调员。" + "question": "您的房屋租賃金券(Voucher)有包含幾間臥室?", + "description": "如果您不確定,請聯絡您的 波房局(BHA) 住房協調員。" }, "stepImportance": { - "question": "What is important to you?", - "commuteTime": "通勤时长", - "schoolQuality": "School Quality", - "publicSafety": "Public safety", - "notImportant": "Not important", - "veryImportant": "Very important" + "question": "對您來說什麼最重要?", + "commuteTime": "通勤時間", + "schoolQuality": "學校質素", + "publicSafety": "公共安全", + "notImportant": "不重要", + "veryImportant": "非常重要" }, "stepTravelMode": { - "question": "How do you typically get around?", - "toggleCar": "私家车", - "toggleTransit": "公交车/轨道交通", - "checkboxDescription": "The Commuter rail and express bus allow us to recommend more neighborhoods, but they usually cost more than the subway or local bus.", - "checkboxLabel": "I'm willing to take the express bus or commuter rail" + "question": "您通常如何四處走動?", + "toggleCar": "汽車", + "toggleTransit": "巴士/地鐵", + "checkboxDescription": "通勤鐵路和巴士快線可以讓我們推薦更多社區,但它們的收費通常比地鐵或當地巴士更高。", + "checkboxLabel": "我願意乘搭巴士快線或通勤鐵路" }, "button": { "continue": "继续", - "finish": "Finish" + "finish": "完成" } } }, "userTrip": { "wizard": { - "header": "Your trip", + "header": "您的行程", "stepAddTrip": { - "question": "Which trips do you make frequently?", - "description": "We use this information to recommend neighborhoods near the places you visit often", - "addATrip": "Add a trip", - "addAnotherTrip": "Add another trip", + "question": "您經常前往哪些地方?", + "description": "我們會使用這些資料,推薦您經常前往的地方鄰近的社區。", + "addATrip": "添加一個行程", + "addAnotherTrip": "增加另一個行程", "error": "You have destinations that are not valid, please remove and try again." }, "addNewTripModal": { "question": "Add new trip", - "purposeLabel": "What kind of place is it?", - "locationLabel": "Where is it?", - "locationPlaceholder": "Enter an address", + "purposeLabel": "那是什麼類型的場所?", + "locationLabel": "在哪裡?", + "locationPlaceholder": "請輸入地址", "finish": "Add trip" }, "button": { @@ -194,38 +194,44 @@ } }, "top10Tour": { - "next": "Next", - "details": "Details", - "prev": "Prev" + "header": "探索社區", + "subHeader": "推薦是根據您的個人檔案和所選行程而提供。", + "bodyText": "使用上方的按鈕編輯您的設定並新增篩選條件", + "showMyRecommendations": "顯示我的推薦", + "listNeighborhoods": "列出所有社區", + "showTopTen": "Show Top 10", + "next": "下一頁", + "details": "詳細資訊", + "prev": "前一頁" }, "filterModal": { - "dialogHeading": "Filter recommendations", - "profileEditHeading": "Your Profile", - "bedroom": "Bedroom", - "edit": "Edit", - "regionsFilterHeading": "Filter by region", - "regionsFilterSubHeading": "Select all regions you are interested in", - "otherFilterHeading": "Other filters", + "dialogHeading": "篩選推薦", + "profileEditHeading": "您的個人檔案", + "bedroom": "個臥室", + "edit": "編輯", + "regionsFilterHeading": "按區域篩選", + "regionsFilterSubHeading": "選擇您感興趣的所有區域", + "otherFilterHeading": "其他篩選條件", "regionMapCaption": "Based on a map by", - "echoLink": "Learn more about ECHO", - "regionsFilterLabel": "Filter by region selections", - "eccFilter": "Only recommend Expanded Choice Communities (ECC)", - "eccFilterDescription": "Moving to an ECC area could qualify you for financial assistance to help with your security deposit, broker fees, and moving expenses." + "echoLink": "了解更多關於 ECHO 的資訊", + "regionsFilterLabel": "按區域篩選", + "eccFilter": "僅推薦 擴大選擇社區(ECC)", + "eccFilterDescription": "搬到 ECC 區域 可能讓您有資格獲得經濟援助,以幫助支付保證金、仲介費和搬遷費用。" }, "editTripsModal": { - "dialogHeading": "Choose a trip", - "dialogSubHeading": "We recommend neighborhoods that are conveniently located.", - "trafficHeading": "Choose traffic conditions", - "travelModeHeading": "How do you usually get around?", - "peak": "Peak", - "offPeak": "Off-peak" + "dialogHeading": "選擇行程", + "dialogSubHeading": "我們推薦位置便利的社區。", + "trafficHeading": "選擇交通狀況", + "travelModeHeading": "您平時如何四處走動?", + "peak": "繁忙時段", + "offPeak": "非繁忙時段" }, - "searchModal": "Search the map", - "searchModalDescription": "Type a neighborhood name to find it on the map", - "searchModalPlaceholder": "Search neighborhoods", + "searchModal": "在地圖上搜尋", + "searchModalDescription": "輸入社區名稱以在地圖上尋找", + "searchModalPlaceholder": "搜尋社區", "comparePage": { "title": "Favorite Neighborhoods", - "subtitle": "Your Favorites", - "introDescription": "Add neighborhoods to your favorites to make them show up in the comparison." + "subtitle": "您的收藏", + "introDescription": "將社區加入您的收藏,使其顯示在比較中。" } } From 46b8de58dadf8c28dc1ac91bf03251355ecafcd9 Mon Sep 17 00:00:00 2001 From: Rachele Morino Date: Tue, 10 Mar 2026 15:02:16 -0400 Subject: [PATCH 4/6] Fix translation errors in frontend --- src/frontend/public/locales/en/translation.json | 6 +++--- src/frontend/public/locales/es/translation.json | 8 ++++---- src/frontend/public/locales/zh/translation.json | 6 +++--- src/frontend/src/components/EditFiltersModal.tsx | 2 +- .../src/components/EditWizard/StepTrips.tsx | 5 ++++- .../NeighborhoodCard/NeighborhoodCard.styles.ts | 13 +++++++++++-- .../NeighborhoodCard/NeighborhoodCard.tsx | 6 +++++- src/frontend/src/components/SchoolMeter.tsx | 7 ++++++- src/frontend/src/components/YourTrips/YourTrips.tsx | 2 +- .../src/components/base/Meter/Meter.styles.ts | 5 +++-- src/frontend/src/components/base/Meter/Meter.tsx | 11 ++++++++--- .../src/components/base/Range/Range.styles.ts | 2 +- src/frontend/src/components/base/Range/Range.tsx | 12 +++++++++--- .../src/libs/formatNeighborhoodDataByCard.ts | 6 +++--- .../src/pages/Discover/Profile/AddTripModal.tsx | 5 ++++- .../src/pages/NeighborhoodDetail/InfoContent.tsx | 8 ++------ 16 files changed, 68 insertions(+), 36 deletions(-) diff --git a/src/frontend/public/locales/en/translation.json b/src/frontend/public/locales/en/translation.json index 01a5096e..51504d31 100644 --- a/src/frontend/public/locales/en/translation.json +++ b/src/frontend/public/locales/en/translation.json @@ -45,7 +45,6 @@ "groupedCountZipCodes": "zip codes", "groupedLoadMore": "Load more", "eccBenefits": "ECC Benefits", - "commute": "Commute", "min": "min", "over2Hours": "Over 2 hr" }, @@ -68,8 +67,9 @@ "schoolChoice": "School choice options", "schoolsSafetyCard": { "header": "Schools & Safety", - "schoolsLabel": "Schools", - "safetyLabel": "Safety", + "schools": "Schools", + "safety": "Safety", + "commute": "Commute", "high": "High", "above": "Above Avg", "average": "Average", diff --git a/src/frontend/public/locales/es/translation.json b/src/frontend/public/locales/es/translation.json index e07de313..cdef249c 100644 --- a/src/frontend/public/locales/es/translation.json +++ b/src/frontend/public/locales/es/translation.json @@ -45,7 +45,6 @@ "groupedCountZipCodes": "códigos postales", "groupedLoadMore": "Mostrar más", "eccBenefits": "Beneficios ECC", - "commute": "Transporte", "min": "minutos", "over2Hours": "Over 2 hr" }, @@ -68,8 +67,9 @@ "schoolChoice": "School choice options", "schoolsSafetyCard": { "header": "Escuelas y Seguridad", - "schoolsLabel": "Escuelas", - "safetyLabel": "Seguridad", + "schools": "Escuelas", + "safety": "Seguridad", + "commute": "Transporte", "high": "Alto", "above": "Por encima del Promedio", "average": "Promedio", @@ -199,7 +199,7 @@ "bodyText": "Edita tus configuraciones y añade filtros usando los botones en la parte superior.", "showMyRecommendations": "Mostrar mis recomendaciones", "listNeighborhoods": "Lista de todos los vecindarios", - "showTopTen": "Mostrar 10 mejores", + "showTopTen": "Mostrar 10 Mejores", "next": "Siguiente", "details": "Detalles", "prev": "Anterior" diff --git a/src/frontend/public/locales/zh/translation.json b/src/frontend/public/locales/zh/translation.json index 347ae411..31b19b5d 100644 --- a/src/frontend/public/locales/zh/translation.json +++ b/src/frontend/public/locales/zh/translation.json @@ -45,7 +45,6 @@ "groupedCountZipCodes": "個郵政編", "groupedLoadMore": "載入更多", "eccBenefits": "擴大選擇社區(ECC)補助", - "commute": "通勤", "min": "分鐘", "over2Hours": "Over 2 hr" }, @@ -68,8 +67,9 @@ "schoolChoice": "School choice options", "schoolsSafetyCard": { "header": "學校與安全", - "schoolsLabel": "學校", - "safetyLabel": "安全", + "schools": "學校", + "safety": "安全", + "commute": "通勤", "high": "高", "above": "高於平均", "average": "平均", diff --git a/src/frontend/src/components/EditFiltersModal.tsx b/src/frontend/src/components/EditFiltersModal.tsx index 74368563..42ee5727 100644 --- a/src/frontend/src/components/EditFiltersModal.tsx +++ b/src/frontend/src/components/EditFiltersModal.tsx @@ -149,7 +149,7 @@ const EditFiltersModal = ({ isMobile = false }) => { customImageClassName="w-full" customCaption={ <> - CC BY-SA 3.0. $ + CC BY-SA 3.0.{" "} {t("filterModal.regionMapCaption")}{" "}

- {destination.purpose} + {t([ + "destinationPurposes." + + destination.purpose, + ])}

{destination.location.label} diff --git a/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.styles.ts b/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.styles.ts index 60947a28..edc0c6b6 100644 --- a/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.styles.ts +++ b/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.styles.ts @@ -13,8 +13,9 @@ export const cardStyles = tv({ zip: "text-rg text-gray-500", tagsContainer: "flex flex-wrap gap-2", tag: " h-[21px] flex items-center gap-2 rounded-[var(--spacing-2)] border border-gray-300 px-2 py-1 text-xs font-bold text-[#006512]", - statsContainer: "flex flex-start gap-5 self-stretch -mt-2", - statItem: "flex flex-1 flex-col px-0 py-3 align-start", + statsContainer: + "flex flex-start gap-5 self-stretch -mt-2 overflow-hidden", + statItem: "flex flex-1 max-w-[33.33%] flex-col px-0 py-3 align-start", navContainer: "flex align-center self-stretch gap-3 border-t border-gray-300 p-3 bg-gray-100", }, @@ -37,5 +38,13 @@ export const cardStyles = tv({ root: "relative", }, }, + isPopup: { + true: { + root: "w-fit", + }, + false: { + root: "w-auto", + }, + }, }, }); diff --git a/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.tsx b/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.tsx index 5a296d09..c9b2f2b3 100644 --- a/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.tsx +++ b/src/frontend/src/components/NeighborhoodCard/NeighborhoodCard.tsx @@ -58,7 +58,11 @@ const NeighborhoodCard = ({ statsContainer, statItem, navContainer, - } = cardStyles({ hasImage: !!imageUrl, ...listViewStyling }); + } = cardStyles({ + hasImage: !!imageUrl, + isPopup: isPopup, + ...listViewStyling, + }); const { t } = useTranslation(); const hasTag = isTopTen || hasECC; diff --git a/src/frontend/src/components/SchoolMeter.tsx b/src/frontend/src/components/SchoolMeter.tsx index da18c294..5f86979f 100644 --- a/src/frontend/src/components/SchoolMeter.tsx +++ b/src/frontend/src/components/SchoolMeter.tsx @@ -29,7 +29,12 @@ const SchoolMeter = ({ return isSchoolChoice ? (

- {props.label} + + {t([ + "neighborhoodDetail.schoolsSafetyCard." + + props.labelKey, + ])} +
[ ...tripsFromDest, { - title: dest.purpose, + title: t(["destinationPurposes." + dest.purpose]), subtitle: dest.location.label, neighborhoodZipcode: activeNeighborhood ?? "", destination: dest, diff --git a/src/frontend/src/components/base/Meter/Meter.styles.ts b/src/frontend/src/components/base/Meter/Meter.styles.ts index 4119ff41..414c56bf 100644 --- a/src/frontend/src/components/base/Meter/Meter.styles.ts +++ b/src/frontend/src/components/base/Meter/Meter.styles.ts @@ -3,9 +3,10 @@ import { tv } from "tailwind-variants"; export const meterStyles = tv({ slots: { root: "flex flex-col gap-3 w-full ", - labelContainer: "flex flex-col", + labelContainer: "flex flex-col w-full", mainLabel: "text-sm text-gray-600", - valueLabel: "text-sm font-bold text-black -mt-1 mb-[1px] text-nowrap", + valueLabel: + "text-sm font-bold text-black -mt-1 mb-[1px] text-nowrap truncate", track: "absolute top-1 h-1 w-full rounded-[var(--spacing-1)] bg-gray-300", fill: "absolute h-[6px] rounded-[var(--spacing-1)]", thumb: "absolute rounded-[var(--spacing-1)] top-[3px] h-4 w-2 -translate-y-1/2 left-[calc(50%-2px)] bg-gray-500 border border-white", diff --git a/src/frontend/src/components/base/Meter/Meter.tsx b/src/frontend/src/components/base/Meter/Meter.tsx index e105bbb4..b3d9ba9d 100644 --- a/src/frontend/src/components/base/Meter/Meter.tsx +++ b/src/frontend/src/components/base/Meter/Meter.tsx @@ -10,7 +10,7 @@ import { meterStyles } from "./Meter.styles"; type MeterStatus = "Low" | "Below Avg" | "Average" | "Above Avg" | "High"; export interface MeterProps extends AriaMeterProps { - label: string; + labelKey: string; showCategory?: boolean; } @@ -22,7 +22,7 @@ const getStatusFromValue = (value: number): MeterStatus => { return "High"; }; -const Meter = ({ label, showCategory = false, ...props }: MeterProps) => { +const Meter = ({ labelKey, showCategory = false, ...props }: MeterProps) => { const { t } = useTranslation(); const status = getStatusFromValue(props.value ?? 0); const { root, labelContainer, mainLabel, valueLabel, track, fill, thumb } = @@ -35,7 +35,12 @@ const Meter = ({ label, showCategory = false, ...props }: MeterProps) => { {({ percentage }) => ( <>
- {label} + + {t([ + "neighborhoodDetail.schoolsSafetyCard." + + labelKey, + ])} + {showCategory && ( {t([ diff --git a/src/frontend/src/components/base/Range/Range.styles.ts b/src/frontend/src/components/base/Range/Range.styles.ts index a780aeeb..51154a92 100644 --- a/src/frontend/src/components/base/Range/Range.styles.ts +++ b/src/frontend/src/components/base/Range/Range.styles.ts @@ -4,7 +4,7 @@ export const rangeStyles = tv({ slots: { root: "flex flex-col gap-3 w-full", labelContainer: "flex flex-col max-w-[80px]", - mainLabel: "text-sm text-gray-600", + mainLabel: "text-sm text-gray-600 truncate", rangeLabel: "text-sm font-bold text-black truncate", track: "absolute top-1 h-1 w-full rounded-[var(--spacing-1)] bg-gray-300", fill: "flex flex-row justify-end absolute h-[6px] rounded-[var(--spacing-1)] bg-gray-500", diff --git a/src/frontend/src/components/base/Range/Range.tsx b/src/frontend/src/components/base/Range/Range.tsx index 635bc288..a9ca9493 100644 --- a/src/frontend/src/components/base/Range/Range.tsx +++ b/src/frontend/src/components/base/Range/Range.tsx @@ -7,7 +7,7 @@ const MIN_DEFAULT = 0; const MAX_DEFAULT = 120; export interface RangeProps { - label?: string; + labelKey?: string; start: number; end: number; className?: string; @@ -16,7 +16,7 @@ export interface RangeProps { } const Range = ({ - label, + labelKey, start, end, className, @@ -42,7 +42,13 @@ const Range = ({ return (
- {label && {label}} + {labelKey && ( + + {t([ + "neighborhoodDetail.schoolsSafetyCard." + labelKey, + ])} + + )} {rangeText}
diff --git a/src/frontend/src/libs/formatNeighborhoodDataByCard.ts b/src/frontend/src/libs/formatNeighborhoodDataByCard.ts index c640d93a..f9526d72 100644 --- a/src/frontend/src/libs/formatNeighborhoodDataByCard.ts +++ b/src/frontend/src/libs/formatNeighborhoodDataByCard.ts @@ -67,7 +67,7 @@ const formatNeighborhoodDataByCard = ( const stats = { schools: { - label: "Schools", + labelKey: "schools", value: neighborhoodDetail.education_percentile ?? undefined, showCategory: true, isBoston: isNeighborhoodBostonTownArea( @@ -76,12 +76,12 @@ const formatNeighborhoodDataByCard = ( isSchoolChoice: neighborhoodDetail.school_choice, }, safety: { - label: "Safety", + labelKey: "safety", value: neighborhoodDetail.crime_percentile ?? undefined, showCategory: true, }, commute: { - label: "Commute", + labelKey: "commute", start: neighborhoodDetail.commutes[activeDestination].commuteMin, end: neighborhoodDetail.commutes[activeDestination].commuteMax, }, diff --git a/src/frontend/src/pages/Discover/Profile/AddTripModal.tsx b/src/frontend/src/pages/Discover/Profile/AddTripModal.tsx index 2754d3e8..d12cdbbb 100644 --- a/src/frontend/src/pages/Discover/Profile/AddTripModal.tsx +++ b/src/frontend/src/pages/Discover/Profile/AddTripModal.tsx @@ -129,7 +129,10 @@ const AddTripModal = ({ className={`${buttonStyles({ variant: "outline" })} w-full h-full rounded-lg !p-4 justify-items-center ${isSelected ? "border-2 border-teal-600" : "border-2 border-gray-300"}`} >

- {item.name} + {t([ + "destinationPurposes." + + item.name, + ])}

)} diff --git a/src/frontend/src/pages/NeighborhoodDetail/InfoContent.tsx b/src/frontend/src/pages/NeighborhoodDetail/InfoContent.tsx index ea628e65..2ef050d1 100644 --- a/src/frontend/src/pages/NeighborhoodDetail/InfoContent.tsx +++ b/src/frontend/src/pages/NeighborhoodDetail/InfoContent.tsx @@ -149,9 +149,7 @@ const InfoContent = ({
From ccf51c576e35cff75a91c3ea50e4016a35aee98f Mon Sep 17 00:00:00 2001 From: Rachele Morino Date: Wed, 11 Mar 2026 16:27:23 -0400 Subject: [PATCH 5/6] Update Components page following type updates --- src/frontend/src/pages/Components.tsx | 52 +++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/frontend/src/pages/Components.tsx b/src/frontend/src/pages/Components.tsx index f0df9779..2ad239e3 100644 --- a/src/frontend/src/pages/Components.tsx +++ b/src/frontend/src/pages/Components.tsx @@ -41,15 +41,15 @@ const tags = { const stats = { schools: { - label: "Schools", + labelKey: "schools", value: 25, showCategory: true, isBoston: false, isSchoolChoice: false, }, - safety: { label: "Safety", value: 75, showCategory: true }, + safety: { labelKey: "safety", value: 75, showCategory: true }, commute: { - label: "Commute", + labelKey: "commute", start: 10, end: 25, }, @@ -402,38 +402,38 @@ const Components = () => {

Criteria

- - - - - + + + + +

Criteria

- - - - - + + + + +

Car

- - - - - + + + + +

Transit

- - - - - - - - + + + + + + + +
From ba7786bd89a7880609023223a50955b72967afef Mon Sep 17 00:00:00 2001 From: Rachele Morino Date: Wed, 11 Mar 2026 20:30:07 -0400 Subject: [PATCH 6/6] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcad9fd4..28871000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add client feedback copy updates [#793](https://github.com/azavea/echo-locator/pull/793) - Add transit routing architecture ADR [#804](https://github.com/azavea/echo-locator/pull/804) - Add neighborhood csv submission instructions [#801](https://github.com/azavea/echo-locator/pull/801) +- Add Spanish and Mandarin translations [#807](https://github.com/azavea/echo-locator/pull/807) ### Changed