From e3219aefca0dd4b6423b018b3245d250abd8b8fe Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:33:29 -0500 Subject: [PATCH 01/46] Pass "renderOtherFirst" config item to LocationFields --- example-config.yml | 3 +++ lib/components/app/batch-routing-panel.tsx | 8 +++++++- lib/components/mobile/batch-search-screen.tsx | 18 ++++++++++++++++-- lib/components/mobile/welcome-screen.tsx | 14 ++++++++++++-- 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/example-config.yml b/example-config.yml index d132b835e..232839897 100644 --- a/example-config.yml +++ b/example-config.yml @@ -179,6 +179,9 @@ map: # geocoder test account can be obtained from the Pelias maintainers at geocode.earth. geocoder: apiKey: PELIAS_API_KEY + # When set to true, geocoder results will be displayed with the "Other" section first, + # above transit stops and stations + renderOtherFirst: false boundary: rect: minLon: -123.2034 diff --git a/lib/components/app/batch-routing-panel.tsx b/lib/components/app/batch-routing-panel.tsx index c1321091e..5e2a02eef 100644 --- a/lib/components/app/batch-routing-panel.tsx +++ b/lib/components/app/batch-routing-panel.tsx @@ -16,6 +16,7 @@ interface Props { activeSearch: any intl: IntlShape mobile?: boolean + renderOtherFirst?: boolean showUserSettings: boolean } @@ -34,7 +35,8 @@ class BatchRoutingPanel extends Component { } render() { - const { activeSearch, intl, mobile, showUserSettings } = this.props + const { activeSearch, intl, mobile, renderOtherFirst, showUserSettings } = + this.props const { planTripClicked } = this.state const mapAction = mobile ? intl.formatMessage({ @@ -71,6 +73,7 @@ class BatchRoutingPanel extends Component { )} isRequired locationType="from" + renderOtherFirst={renderOtherFirst} selfValidate={planTripClicked} showClearButton={!mobile} /> @@ -81,6 +84,7 @@ class BatchRoutingPanel extends Component { )} isRequired locationType="to" + renderOtherFirst={renderOtherFirst} selfValidate={planTripClicked} showClearButton={!mobile} /> @@ -115,8 +119,10 @@ const mapStateToProps = (state: any) => { getShowUserSettings(state) && (state.user.loggedInUser?.hasConsentedToTerms || getPersistenceMode(state.otp.config.persistence).isLocalStorage) + const { renderOtherFirst } = state.otp.config.geocoder return { activeSearch: getActiveSearch(state), + renderOtherFirst, showUserSettings } } diff --git a/lib/components/mobile/batch-search-screen.tsx b/lib/components/mobile/batch-search-screen.tsx index 930112a88..99b632439 100644 --- a/lib/components/mobile/batch-search-screen.tsx +++ b/lib/components/mobile/batch-search-screen.tsx @@ -17,6 +17,7 @@ const { SET_FROM_LOCATION, SET_TO_LOCATION } = MobileScreens interface Props { intl: IntlShape map: React.ReactElement + renderOtherFirst: boolean setMobileScreen: (screen: number) => void } @@ -34,7 +35,7 @@ class BatchSearchScreen extends Component { } render() { - const { intl } = this.props + const { intl, renderOtherFirst } = this.props const { planTripClicked } = this.state return ( @@ -52,6 +53,7 @@ class BatchSearchScreen extends Component { isRequired locationType="from" onTextInputClick={this._fromFieldClicked} + renderOtherFirst={renderOtherFirst} selfValidate={planTripClicked} showClearButton={false} /> @@ -62,6 +64,7 @@ class BatchSearchScreen extends Component { isRequired locationType="to" onTextInputClick={this._toFieldClicked} + renderOtherFirst={renderOtherFirst} selfValidate={planTripClicked} showClearButton={false} /> @@ -85,4 +88,15 @@ const mapDispatchToProps = { setMobileScreen: uiActions.setMobileScreen } -export default connect(null, mapDispatchToProps)(injectIntl(BatchSearchScreen)) +const mapStateToProps = (state: any) => { + const { renderOtherFirst } = state.otp.config.geocoder + + return { + renderOtherFirst + } +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(injectIntl(BatchSearchScreen)) diff --git a/lib/components/mobile/welcome-screen.tsx b/lib/components/mobile/welcome-screen.tsx index 9a3492407..484eae79b 100644 --- a/lib/components/mobile/welcome-screen.tsx +++ b/lib/components/mobile/welcome-screen.tsx @@ -12,10 +12,11 @@ import MobileContainer from './container' import MobileNavigationBar from './navigation-bar' interface Props { + renderOtherFirst: boolean setMobileScreen: (screen: number) => void } -const MobileWelcomeScreen = ({ setMobileScreen }: Props) => { +const MobileWelcomeScreen = ({ renderOtherFirst, setMobileScreen }: Props) => { const intl = useIntl() const toFieldClicked = useCallback( @@ -38,6 +39,7 @@ const MobileWelcomeScreen = ({ setMobileScreen }: Props) => { })} locationType="to" onTextInputClick={toFieldClicked} + renderOtherFirst={renderOtherFirst} showClearButton={false} /> @@ -56,4 +58,12 @@ const mapDispatchToProps = { setMobileScreen: uiActions.setMobileScreen } -export default connect(null, mapDispatchToProps)(MobileWelcomeScreen) +const mapStateToProps = (state: any) => { + const { renderOtherFirst } = state.otp.config.geocoder + + return { + renderOtherFirst + } +} + +export default connect(mapStateToProps, mapDispatchToProps)(MobileWelcomeScreen) From ab685cb0ae273da666e6205fae6ac51a9a28daf5 Mon Sep 17 00:00:00 2001 From: Cyprien Huissoud Date: Fri, 27 Sep 2024 10:21:59 +0200 Subject: [PATCH 02/46] replace hardcoded 'node_modules' path --- lib/util/i18n.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/util/i18n.js b/lib/util/i18n.js index 6f210c071..b17e001a6 100644 --- a/lib/util/i18n.js +++ b/lib/util/i18n.js @@ -97,8 +97,9 @@ async function loadOtpUiLocaleData(matchedLocale) { .filter((pkg) => pkg.startsWith('@opentripplanner')) .map(async (pkg) => { try { + const packagePath = pkg.replace('@opentripplanner/', '') const msgs = await import( - `../../node_modules/${pkg}/i18n/${matchedLocale}.yml` + `@opentripplanner/${packagePath}/i18n/${matchedLocale}.yml` ) if (msgs) return msgs.default } catch (ex) { From 3112eae8c3208d860f8ff9f4c0400971e8f9a796 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Tue, 22 Oct 2024 10:18:36 -0400 Subject: [PATCH 03/46] sync departArrive in calltaker as well --- .../form/call-taker/date-time-picker.tsx | 35 +++++++++++++++++-- lib/components/form/date-time-modal.tsx | 4 +-- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/components/form/call-taker/date-time-picker.tsx b/lib/components/form/call-taker/date-time-picker.tsx index 282c104cc..ea310ef99 100644 --- a/lib/components/form/call-taker/date-time-picker.tsx +++ b/lib/components/form/call-taker/date-time-picker.tsx @@ -7,6 +7,10 @@ import { OverlayTrigger, Tooltip } from 'react-bootstrap' import coreUtils from '@opentripplanner/core-utils' import React, { useEffect, useRef, useState } from 'react' +import * as narriativeActions from '../../../actions/narrative' +import { DepartArriveTypeMap, DepartArriveValue } from '../date-time-modal' +import { FilterType, SortType } from '../../../util/state-types' + const { getCurrentDate, OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } = coreUtils.time @@ -80,8 +84,11 @@ type Props = { departArrive: string time: string }) => void + sort: SortType + syncSortWithDepartArrive?: boolean time?: string timeFormat: string + updateItineraryFilter: (payload: FilterType) => void } /** * Contains depart/arrive selector and time/date inputs for the admin-oriented @@ -103,8 +110,11 @@ const DateTimeOptions = ({ homeTimezone, onKeyDown, setQueryParam, + sort, + syncSortWithDepartArrive, time: initialTime, - timeFormat + timeFormat, + updateItineraryFilter }: Props) => { const [departArrive, setDepartArrive] = useState( initialDate || initialTime ? 'DEPART' : 'NOW' @@ -187,6 +197,18 @@ const DateTimeOptions = ({ }) }) } + + if ( + syncSortWithDepartArrive && + DepartArriveTypeMap[departArrive as DepartArriveValue] !== sort.type + ) { + updateItineraryFilter({ + sort: { + ...sort, + type: DepartArriveTypeMap[departArrive as DepartArriveValue] + } + }) + } }, [dateTime, departArrive, homeTimezone, setQueryParam]) // Handler for updating the time and date fields when NOW is selected @@ -283,11 +305,18 @@ const DateTimeOptions = ({ // connect to the redux store const mapStateToProps = (state: any) => { - const { dateTime, homeTimezone } = state.otp.config + const { dateTime, homeTimezone, itinerary } = state.otp.config + const { syncSortWithDepartArrive } = itinerary + const { sort } = state.otp.filter return { homeTimezone, + sort, + syncSortWithDepartArrive, timeFormat: dateTime?.timeFormat || 'h:mm a' } } +const mapDispatchToProps = { + updateItineraryFilter: narriativeActions.updateItineraryFilter +} -export default connect(mapStateToProps)(DateTimeOptions) +export default connect(mapStateToProps, mapDispatchToProps)(DateTimeOptions) diff --git a/lib/components/form/date-time-modal.tsx b/lib/components/form/date-time-modal.tsx index e9f31407b..bd7082eef 100644 --- a/lib/components/form/date-time-modal.tsx +++ b/lib/components/form/date-time-modal.tsx @@ -21,9 +21,9 @@ type Props = { updateItineraryFilter: (payload: FilterType) => void } -type DepartArriveValue = 'NOW' | 'DEPART' | 'ARRIVE' +export type DepartArriveValue = 'NOW' | 'DEPART' | 'ARRIVE' -const DepartArriveTypeMap: Record< +export const DepartArriveTypeMap: Record< DepartArriveValue, FilterType['sort']['type'] > = { From 2128ad7da9fe16741505a7e4d641cc63cdc232f3 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Wed, 30 Oct 2024 12:14:02 -0400 Subject: [PATCH 04/46] support naming and keying transit vehicle overlay --- lib/components/map/default-map.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/components/map/default-map.tsx b/lib/components/map/default-map.tsx index 5548f8171..99caa0490 100644 --- a/lib/components/map/default-map.tsx +++ b/lib/components/map/default-map.tsx @@ -318,6 +318,10 @@ class DefaultMap extends Component { const baseLayerUrls = baseLayersWithNames?.map((bl) => bl.url) const baseLayerNames = baseLayersWithNames?.map((bl) => bl.name) + const routeBasedTransitVehicleOverlayNameOverride = overlays.find( + (o) => o.type === 'vehicles-one-route' + )?.name + return ( - + { getCurrentPosition(intl) From 0b2a585d33a25d71fe4191999edea10eb56d082e Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:39:56 -0600 Subject: [PATCH 05/46] fix(pattern-viewer): fix gap in pattern buttons --- lib/components/viewers/styled.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/viewers/styled.ts b/lib/components/viewers/styled.ts index 5509975be..9e0131c07 100644 --- a/lib/components/viewers/styled.ts +++ b/lib/components/viewers/styled.ts @@ -50,7 +50,7 @@ export const PatternContainer = styled.div` & > span { width: 85%; - button { + button#headsign-selector-label { align-items: center; display: flex; justify-content: space-between; From 04d63c3996466a88ba67a867ea49fcdae7291728 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:42:40 -0600 Subject: [PATCH 06/46] Fix clipping on loading spinner in narrative itineraries --- lib/components/narrative/loading.tsx | 2 +- lib/components/narrative/styled.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/components/narrative/loading.tsx b/lib/components/narrative/loading.tsx index 6761eeae4..9b4749382 100644 --- a/lib/components/narrative/loading.tsx +++ b/lib/components/narrative/loading.tsx @@ -10,7 +10,7 @@ type Props = { const Loading = ({ extraSmall, small }: Props): JSX.Element => { return ( -
+
diff --git a/lib/components/narrative/styled.js b/lib/components/narrative/styled.js index 9ca966693..8381eef24 100644 --- a/lib/components/narrative/styled.js +++ b/lib/components/narrative/styled.js @@ -14,6 +14,11 @@ export const NarrativeItinerariesContainer = styled.div` display: flex; flex-direction: column; height: 100%; + + // Prevent the loading spinner from clipping the top of the container + .loading-container { + margin-top: 25px; + } ` export const ULContainer = styled.ul` From 1d1cd5ea9718b86666253d4a3b9d2d2d8e98e504 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Wed, 6 Nov 2024 11:46:56 -0600 Subject: [PATCH 07/46] Fix navbar spacing and positioning --- index.css | 1 - lib/components/app/app.css | 68 ++++++++++++++++++++++++ lib/components/app/desktop-nav.tsx | 28 ++++------ lib/components/app/nav-item.tsx | 4 -- lib/components/app/view-switcher.tsx | 15 +----- lib/components/mobile/mobile.css | 9 +--- lib/components/user/nav-login-button.css | 5 -- 7 files changed, 79 insertions(+), 51 deletions(-) diff --git a/index.css b/index.css index 697d3b1b6..94a39b976 100644 --- a/index.css +++ b/index.css @@ -31,7 +31,6 @@ input[type="text"]::-ms-clear { height: 15px; justify-content: space-between; padding: 0; - position: absolute; top: 16px; transition: all 1s ease; width: 21px; diff --git a/lib/components/app/app.css b/lib/components/app/app.css index 87fe44222..efadb689d 100644 --- a/lib/components/app/app.css +++ b/lib/components/app/app.css @@ -47,6 +47,74 @@ } } +/* Navbar settings */ + +.navbar .navbar-header { + display: grid; + grid-template-columns: 300px auto 150px; +} + +.navbar .navbar-nav { + margin: 0; + grid-column: 3; +} + +.navbar .navbar-brand { + display: flex; + gap: 35px; + align-items: center; + grid-column: 1 / span 1; + width: 100%; +} + +@media (min-width: 992px) { + #view-switcher { + height: 100%; + left: 0; + position: absolute; + width: 100% + } +} + + +@media (max-width: 768px) { + .navbar .navbar-header { + grid-template-columns: 50px auto 50px; + width: auto !important; + } + + .navbar .navbar-brand { + grid-column: 1 / span 2; + gap: 15px; + padding: 10px; + } + + #view-switcher { + position: relative; + } + +} + +/* Mobile navbar */ +.mobile-navbar-container .navbar-header { + display: block; + grid-column: 1; + justify-self: center; + width: 25px; +} + +.mobile-navbar-container .mobile-header { + height: 100%; + justify-self: center; +} + +.mobile-navbar-container .container-fluid { + display: grid; + grid-template-columns: 50px auto 50px; + align-items: center; + height: 100%; +} + /* PrintLayout styles */ .otp.print-layout { diff --git a/lib/components/app/desktop-nav.tsx b/lib/components/app/desktop-nav.tsx index f9a265b86..419ee247b 100644 --- a/lib/components/app/desktop-nav.tsx +++ b/lib/components/app/desktop-nav.tsx @@ -19,8 +19,6 @@ import NavbarItem from './nav-item' import ViewSwitcher from './view-switcher' const StyledNav = styled(Nav)` - /* Almost override bootstrap's margin-right: -15px */ - margin-right: -5px; /* Target only the svgs in the Navbar */ & > li > button > svg, & > li > span > button > span > svg { @@ -41,10 +39,6 @@ const StyledNav = styled(Nav)` padding: 15px; line-height: 20px; - @media (max-width: 768px) { - padding: 10px; - } - &:hover { background: rgba(0, 0, 0, 0.05); color: #ececec; @@ -99,18 +93,14 @@ const DesktopNav = ({ const BrandingElement = brandClickable ? 'a' : 'div' - const commonStyles = { marginLeft: 50 } - const brandingProps = brandClickable - ? { - href: '/#/', - style: { - ...commonStyles, - display: 'block', - position: 'relative', - zIndex: 10 - } - } - : { style: { ...commonStyles } } + const brandingProps = brandClickable && { + href: '/#/', + style: { + display: 'block', + position: 'relative', + zIndex: 10 + } + } const popupButtonText = popupTarget && intl.formatMessage({ @@ -142,7 +132,7 @@ const DesktopNav = ({ )} - + {popupTarget && ( diff --git a/lib/components/app/nav-item.tsx b/lib/components/app/nav-item.tsx index d6cd2f9f9..9c4c92be8 100644 --- a/lib/components/app/nav-item.tsx +++ b/lib/components/app/nav-item.tsx @@ -19,10 +19,6 @@ export const NavbarButton = styled.button` padding: 15px; transition: all 0.1s ease-in-out; - @media (max-width: 768px) { - padding: 10px; - } - &:hover, &[aria-expanded='true'] { background: rgba(0, 0, 0, 0.05); diff --git a/lib/components/app/view-switcher.tsx b/lib/components/app/view-switcher.tsx index fc500f9b5..0bd47d5e8 100644 --- a/lib/components/app/view-switcher.tsx +++ b/lib/components/app/view-switcher.tsx @@ -3,14 +3,11 @@ import React from 'react' import Link from '../util/link' -type Props = { - sticky?: boolean -} /** * This component is a switcher between * the main views of the application. */ -const ViewSwitcher = ({ sticky }: Props) => { +const ViewSwitcher = (): JSX.Element => { const intl = useIntl() return (
{ className="view-switcher" id="view-switcher" role="group" - style={ - sticky - ? { - height: '100%', - left: 0, - position: 'absolute', - width: '100%' - } - : {} - } > diff --git a/lib/components/mobile/mobile.css b/lib/components/mobile/mobile.css index b1197cfbd..9685a7a52 100644 --- a/lib/components/mobile/mobile.css +++ b/lib/components/mobile/mobile.css @@ -20,12 +20,9 @@ .otp .navbar .mobile-header { align-items: center; display: flex; - height: 50px; + height: 100%; justify-content: center; - left: 50px; max-width: 90%; - position: fixed; - right: 50px; text-align: center; } @@ -68,10 +65,6 @@ font-size: 18px; } -.otp .navbar-brand { - padding: 7px 10px; -} - /* Welcome screen */ .otp.mobile .welcome-location { diff --git a/lib/components/user/nav-login-button.css b/lib/components/user/nav-login-button.css index 3bb007cb1..bf20205d4 100644 --- a/lib/components/user/nav-login-button.css +++ b/lib/components/user/nav-login-button.css @@ -13,11 +13,6 @@ min-width: 0px; } -.otp.mobile .navbar .container-fluid .locale-selector-and-login { - position: fixed; - right: 0; - top: 0; -} .otp.mobile .navbar .container-fluid .locale-selector-and-login > li { display: inline-block; } From 45464f6183ddc25feee2c9ce26864d1af3b7d134 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:02:30 -0600 Subject: [PATCH 08/46] clean up view switcher and mobile styling --- index.css | 167 +------------------- lib/components/app/app.css | 186 +++++++++++++++++++++-- lib/components/mobile/mobile.css | 3 - lib/components/user/nav-login-button.css | 3 + 4 files changed, 179 insertions(+), 180 deletions(-) diff --git a/index.css b/index.css index 94a39b976..fe75647f8 100644 --- a/index.css +++ b/index.css @@ -1,5 +1,6 @@ @import url(node_modules/bootstrap/dist/css/bootstrap.min.css); - +@import url(react-sliding-pane/dist/react-sliding-pane.css); +@import url(lib/bike-rental.css); @import url(node_modules/maplibre-gl/dist/maplibre-gl.css); @import url(lib/components/admin/call-taker.css); @@ -12,177 +13,13 @@ @import url(lib/components/user/nav-login-button.css); @import url(lib/components/viewers/viewers.css); -@import url(lib/bike-rental.css); -@import url(react-sliding-pane/dist/react-sliding-pane.css); /* Hide IE/Edge clear button in text input fields. */ input[type="text"]::-ms-clear { display: none; } -/* New app menu */ -.app-menu-icon { - background: none; - border: none; - cursor: pointer; - display: flex; - flex-direction: column; - height: 15px; - justify-content: space-between; - padding: 0; - top: 16px; - transition: all 1s ease; - width: 21px; - z-index: 10; -} - -@media only screen and (max-width: 768px) { - #locale-selector-wrapper { - display: none; - } - .app-menu-icon { - left: 15px; - } -} - -.app-menu-icon .menu-line { - border-bottom: 3px solid #ffffff; - display: block; - position: relative; - transition: all 0.5s ease; - width: 100%; -} - -.app-menu-icon[aria-expanded="true"] .menu-line.top { - transform: rotate(45deg); - top: 7px; -} -.app-menu-icon[aria-expanded="true"] .menu-line.bottom { - transform: rotate(-45deg); - bottom: 5px; -} -.app-menu-icon[aria-expanded="true"] .menu-line.middle { - display: none; -} - -.slide-pane { - transition: all 0.2s ease-in-out; -} - -.slide-pane_from_left { - margin: 52px auto 0 0; - /* Keep pane from overflowing on smaller screens */ - height: calc(100% - 52px); -} - -.slide-pane__content { - padding: 6px 0; -} - -.slide-pane__overlay { - z-index: 1000; -} - -.app-menu { - margin: 0; - padding: 0.5rem 0; -} - -.app-menu img, -.app-menu svg { - max-height: 1em; - margin: 0 2rem; - vertical-align: middle; - width: 1em; -} - -.app-menu a, -.app-menu button { - background: none; - border: none; - color: inherit; - cursor: pointer; - display: flex; - font-size: 20px; - padding: 0.5rem 0; - text-decoration: none; - width: 100%; -} - -/* Prevents hover styles from getting triggered on mobile */ -@media (hover: hover) { - .app-menu a:hover, - .app-menu button:hover { - color: #4c97f5; - } -} - -.app-menu a:focus, -.app-menu button:focus { - background-color: #ddd; - outline: 2px solid #4c97f5; - outline-offset: -2px; -} - -.app-menu button[aria-selected="true"], -.sort-option button[aria-selected="true"], -#locale-selector button[aria-selected="true"] { - font-weight: bold; -} - -.skip-nav-button { - color: initial; - position: fixed; - top: -30px; -} -.skip-nav-button:focus { - padding: 7px 24px; - top: 7px; - z-index: 100; -} - -.view-switcher { - display: none; -} - -@media (min-width: 768px) { - .view-switcher { - display: flex; - } -} - -.expand-menu-chevron { - flex-grow: 1; - text-align: end; -} - -.dropdown-header { - font-size: inherit; - line-height: normal; - color: inherit; - white-space: nowrap; -} - -.sub-menu-container { - border-top: 1px solid #cccccc; - margin-top: 0.5rem; - padding-left: 2rem; -} - -.app-menu .app-menu-divider { - border-bottom: 1px solid #ccc; - padding: 1rem 0; -} - -/* Header image or title */ -/* If an icon is used, visually-hide the title (but keep it visible to screen readers). */ -.with-icon div.navbar-title { - height: 0; - overflow: hidden; - width: 0; -} - /* Buttons */ button.header, diff --git a/lib/components/app/app.css b/lib/components/app/app.css index efadb689d..4c457c138 100644 --- a/lib/components/app/app.css +++ b/lib/components/app/app.css @@ -67,8 +67,14 @@ width: 100%; } +.view-switcher { + align-items: center; + display: flex; + justify-content: center; +} + @media (min-width: 992px) { - #view-switcher { + .view-switcher { height: 100%; left: 0; position: absolute; @@ -79,8 +85,9 @@ @media (max-width: 768px) { .navbar .navbar-header { - grid-template-columns: 50px auto 50px; + grid-template-columns: 50px auto 70px; width: auto !important; + } .navbar .navbar-brand { @@ -89,9 +96,9 @@ padding: 10px; } - #view-switcher { - position: relative; - } + .view-switcher { + display: none; +} } @@ -99,6 +106,7 @@ .mobile-navbar-container .navbar-header { display: block; grid-column: 1; + grid-row: 1; justify-self: center; width: 25px; } @@ -106,13 +114,172 @@ .mobile-navbar-container .mobile-header { height: 100%; justify-self: center; + grid-row: 1; +} + +.mobile-navbar-container .locale-selector-and-login { + grid-row: 1; + height: 50px; + justify-self: flex-end; } .mobile-navbar-container .container-fluid { display: grid; - grid-template-columns: 50px auto 50px; + grid-template-columns: 50px auto 70px; + grid-template-rows: 50px; align-items: center; - height: 100%; + padding: 0; +} + +/* New app menu */ +.app-menu-icon { + background: none; + border: none; + cursor: pointer; + display: flex; + flex-direction: column; + height: 15px; + justify-content: space-between; + padding: 0; + transition: all 1s ease; + width: 21px; + z-index: 10; +} + +@media only screen and (max-width: 768px) { + #locale-selector-wrapper { + display: none; + } + .app-menu-icon { + left: 15px; + } +} + +.app-menu-icon .menu-line { + border-bottom: 3px solid #ffffff; + display: block; + position: relative; + transition: all 0.5s ease; + width: 100%; +} + +.app-menu-icon[aria-expanded="true"] .menu-line.top { + transform: rotate(45deg); + top: 7px; +} +.app-menu-icon[aria-expanded="true"] .menu-line.bottom { + transform: rotate(-45deg); + bottom: 5px; +} +.app-menu-icon[aria-expanded="true"] .menu-line.middle { + display: none; +} + +.slide-pane { + transition: all 0.2s ease-in-out; +} + +.slide-pane_from_left { + margin: 52px auto 0 0; + /* Keep pane from overflowing on smaller screens */ + height: calc(100% - 52px); +} + +.slide-pane__content { + padding: 6px 0; +} + +.slide-pane__overlay { + z-index: 1000; +} + +.app-menu { + margin: 0; + padding: 0.5rem 0; +} + +.app-menu img, +.app-menu svg { + max-height: 1em; + margin: 0 2rem; + vertical-align: middle; + width: 1em; +} + +.app-menu a, +.app-menu button { + background: none; + border: none; + color: inherit; + cursor: pointer; + display: flex; + font-size: 20px; + padding: 0.5rem 0; + text-decoration: none; + width: 100%; +} + +/* Prevents hover styles from getting triggered on mobile */ +@media (hover: hover) { + .app-menu a:hover, + .app-menu button:hover { + color: #4c97f5; + } +} + +.app-menu a:focus, +.app-menu button:focus { + background-color: #ddd; + outline: 2px solid #4c97f5; + outline-offset: -2px; +} + +.app-menu button[aria-selected="true"], +.sort-option button[aria-selected="true"], +#locale-selector button[aria-selected="true"] { + font-weight: bold; +} + +.skip-nav-button { + color: initial; + position: fixed; + top: -30px; +} +.skip-nav-button:focus { + padding: 7px 24px; + top: 7px; + z-index: 100; +} + +.expand-menu-chevron { + flex-grow: 1; + text-align: end; +} + +.dropdown-header { + font-size: inherit; + line-height: normal; + color: inherit; + white-space: nowrap; +} + +.sub-menu-container { + border-top: 1px solid #cccccc; + margin-top: 0.5rem; + padding-left: 2rem; +} + +.app-menu .app-menu-divider { + border-bottom: 1px solid #ccc; + padding: 1rem 0; +} + +/* Header image or title */ +/* If an icon is used, visually-hide the title (but keep it visible to screen readers). */ +.with-icon div.navbar-title { + height: 0; + overflow: hidden; + width: 0; } /* PrintLayout styles */ @@ -137,11 +304,6 @@ } /* View Switcher Styling */ -.view-switcher { - align-items: center; - display: flex; - justify-content: center; -} .view-switcher a { color: rgba(255, 255, 255, 0.85); border-radius: 15px; diff --git a/lib/components/mobile/mobile.css b/lib/components/mobile/mobile.css index 9685a7a52..5e07d9fd7 100644 --- a/lib/components/mobile/mobile.css +++ b/lib/components/mobile/mobile.css @@ -35,7 +35,6 @@ @media (max-width: 768px) { .otp .navbar .mobile-header-text { - margin-top: 2px; word-break: break-all; } } @@ -53,8 +52,6 @@ border: none; color: white; font-size: 18px; - left: 7px; - position: fixed; } .otp .navbar .mobile-close { diff --git a/lib/components/user/nav-login-button.css b/lib/components/user/nav-login-button.css index bf20205d4..fcc63d9f0 100644 --- a/lib/components/user/nav-login-button.css +++ b/lib/components/user/nav-login-button.css @@ -45,5 +45,8 @@ } #user-selector-label { background-color: transparent; + border: 0; + height: 50px; + color: white; } } From af60baded6b3c18c0a45d00d5f1c737b0e5468bb Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:07:36 -0600 Subject: [PATCH 09/46] Sort CSS --- index.css | 8 +- lib/components/app/app.css | 36 +++--- lib/components/mobile/mobile.css | 136 +++++++++++------------ lib/components/user/nav-login-button.css | 8 +- 4 files changed, 94 insertions(+), 94 deletions(-) diff --git a/index.css b/index.css index fe75647f8..c5a4df16f 100644 --- a/index.css +++ b/index.css @@ -26,12 +26,12 @@ button.header, button.step, .clear-button-formatting { background: transparent; - color: inherit; border: 0; + color: inherit; + margin: 0; + padding: 0; text-align: inherit; text-decoration: none; - padding: 0; - margin: 0; } .clear-button-formatting:active { @@ -53,9 +53,9 @@ button.step { } .overflow-ellipsis { - white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + white-space: nowrap; } .map-container .leaflet-top { diff --git a/lib/components/app/app.css b/lib/components/app/app.css index 4c457c138..0f1397663 100644 --- a/lib/components/app/app.css +++ b/lib/components/app/app.css @@ -1,8 +1,8 @@ /* application menu styling */ .app-menu-button { - border: none; background: none; + border: none; color: #fff; font-size: 24px; padding: 0px 0px; @@ -21,10 +21,10 @@ .app-menu .btn-default:active, .app-menu .open > .dropdown-toggle.btn-default:focus, .app-menu .open > .dropdown-toggle.btn-default { - color: #fff; background: none; - box-shadow: none; border: none; + box-shadow: none; + color: #fff; } .app-menu .btn-default:hover { @@ -55,14 +55,14 @@ } .navbar .navbar-nav { - margin: 0; grid-column: 3; + margin: 0; } .navbar .navbar-brand { + align-items: center; display: flex; gap: 35px; - align-items: center; grid-column: 1 / span 1; width: 100%; } @@ -91,8 +91,8 @@ } .navbar .navbar-brand { - grid-column: 1 / span 2; gap: 15px; + grid-column: 1 / span 2; padding: 10px; } @@ -112,9 +112,9 @@ } .mobile-navbar-container .mobile-header { + grid-row: 1; height: 100%; justify-self: center; - grid-row: 1; } .mobile-navbar-container .locale-selector-and-login { @@ -124,10 +124,10 @@ } .mobile-navbar-container .container-fluid { + align-items: center; display: grid; grid-template-columns: 50px auto 70px; grid-template-rows: 50px; - align-items: center; padding: 0; } @@ -164,12 +164,12 @@ } .app-menu-icon[aria-expanded="true"] .menu-line.top { - transform: rotate(45deg); top: 7px; + transform: rotate(45deg); } .app-menu-icon[aria-expanded="true"] .menu-line.bottom { - transform: rotate(-45deg); bottom: 5px; + transform: rotate(-45deg); } .app-menu-icon[aria-expanded="true"] .menu-line.middle { display: none; @@ -180,9 +180,9 @@ } .slide-pane_from_left { - margin: 52px auto 0 0; /* Keep pane from overflowing on smaller screens */ height: calc(100% - 52px); + margin: 52px auto 0 0; } .slide-pane__content { @@ -200,8 +200,8 @@ .app-menu img, .app-menu svg { - max-height: 1em; margin: 0 2rem; + max-height: 1em; vertical-align: middle; width: 1em; } @@ -257,9 +257,9 @@ } .dropdown-header { + color: inherit; font-size: inherit; line-height: normal; - color: inherit; white-space: nowrap; } @@ -285,28 +285,28 @@ /* PrintLayout styles */ .otp.print-layout { - max-width: 640px; margin: 30px auto; + max-width: 640px; } .otp.print-layout > .header { - margin-bottom: 30px; border-bottom: 4px solid black; font-size: 36px; font-weight: 600; + margin-bottom: 30px; } .otp.print-layout > .map-container { border: 2px solid black; + box-sizing: border-box; height: 400px; margin-bottom: 30px; - box-sizing: border-box; } /* View Switcher Styling */ .view-switcher a { - color: rgba(255, 255, 255, 0.85); border-radius: 15px; + color: rgba(255, 255, 255, 0.85); font-size: 14px; padding: 6px 12px; user-select: none; @@ -328,8 +328,8 @@ /* Full screen modal styling */ .fullscreen-modal { - width: 75vw; height: 60vh; + width: 75vw; } .fullscreen-modal .modal-content { height: 90vh; diff --git a/lib/components/mobile/mobile.css b/lib/components/mobile/mobile.css index 5e07d9fd7..77a8ef225 100644 --- a/lib/components/mobile/mobile.css +++ b/lib/components/mobile/mobile.css @@ -3,18 +3,18 @@ } .otp .mobile-bottom-button-container { - position: fixed; bottom: 0; - right: 0; - left: 0; height: 40px; + left: 0; + position: fixed; + right: 0; } /* Navbar settings */ .otp.mobile .navbar { - margin-bottom: 0; border: none; + margin-bottom: 0; } .otp .navbar .mobile-header { @@ -55,129 +55,129 @@ } .otp .navbar .mobile-close { - position: fixed; - top: 4px; - right: 6px; color: white; font-size: 18px; + position: fixed; + right: 6px; + top: 4px; } /* Welcome screen */ .otp.mobile .welcome-location { - position: fixed; - top: 50px; + height: 60px; left: 0; + position: fixed; right: 0; - height: 60px; + top: 50px; } .otp.mobile .welcome-map { - position: fixed; - top: 110px; + bottom: 0; left: 0; + position: fixed; right: 0; - bottom: 0; + top: 110px; } /* Location search screen */ .otp.mobile .location-search { - position: fixed; - top: 50px; + bottom: 0; left: 0; + position: fixed; right: 0; - bottom: 0; + top: 50px; } /* Main search screen */ .otp.mobile .search-settings { - position: fixed; - top: 50px; + box-shadow: 3px 0px 12px #00000052; + height: 250px; left: 0; + position: fixed; right: 0; - height: 250px; - box-shadow: 3px 0px 12px #00000052; + top: 50px; } .otp.mobile .search-map { - position: fixed; - top: 300px; + bottom: 0; left: 0; + position: fixed; right: 0; - bottom: 0; + top: 300px; } /* Batch routing search screen */ .otp.mobile .batch-search-map { - position: fixed; - top: 282px; + bottom: 0; left: 0; + position: fixed; right: 0; - bottom: 0; + top: 282px; } /* Detailed options screen */ .otp.mobile .options-main-content { - position: fixed; - top: 50px; - left: 0; - right: 0; bottom: 55px; - overflow-y: auto; + left: 0; overflow-x: hidden; + overflow-y: auto; + position: fixed; + right: 0; + top: 50px; } .otp.mobile .options-lower-tray { - position: fixed; + bottom: 0; height: 55px; left: 0; + position: fixed; right: 0; - bottom: 0; } /* Results screen: normal display */ .otp.mobile .mobile-narrative-header { - position: fixed; - height: 40px; - left: 0; - right: 0; background-color: #444; color: #fff; - text-align: center; font-size: 20px; font-weight: 500; + height: 40px; + left: 0; + position: fixed; + right: 0; + text-align: center; } .otp.mobile .mobile-narrative-container { - position: fixed; bottom: 20px; - right: 0; left: 0; padding: 8px 12px; + position: fixed; + right: 0; } .otp.mobile .dots-container { - position: fixed; bottom: 0; - right: 0; - left: 0; height: 20px; + left: 0; + position: fixed; + right: 0; text-align: center; } .otp.mobile .dots-container .dot { + background-color: #ddd; + border-radius: 4px; display: inline-block; - width: 8px; height: 8px; - border-radius: 4px; - background-color: #ddd; margin: 0px 3px; vertical-align: 2px; + width: 8px; } .otp.mobile .dots-container .dot.active { @@ -185,64 +185,64 @@ } .otp.mobile .results-map { - position: fixed; - top: 100px; + bottom: 140px; left: 0; + position: fixed; right: 0; - bottom: 140px; + top: 100px; } /* Results screen: error display */ .otp.mobile .results-error-map { - position: fixed; - top: 100px; + height: 200px; left: 0; + position: fixed; right: 0; - height: 200px; + top: 100px; } .otp.mobile .results-error-message { - position: fixed; - left: 0; - right: 0; bottom: 0; + left: 0; padding-top: 12px; + position: fixed; + right: 0; } /* User Settings */ .otp.mobile .user-settings { - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); background-color: white; - position: fixed; - left: 0; - right: 0; + border-radius: 5px; bottom: 0; - margin-bottom: 18px; + box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); height: 165px; - z-index: 999999; + left: 0; + margin-bottom: 18px; overflow-y: scroll; - border-radius: 5px; + position: fixed; + right: 0; + z-index: 999999; } /* Stop/Trip/Route Viewer screens */ .otp.mobile .viewer-container { - position: fixed; - top: 250px; bottom: 0; left: 0; - right: 0; overflow-y: auto; + position: fixed; + right: 0; + top: 250px; } .otp.mobile .viewer-map { - position: fixed; - top: 50px; + height: 200px; left: 0; + position: fixed; right: 0; - height: 200px; + top: 50px; } .otp.mobile .route-viewer-header { diff --git a/lib/components/user/nav-login-button.css b/lib/components/user/nav-login-button.css index fcc63d9f0..417c18a36 100644 --- a/lib/components/user/nav-login-button.css +++ b/lib/components/user/nav-login-button.css @@ -21,10 +21,10 @@ } .navBarItem p { - padding: 5px 15px; - margin: 0; - font-weight: 600; font-size: 16px; + font-weight: 600; + margin: 0; + padding: 5px 15px; } .navBarItem ul { @@ -46,7 +46,7 @@ #user-selector-label { background-color: transparent; border: 0; - height: 50px; color: white; + height: 50px; } } From ed5ba5f9e8f26caf7b2ac5594b6af8192861fb63 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:43:56 -0600 Subject: [PATCH 10/46] Fix spacing when logged in --- lib/components/app/app.css | 2 +- lib/components/app/desktop-nav.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/components/app/app.css b/lib/components/app/app.css index 0f1397663..fe1c0a916 100644 --- a/lib/components/app/app.css +++ b/lib/components/app/app.css @@ -51,7 +51,7 @@ .navbar .navbar-header { display: grid; - grid-template-columns: 300px auto 150px; + grid-template-columns: 300px auto 170px; } .navbar .navbar-nav { diff --git a/lib/components/app/desktop-nav.tsx b/lib/components/app/desktop-nav.tsx index 419ee247b..b2e1ad3c2 100644 --- a/lib/components/app/desktop-nav.tsx +++ b/lib/components/app/desktop-nav.tsx @@ -19,6 +19,8 @@ import NavbarItem from './nav-item' import ViewSwitcher from './view-switcher' const StyledNav = styled(Nav)` + display: flex; + justify-content: end; /* Target only the svgs in the Navbar */ & > li > button > svg, & > li > span > button > span > svg { From 6cc7abae839dbddc24c7c1e5f89a0ed46fd619ef Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Wed, 13 Nov 2024 15:34:42 -0500 Subject: [PATCH 11/46] address pr feedback --- lib/components/map/default-map.tsx | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/components/map/default-map.tsx b/lib/components/map/default-map.tsx index 99caa0490..1eb602d99 100644 --- a/lib/components/map/default-map.tsx +++ b/lib/components/map/default-map.tsx @@ -318,9 +318,8 @@ class DefaultMap extends Component { const baseLayerUrls = baseLayersWithNames?.map((bl) => bl.url) const baseLayerNames = baseLayersWithNames?.map((bl) => bl.name) - const routeBasedTransitVehicleOverlayNameOverride = overlays.find( - (o) => o.type === 'vehicles-one-route' - )?.name + const routeBasedTransitVehicleOverlayNameOverride = + overlays.find((o) => o.type === 'vehicles-one-route')?.name || undefined return ( @@ -346,10 +345,10 @@ class DefaultMap extends Component { Date: Thu, 10 Oct 2024 17:12:01 +0200 Subject: [PATCH 12/46] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/ --- i18n/ru.yml | 71 ++++++++++++++++++++++++++++++++--------------------- i18n/vi.yml | 55 +++++++++++++++++++++++++---------------- 2 files changed, 77 insertions(+), 49 deletions(-) diff --git a/i18n/ru.yml b/i18n/ru.yml index b7a2eedd4..5130b920a 100644 --- a/i18n/ru.yml +++ b/i18n/ru.yml @@ -18,7 +18,8 @@ actions: itineraryCapacityError: >- Невозможно сохранить план. Этот план невозможно сохранить из-за нехватки мест в одном или нескольких транспортных средствах. Измените план поездки. - maxTripRequestsExceeded: Превышено количество запросов на поездку без действительных результатов + maxTripRequestsExceeded: Превышено количество запросов на поездку без действительных + результатов saveItinerariesError: "Не удалось сохранить маршруты: {err}" setDateError: "Ошибка введения данных:" location: @@ -37,9 +38,11 @@ actions: authTokenError: Ошибка получения токена на авторизацию. confirmDeleteMonitoredTrip: Удалить эту поездку? confirmDeletePlace: Удалить это место? - emailVerificationResent: Сообщение с подтверждением адреса электронной почты отправлено повторно. + emailVerificationResent: Сообщение с подтверждением адреса электронной почты отправлено + повторно. genericError: "Произошла ошибка: {err}" - itineraryExistenceCheckFailed: При проверке возможности выбранной поездки произошла ошибка. + itineraryExistenceCheckFailed: При проверке возможности выбранной поездки произошла + ошибка. mustAcceptTermsToSavePlace: >- Примите «Условия использования» (в разделе «Моя учетная запись»), чтобы сохранять местоположения. @@ -99,15 +102,11 @@ common: submitting: Отправка… "yes": Да itineraryDescriptions: - calories: "{calories, number} кал" fareUnknown: Информации о стоимости поездки нет. noItineraryToDisplay: Нет маршрута для отображения. relativeCo2: > {co2} {isMore, select, true {больше } other {меньше} } CO₂, чем при вождении в одиночку - transfers: >- - {transfers, plural, =0 {} one {# пересадка} other {несколько пересадок - (#)}} linkOpensNewWindow: (Открывает новое окно) modes: bicycle_rent: Прокат велосипедов @@ -146,7 +145,6 @@ common: enterStartLocation: Введите место отправления или {mapAction} на карте… tap: коснитесь его time: - departureArrivalTimes: "{startTime, time, short}\_— {endTime, time, short}" duration: aFewSeconds: несколько секунд nDays: "{days} дн." @@ -256,7 +254,6 @@ components: ariaLabel: Навигационная форма ItinerarySummary: itineraryDetails: Сведения о маршруте - minMaxFare: "{minTotalFare}\_— {maxTotalFare}" LocationSearch: enterLocation: Ввести местоположение setDestination: Выбрать место назначения @@ -285,7 +282,8 @@ components: header: Задать параметры поиска NarrativeItinerariesHeader: changeSortDir: Изменить направление сортировки - howToFindResults: Чтобы просмотреть результаты, см. заголовок «Найденные маршруты» ниже. + howToFindResults: Чтобы просмотреть результаты, см. заголовок «Найденные маршруты» + ниже. itinerariesFound: |- {itineraryNum, plural, one {найден # маршрут} @@ -388,7 +386,7 @@ components: TO: Mесто назначения PhoneNumberEditor: changeNumber: Изменить номер - invalidCode: "Введите проверочный код из 6\_цифр." + invalidCode: "Введите проверочный код из 6 цифр." invalidPhone: Введите действительный номер телефона. pending: Ожидание phoneNumberSubmitted: Номер телефона{phoneNumber} был успешно отправлен. @@ -402,7 +400,9 @@ components: подтверждением и мониторингом поездки. Вашим оператором мобильной связи могут взиматься дополнительные пени. verificationCode: "Код подтверждения:" - verificationInstructions: "Откройте приложение для обмена SMS на телефоне и найдите текстовое сообщение с кодом подтверждения. Затем введите код ниже (срок действия кода: 10\_минут).\n" + verificationInstructions: "Откройте приложение для обмена SMS на телефоне и найдите + текстовое сообщение с кодом подтверждения. Затем введите код ниже (срок действия + кода: 10 минут).\n" verified: Подтверждено verify: Подтвердить Place: @@ -498,7 +498,8 @@ components: tooManyTrips: > Можно сохранить не более пяти поездок. Удалите неиспользуемые поездки из раздела сохраненных и попробуйте еще раз. - tripNameAlreadyUsed: У вас уже сохранена поездка с таким именем. Укажите другое имя. + tripNameAlreadyUsed: У вас уже сохранена поездка с таким именем. Укажите другое + имя. tripNameRequired: Укажите имя поездки. SequentialPaneDisplay: stepNumber: Шаг {шаг} из {общее кол-во} @@ -553,9 +554,13 @@ components: defaultContent: Переключить switchLocations: Переключить местоположения TermsOfUsePane: - confirmDeletionPrompt: "Недавние поисковые запросы и\_(или) места сохранены. Отключение сохранения недавних мест и\_(или) поисковых запросов приведет к удалению этих элементов. Продолжить?\n" + confirmDeletionPrompt: "Недавние поисковые запросы и (или) места сохранены. Отключение + сохранения недавних мест и (или) поисковых запросов приведет к удалению этих + элементов. Продолжить?\n" mustAgreeToTerms: Для продолжения примите условия использования. - termsOfServiceStatement: "Я подтверждаю, что мне исполнилось 18\_лет и что я прочитал и принимаю Условия использования планировщика поездок.\n" + termsOfServiceStatement: "Я подтверждаю, что мне исполнилось 18 лет и что я прочитал + и принимаю Условия использования планировщика + поездок.\n" termsOfStorageStatement: > Необязательно: я даю согласие на то, чтобы планировщик поездок хранил архивные данные о моих запланированных поездках с целью улучшения услуг @@ -573,8 +578,10 @@ components: tripIsAvailableOnDaysIndicated: Поездка доступна для указанных выше дней. tripNamePrompt: "Укажите имя поездки:" tripNotAvailableOnDay: "Поездка недоступна для следующих дней: {repeatedDay}" - unsavedChangesExistingTrip: Вы не сохранили поездку. Если вы выйдете, все изменения будут утеряны. - unsavedChangesNewTrip: Вы не сохранили новую поездку. Если вы выйдете, она будет удалена. + unsavedChangesExistingTrip: Вы не сохранили поездку. Если вы выйдете, все изменения + будут утеряны. + unsavedChangesNewTrip: Вы не сохранили новую поездку. Если вы выйдете, она будет + удалена. TripNotificationsPane: advancedSettings: Расширенные настройки altRouteRecommended: Рекомендуется использовать пересадку или альтернативный маршрут @@ -585,7 +592,7 @@ components: monitorThisTrip: "Мониторинг данной поездки до ее начала:" notificationsTurnedOff: Уведомления отключены в настройках вашей учетной записи. notifyViaChannelWhen: "Использовать канал «{channel}» для уведомлений, когда:" - oneHour: "1\_ч" + oneHour: "1 ч" realtimeAlertFlagged: Для моего пути есть предупреждение в режиме реального времени timeBefore: "{time} до" TripStatus: @@ -644,14 +651,16 @@ components: реальном времени запустится в {monitoringStart, time, short}.) tripStartIsDelayed: Начало поездки откладывается на {duration}! tripStartIsEarly: Начало поездки произойдет на {duration} раньше ожидаемого! - tripStartsSoonNoUpdates: Поездка скоро начнется (обновления в реальном времени недоступны). + tripStartsSoonNoUpdates: Поездка скоро начнется (обновления в реальном времени + недоступны). tripStartsSoonOnTime: Поездка скоро начнется. Без задержек. TripSummary: arriveAt: "Прибытие в " leaveAt: "Оставить " TripSummaryPane: happensOnDays: "Проходит в такие дни: {days}" - notifications: за {leadTimeInMinutes} мин до запланированного времени отправления + notifications: за {leadTimeInMinutes} мин до запланированного времени + отправления notificationsDisabled: "Уведомления: отключены" TripTools: copyLink: Скопировать ссылку @@ -691,17 +700,23 @@ components: storeTripHistory: Сохранять историю поездок updating: Обновляется UserSettings: - confirmDeletion: "Недавние поисковые запросы и\_(или) места сохранены. Отключение сохранения недавних мест и\_(или) поисковых запросов приведет к удалению этих элементов. Продолжить?" + confirmDeletion: "Недавние поисковые запросы и (или) места сохранены. Отключение + сохранения недавних мест и (или) поисковых запросов приведет к удалению этих + элементов. Продолжить?" favoriteStops: Избранные остановки myPreferences: Мои параметры mySavedPlaces: Мои сохраненные места (изменить) noFavoriteStops: Избранные остановки recentPlaces: Недавние места - recentSearchSummary: "Режим «{mode}». {from}\_— {to}" + recentSearchSummary: "Режим «{mode}». {from} — {to}" recentSearches: Недавние поисковые запросы - rememberSearches: "Сохранить недавние места\_/ поисковые запросы?" + rememberSearches: "Сохранить недавние места / поисковые запросы?" stopId: "Идентификатор остановки: {stopId}" - storageDisclaimer: "Все сохраненные параметры, места и настройки будут храниться в локальном хранилище браузера. TriMet не получит доступ к данным о вашем доме, месте работы или другим местоположениям. В любой момент вы можете отключить сохранение недавних мест\_/ поисковых запросов и очистить список местоположений дома/работы, а также избранных остановок.\n" + storageDisclaimer: "Все сохраненные параметры, места и настройки будут храниться + в локальном хранилище браузера. TriMet не получит доступ к данным о вашем доме, + месте работы или другим местоположениям. В любой момент вы можете отключить + сохранение недавних мест / поисковых запросов и очистить список местоположений + дома/работы, а также избранных остановок.\n" UserTripSettings: forgetOptions: Удалить варианты rememberOptions: Сохранить варианты поездки @@ -723,12 +738,12 @@ components: prompt: Куда вы хотите отправиться? config: accessModes: - bicycle: "Общественный транспорт\_+\_личный велосипед" - bicycle_rent: "Общественный транспорт\_+\_прокат велосипеда" + bicycle: "Общественный транспорт + личный велосипед" + bicycle_rent: "Общественный транспорт + прокат велосипеда" car_hail: Заказная поездка car_park: Парковочное место - micromobility: "Общественный транспорт\_+\_личный самокат" - micromobility_rent: "Общественный транспорт\_+\_прокат электросамоката" + micromobility: "Общественный транспорт + личный самокат" + micromobility_rent: "Общественный транспорт + прокат электросамоката" bicycleModes: bicycle: Личный велосипед bicycle_rent: Прокат велосипедов diff --git a/i18n/vi.yml b/i18n/vi.yml index 719ee0898..dd44b335f 100644 --- a/i18n/vi.yml +++ b/i18n/vi.yml @@ -5,7 +5,8 @@ actions: callQuerySaveError: "Lỗi khi lưu trữ các truy vấn cuộc gọi: {err}" callSaveError: "Không thể lưu cuộc gọi: {err}" checkSessionError: "Lỗi khi thiết lập phiên ủy quyền: {err}" - couldNotFindCallError: Không thể tìm thấy cuộc gọi. Đang hủy yêu cầu lưu truy vấn. + couldNotFindCallError: Không thể tìm thấy cuộc gọi. Đang hủy yêu cầu lưu truy + vấn. fetchCallsError: "Lỗi khi tìm nạp cuộc gọi: {err}" queryFetchError: "Lỗi khi tìm nạp các truy vấn: {err}" fieldTrip: @@ -28,7 +29,8 @@ actions: Không thể lưu kế hoạch chuyến đi: Không thể lưu kế hoạch chuyến đi này do thiếu sức chứa trên một hoặc nhiều xe. Vui lòng lên kế hoạch lại chuyến đi của bạn. - maxTripRequestsExceeded: Đã vượt quá số lượng yêu cầu chuyến đi mà không có kết quả hợp lệ + maxTripRequestsExceeded: Đã vượt quá số lượng yêu cầu chuyến đi mà không có kết + quả hợp lệ saveItinerariesError: "Không lưu được hành trình: {err}" setDateError: "Lỗi khi cài đặt ngày:" setGroupSizeError: "Lỗi khi cài đặt kích thước nhóm:" @@ -40,7 +42,8 @@ actions: Để sử dụng địa điểm hiện tại của mình, quý vị hãy cho phép sử dụng vị trí trong trình duyệt và tải lại trang này. - geolocationNotSupportedError: Định vị địa lý không được hỗ trợ bởi trình duyệt của bạn + geolocationNotSupportedError: Định vị địa lý không được hỗ trợ bởi trình duyệt + của bạn unknownPositionError: Lỗi không xác định khi tìm vị trí userDeniedPermission: Người dùng từ chối cấp quyền map: @@ -52,7 +55,8 @@ actions: confirmDeletePlace: Bạn có muốn loại bỏ nơi này không? emailVerificationResent: Thông báo xác minh email đã được gửi lại. genericError: "Phát sinh lỗi: {err}" - itineraryExistenceCheckFailed: Lỗi kiểm tra xem chuyến đi được chọn của bạn là có thể. + itineraryExistenceCheckFailed: Lỗi kiểm tra xem chuyến đi được chọn của bạn là + có thể. mustAcceptTermsToSavePlace: >- Vui lòng chấp nhận Điều Khoản Sử Dụng (trong phần Tài Khoản Của Tôi) để lưu lại địa điểm. @@ -112,12 +116,10 @@ common: submitting: Đang gửi… "yes": Đúng itineraryDescriptions: - calories: "{calories, number} calo" fareUnknown: Không có thông tin giá vé noItineraryToDisplay: Không có hành trình để hiển thị. relativeCo2: | {co2} CO₂ {isMore, select, true {nhiều} other {ít} } hơn so với xe hơi - transfers: "{transfers, plural, =0 {} other {# chuyển}}" linkOpensNewWindow: (Mở khoảng thời gian mới) modes: bicycle_rent: Chia sẻ xe đạp @@ -156,7 +158,6 @@ common: enterStartLocation: Nhập vị trí bắt đầu hoặc {mapAction} vào bản đồ… tap: chạm time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: vài giây nDays: "{days} ngày" @@ -168,12 +169,14 @@ common: {} other {# giây}} components: A11yPrefs: - accessibilityRoutingByDefault: Thích những chuyến đi có thể truy cập theo mặc định + accessibilityRoutingByDefault: Thích những chuyến đi có thể truy cập theo mặc + định AccountSetupFinishPane: message: Bạn đã sẵn sàng để bắt đầu lên kế hoạch cho các chuyến đi của bạn. AddPlaceButton: addPlace: Thêm địa điểm - needOriginDestination: Xác định nguồn gốc hoặc đích đến để thêm các địa điểm trung gian + needOriginDestination: Xác định nguồn gốc hoặc đích đến để thêm các địa điểm trung + gian tooManyPlaces: Địa điểm trung gian tối đa đạt được AdvancedOptions: bannedRoutes: Chọn các tuyến đường bị cấm… @@ -259,14 +262,14 @@ components: editPlaceGeneric: Chỉnh sửa vị trí invalidAddress: Vui lòng cài đặt một vị trí cho nơi này. invalidName: Vui lòng nhập tên cho nơi này. - nameAlreadyUsed: Bạn đã sử dụng tên này cho một nơi khác. Vui lòng nhập một tên khác. + nameAlreadyUsed: Bạn đã sử dụng tên này cho một nơi khác. Vui lòng nhập một tên + khác. placeNotFound: Không tìm thấy địa điểm placeNotFoundDescription: Xin lỗi, địa điểm được yêu cầu không được tìm thấy. FormNavigationButtons: ariaLabel: Điều hướng hình thức ItinerarySummary: itineraryDetails: Chi tiết hành trình - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: Nhập vị trí setDestination: Chọn điểm đến @@ -335,8 +338,10 @@ components: description: Nội dung bạn yêu cầu không có sẵn. header: Không tìm thấy nội dung NotificationPrefsPane: - devicesRegistered: "{count, plural, one {# device} other {# devices}} đã đăng ký" - noDeviceForPush: Đăng ký thiết bị của quý vị bằng ứng dụng di động để nhận thông báo đẩy. + devicesRegistered: "{count, plural, one {# device} other {# devices}} đã đăng + ký" + noDeviceForPush: Đăng ký thiết bị của quý vị bằng ứng dụng di động để nhận thông + báo đẩy. notificationChannelPrompt: "Nhận thông báo về các chuyến đi đã lưu bằng:" OTP2ErrorRenderer: LOCATION_NOT_FOUND: @@ -577,16 +582,21 @@ components: travelingAt: di chuyển với tốc độ {milesPerHour} vehicleName: Phương tiện giao thông {vehicleNumber} TripBasicsPane: - checkingItineraryExistence: Kiểm tra sự tồn tại của hành trình cho mỗi ngày trong tuần… + checkingItineraryExistence: Kiểm tra sự tồn tại của hành trình cho mỗi ngày trong + tuần… tripDaysPrompt: Bạn thực hiện chuyến đi này vào những ngày nào? - tripIsAvailableOnDaysIndicated: Chuyến đi của bạn có sẵn vào những ngày trong tuần như đã nêu ở trên. + tripIsAvailableOnDaysIndicated: Chuyến đi của bạn có sẵn vào những ngày trong + tuần như đã nêu ở trên. tripNamePrompt: "Vui lòng cung cấp tên cho chuyến đi này:" tripNotAvailableOnDay: Chuyến đi không có sẵn vào {repeatedDay} - unsavedChangesExistingTrip: Bạn chưa lưu chuyến đi của mình. Nếu bạn rời đi, những thay đổi sẽ bị mất. - unsavedChangesNewTrip: Bạn chưa lưu chuyến đi mới của mình. Nếu bạn rời đi, nó sẽ bị mất. + unsavedChangesExistingTrip: Bạn chưa lưu chuyến đi của mình. Nếu bạn rời đi, những + thay đổi sẽ bị mất. + unsavedChangesNewTrip: Bạn chưa lưu chuyến đi mới của mình. Nếu bạn rời đi, nó + sẽ bị mất. TripNotificationsPane: advancedSettings: Cài đặt nâng cao - altRouteRecommended: Một tuyến đường hoặc điểm trung chuyển thay thế được khuyến nghị + altRouteRecommended: Một tuyến đường hoặc điểm trung chuyển thay thế được khuyến + nghị delaysAboveThreshold: Có sự chậm trễ hoặc gián đoạn của hơn howToReceiveAlerts: > Để nhận thông báo cho các chuyến đi đã lưu của bạn, bật thông báo trong @@ -595,7 +605,8 @@ components: notificationsTurnedOff: Thông báo được tắt cho tài khoản của bạn. notifyViaChannelWhen: "Thông báo cho tôi qua {channel} khi:" oneHour: 1 tiếng - realtimeAlertFlagged: Có một cảnh báo thời gian thực được gắn cờ trên hành trình của tôi + realtimeAlertFlagged: Có một cảnh báo thời gian thực được gắn cờ trên hành trình + của tôi timeBefore: "{time} trước" TripStatus: alerts: "{alerts, plural, one {# cảnh báo!} other {# cảnh báo!}}" @@ -608,7 +619,8 @@ components: earlyHeading: >- Chuyến đi đang diễn ra và sẽ đến sớm hơn {formattedDuration} so với dự kiến! - noDataHeading: Chuyến đi đang được tiến hành (không có cập nhật thời gian thực có sẵn). + noDataHeading: Chuyến đi đang được tiến hành (không có cập nhật thời gian thực + có sẵn). onTimeHeading: Chuyến đi đang được tiến hành và đúng giờ. base: lastCheckedDefaultText: Thời gian được kiểm tra lần cuối không xác định @@ -651,7 +663,8 @@ components: tripStartIsEarly: >- Thời gian bắt đầu chuyến đi đang diễn ra sớm hơn {duration} so với dự kiến! - tripStartsSoonNoUpdates: Chuyến đi đang bắt đầu sớm (không có cập nhật về thời gian thực). + tripStartsSoonNoUpdates: Chuyến đi đang bắt đầu sớm (không có cập nhật về thời + gian thực). tripStartsSoonOnTime: Chuyến đi đang bắt đầu sớm và sắp đúng giờ. TripSummary: arriveAt: "Đến nơi " From deaa9a5d52061310568ecdb4512d002f9e395e6b Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Thu, 10 Oct 2024 15:43:18 +0000 Subject: [PATCH 13/46] Translated using Weblate (Spanish) Currently translated at 100.0% (553 of 553 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/i18n/es.yml b/i18n/es.yml index 2a25daa1a..6675da344 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -30,7 +30,8 @@ actions: No se puede guardar el plan: este plan no se pudo guardar debido a la falta de capacidad en uno o más vehículos. Por favor, vuelva a planificar su viaje. - maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados válidos + maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados + válidos saveItinerariesError: "No se pudieron guardar los itinerarios: {err}" setDateError: "Error al establecer la fecha:" setGroupSizeError: "No se pudo establecer el tamaño del grupo:" @@ -52,10 +53,13 @@ actions: authTokenError: Error al obtener un token de autorización. confirmDeleteMonitoredTrip: ¿Desea eliminar este viaje? confirmDeletePlace: ¿Quiere eliminar este lugar? - emailVerificationResent: El mensaje de verificación de correo electrónico ha sido reenviado. + emailVerificationResent: El mensaje de verificación de correo electrónico ha sido + reenviado. genericError: "Se ha encontrado un error: {err}" - itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado es posible. - mustAcceptTermsToSavePlace: Acepte los Términos de uso (en Mi Cuenta) para guardar las ubicaciones. + itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado + es posible. + mustAcceptTermsToSavePlace: Acepte los Términos de uso (en Mi Cuenta) para guardar + las ubicaciones. mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. placeRemembered: La configuración de este lugar se ha guardado. preferencesSaved: Sus preferencias se han guardado. @@ -112,13 +116,12 @@ common: submitting: Enviando… "yes": Sí itineraryDescriptions: - calories: "{calories, number} kcal" fareUnknown: No hay información de las tarifas noItineraryToDisplay: No hay itinerario que mostrar. relativeCo2: > {co2} de CO₂ en {isMore, select, true {más} other {menos} } que conducir solo - transfers: "{transfers, plural, =0 {} one {# transferencia} other {# transferencias}}" + timeStartEnd: '{start} – {end}' linkOpensNewWindow: (Abre una nueva ventana) modes: bicycle_rent: Compartir bicicleta @@ -157,7 +160,6 @@ common: enterStartLocation: Introduzca la ubicación de inicio o {mapAction} en el mapa… tap: toque time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: unos segundos nDays: "{days, plural, =1 {un día} other {# días}}" @@ -201,6 +203,13 @@ components: BatchSearchScreen: header: Planifique su viaje modeSelectorLabel: Seleccione un modo de desplazamiento + moreOptions: Más opciones + saveAndReturn: Guardar y volver + saved: Guardado + tripOptions: Opciones de ruta + submodeSelectorLabel: Seleccionar modos y submodos de desplazamiento + advancedHeader: Ajustes avanzados + modeOptions: Más opciones BatchSettings: destination: destino invalidModeSelection: >- @@ -208,7 +217,8 @@ components: a incluir el transporte publico en la selección de modos. origin: origen planTripTooltip: Planificar viaje - validationMessage: "Por favor, defina los siguientes campos para planificar un viaje: {issues}" + validationMessage: "Por favor, defina los siguientes campos para planificar un + viaje: {issues}" BeforeSignInScreen: mainTitle: Iniciando sesión message: > @@ -267,7 +277,6 @@ components: ariaLabel: Navegar por los formularios ItinerarySummary: itineraryDetails: Detalles del itinerario - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: Introduzca la ubicación setDestination: Establecer el destino @@ -281,6 +290,7 @@ components: shared-vehicles: Vehículos compartidos stops: Paradas de tránsito streets: Calles + stations: Estaciones de transporte MapillaryFrame: title: Imágenes de la calle MetroUI: @@ -292,6 +302,7 @@ components: originallyScheduledTime: (originalmente {originalTime}) singleModeItineraryDescription: Viaja {time} {mode} timeWalking: "{time} caminando" + itinerarySummary: Desde {stopName} | {cost} MobileOptions: header: Configurar las opciones de búsqueda MobilityProfile: @@ -370,6 +381,7 @@ components: nearbyListIntro: Lista de {count} entidades cercanas. nothingNearby: No ubicaciónes cercanas. spacesAvailable: "{spacesAvailable} espacios libres disponibles" + headsign: '{destination}' NewAccountWizard: createNewAccount: Crear una nueva cuenta finish: ¡Configuración de la cuenta completa! @@ -549,6 +561,7 @@ components: Otro viaje guardado ya utiliza este nombre. Por favor, elija un nombre diferente. tripNameRequired: Por favor, introduzca el nombre del viaje. + selectAtLeastOneDay: Por favor, seleccione al menos un día para realizar el seguimiento. SequentialPaneDisplay: stepNumber: Paso {step} de {total} SessionTimeout: @@ -558,7 +571,8 @@ components: header: ¡La sesión está a punto de terminar! keepSession: Continuar sesión SimpleRealtimeAnnotation: - usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo real + usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo + real StackedPaneDisplay: savePreferences: Guardar preferencias StopScheduleTable: @@ -620,15 +634,18 @@ components: travelingAt: Viajando a {milesPerHour} vehicleName: Vehículo {vehicleNumber} TripBasicsPane: - checkingItineraryExistence: Comprobación de la existencia de itinerarios para cada día de la semana… + checkingItineraryExistence: Comprobación de la existencia de itinerarios para + cada día de la semana… tripDaysPrompt: ¿Qué días hace este viaje? - tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana indicados anteriormente. + tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana + indicados anteriormente. tripNamePrompt: "Por favor, indique un nombre para este viaje:" tripNotAvailableOnDay: El viaje no está disponible el {repeatedDay} unsavedChangesExistingTrip: >- Todavía no ha guardado su viaje. Si abandona la página, los cambios se perderán. - unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, se perderá. + unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, + se perderá. TripNotificationsPane: advancedSettings: Configuración avanzada altRouteRecommended: Se recomienda una ruta alternativa o un punto de transferencia @@ -694,11 +711,15 @@ components: El viaje debe comenzar a las {tripStart, time, short}. (El seguimiento en tiempo real comenzará a las {monitoringStart, time, short}.) tripStartIsDelayed: ¡La hora de inicio del viaje se retrasa {duration}! - tripStartIsEarly: ¡La hora de inicio del viaje se produce {duration} antes de lo previsto! + tripStartIsEarly: ¡La hora de inicio del viaje se produce {duration} antes de + lo previsto! tripStartsSoonNoUpdates: >- El viaje comienza pronto (no hay actualizaciones disponibles en tiempo real). tripStartsSoonOnTime: El viaje comienza pronto y es más o menos puntual. + past: + heading: Viaje realizado + description: Un viaje que ocurrió el pasado. TripSummary: arriveAt: "Llegue a las " leaveAt: "Salida a las " From 3f6d69d72d9592ab5e64598844430696d0ee9c0a Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Thu, 10 Oct 2024 15:14:45 +0000 Subject: [PATCH 14/46] Translated using Weblate (Spanish) Currently translated at 100.0% (553 of 553 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/es.yml b/i18n/es.yml index 6675da344..9ba66b675 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -646,6 +646,8 @@ components: perderán. unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, se perderá. + onlyOnDate: Solo el {date, date, ::eeeee yyyyMMdd} + recurringEachWeek: En ciertos días de cada semana TripNotificationsPane: advancedSettings: Configuración avanzada altRouteRecommended: Se recomienda una ruta alternativa o un punto de transferencia From 13c464f03d6f7747275056c4d7ce9327b5134c25 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Thu, 10 Oct 2024 15:44:32 +0000 Subject: [PATCH 15/46] Translated using Weblate (Spanish) Currently translated at 100.0% (553 of 553 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/es.yml b/i18n/es.yml index 9ba66b675..c8059863b 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -647,7 +647,7 @@ components: unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, se perderá. onlyOnDate: Solo el {date, date, ::eeeee yyyyMMdd} - recurringEachWeek: En ciertos días de cada semana + recurringEachWeek: Algunos días de la semana TripNotificationsPane: advancedSettings: Configuración avanzada altRouteRecommended: Se recomienda una ruta alternativa o un punto de transferencia From 973aad8fc9de424e5aedcec43271972882ba7272 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 18 Oct 2024 17:33:51 +0000 Subject: [PATCH 16/46] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/ --- i18n/ko.yml | 10 ++++------ i18n/tl.yml | 28 ++++++++++++++++------------ i18n/zh_Hans.yml | 4 ---- i18n/zh_Hant.yml | 4 ---- 4 files changed, 20 insertions(+), 26 deletions(-) diff --git a/i18n/ko.yml b/i18n/ko.yml index e333e7e62..6b2288763 100644 --- a/i18n/ko.yml +++ b/i18n/ko.yml @@ -22,7 +22,8 @@ actions: fetchFieldTripsError: "트립을 가져오는 중에 오류가 발생했습니다: {err}" fetchTripsForDateError: "필트 트립 날짜에 대한 트립을 가져오는 중에 오류가 발생했습니다: {err}" incompatibleTripDateError: 계획한 트립 날짜({tripDate})가 요청한 트립 날짜({requestDate})가 아닙니다 - itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. 트립을 다시 계획하세요." + itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. + 트립을 다시 계획하세요." maxTripRequestsExceeded: 유효한 결과없이 초과된 트립 요청의 개수 saveItinerariesError: "트립을 저장하는 데 실패했습니다: {err}" setDateError: "날짜를 설정하는 중에 오류가 발생했습니다:" @@ -99,12 +100,10 @@ common: submitting: 제출 중… "yes": 예 itineraryDescriptions: - calories: "{calories, number} 칼로리" fareUnknown: 운임 정보 없음 noItineraryToDisplay: 표시할 일정이 없습니다. relativeCo2: | {co2} CO₂ 를 자동차보다 {isMore, select, true {더} other {덜} } 사용합니다 - transfers: "{transfers, plural, =0 {} other {# 전송}}" linkOpensNewWindow: (새 창 열림) modes: bicycle_rent: 공유자전거 @@ -143,7 +142,6 @@ common: enterStartLocation: 시작 위치 또는 {mapAction}을(를) 지도에 입력하십시오… tap: 클릭 time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: 몇 초 nDays: "{days} 일" @@ -244,7 +242,6 @@ components: ariaLabel: 내비게이션 양식 ItinerarySummary: itineraryDetails: 여정 세부 정보 - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: 위치 입력 setDestination: 목적지 선택 @@ -685,5 +682,6 @@ util: networkUnavailable: 현재 {network} 네트워크를 사용할 수 없습니다. noTripFound: 트립을 찾을 수 없습니다. noTripFoundForMode: "{modes}의 트립을 찾을 수 없습니다." - noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 못할 수 있습니다. + noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 + 못할 수 있습니다. noTripFoundWithReason: "{noTripFound} {reason}" diff --git a/i18n/tl.yml b/i18n/tl.yml index d1e65084a..87e851dce 100644 --- a/i18n/tl.yml +++ b/i18n/tl.yml @@ -45,7 +45,8 @@ actions: confirmDeletePlace: Gusto mo bang alisin ang lugar na ito? emailVerificationResent: Ipinadala ulit ang mensahe ng pag-verify sa email. genericError: "Nagka-error: {err}" - itineraryExistenceCheckFailed: Nagka-error sa pagtingin kung posible ang napili mong biyahe. + itineraryExistenceCheckFailed: Nagka-error sa pagtingin kung posible ang napili + mong biyahe. mustAcceptTermsToSavePlace: >- Pakitanggap ang Mga Tuntunin ng Paggamit (sa ilalim ng Aking Account) para mag-save ng mga lokasyon. @@ -106,13 +107,11 @@ common: submitting: Isinusumite… "yes": Oo itineraryDescriptions: - calories: "{calories, number} Cal" fareUnknown: Walang impormasyon sa pamasahe noItineraryToDisplay: Walang ipapakitang itinerary. relativeCo2: > {co2} {isMore, select, true {mas maraming} other {mas kaunting} } CO₂ kaysa magmaneho nang mag-isa - transfers: "{transfers, plural, =0 {} one {# transfer} other {# transfers}}" linkOpensNewWindow: (Magbubukas sa bagong window) modes: bicycle_rent: Bikeshare @@ -151,7 +150,6 @@ common: enterStartLocation: Ilagay ang lokasyon ng pagsisimula o {mapAction} sa mapa… tap: tap time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: a few seconds nDays: "{days, plural, =1 {one day} other {# days}}" @@ -204,7 +202,8 @@ components: ang pampublikong transportasyon sa pagpili mo ng mode. origin: pinagmulan planTripTooltip: Planuhin ang biyahe - validationMessage: "Ilarawan ang mga sumusunod na field para makapagplano ng biyahe: {issues}" + validationMessage: "Ilarawan ang mga sumusunod na field para makapagplano ng biyahe: + {issues}" BeforeSignInScreen: mainTitle: Sina-sign in ka message: > @@ -263,7 +262,6 @@ components: ariaLabel: Pag-navigate sa form ItinerarySummary: itineraryDetails: Mga detalye ng itinerary - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: Ilagay ang lokasyon setDestination: Itakda ang Patutunguhan @@ -397,7 +395,8 @@ components: invalidPhone: Maglagay ng valid na numero ng telepono. pending: Nakabinbin phoneNumberSubmitted: Matagumpay na naisumite ang numero ng teleponong {phoneNumber}. - phoneNumberVerified: Matagumpay na na-verify ang numero ng teleponong {phoneNumber} . + phoneNumberVerified: Matagumpay na na-verify ang numero ng teleponong {phoneNumber} + . placeholder: Ilagay ang numero ng iyong telepono prompt: "Ilagay ang numero ng iyong telepono para sa mga SMS na notification:" requestNewCode: Humiling ng bagong code @@ -583,9 +582,11 @@ components: travelingAt: Bumibiyahe nang {milesPerHour} vehicleName: Sasakyan {vehicleNumber} TripBasicsPane: - checkingItineraryExistence: Tinitingnan kung may itinerary para sa bawat araw ng linggo... + checkingItineraryExistence: Tinitingnan kung may itinerary para sa bawat araw + ng linggo... tripDaysPrompt: Anong mga araw mo ginagawa ang biyaheng ito? - tripIsAvailableOnDaysIndicated: Available ang iyong biyahe sa mga araw ng linggo na nakasaad sa itaas. + tripIsAvailableOnDaysIndicated: Available ang iyong biyahe sa mga araw ng linggo + na nakasaad sa itaas. tripNamePrompt: "Pangalanan ang biyaheng ito:" tripNotAvailableOnDay: Hindi available ang biyahe sa {repeatedDay} unsavedChangesExistingTrip: >- @@ -630,7 +631,8 @@ components: unknownState: Hindi Alam ang Status ng Biyahe untogglePause: Ipagpatuloy inactive: - description: Ipagpatuloy ang pagsubaybay sa biyahe para makita ang updated na status + description: Ipagpatuloy ang pagsubaybay sa biyahe para makita ang updated na + status heading: Naka-pause ang pagsubaybay sa biyahe nextTripNotPossible: description: > @@ -649,7 +651,8 @@ components: description: Hinihintay na makalkula ang biyahe. heading: Hindi pa nakakalkula ang biyahe snoozed: - description: I-unsnooze ang pagsubaybay sa biyahe para makita ang updated na status. + description: I-unsnooze ang pagsubaybay sa biyahe para makita ang updated na + status. heading: Naka-snooze ang pagsubaybay sa biyahe ngayong araw upcoming: nextTripBegins: >- @@ -659,7 +662,8 @@ components: Magsisimula ang biyahe nang {tripStart, time, short}. (Magsisimula ang realtime na pagsubaybay nang {monitoringStart, time, short}.) tripStartIsDelayed: Naantala ang oras ng pagsisimula ng biyahe nang {duration}! - tripStartIsEarly: Nagsisimula na ang biyahe {duration} na mas maaga kaysa sa inaasahan! + tripStartIsEarly: Nagsisimula na ang biyahe {duration} na mas maaga kaysa sa + inaasahan! tripStartsSoonNoUpdates: >- Malapit nang magsimula ang biyahe (walang realtime na update na available). diff --git a/i18n/zh_Hans.yml b/i18n/zh_Hans.yml index 47464fc2c..1458db732 100644 --- a/i18n/zh_Hans.yml +++ b/i18n/zh_Hans.yml @@ -99,12 +99,10 @@ common: submitting: 正在提交… "yes": 是 itineraryDescriptions: - calories: "{calories, number} 大卡" fareUnknown: 无票价信息 noItineraryToDisplay: 没有显示行程. relativeCo2: | {co2} {isMore, select, true {更多} other {更少} } CO₂ 比单独驾车 - transfers: "{transfers, plural, =0 {} other {# 换乘}}" linkOpensNewWindow: (打开新窗口) modes: bicycle_rent: 共享单车 @@ -143,7 +141,6 @@ common: enterStartLocation: 输入出发地点或{mapAction}地图… tap: 点击 time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: 几秒钟 nDays: "{days} 天" @@ -244,7 +241,6 @@ components: ariaLabel: 表格导航 ItinerarySummary: itineraryDetails: 行程详情 - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: 输入位置 setDestination: 设置目的地 diff --git a/i18n/zh_Hant.yml b/i18n/zh_Hant.yml index e625d04c7..b94f45d0a 100644 --- a/i18n/zh_Hant.yml +++ b/i18n/zh_Hant.yml @@ -99,12 +99,10 @@ common: submitting: 正在提交… "yes": 是 itineraryDescriptions: - calories: "{calories, number}卡" fareUnknown: 無票價資訊 noItineraryToDisplay: 沒有預定行程可顯示。 relativeCo2: | {co2}比單獨開車排放的CO₂{isMore, select, true {要多} other {少}} - transfers: "{transfers}次轉乘" linkOpensNewWindow: (開啟新視窗) modes: bicycle_rent: 自行車共享 @@ -143,7 +141,6 @@ common: enterStartLocation: 輸入開始位置或{mapAction} 地圖…… tap: 輕觸 time: - departureArrivalTimes: "{startTime, time, short}—{endTime, time, short}" duration: aFewSeconds: 幾秒鐘 nDays: "{days}天" @@ -244,7 +241,6 @@ components: ariaLabel: 表單導航 ItinerarySummary: itineraryDetails: 路線詳細資訊 - minMaxFare: "{minTotalFare} - {maxTotalFare}" LocationSearch: enterLocation: 輸入位置 setDestination: 設定目的地 From aca5acffd21824843d4bcad727a258762c5caa81 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Fri, 18 Oct 2024 17:58:09 +0000 Subject: [PATCH 17/46] Translated using Weblate (Spanish) Currently translated at 100.0% (554 of 554 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/es.yml b/i18n/es.yml index c8059863b..7d9dbc970 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -816,6 +816,8 @@ components: switcher: Botón de cambio WelcomeScreen: prompt: ¿A donde quiere ir? + TripPreviewLayout: + previewTrip: Vista previa del viaje config: accessModes: bicycle: Tránsito + Bicicleta Personal From 8ce18b29279bbed75f9e5a1fec47c0c7621d4024 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Thu, 14 Nov 2024 16:24:50 -0500 Subject: [PATCH 18/46] address pr feedback --- lib/components/form/call-taker/date-time-picker.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/components/form/call-taker/date-time-picker.tsx b/lib/components/form/call-taker/date-time-picker.tsx index ea310ef99..7cf2101e8 100644 --- a/lib/components/form/call-taker/date-time-picker.tsx +++ b/lib/components/form/call-taker/date-time-picker.tsx @@ -8,8 +8,8 @@ import coreUtils from '@opentripplanner/core-utils' import React, { useEffect, useRef, useState } from 'react' import * as narriativeActions from '../../../actions/narrative' +import { AppReduxState, FilterType, SortType } from '../../../util/state-types' import { DepartArriveTypeMap, DepartArriveValue } from '../date-time-modal' -import { FilterType, SortType } from '../../../util/state-types' const { getCurrentDate, OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } = coreUtils.time @@ -304,8 +304,9 @@ const DateTimeOptions = ({ } // connect to the redux store -const mapStateToProps = (state: any) => { +const mapStateToProps = (state: AppReduxState) => { const { dateTime, homeTimezone, itinerary } = state.otp.config + // @ts-expect-error TS doesn't understand it's fine if this value is undefined const { syncSortWithDepartArrive } = itinerary const { sort } = state.otp.filter return { From ac2e27457caee17edf9e634404b52c91b1049570 Mon Sep 17 00:00:00 2001 From: Daniel Heppner Date: Mon, 18 Nov 2024 17:43:04 -0500 Subject: [PATCH 19/46] fix typescript for @miles-grant-ibigroup --- .../form/call-taker/date-time-picker.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/components/form/call-taker/date-time-picker.tsx b/lib/components/form/call-taker/date-time-picker.tsx index 7cf2101e8..3fddd8444 100644 --- a/lib/components/form/call-taker/date-time-picker.tsx +++ b/lib/components/form/call-taker/date-time-picker.tsx @@ -1,5 +1,5 @@ import { connect } from 'react-redux' -import { format, toDate } from 'date-fns-tz' +import { format, OptionsWithTZ, toDate } from 'date-fns-tz' import { getCurrentTime } from '@opentripplanner/core-utils/lib/time' import { IntlShape, useIntl } from 'react-intl' import { isMatch, parse } from 'date-fns' @@ -60,7 +60,7 @@ const SUPPORTED_TIME_FORMATS = [ 'HH:mm' ] -const safeFormat = (date: Date | '', time: string, options: any) => { +const safeFormat = (date: Date | '', time: string, options?: OptionsWithTZ) => { if (date === '') return '' try { return format(date, time, options) @@ -72,7 +72,7 @@ const safeFormat = (date: Date | '', time: string, options: any) => { type Props = { date?: string - departArrive?: string + departArrive?: DepartArriveValue homeTimezone: string onKeyDown: () => void setQueryParam: ({ @@ -116,7 +116,7 @@ const DateTimeOptions = ({ timeFormat, updateItineraryFilter }: Props) => { - const [departArrive, setDepartArrive] = useState( + const [departArrive, setDepartArrive] = useState( initialDate || initialTime ? 'DEPART' : 'NOW' ) const [date, setDate] = useState(initialDate) @@ -200,12 +200,12 @@ const DateTimeOptions = ({ if ( syncSortWithDepartArrive && - DepartArriveTypeMap[departArrive as DepartArriveValue] !== sort.type + DepartArriveTypeMap[departArrive] !== sort.type ) { updateItineraryFilter({ sort: { ...sort, - type: DepartArriveTypeMap[departArrive as DepartArriveValue] + type: DepartArriveTypeMap[departArrive] } }) } @@ -231,8 +231,8 @@ const DateTimeOptions = ({ return ( <>