summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md186
-rw-r--r--doc/contributing.md33
-rw-r--r--doc/setup.md136
-rw-r--r--doc/usage.md34
-rwxr-xr-xlib/Travelynx.pm12
-rw-r--r--lib/Travelynx/Command/translation.pm7
-rwxr-xr-xlib/Travelynx/Model/Journeys.pm14
-rw-r--r--share/locales/de_DE.po14
-rw-r--r--share/locales/en_GB.po14
-rw-r--r--share/locales/reference.md40
-rw-r--r--share/locales/template.pot48
-rw-r--r--templates/changelog.html.ep16
12 files changed, 359 insertions, 195 deletions
diff --git a/README.md b/README.md
index a8e5bc7..aaf37b0 100644
--- a/README.md
+++ b/README.md
@@ -13,183 +13,13 @@ Instances](https://finalrewind.org/projects/Travel-Status-DE-HAFAS/). Support
for EFA instances and bahn.de is under way.
You can use the public instance on [travelynx.de](https://travelynx.de) or
-host your own. See the Installation and Setup notes below.
+host your own. Further reading:
-Dependencies
----
-
- * perl ≥ 5.20
- * carton
- * build-essential
- * libpq-dev
- * git
-
-Installation
----
-
-travelynx depends on a set of Perl modules which are documented in `cpanfile`.
-After installing the dependencies mentioned above, you can use carton to
-install Perl depenencies locally. You may alsobe able to use cpanminus;
-however this method is untested.
-
-In the project root directory (where `cpanfile` resides), run
-
-```
-carton install --deployment
-```
-
-and set `PERL5LIB=.../local/lib/perl5` before executing any travelynx
-commands (see configs in the examples directory) or wrap them with `carton
-exec`, e.g. `carton exec hypnotoad index.pl`
-
-Setup
----
-
-First, you need to set up a PostgreSQL database so that travelynx can store
-user accounts and journeys. It must be at least version 9.4 and must use a
-UTF-8 locale. The following steps describe setup on a Debian 9 system;
-setup on other distributions should be similar.
-
-* Write down a strong random password
-* Create a postgres user for travelynx: `sudo -u postgres createuser -P travelynx`
- (enter password when prompted)
-* Create the database: `sudo -u postgres createdb -O travelynx travelynx`
-* Copy `examples/travelynx.conf` to the application root directory
- (the one in which `index.pl` resides) and edit it. Make sure to configure
- db, cache, mail, and secrets.
-* Initialize the database: `carton exec perl index.pl database migrate`
- or `PERL5LIB=local/lib/perl5 perl index.pl database migrate`
+* [Contributing](doc/contributing.md) to travelynx development
+* [Setup](doc/setup.md) for hosting your own instance
+* [Usage](doc/usage.md) primer (what is this whole “checking in” about?)
-Your server also needs to be able to send mail. Set up your MTA of choice and
-make sure that the sendmail binary can be used for outgoing mails. Mail
-reception on the server is not required.
-
-Finally, configure the web service:
-
-* Set up a travelynx service using the service supervisor of your choice
- (see `examples/travelynx.service` for a systemd unit file)
-* Configure your web server to reverse-provy requests to the travelynx
- instance. See `examples/nginx-site` for an nginx config.
-* Install a `timeout 5m perl index.pl work -m production` cronjob. It is used
- to update realtime data and perform automatic checkout and should run
- every three minutes or so, see `examples/cron`.
-
-You can now start the travelynx service, navigate to the website and register
-your first account. There is no admin account, all management is performed
-via cron or (in non-standard cases) on the command line.
-
-Please open an issue on <https://github.com/derf/travelynx/issues> or send a
-mail to derf+travelynx@finalrewind.org if there is anything missing or
-ambiguous in this setup manual.
-
-Note that Deutsche Bahn have put parts of their API behind an IP reputation
-filter. In general, checkins with the bahn.de backend will only be possible if
-travelynx is accessing it from a residential (non-server) IP range. See the
-dbris bahn.de proxy / proxies setting in `example/travelynx.conf` for
-workarounds.
-
-Updating
----
-
-It is recommended to run travelynx directly from the git repository. When
-updating, the workflow depends on whether schema updates need to be applied
-or not.
-
-```
-git pull
-carton install --deployment # if you are using carton: update dependencies
-chmod -R a+rX . # only needed if travelynx is running under a different user
-if perl index.pl database has-current-schema; then
- systemctl reload travelynx
-else
- systemctl stop travelynx
- perl index.pl database migrate
- systemctl start travelynx
-fi
-```
-
-Note that this is subject to change -- the application may perform schema
-updates automatically in the future. If you used carton for installation,
-use `carton exec perl ...` in the snippet above; otherwise, export
-`PERL5LIB=.../local/lib/perl5`.
-
-Setup with Docker
----
-
-Note that travelynx Docker support is experimental and, in its current form,
-far from best practices. Pull requests are appreciated.
-
-First, you need to set up a PostgreSQL database so that travelynx can store
-user accounts and journeys. It must be at least version 9.4 and must use a
-UTF-8 locale. See above (or `examples/docker/postgres-init.sh`) for database
-initialization. You do not need to perform the `database migrate` step.
-
-Next, you need to prepare three files that will be mounted into the travelynx
-container: travelynx configuration, e-mail configuration, and imprint and
-privacy policy. For the sake of this readme, we assume that you are using the
-`local/` directory to store these
-
-* `mkdir local`
-* copy examples/travelynx.conf to local/travelynx.conf and configure it.
-* copy examples/docker/email-transport.sh to local/email-transport.sh and configure it.
- The travelynx container does not contain a mail server, so it needs a
- separate SMTP server to send mail. It does not receive mail.
-* create local/imprint.html.ep and enter imprint as well as privacy policy data.
-* create local/terms-of-service.html.ep and enter your terms of service.
-* Configure your web server to reverse-provy requests to the travelynx
- instance. See `examples/nginx-site` for an nginx config.
-
-travelynx consists of two runtimes: the web application and a background
-worker. Your service supervisor (or docker compose / docker stack / kubernetes
-setup) should orchestrate them somewhere along these lines.
-
-* `docker pull derfnull/travelynx:latest`
-* Start web application: `docker run -p 8093:8093 -v ${PWD}/local:/local:ro travelynx:latest`
-* Wait until localhost:8093 responds to requests
-* Start worker: `docker run -v ${PWD}/local:/local:ro travelynx:latest worker`
-
-To install an update: stop worker and web application, update the travelynx
-image, and start them again. Database migrations will be performed
-automatically. Note that downgrades are not supported.
-
-Usage
----
-
-For the sake of this manual, we will assume your travelynx instance is running
-on `travelynx.de`
-
-travelynx journey logging is based on checkin and checkout actions: You check
-into a train when boarding it, select a destination, and are automatically
-checked out when you arrive. Real-time data is saved on both occasions and
-continuously updated while in transit, providing an accurate overview of both
-scheduled and actual journey times.
-
-## Checking in
-
-You can check into a train up to 30 minutes before its scheduled departure and
-up to two hours after its actual departure (including delays).
-
-First, you need to select the station you want to check in from.
-Navigate to `travelynx.de` or click/tap on the travelynx text in the navigation
-bar. You will see a list of the five stations closest to your current location
-(as reported by your browser). Select the station you're at or enter its
-name or DS100 code manually.
-
-As soon as you select a train, you will be checked in and travelynx will switch
-to the journey / checkout view. If you already know where you're headed, you
-should click/tap on the destination station in the station list now. You can
-change the destination by selecting a new one anytime.
-
-## Checking out
-
-You are automatically checked out a few minutes after arrival at your
-destination. If the train has already arrived when you select a destination and
-its arrival was less than two hours ago, you are checked out immediately. If
-it's more than two hours, you need to perform a manual checkout (without
-arrival data) using the link at the bottom of the checkin menu's station list.
-
-Testing
----
+## Testing
The test scripts assume that travelynx.conf contains a valid database
connection. They will create a test-specific schema, perform all operations in
@@ -202,8 +32,7 @@ Please use a separate development database instead.
Run the tests by executing `prove`. Use `prove -v` for debug output and
`DBI_TRACE=SQL prove -v` to monitor SQL queries.
-Licensing
----
+## Licensing
The copyright of individual files is documented in the file's header or in
.reuse/dep5. The referenced licenses are stored in the LICENSES directory.
@@ -223,8 +52,7 @@ The easiest way of making changes available is by maintaining a public fork of
the Git repository. A tarball is also acceptable. Please change the `source`
ref in travelynx.conf if you are using a fork with custom changes.
-References
----
+## References
Mirrors of the travelynx repository are maintained at the following locations:
diff --git a/doc/contributing.md b/doc/contributing.md
new file mode 100644
index 0000000..a31ed4f
--- /dev/null
+++ b/doc/contributing.md
@@ -0,0 +1,33 @@
+# Contributing to travelynx Development
+
+First, a note upfront: travelynx is a hobby project.
+While I appreciate suggestions, bug reports, and merge requests / patches, I want to make sure that it remains a hobby project and does not turn into a chore.
+As such, please do not expect a timely response to anything you submit.
+I typically only address issues and merge requests when I have the capacity for them _and_ when doing so does not feel like a chore.
+
+That being said, I do appreciate bug reports, feature requests, and (simple!) patches, even if I may take quite a while to address or review them.
+If you are planning a more involved patch set, please get in touch first.
+
+## Translations
+
+This is probably the easiest way to improve the life of any travelynx users who are not native German speakers.
+Note that travelynx does _not_ use Weblate.
+
+### Updating or Extending Translations
+
+* Look at the [translation reference](../share/locales/reference.md)
+* Pick a language that you'd like to fix / update / extend
+* Adjust the corresponding `share/locales/ab-CD.po` file
+* Open a merge request, either on [Codeberg](https://codeberg.org/derf/travelynx/pulls) or [GitHub](https://github.com/derf/travelynx/pulls)
+
+### Adding a new Language
+
+* Copy `share/locales/template.pot` to `share/locales/ab-CD.po`, replacing ab-CD with the appropriate language code
+* Add the language / locale to `$self->helper(loc_handle …` in `lib/Travelynx.pm`
+* Add the language / locale to `templates/language.html.ep`
+* Provide as many translations as you feel comfortable with – partial translation files are fine; any entry left as `msgstr ""` will cause travelynx to fall back to English or German.
+* Open a merge request, either on [Codeberg](https://codeberg.org/derf/travelynx/pulls) or [GitHub](https://github.com/derf/travelynx/pulls)
+
+## Bug Reports
+
+You may report bugs and request features either on [Codeberg](https://codeberg.org/derf/travelynx/issues) or [GitHub](https://github.com/derf/travelynx/issues).
diff --git a/doc/setup.md b/doc/setup.md
new file mode 100644
index 0000000..82a2348
--- /dev/null
+++ b/doc/setup.md
@@ -0,0 +1,136 @@
+# Hosting your own travelynx
+
+This document describes how to host your own travelynx instance.
+
+## Dependencies
+
+ * perl ≥ 5.20
+ * carton
+ * build-essential
+ * libpq-dev
+ * git
+
+## Installation
+
+travelynx depends on a set of Perl modules which are documented in `cpanfile`.
+After installing the dependencies mentioned above, you can use carton to
+install Perl depenencies locally. You may alsobe able to use cpanminus;
+however this method is untested.
+
+In the project root directory (where `cpanfile` resides), run
+
+```
+carton install --deployment
+```
+
+and set `PERL5LIB=.../local/lib/perl5` before executing any travelynx
+commands (see configs in the examples directory) or wrap them with `carton
+exec`, e.g. `carton exec hypnotoad index.pl`
+
+## Setup
+
+First, you need to set up a PostgreSQL database so that travelynx can store
+user accounts and journeys. It must be at least version 9.4 and must use a
+UTF-8 locale. The following steps describe setup on a Debian 9 system;
+setup on other distributions should be similar.
+
+* Write down a strong random password
+* Create a postgres user for travelynx: `sudo -u postgres createuser -P travelynx`
+ (enter password when prompted)
+* Create the database: `sudo -u postgres createdb -O travelynx travelynx`
+* Copy `examples/travelynx.conf` to the application root directory
+ (the one in which `index.pl` resides) and edit it. Make sure to configure
+ db, cache, mail, and secrets.
+* Initialize the database: `carton exec perl index.pl database migrate`
+ or `PERL5LIB=local/lib/perl5 perl index.pl database migrate`
+
+Your server also needs to be able to send mail. Set up your MTA of choice and
+make sure that the sendmail binary can be used for outgoing mails. Mail
+reception on the server is not required.
+
+Finally, configure the web service:
+
+* Set up a travelynx service using the service supervisor of your choice
+ (see `examples/travelynx.service` for a systemd unit file)
+* Configure your web server to reverse-provy requests to the travelynx
+ instance. See `examples/nginx-site` for an nginx config.
+* Install a `timeout 5m perl index.pl work -m production` cronjob. It is used
+ to update realtime data and perform automatic checkout and should run
+ every three minutes or so, see `examples/cron`.
+
+You can now start the travelynx service, navigate to the website and register
+your first account. There is no admin account, all management is performed
+via cron or (in non-standard cases) on the command line.
+
+Please open an issue on <https://github.com/derf/travelynx/issues> or send a
+mail to derf+travelynx@finalrewind.org if there is anything missing or
+ambiguous in this setup manual.
+
+Note that Deutsche Bahn have put parts of their API behind an IP reputation
+filter. In general, checkins with the bahn.de backend will only be possible if
+travelynx is accessing it from a residential (non-server) IP range. See the
+dbris bahn.de proxy / proxies setting in `example/travelynx.conf` for
+workarounds.
+
+## Updating
+
+It is recommended to run travelynx directly from the git repository. When
+updating, the workflow depends on whether schema updates need to be applied
+or not.
+
+```
+git pull
+carton install --deployment # if you are using carton: update dependencies
+chmod -R a+rX . # only needed if travelynx is running under a different user
+if perl index.pl database has-current-schema; then
+ systemctl reload travelynx
+else
+ systemctl stop travelynx
+ perl index.pl database migrate
+ systemctl start travelynx
+fi
+```
+
+Note that this is subject to change -- the application may perform schema
+updates automatically in the future. If you used carton for installation,
+use `carton exec perl ...` in the snippet above; otherwise, export
+`PERL5LIB=.../local/lib/perl5`.
+
+## Setup with Docker
+---
+
+Note that travelynx Docker support is experimental and, in its current form,
+far from best practices. Pull requests are appreciated.
+
+First, you need to set up a PostgreSQL database so that travelynx can store
+user accounts and journeys. It must be at least version 9.4 and must use a
+UTF-8 locale. See above (or `examples/docker/postgres-init.sh`) for database
+initialization. You do not need to perform the `database migrate` step.
+
+Next, you need to prepare three files that will be mounted into the travelynx
+container: travelynx configuration, e-mail configuration, and imprint and
+privacy policy. For the sake of this readme, we assume that you are using the
+`local/` directory to store these
+
+* `mkdir local`
+* copy examples/travelynx.conf to local/travelynx.conf and configure it.
+* copy examples/docker/email-transport.sh to local/email-transport.sh and configure it.
+ The travelynx container does not contain a mail server, so it needs a
+ separate SMTP server to send mail. It does not receive mail.
+* create local/imprint.html.ep and enter imprint as well as privacy policy data.
+* create local/terms-of-service.html.ep and enter your terms of service.
+* Configure your web server to reverse-provy requests to the travelynx
+ instance. See `examples/nginx-site` for an nginx config.
+
+travelynx consists of two runtimes: the web application and a background
+worker. Your service supervisor (or docker compose / docker stack / kubernetes
+setup) should orchestrate them somewhere along these lines.
+
+* `docker pull derfnull/travelynx:latest`
+* Start web application: `docker run -p 8093:8093 -v ${PWD}/local:/local:ro travelynx:latest`
+* Wait until localhost:8093 responds to requests
+* Start worker: `docker run -v ${PWD}/local:/local:ro travelynx:latest worker`
+
+To install an update: stop worker and web application, update the travelynx
+image, and start them again. Database migrations will be performed
+automatically. Note that downgrades are not supported.
diff --git a/doc/usage.md b/doc/usage.md
new file mode 100644
index 0000000..2d8bb42
--- /dev/null
+++ b/doc/usage.md
@@ -0,0 +1,34 @@
+# travelynx primer
+
+For the sake of this manual, we will assume your travelynx instance is running
+on `travelynx.de`
+
+travelynx journey logging is based on checkin and checkout actions: You check
+into a train when boarding it, select a destination, and are automatically
+checked out when you arrive. Real-time data is saved on both occasions and
+continuously updated while in transit, providing an accurate overview of both
+scheduled and actual journey times.
+
+## Checking in
+
+You can check into a train at nearly any point in time, though it's usually a
+good idea to do it within a 30-minute window befor/after its departure. The
+precise constraints depend on the selected backend (i.e., data provider).
+
+First, you need to select the stop you want to check in from. Navigate to
+`travelynx.de` or click/tap on the travelynx text in the navigation bar. You
+will see a list of the five stops closest to your current location (as reported
+by your browser). Select the stop you're at or enter its name manually.
+
+As soon as you select a train, you will be checked in and travelynx will switch
+to the journey / checkout view. If you already know where you're headed, you
+should click/tap on the destination stop in the stop list now. You can change
+the destination by selecting a new one anytime.
+
+## Checking out
+
+You are automatically checked out a few minutes after arrival at your
+destination. If the train has already arrived when you select a destination and
+its arrival was less than two hours ago, you are checked out immediately. If
+it's more than two hours, you need to perform a manual checkout (without
+arrival data) using the link at the bottom of the checkin menu's stop list.
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index bf999bc..607b153 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -2829,10 +2829,14 @@ sub startup {
my $from_eva = $journey->{from_eva} // $journey->{dep_eva};
my $to_eva = $journey->{to_eva} // $journey->{arr_eva};
- my $from_index
- = first_index { $_->[2] and $_->[2] == $from_eva } @polyline;
- my $to_index
- = first_index { $_->[2] and $_->[2] == $to_eva } @polyline;
+ # poly_dep_index, poly_arr_index are only available for
+ # journeys that were processed by get_travel_distance
+ # beforehand. However, they are much less error-prone than this
+ # first_index / last_index kludge when it comes to ring lines.
+ my $from_index = $journey->{poly_dep_index}
+ // first_index { $_->[2] and $_->[2] == $from_eva } @polyline;
+ my $to_index = $journey->{poly_arr_index}
+ // first_index { $_->[2] and $_->[2] == $to_eva } @polyline;
# Work around inconsistencies caused by a multiple EVA IDs mapping to the same station name
if ( $from_index == -1 ) {
diff --git a/lib/Travelynx/Command/translation.pm b/lib/Travelynx/Command/translation.pm
index 70bdaba..cc3a5ac 100644
--- a/lib/Travelynx/Command/translation.pm
+++ b/lib/Travelynx/Command/translation.pm
@@ -92,7 +92,8 @@ __END__
=head1 SYNOPSIS
- Usage: index.pl dumpstops <format> <filename>
+ Usage: index.pl translation <command>
- Exports known stops to <filename>.
- Right now, only the "csv" format is supported.
+ Supported commands:
+
+ * update-ref: update share/locales/reference.md
diff --git a/lib/Travelynx/Model/Journeys.pm b/lib/Travelynx/Model/Journeys.pm
index c0ba2a9..9efa365 100755
--- a/lib/Travelynx/Model/Journeys.pm
+++ b/lib/Travelynx/Model/Journeys.pm
@@ -1296,7 +1296,7 @@ sub get_travel_distance {
# Assumption: polyline entries are always [lat, lon] or [lat, lon, stop ID]
%seen = ();
- for my $entry ( @{$polyline_ref} ) {
+ for my $entry ( @{ $polyline_ref // [] } ) {
if ( $entry->[2] ) {
$seen{ $entry->[2] } //= 1;
$entry->[3] = $seen{ $entry->[2] };
@@ -1311,17 +1311,19 @@ sub get_travel_distance {
# Just like the route, the polyline may contain the same stop more than
# once. So we need to select based on the seen counter.
- my @polyline = after_incl {
+ my $poly_start = first_index {
$_->[2] and $_->[2] == $from_eva and $_->[3] == $route[0][2]{n}
}
@{ $polyline_ref // [] };
- @polyline = before_incl {
+ my $poly_end = first_index {
$_->[2] and $_->[2] == $to_eva and $_->[3] == $route[-1][2]{n}
}
- @polyline;
+ @{ $polyline_ref // [] };
- # ensure that before_incl matched -- otherwise, @polyline is too long
- if ( @polyline and $polyline[-1][2] == $to_eva ) {
+ if ( defined $poly_start and defined $poly_end ) {
+ $journey->{poly_dep_index} = $poly_start;
+ $journey->{poly_arr_index} = $poly_end;
+ my @polyline = @{$polyline_ref}[ $poly_start .. $poly_end ];
my $prev_station = shift @polyline;
for my $station (@polyline) {
$distance_polyline += $geo->distance_metal(
diff --git a/share/locales/de_DE.po b/share/locales/de_DE.po
index 028dda0..abbe998 100644
--- a/share/locales/de_DE.po
+++ b/share/locales/de_DE.po
@@ -188,6 +188,20 @@ msgstr "offene Anfragen"
msgid "account.interaction.disabled"
msgstr "Accounts können dir nicht folgen"
+# changelog.html.ep
+
+msgid "changelog.added"
+msgstr "Neues Feature"
+
+msgid "changelog.bugfix"
+msgstr "Bugfix"
+
+msgid "changelog.2-16.1"
+msgstr "Infrastruktur zur Übersetzung von travelynx in andere Sprachen. Der Großteil der Website ist noch Deutsch; einzelne Seiten sind bereits auf Englisch und Teilmengen davon zusätzlich auf Französisch, Polnisch und Ungarisch verfügbar. Weitere Übersetzungen und ggf. Sprachen sowie Dokumentation zur Unterstützung dabei folgen bei Zeiten. Die Sprache wird auf Basis des Accept-Language-Headers ausgewählt und kann zusätzlich in den Account-Einstellungen konfiguriert werden."
+
+msgid "changelog.2-16.2"
+msgstr "Korrekte Berechnung und Visualisierung der Wegstrecke bei Fahrten mit Ringlinien. Die Anzeige der Fahrten in der Fahrtenkarte ist noch teilweise fehlerhaft."
+
# journey.html.ep
msgid "journey.not-found"
diff --git a/share/locales/en_GB.po b/share/locales/en_GB.po
index e4bb7aa..6ee0329 100644
--- a/share/locales/en_GB.po
+++ b/share/locales/en_GB.po
@@ -188,6 +188,20 @@ msgstr "open requests"
msgid "account.interaction.disabled"
msgstr "Accounts cannot follow you"
+# changelog.html.ep
+
+msgid "changelog.added"
+msgstr "New Feature"
+
+msgid "changelog.bugfix"
+msgstr "Bugfix"
+
+msgid "changelog.2-16.1"
+msgstr "Localization support. Parts of travelynx are now available in English, and a subset of those is also available in French, Hungarian, and Polish. Further translations, languages, and translation how-tos will follow in due time. Locale selection respects the Accept-Language header and can be configured on the account settings page."
+
+msgid "changelog.2-16.2"
+msgstr "Fix distance calculation and visualization of ring line trips. Trips shown in the history map are still partially incorrect."
+
# journey.html.ep
msgid "journey.not-found"
diff --git a/share/locales/reference.md b/share/locales/reference.md
index a93c64a..5b3fb6c 100644
--- a/share/locales/reference.md
+++ b/share/locales/reference.md
@@ -2,9 +2,9 @@
* de-DE: 100.0% complete (0 missing)
* en-GB: 100.0% complete (0 missing)
-* fr-FR: 36.2% complete (102 missing)
-* hu-HU: 87.5% complete (20 missing)
-* pl-PL: 36.2% complete (102 missing)
+* fr-FR: 35.4% complete (106 missing)
+* hu-HU: 85.4% complete (24 missing)
+* pl-PL: 35.4% complete (106 missing)
###
@@ -498,6 +498,40 @@ Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n>=2 && n<=4 && (n<10 || n>=20) ? 1
* hu-HU: Senki sem követhet
* pl-PL: Inne konta nie mogą cię obserwować
+## changelog.html.ep
+
+### changelog.added
+
+* de-DE: Neues Feature
+* en-GB: New Feature
+* fr-FR *missing*
+* hu-HU *missing*
+* pl-PL *missing*
+
+### changelog.bugfix
+
+* de-DE: Bugfix
+* en-GB: Bugfix
+* fr-FR *missing*
+* hu-HU *missing*
+* pl-PL *missing*
+
+### changelog.2-16.1
+
+* de-DE: Infrastruktur zur Übersetzung von travelynx in andere Sprachen. Der Großteil der Website ist noch Deutsch; einzelne Seiten sind bereits auf Englisch und Teilmengen davon zusätzlich auf Französisch, Polnisch und Ungarisch verfügbar. Weitere Übersetzungen und ggf. Sprachen sowie Dokumentation zur Unterstützung dabei folgen bei Zeiten. Die Sprache wird auf Basis des Accept-Language-Headers ausgewählt und kann zusätzlich in den Account-Einstellungen konfiguriert werden.
+* en-GB: Localization support. Parts of travelynx are now available in English, and a subset of those is also available in French, Hungarian, and Polish. Further translations, languages, and translation how-tos will follow in due time. Locale selection respects the Accept-Language header and can be configured on the account settings page.
+* fr-FR *missing*
+* hu-HU *missing*
+* pl-PL *missing*
+
+### changelog.2-16.2
+
+* de-DE: Korrekte Berechnung und Visualisierung der Wegstrecke bei Fahrten mit Ringlinien. Die Anzeige der Fahrten in der Fahrtenkarte ist noch teilweise fehlerhaft.
+* en-GB: Fix distance calculation and visualization of ring line trips. Trips shown in the history map are still partially incorrect.
+* fr-FR *missing*
+* hu-HU *missing*
+* pl-PL *missing*
+
## journey.html.ep
### journey.not-found
diff --git a/share/locales/template.pot b/share/locales/template.pot
index cb11a2f..e1a3a00 100644
--- a/share/locales/template.pot
+++ b/share/locales/template.pot
@@ -1,5 +1,6 @@
msgid ""
msgstr ""
+"Language: FIXME\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
@@ -88,6 +89,36 @@ msgstr ""
# account.html.ep
+msgid "account.changed-name"
+msgstr ""
+
+msgid "account.changed-mail"
+msgstr ""
+
+msgid "account.changed-password"
+msgstr ""
+
+msgid "account.changed-language"
+msgstr ""
+
+msgid "account.changed-privacy"
+msgstr ""
+
+msgid "account.changed-social"
+msgstr ""
+
+msgid "account.changed-traewelling"
+msgstr ""
+
+msgid "account.changed-history"
+msgstr ""
+
+msgid "account.changed-webhook"
+msgstr ""
+
+msgid "account.cleared-notifications"
+msgstr ""
+
msgid "account.account"
msgstr ""
@@ -157,6 +188,20 @@ msgstr ""
msgid "account.interaction.disabled"
msgstr ""
+# changelog.html.ep
+
+msgid "changelog.added"
+msgstr ""
+
+msgid "changelog.bugfix"
+msgstr ""
+
+msgid "changelog.2-16.1"
+msgstr ""
+
+msgid "changelog.2-16.2"
+msgstr ""
+
# journey.html.ep
msgid "journey.not-found"
@@ -219,6 +264,9 @@ msgstr ""
msgid "journey.share"
msgstr ""
+msgid "journey.export"
+msgstr ""
+
msgid "journey.edit"
msgstr ""
diff --git a/templates/changelog.html.ep b/templates/changelog.html.ep
index 0d1ecc5..f4b6449 100644
--- a/templates/changelog.html.ep
+++ b/templates/changelog.html.ep
@@ -2,6 +2,22 @@
<div class="row">
<div class="col s12 m1 l1">
+ 2.16
+ </div>
+ <div class="col s12 m11 l11">
+ <p>
+ <i class="material-icons left" aria-label="<%= L('changelog.added') %>">add</i>
+ %= L('changelog.2-16.1')
+ </p>
+ <p>
+ <i class="material-icons left" aria-label="<%= L('changelog.bugfix') %>">build</i>
+ %= L('changelog.2-16.2')
+ </p>
+ </div>
+</div>
+
+<div class="row">
+ <div class="col s12 m1 l1">
2.15
</div>
<div class="col s12 m11 l11">