A library for writing modern OpenTripPlanner-compatible multimodal journey planning applications using React and Redux.
An example of an OTP-RR application is included in the repository. The example project is a single page application with a root entry point of the example.js
file. This example.js file can be modified to suit the needs of a particular implementation.
To run, first clone the repo and install yarn if needed.
Update example-config.yml
with the needed API keys, and optionally, the OTP endpoint and initial map origin. (The default values are for a test server for Portland, OR.). See the comments at the head of the config file for further details.
Install the dependencies and start a local development server using the following script:
yarn start
The port on which the development server listens can be configured in .env
.
Should you want to maintain multiple configuration files, OTP-RR can be made to use a custom config file by using environment variables. Other environment variables also exist. CUSTOM_CSS
can be used to point to a css file to inject, and JS_CONFIG
can be used to point to a config.js
file to override the one shipped with OTP-RR.
env YAML_CONFIG=/absolute/path/to/config.yml yarn start
Build a production js/css bundle by running yarn build
. The build will appear in the dist/
directory). It consists entirely of static files and can be served by a simple static web server or CDN.
The same environment variables which affect the behavior of yarn start
also affect yarn build
. Running the following command builds OTP-RR with customized js and css:
env JS_CONFIG=my-custom-js.js CUSTOM_CSS=my-custom-css.css yarn build
OTP-react-redux uses react-intl
from the formatjs
library for internationalization.
Both react-intl
and formatjs
take advantage of native internationalization features provided by web browsers.
The example application supports several different languages out of the box, but language selection must be enabled. See the language
section of the YAML config. Once enabled, the application will first check the lang
key in window.localstorage
for ISO language codes such as fr
or es
matching files in the i18n directory, then fall back on the navigator.language
that is typically configured via your web browser's settings, before finally falling back on the localization: defaultLocale
item defined in example-config.yml
.
Language-specific content is located in YML files under the i18n
folder
(e.g. en-US.yml
for American English, fr.yml
for generic French, etc.).
In each of these files:
- Messages are organized in various categories and sub-categories.
- A component or JS module can use messages from one or more categories.
- In the code, messages are retrieved using an ID that is simply the path to the message.
Use the dot '.' to separate categories and sub-categories in the path.
For instance, for the message defined in YML below:
then use the snippet below with the corresponding message id:
common modes subway: Metro
<FormattedMessage id="common.modes.subway" /> // renders "Metro".
In these YML files, it is important that message ids in the code be consistent with the categories in this file. Below are some general guidelines:
- For starters, there are an
actions
,common
,components
, andconfig
categories. Additional categories may be added as needed. - Each sub-category under
components
denotes a React component and should contain messages that are used only by that component (e.g. button captions). - In contrast, some strings are common to multiple components,
so it makes sense to group them by theme (e.g. accessModes) under the
common
category.
Note: Do not put comments in the YML files! They will be removed by yaml-sort
.
Instead, comments for other developers should be placed in the corresponding js/jsx/ts/tsx file.
Comments for translators should be entered into Weblate (see Contributing Translations)
Most textual content from the i18n
folder can also be customized on a per-configuration basis
using the language
section of config.yml
, whether for all languages at once,
or for each supported individual language.
Use message id literals (no variables or other dynamic content) with either
<FormattedMessage id="..." />
or
intl.formatMessage({ id: ... })
The reason for passing literals to FormattedMessage
and intl.formatMessage
is that we have a checker script yarn check:i18n
that is based on the formatJS
CLI and that detects unused messages in the code and exports translation tables.
Passing variables or dynamic content will cause the formatJS
CLI and the checker to ignore the corresponding messages and
incorrectly claim that a string is unused or missing from a translation file.
One exception to this rule concerns configuration settings where message ids can be constructed dynamically.
OTP-react-redux now uses Hosted Weblate to manage translations!
Translation status for OTP-react-redux and OTP-UI on Hosted WeblateTranslations from the community are welcome and very much appreciated,
please see instructions at https://hosted.weblate.org/projects/otp-react-redux/.
Community input from Weblate will appear as pull requests with changes to files in the i18n
folder for our review.
(Contributions may be edited or rejected to remain in line with long-term project goals.)
If changes to a specific language file is needed but not enabled in Weblate, please open an issue or a pull request with the changes needed.
You can chat with the main OTP-RR developers in our Gitter chat. Support is not guaranteed, but we may be able to answer questions and assist people wishing to make contributions.
As of version 2.0, otp-react-redux utilizes React's context API in a number of components. This changed the way that some components receive props such that they will not work properly unless wrapped with the context provider used in the ResponsiveWebapp
component.