diff --git a/packages/core-utils/src/index.ts b/packages/core-utils/src/index.ts index 5ce856f76..79cfb3db6 100644 --- a/packages/core-utils/src/index.ts +++ b/packages/core-utils/src/index.ts @@ -7,6 +7,7 @@ import * as route from "./route"; import * as storage from "./storage"; import * as time from "./time"; import * as ui from "./ui"; +import * as metricUnits from "./metricUnits"; import * as queryGen from "./query-gen"; const core = { @@ -19,6 +20,7 @@ const core = { route, storage, time, + metricUnits, ui }; diff --git a/packages/core-utils/src/metricUnits.ts b/packages/core-utils/src/metricUnits.ts new file mode 100644 index 000000000..07431e5ee --- /dev/null +++ b/packages/core-utils/src/metricUnits.ts @@ -0,0 +1,43 @@ +// Reference: https://en.wikipedia.org/wiki/Mile +// While most countries abandoned the mile when switching to the metric system, +// the international mile continues to be used in some countries, such as Liberia, +// Myanmar, the United Kingdom and the United States. It is also used in a number +// of territories with less than a million inhabitants, most of which are UK or US territories, +// or have close historical ties with the UK or US: American Samoa, Bahamas, Belize, +// British Virgin Islands, Cayman Islands, Dominica, Falkland Islands, Grenada,Guam, +// The N. Mariana Islands, Samoa, St. Lucia, St. Vincent & The Grenadines, St. Helena, +// St. Kitts & Nevis, the Turks & Caicos Islands, and the US Virgin Islands. +// The mile is even encountered in Canada, though this is predominantly in rail transport +// and horse racing, as the roadways have been metricated since 1977. + +export const areMetricUnitsUsed = (locale: string): boolean => { + const localesUsingImperialUnits = [ + "en-US", + "en-GB", + "en-LR", + "en-AS", + "sm-AS", + "en-BS", + "en-BZ", + "es-BZ", + "en-VG", + "en-KY", + "en-DM", + "en-GD", + "en-GU", + "en-MP", + "en-WS", + "sm-WS", + "en-LC", + "en-VC", + "en-SH", + "en-KN", + "en-TC", + "en-VI", + "my-MM" + ]; + + return !localesUsingImperialUnits.includes(locale); +}; + +export default areMetricUnitsUsed; diff --git a/packages/itinerary-body/i18n/es.yml b/packages/itinerary-body/i18n/es.yml index 623a44ba6..787b09271 100644 --- a/packages/itinerary-body/i18n/es.yml +++ b/packages/itinerary-body/i18n/es.yml @@ -10,30 +10,27 @@ otpUi: vehicleType: bike: la bicicleta bikeshare: la bicicleta compartida - car: el carro - escooter: la patineta + car: el coche + escooter: el patín vehicle: el vehículo - walkVehicle: Caminar vehículo por la {place} + walkVehicle: Conduzca el vehículo por {place} TncLeg: bookRide: Reservar un viaje - bookRideLater: Espere hasta las {timeMillis, time, short} para reservar + bookRideLater: Espera hasta las {timeMillis, time, short} para reservar estimatedCost: "Costo estimado: {minFare} - {maxFare}" - estimatedTravelTime: "Tiempo de viaje estimado: {duration} (no tiene en cuenta - el tráfico)" - waitForPickup: "Espera al conductor {company}{minutes, plural, =0 {} other { - # minutos}}" + estimatedTravelTime: "Tiempo de viaje estimado: {duration} (no tiene en cuenta el tráfico)" + waitForPickup: "Espera al conductor {company}{minutes, plural, =0 {} other { # minutos}}" mapillaryTooltip: Mostrar imágenes de la calle en esta ubicación step: - circleClockwise: Siga el círculo en el sentido de las agujas del reloj - circleCounterClockwise: Siga el círculo en sentido contrario a las agujas del - reloj - continue: Continuar - enterStation: Entrar a la estación - exitStation: Salir de la estación - hardLeft: Giro a la izquierda - hardRight: Giro a la derecha - left: Vire a la izquierda - right: Vire a la derecha + circleClockwise: Sigue el círculo en el sentido de las agujas del reloj + circleCounterClockwise: Sigue el círculo en sentido contrario a las agujas del reloj + continue: Continua + enterStation: Entra en la estación + exitStation: Sal de la estación + hardLeft: Turce a la izquierda + hardRight: Tuerce a la derecha + left: Gira a la izquierda + right: Gira a la derecha slightlyLeft: Ligeramente a la izquierda slightlyRight: Ligeramente a la derecha uTurnLeft: Media vuelta a la izquierda @@ -52,15 +49,15 @@ otpUi: southwest: el suroeste west: el oeste stepStation: "{step} en {street}" - summary: "{mode} a {place}" - summaryAndDistance: "{mode} - {distance} a {place}" + summary: "{mode} hacia {place}" + summaryAndDistance: "{mode} {distance} hacia {place}" summaryMode: bike: Bicicleta bikeshare: Bicicleta compartida carDrive: Coche carHail: Paseo - escooter: Patineta - walk: Caminar + escooter: Patín + walk: Camine unnamedPath: Sendero sin nombre unnamedRoad: Calle sin nombre vehicleTitle: "{vehicleType} {company}" @@ -68,13 +65,12 @@ otpUi: bike: Bicicleta bikeshare: Bicicleta compartida car: Coche - escooter: Patineta + escooter: Patín vehicle: Vehículo ItineraryBody: common: durationShort: "{hours, plural, =0 {} other {# hr. }}{minutes} min" - flexAdvanceNotice: " al menos {leadDays, plural, one {# día} other {# días}} de - antelación" + flexAdvanceNotice: " al menos {leadDays, plural, one {# día} other {# días}} de antelación" flexCallAhead: llama con anticipación flexCallNumber: llama {phoneNumber} flexPickupMessage: Para tomar esta ruta, tiene que {action}{advanceNotice}. @@ -85,13 +81,13 @@ otpUi: car: en carro escooter: en patineta walk: a pie - viewOnMap: Ver en el mapa tripAccessibility: inaccessible: inaccesible - unclear: desconocido - legAccessibility: 'Accesibilidad para sillas de ruedas en este tramo del viaje: ' + itineraryAccessibility: "Accesibilidad para sillas de ruedas en este viaje: " + legAccessibility: "Accesibilidad para sillas de ruedas en este tramo del viaje: " likelyAccessible: probablemente accesible - itineraryAccessibility: 'Accesibilidad para sillas de ruedas en este viaje: ' + unclear: desconocido + viewOnMap: Ver en el mapa TransitLegBody: AlertsBody: effectiveDate: A partir de {dateTime, date, long} diff --git a/packages/itinerary-body/src/defaults/access-leg-description.tsx b/packages/itinerary-body/src/defaults/access-leg-description.tsx index 19ae3c1de..3e92f4ea5 100644 --- a/packages/itinerary-body/src/defaults/access-leg-description.tsx +++ b/packages/itinerary-body/src/defaults/access-leg-description.tsx @@ -1,3 +1,4 @@ +import coreUtils from "@opentripplanner/core-utils"; import { humanizeDistanceString } from "@opentripplanner/humanize-distance"; import { Config, Leg } from "@opentripplanner/types"; import React, { HTMLAttributes, ReactElement } from "react"; @@ -98,8 +99,11 @@ export default function AccessLegDescription({ description="Summarizes an access leg, including distance" id="otpUi.AccessLegBody.summaryAndDistance" values={{ - // TODO: Implement metric vs imperial (up until now it's just imperial). - distance: humanizeDistanceString(leg.distance, false, intl), + distance: humanizeDistanceString( + leg.distance, + coreUtils.metricUnits.areMetricUnitsUsed(intl.locale), + intl + ), mode: modeContent, place: placeContent }} diff --git a/packages/itinerary-body/src/defaults/access-leg-step.tsx b/packages/itinerary-body/src/defaults/access-leg-step.tsx index d76b60591..3150ee2a3 100644 --- a/packages/itinerary-body/src/defaults/access-leg-step.tsx +++ b/packages/itinerary-body/src/defaults/access-leg-step.tsx @@ -1,5 +1,6 @@ /* eslint-disable no-case-declarations */ import { Step } from "@opentripplanner/types"; +import coreUtils from "@opentripplanner/core-utils"; import React, { HTMLAttributes, ReactElement } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import { humanizeDistanceString } from "@opentripplanner/humanize-distance"; @@ -104,10 +105,13 @@ export default function AccessLegStep({ // for styled-components support. {stepContent} - {/* TODO: Implement metric vs imperial (up until now it's just imperial). */} {step?.distance > 0 && ( - {humanizeDistanceString(step.distance, false, intl)} + {humanizeDistanceString( + step.distance, + coreUtils.metricUnits.areMetricUnitsUsed(intl.locale), + intl + )} )} diff --git a/packages/location-field/src/options.tsx b/packages/location-field/src/options.tsx index 44527ef8a..6dce447ef 100644 --- a/packages/location-field/src/options.tsx +++ b/packages/location-field/src/options.tsx @@ -1,7 +1,8 @@ -import { humanizeDistanceStringImperial } from "@opentripplanner/humanize-distance"; +import { humanizeDistanceString } from "@opentripplanner/humanize-distance"; import { Stop, UserLocation } from "@opentripplanner/types"; +import coreUtils from "@opentripplanner/core-utils"; import React from "react"; -import { IntlShape } from "react-intl"; +import { IntlShape, useIntl } from "react-intl"; import { Bus } from "@styled-icons/fa-solid/Bus"; import { Briefcase } from "@styled-icons/fa-solid/Briefcase"; import { Home } from "@styled-icons/fa-solid/Home"; @@ -118,12 +119,17 @@ export function TransitStopOption({ stop: Stop; stopOptionIcon: React.ReactNode; }): React.ReactElement { + const intl = useIntl(); return ( {stopOptionIcon} - {humanizeDistanceStringImperial(stop.dist, true)} + {humanizeDistanceString( + stop.dist, + coreUtils.metricUnits.areMetricUnitsUsed(intl.locale), + intl + )} diff --git a/yarn.lock b/yarn.lock index 886be9fff..1efbb8130 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3246,6 +3246,11 @@ resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== +"@opentripplanner/types@6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@opentripplanner/types/-/types-6.4.0.tgz#6f7a3475ea982c7b7d8b2f1383a6d775dfabe62a" + integrity sha512-PS+CUwETLf0WzAUZg3qiey+SBigaf0CfknKF1XMOM+zJVc2c8nN34hgnwV7sS+RKs030KZFAgIn8p035ErcBuQ== + "@peculiar/asn1-schema@^2.1.6", "@peculiar/asn1-schema@^2.3.0": version "2.3.3" resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz#21418e1f3819e0b353ceff0c2dad8ccb61acd777"