Bimba.git

commit b0f9c5640c0f0a0f22d9c87949e695b3b2311a13

Author: Adam Evyčędo <git@apiote.xyz>

show distance in units

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/app/build.gradle b/app/build.gradle
index ac26e06a71c52aa0be420a23dec120bb67e4d13d..f931b1b48dc9a36904514b488590addb09d64851 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -26,7 +26,7 @@         versionCode 28
         versionName "3.4.0"
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        resourceConfigurations += ["en", "pl", "it", "de", "fr"]
+        resourceConfigurations += ["en", "pl", "it", "de", "fr", "en-rUS"]
     }
 
     applicationVariants.configureEach { variant ->




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt
index f046fad8cedf37d2d2164eff4e63ba9e40af7781..324169dea1b496d9daa3162b5c04dc6281fd1909 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt
@@ -83,8 +83,12 @@ 			content.findViewById(R.id.wheelchair_icon).visibility = View.GONE
 
 			Log.i("unit", "${vehicle.Speed.mps}")
 			UnitSystem.getSelected(requireContext()).let { us ->
-				content.findViewById<TextView>(R.id.speed_text).text =
-					us.toString(requireContext(), us.speedUnit(vehicle.Speed))
+				content.findViewById<TextView>(R.id.speed_text).apply {
+					text =
+						us.toString(requireContext(), us.speedUnit(vehicle.Speed))
+					contentDescription =
+						us.speedUnit(vehicle.Speed).contentDescription(requireContext(), us.base)
+				}
 			}
 
 			content.findViewById<LinearLayout>(R.id.congestion).visibility =




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
index 4c9945746d503aeed8749870d75dcca08a0d2d1a..bd20eaf7e474954a96ea993491dddebf413e1fb9 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
@@ -305,8 +305,12 @@ 			}
 
 			findViewById<TextView>(R.id.boarding_text).text = departure.boardingText(ctx)
 			UnitSystem.getSelected(requireContext()).let { us ->
-				findViewById<TextView>(R.id.speed_text).text =
-					us.toString(context, us.speedUnit(departure.vehicle.Speed))
+				findViewById<TextView>(R.id.speed_text).apply {
+					text =
+						us.toString(context, us.speedUnit(departure.vehicle.Speed))
+					contentDescription =
+						us.speedUnit(departure.vehicle.Speed).contentDescription(requireContext(), us.base)
+				}
 			}
 
 			findViewById<LinearLayout>(R.id.congestion).visibility =




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
index 930c33fd4f177d77db3a0129bcafb98dfe86305a..7f09c54a9d644a3a21748a6996d655eb78912e24 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Departure.kt
@@ -157,6 +157,7 @@ 		d.boarding,
 		d.alerts.map { Alert(it) }
 	)
 
+	// TODO content description
 	fun statusText(context: Context?, showAsTime: Boolean, at: ZonedDateTime? = null): String {
 		val now = at ?: Instant.now().atZone(ZoneId.systemDefault())
 		val departureTime = ZonedDateTime.of(




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
index 047b8c576a927a9c8359d9214a08d6df1ac10d34..44aa528a021dd99af6f62a3f5f09bff65dbe9897 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/repo/Vehicle.kt
@@ -5,7 +5,6 @@
 package xyz.apiote.bimba.czwek.repo
 
 import android.content.Context
-import android.util.Log
 import xyz.apiote.bimba.czwek.R
 import xyz.apiote.bimba.czwek.api.CongestionLevelV1
 import xyz.apiote.bimba.czwek.api.OccupancyStatusV1
@@ -90,9 +89,7 @@ 		LineStub(v.Line),
 		v.Headsign,
 		CongestionLevel.of(v.CongestionLevel),
 		OccupancyStatus.of(v.OccupancyStatus)
-	) {
-		Log.i("unit", "veh: ${v.Speed}")
-	}
+	)
 
 	constructor(v: VehicleV2) : this(
 		v.ID,
@@ -103,9 +100,7 @@ 		LineStub(v.Line),
 		v.Headsign,
 		CongestionLevel.of(v.CongestionLevel),
 		OccupancyStatus.of(v.OccupancyStatus)
-	) {
-		Log.i("unit", "veh: ${v.Speed.toDouble()}")
-	}
+	)
 
 	constructor(v: VehicleV3) : this(
 		v.ID,
@@ -116,9 +111,7 @@ 		LineStub(v.Line),
 		v.Headsign,
 		CongestionLevel.of(v.CongestionLevel),
 		OccupancyStatus.of(v.OccupancyStatus)
-	) {
-		Log.i("unit", "veh: ${v.Speed.toDouble()}")
-	}
+	)
 
 	enum class Capability(val bit: UShort) {
 		RAMP(0b0001u), LOW_FLOOR(0b0010u), LOW_ENTRY(0b0001_0000_0000u), AC(0b0100u), BIKE(0b1000u), VOICE(




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/units/TGM.kt b/app/src/main/java/xyz/apiote/bimba/czwek/units/TGM.kt
index ca2c62ff76293c56f939852f078c0e1514eae3cf..43ed82ee09dbd47a231fc6a11a0587253c695858 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/units/TGM.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/units/TGM.kt
@@ -13,8 +13,13 @@ 	override fun timeUnit(other: TimeUnit): TimeUnit = Tim(other)
 
 	override fun speedUnit(count: Double): SpeedUnit = Vlos(count)
 	override fun speedUnit(other: SpeedUnit): SpeedUnit = Vlos(other)
+
+	override fun distanceUnit(count: Double): DistanceUnit = Grafut(count)
+	override fun distanceUnit(other: DistanceUnit): DistanceUnit = Grafut(other)
+
 	override fun toString(context: Context, s: SpeedUnit): String = s.toString(context, base)
 	override fun toString(context: Context, t: TimeUnit): String = t.toString(context, base)
+	override fun toString(context: Context, d: DistanceUnit): String = d.toString(context, base)
 }
 
 class Tim(val tims: Long) : TimeUnit {
@@ -27,13 +32,13 @@ 			R.string.time_in_tm_past
 		} else {
 			R.string.time_in_tm
 		}
-		val (t,m) = if (tims > base.toDouble().pow(4)) {
-			Pair(tims/base.toDouble().pow(4).toInt(), "⁴")
+		val (t, m) = if (tims > base.toDouble().pow(4)) {
+			Pair(tims / base.toDouble().pow(4).toInt(), "⁴")
 		} else {
-			Pair(tims/base.toDouble().pow(2).toInt(), "²")
+			Pair(tims / base.toDouble().pow(2).toInt(), "²")
 		}
 		return if (base == 10) {
-			context.getString(res, NumberFormat.getInstance().format(abs(t)), m)
+			context.getString(res, NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(abs(t)), m)
 		} else {
 			context.getString(
 				res,
@@ -45,6 +50,36 @@ 	}
 
 	override fun contentDescription(context: Context, base: Int): String =
 		context.resources.getQuantityString(R.plurals.time_in_tm_cd, tims.toInt(), tims)
+}
+
+class Grafut(val grafut: Double) : DistanceUnit {
+	constructor(other: DistanceUnit) : this(other.meters() / .295682912)
+
+	override fun meters(): Double = grafut * .295682912
+
+	override fun toString(context: Context, base: Int): String {
+		val (g, m) = if (grafut > base.toDouble().pow(3)) {
+			Pair(grafut / base.toDouble().pow(3), "³")
+		} else {
+			Pair(grafut, "")
+		}
+
+		return if (base == 10) {
+			context.getString(R.string.distance_in_gf, NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(g), m)
+		} else {
+			context.getString(
+				R.string.distance_in_gf,
+				g.toString(12, 2).lowercase().replace("a", "↊").replace("b", "↋"),
+				m
+			)
+		}
+	}
+
+	override fun contentDescription(context: Context, base: Int): String {
+		// TODO
+		return ""
+	}
+
 }
 
 class Vlos(val vlos: Double) : SpeedUnit {




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/units/UnitSystem.kt b/app/src/main/java/xyz/apiote/bimba/czwek/units/UnitSystem.kt
index 5eb08d0ec6755433ff0c4278094fd23c552076fb..9d0e88c75fc8e29c60f42e938836d8aea33f5b09 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/units/UnitSystem.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/units/UnitSystem.kt
@@ -64,9 +64,12 @@ 	abstract fun timeUnit(count: Long): TimeUnit
 	abstract fun timeUnit(other: TimeUnit): TimeUnit
 	abstract fun speedUnit(count: Double): SpeedUnit
 	abstract fun speedUnit(other: SpeedUnit): SpeedUnit
+	abstract fun distanceUnit(count: Double): DistanceUnit
+	abstract fun distanceUnit(other: DistanceUnit): DistanceUnit
 
 	abstract fun toString(context: Context, s: SpeedUnit): String
 	abstract fun toString(context: Context, t: TimeUnit): String
+	abstract fun toString(context: Context, d: DistanceUnit): String
 }
 
 interface TimeUnit {
@@ -80,3 +83,9 @@ 	fun mps(): Double
 	fun toString(context: Context, base: Int): String
 	fun contentDescription(context: Context, base: Int): String
 }
+
+interface DistanceUnit {
+	fun meters(): Double
+	fun toString(context: Context, base: Int): String
+	fun contentDescription(context: Context, base: Int): String
+}




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/units/imperial.kt b/app/src/main/java/xyz/apiote/bimba/czwek/units/imperial.kt
index 964a97973865f2c5ba98e432f3fdd3427cf1ca8d..842cc216d883112519b85fb77638d0ccf126fef7 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/units/imperial.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/units/imperial.kt
@@ -10,8 +10,13 @@ 	override fun timeUnit(other: TimeUnit): TimeUnit = Second(other)
 
 	override fun speedUnit(count: Double): SpeedUnit = Miph(count)
 	override fun speedUnit(other: SpeedUnit): SpeedUnit = Miph(other)
+
+	override fun distanceUnit(count: Double): DistanceUnit = MiYd(count)
+	override fun distanceUnit(other: DistanceUnit): DistanceUnit = MiYd(other)
+
 	override fun toString(context: Context, s: SpeedUnit): String = s.toString(context, base)
 	override fun toString(context: Context, t: TimeUnit): String = t.toString(context, base)
+	override fun toString(context: Context, d: DistanceUnit): String = d.toString(context, base)
 }
 
 class Miph(val miph: Double) : SpeedUnit {
@@ -19,8 +24,52 @@ 	constructor(s: Int) : this(s.toDouble())
 	constructor(other: SpeedUnit) : this(other.mps() / 0.44704)
 
 	override fun mps(): Double = miph * 0.44704
-	override fun toString(context: Context, base: Int): String = context.getString(R.string.speed_in_mi_per_h, NumberFormat.getInstance().format(miph))
-	override fun contentDescription(context: Context, base: Int): String = context.resources.getQuantityString(
-		R.plurals.speed_in_mi_per_h_cd, miph.toInt(), miph)
+	override fun toString(context: Context, base: Int): String =
+		context.getString(
+			R.string.speed_in_mi_per_h,
+			NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(miph)
+		)
+
+	override fun contentDescription(context: Context, base: Int): String =
+		context.resources.getQuantityString(
+			R.plurals.speed_in_mi_per_h_cd, miph.toInt(), miph
+		)
+}
+
+class MiYd(val mi: Double) : DistanceUnit {
+	constructor(other: DistanceUnit) : this(other.meters() / 1609.344)
+
+	override fun meters(): Double = mi * 1609.344
+
+	override fun toString(context: Context, base: Int): String =
+		if (mi < 1) {
+			context.getString(
+				R.string.distance_in_yd,
+				NumberFormat.getIntegerInstance().format((mi * 1760).toInt())
+			)
+		} else {
+			context.getString(
+				R.string.distance_in_mi,
+				NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(mi)
+			)
+		}
 
+	override fun contentDescription(context: Context, base: Int): String =
+		if (mi < 1) {
+			context.resources.getQuantityString(
+				R.plurals.distance_in_yd_cd,
+				(mi / 1760).toInt(),
+				(mi / 1760).toInt()
+			)
+		} else {
+			val miles = mi.toInt()
+			val yards = ((mi - miles) * 1760).toInt()
+			val miString = context.resources.getQuantityString(R.plurals.distance_in_mi_cd, miles)
+			val ydString = context.resources.getQuantityString(R.plurals.distance_in_yd_cd, yards)
+			if (yards > 0) {
+				context.getString(R.string.distance_in_two_units_cd, miString, ydString)
+			} else {
+				miString
+			}
+		}
 }
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/units/metric.kt b/app/src/main/java/xyz/apiote/bimba/czwek/units/metric.kt
index 2492c4d0ff00a56037de882cdb0888bdc1ad8144..aed10d7ef19c109c30c28b1747ad597758e1d978 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/units/metric.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/units/metric.kt
@@ -11,8 +11,56 @@ 	override fun timeUnit(other: TimeUnit): TimeUnit = Second(other)
 
 	override fun speedUnit(count: Double): SpeedUnit = Kmph(count)
 	override fun speedUnit(other: SpeedUnit): SpeedUnit = Kmph(other)
+
+	override fun distanceUnit(count: Double): DistanceUnit = Km(count)
+	override fun distanceUnit(other: DistanceUnit): DistanceUnit = Km(other)
+
 	override fun toString(context: Context, s: SpeedUnit): String = s.toString(context, base)
 	override fun toString(context: Context, t: TimeUnit): String = t.toString(context, base)
+	override fun toString(context: Context, d: DistanceUnit): String = d.toString(context, base)
+}
+
+class Km(val km: Double) : DistanceUnit {
+	constructor(other: DistanceUnit) : this(other.meters() / 1000)
+
+	override fun meters(): Double = km * 1000
+	override fun toString(context: Context, base: Int): String =
+		if (km < 1) {
+			context.getString(
+				R.string.distance_in_m,
+				NumberFormat.getIntegerInstance().format((km * 1000).toInt())
+			)
+		} else {
+			context.getString(
+				R.string.distance_in_km,
+				NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(km)
+			)
+		}
+
+	override fun contentDescription(context: Context, base: Int): String =
+		if (km < 1) {
+			context.resources.getQuantityString(R.plurals.distance_in_m_cd, (km * 1000).toInt())
+		} else {
+			val kilometres = km.toInt()
+			val metres = ((km - kilometres) * 1000).toInt()
+			val kmString = context.resources.getQuantityString(R.plurals.distance_in_km_cd, kilometres)
+			val mString = context.resources.getQuantityString(R.plurals.distance_in_m_cd, metres)
+			if (metres > 0) {
+				context.getString(R.string.distance_in_two_units_cd, kmString, mString)
+			} else {
+				kmString
+			}
+		}
+}
+
+class Metre(val m: Double) : DistanceUnit {
+	override fun meters(): Double = m
+
+	override fun toString(context: Context, base: Int): String =
+		context.getString(R.string.distance_in_m, NumberFormat.getIntegerInstance().format(m.toInt()))
+
+	override fun contentDescription(context: Context, base: Int): String =
+		context.resources.getQuantityString(R.plurals.distance_in_m_cd, m.toInt(), m.toInt())
 }
 
 class Second(val seconds: Double) : TimeUnit {
@@ -20,8 +68,14 @@ 	constructor(s: Int) : this(s.toDouble())
 	constructor(other: TimeUnit) : this((other.milliseconds().toDouble() / 1000))
 
 	override fun milliseconds(): Long = (seconds * 1000).toLong()
-	override fun toString(context: Context, base: Int): String = context.getString(R.string.time_in_s, NumberFormat.getInstance().format(seconds))
-	override fun contentDescription(context: Context, base: Int): String = context.resources.getQuantityString(R.plurals.time_in_s_cd, seconds.toInt(), seconds)
+	override fun toString(context: Context, base: Int): String =
+		context.getString(
+			R.string.time_in_s,
+			NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(seconds)
+		)
+
+	override fun contentDescription(context: Context, base: Int): String =
+		context.resources.getQuantityString(R.plurals.time_in_s_cd, seconds.toInt(), seconds)
 }
 
 class Mps(val mps: Double) : SpeedUnit {
@@ -29,8 +83,14 @@ 	constructor(s: Int) : this(s.toDouble())
 	constructor(other: SpeedUnit) : this(other.mps())
 
 	override fun mps(): Double = mps
-	override fun toString(context: Context, base: Int): String = context.getString(R.string.speed_in_m_per_s, NumberFormat.getInstance().format(mps))
-	override fun contentDescription(context: Context, base: Int): String = context.resources.getQuantityString(R.plurals.speed_in_m_per_s_cd, mps.toInt(), mps)
+	override fun toString(context: Context, base: Int): String =
+		context.getString(
+			R.string.speed_in_m_per_s,
+			NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(mps)
+		)
+
+	override fun contentDescription(context: Context, base: Int): String =
+		context.resources.getQuantityString(R.plurals.speed_in_m_per_s_cd, mps.toInt(), mps)
 }
 
 class Kmph(val kmph: Double) : SpeedUnit {
@@ -38,7 +98,12 @@ 	constructor(s: Int) : this(s.toDouble())
 	constructor(other: SpeedUnit) : this(other.mps() * 3.6)
 
 	override fun mps(): Double = kmph / 3.6
-	override fun toString(context: Context, base: Int): String = context.getString(R.string.speed_in_km_per_h, NumberFormat.getInstance().format(kmph))
-	override fun contentDescription(context: Context, base: Int): String = context.resources.getQuantityString(R.plurals.speed_in_km_per_h_cd, kmph.toInt(), kmph)
+	override fun toString(context: Context, base: Int): String =
+		context.getString(
+			R.string.speed_in_km_per_h,
+			NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(kmph)
+		)
 
+	override fun contentDescription(context: Context, base: Int): String =
+		context.resources.getQuantityString(R.plurals.speed_in_km_per_h_cd, kmph.toInt(), kmph)
 }
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/units/usCustomary.kt b/app/src/main/java/xyz/apiote/bimba/czwek/units/usCustomary.kt
index 8b2317362a850d7bde70b60e0f2c41216bf4d3f4..eb5013c9735a7166f5f822311799e00b4beb072d 100644
--- a/app/src/main/java/xyz/apiote/bimba/czwek/units/usCustomary.kt
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/units/usCustomary.kt
@@ -1,13 +1,53 @@
 package xyz.apiote.bimba.czwek.units
 
 import android.content.Context
+import xyz.apiote.bimba.czwek.R
+import java.text.NumberFormat
 
-object USCustomary: UnitSystem(10) {
+object USCustomary : UnitSystem(10) {
 	override fun timeUnit(count: Long): TimeUnit = Second(count.toDouble())
 	override fun timeUnit(other: TimeUnit): TimeUnit = Second(other)
 
 	override fun speedUnit(count: Double): SpeedUnit = Miph(count)
 	override fun speedUnit(other: SpeedUnit): SpeedUnit = Miph(other)
+
+	override fun distanceUnit(count: Double): DistanceUnit = MiFt(count)
+	override fun distanceUnit(other: DistanceUnit): DistanceUnit = MiFt(other)
+
 	override fun toString(context: Context, s: SpeedUnit): String = s.toString(context, base)
 	override fun toString(context: Context, t: TimeUnit): String = t.toString(context, base)
+	override fun toString(context: Context, d: DistanceUnit): String = d.toString(context, base)
+}
+
+class MiFt(val mi: Double) : DistanceUnit {
+	constructor(other: DistanceUnit) : this(other.meters() / 1609.344)
+
+	override fun meters(): Double = mi * 1609.344
+
+	override fun toString(context: Context, base: Int): String = if (mi < 1) {
+		context.getString(
+			R.string.distance_in_ft,
+			NumberFormat.getIntegerInstance().format((mi * 5280).toInt())
+		)
+	} else {
+		context.getString(
+			R.string.distance_in_mi,
+			NumberFormat.getInstance().apply { maximumFractionDigits = 2 }.format(mi)
+		)
+	}
+
+	override fun contentDescription(context: Context, base: Int): String =
+		if (mi < 1) {
+			context.resources.getQuantityString(R.plurals.distance_in_ft_cd, (mi * 5280).toInt())
+		} else {
+			val miles = mi.toInt()
+			val feet = ((mi - miles) * 5280).toInt()
+			val miString = context.resources.getQuantityString(R.plurals.distance_in_mi_cd, miles)
+			val ftString = context.resources.getQuantityString(R.plurals.distance_in_ft_cd, feet)
+			if (feet > 0) {
+				context.getString(R.string.distance_in_two_units_cd, miString, ftString)
+			} else {
+				miString
+			}
+		}
 }




diff --git a/app/src/main/res/navigation/front_navigation.xml b/app/src/main/res/navigation/front_navigation.xml
index 1c383d702f4123fb51c68712cce1ca3139ace99a..1049aa1728a3a4a9591aad523c1527025415d860 100644
--- a/app/src/main/res/navigation/front_navigation.xml
+++ b/app/src/main/res/navigation/front_navigation.xml
@@ -27,6 +27,6 @@
 	<fragment
 		android:id="@+id/navigation_voyage"
 		android:name="xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment"
-		android:label="@string/title_voyage"
+		android:label="@string/title_journey"
 		tool:layout="@layout/fragment_voyage" />
 </navigation>
\ No newline at end of file




diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a32435ac389fb8240427984e8b571754f5b7f833..9318bde41054eae756a82ecd5ff0e04c004189af 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,14 +1,16 @@
 <!--
-SPDX-FileCopyrightText: Adam Evyčędo
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
 
 SPDX-License-Identifier: GPL-3.0-or-later
 -->
 
+<!-- NOTE base strings are in en-GB -->
+
 <resources>
 	<string name="app_name">Bimba</string>
 	<string name="title_home">Home</string>
 	<string name="title_map">Map</string>
-	<string name="title_voyage">Voyage</string>
+	<string name="title_journey">Journey</string>
 	<string name="home_fab_description">GPS icon</string>
 	<string name="search_placeholder">stops, lines, or plus codes</string>
 	<string name="title_activity_results">Results</string>
@@ -27,6 +29,37 @@ 	Cannot obtain current location
 	<string name="no_departures">No departures</string>
 	<string name="waiting_position">waiting for position</string>
 	<string name="vehicle_headsign">%1$s » %2$s</string>
+	<string name="distance_in_m">%1$s m</string>
+	<plurals name="distance_in_m_cd">
+		<item quantity="one">%1$d metre</item>
+		<item quantity="other">%1$d metres</item>
+	</plurals>
+	<string name="distance_in_km">%1$s km</string>
+	<plurals name="distance_in_km_cd">
+		<item quantity="one">%1$d kilometre</item>
+		<item quantity="other">%1$d kilometres</item>
+	</plurals>
+	<string name="distance_in_two_units_cd">%1$s and %2$s</string>
+	<string name="distance_in_yd">%1$s yd</string>
+	<plurals name="distance_in_yd_cd">
+		<item quantity="one">%1$d yard</item>
+		<item quantity="other">%1$d yards</item>
+	</plurals>
+	<string name="distance_in_ft">%1$s ft</string>
+	<plurals name="distance_in_ft_cd">
+		<item quantity="one">%1$d foot</item>
+		<item quantity="other">%1$d feet</item>
+	</plurals>
+	<string name="distance_in_mi">%1$s mi</string>
+	<plurals name="distance_in_mi_cd">
+		<item quantity="one">%1$d mile</item>
+		<item quantity="other">%1$d miles</item>
+	</plurals>
+	<string name="distance_in_gf">%1$s %2$sGf</string>
+	<plurals name="distance_in_gf_cd">
+		<item quantity="one">%1$d grafut</item>
+		<item quantity="other">%1$d grafuts</item>
+	</plurals>
 	<string name="time_in_s">%1$s s</string>
 	<plurals name="time_in_s_cd">
 		<item quantity="one">%1$d second</item>
@@ -133,7 +166,7 @@ 	» %1$s
 	<string name="credits">Font yellowcircle8 (https://git.apiote.xyz/yellowcircle8.git) based on Railway Sans © Greg Fleming, OFL-1.1 https://github.com/davelab6/Railway-Sans\n\n Mastodon icon (https://github.com/mastodon/joinmastodon) © Mastodon contributors, AGPL-3.0-or-later\n\n Bimba logo created by https://github.com/tebriz159\n\n Material icons © Google, Apache-2.0\n\n Map data © OpenStreetMap contributors (https://www.openstreetmap.org/copyright), ODbL-1.0</string>
 	<string name="title_about">About</string>
 	<string name="translation_button_description">link to translations service</string>
-	<string name="app_description">FLOSS public transport passenger companion; a timetable in your pocket.</string>
+	<string name="app_description">FLOSS public transport passenger companion; a timetable in your pocket.</string>
 	<string name="website_button_description">link to website</string>
 	<string name="code_button_description">link to source code</string>
 	<string name="mastodon_button_description">link to Mastodon</string>
@@ -175,5 +208,4 @@ 	US Customary
 	<string name="units_tgm10">TGM (base 10)</string>
 	<string name="units_tgm12">TGM (base 12)</string>
 	<string name="title_settings">Settings</string>
-
 </resources>




diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index c05c82928aa6e68cb4fd603ae8558e5f65972f90..94cbc875e7d3d23c03c9a58c20d9d32af4282982 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -47,7 +47,7 @@     Link zu Übersetzungsdienst
     <string name="code_button_description">Link zu Quellcode</string>
     <string name="mastodon_button_description">Link zu Mastodon</string>
     <string name="app_name">Bimba</string>
-    <string name="title_voyage">Reise</string>
+    <string name="title_journey">Reise</string>
     <string name="save">Speichern</string>
     <string name="error_404">Nicht gefunden</string>
     <string name="at_time_realtime">um %1$02d:%2$02d:%3$02d</string>




diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml
deleted file mode 100644
index 68de08ea5bcbaf161327f182bc53ee5445d4beb6..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-en-rGB/strings.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
-
-SPDX-License-Identifier: GPL-3.0-or-later
---><resources>
-    <string name="app_name">Bimba</string>
-    <string name="title_home">Home</string>
-    <string name="title_map">Map</string>
-    <string name="title_voyage">Journey</string>
-    <string name="title_activity_results">Results</string>
-    <string name="cont">Continue</string>
-    <string name="save">Save</string>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-en-rUS/strings.xml b/app/src/main/res/values-en-rUS/strings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f00aeccfaea80621a1d6c99e5bc763279b250d00
--- /dev/null
+++ b/app/src/main/res/values-en-rUS/strings.xml
@@ -0,0 +1,188 @@
+<!--
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
+
+SPDX-License-Identifier: GPL-3.0-or-later
+-->
+
+<resources>
+	<string name="app_name">Bimba</string>
+	<string name="title_home">Home</string>
+	<string name="title_map">Map</string>
+	<string name="title_journey">Journey</string>
+	<string name="home_fab_description">GPS icon</string>
+	<string name="search_placeholder">stops, lines, or plus codes</string>
+	<string name="title_activity_results">Results</string>
+	<string name="cont">Continue</string>
+	<string name="save">Save</string>
+	<string name="error_400">The application made a malformed request</string>
+	<string name="error_401">A token is needed to use this server</string>
+	<string name="error_403">The token you provided is incorrect</string>
+	<string name="error_404">Not found</string>
+	<string name="error_429">Rate limit exceeded. Try again later</string>
+	<string name="error_50x">There was an error on the sever. Try again later</string>
+	<string name="error_unknown">Unknown error happened</string>
+	<string name="error_connecting">Error connecting to the server. Try again later</string> <!-- send a bug report to bimba@git.apiote.xyz, details are: url=$URL, response=$response -->
+	<string name="error_offline">You are offline. Connect to the Internet</string>
+	<string name="error_gps">Cannot obtain current location</string>
+	<string name="no_departures">No departures</string>
+	<string name="waiting_position">waiting for position</string>
+	<string name="vehicle_headsign">%1$s » %2$s</string>
+	<string name="distance_in_m">%1$s m</string>
+	<plurals name="distance_in_m_cd">
+		<item quantity="one">%1$d meter</item>
+		<item quantity="other">%1$d meters</item>
+	</plurals>
+	<string name="distance_in_km">%1$s km</string>
+	<plurals name="distance_in_km_cd">
+		<item quantity="one">%1$d kilometer</item>
+		<item quantity="other">%1$d kilometers</item>
+	</plurals>
+	<string name="time_in_s">%1$s s</string>
+	<plurals name="time_in_s_cd">
+		<item quantity="one">%1$d second</item>
+		<item quantity="other">%1$d seconds</item>
+	</plurals>
+	<string name="time_in_tm">%1$s %2$sTm</string>
+	<string name="time_in_tm_past">%1$s %2$sTm ago</string>
+	<plurals name="time_in_tm_cd">
+		<item quantity="one">%1$d tim</item>
+		<item quantity="other">%1$d tims</item>
+	</plurals>
+	<string name="speed_in_km_per_h">%1$s km/h</string>
+	<string name="speed_in_m_per_s">%1$s m/s</string>
+	<string name="speed_in_mi_per_h">%1$s mph</string>
+	<string name="speed_in_vl">%1$s Vl</string>
+	<plurals name="speed_in_m_per_s_cd">
+		<item quantity="one">%1$d meter per second</item>
+		<item quantity="other">%1$d meters per second</item>
+	</plurals>
+	<plurals name="speed_in_km_per_h_cd">
+		<item quantity="one">%1$d kilometer per hour</item>
+		<item quantity="other">%1$d kilometers per hour</item>
+	</plurals>
+	<plurals name="speed_in_mi_per_h_cd">
+		<item quantity="one">%1$d mile per hour</item>
+		<item quantity="other">%1$d mile per hour</item>
+	</plurals>
+	<plurals name="speed_in_vl_cd">
+		<item quantity="one">%1$s vlos</item>
+		<item quantity="other">%1$s vlos</item>
+	</plurals>
+	<string name="congestion_unknown">unknown</string>
+	<string name="congestion_smooth">smooth</string>
+	<string name="congestion_stop_and_go">stop and go</string>
+	<string name="congestion_congestion">congestion</string>
+	<string name="congestion_jams">jams</string>
+	<string name="occupancy_unknown">unknown</string>
+	<string name="occupancy_empty">empty</string>
+	<string name="occupancy_many_seats">many seats</string>
+	<string name="occupancy_few_seats">few seats</string>
+	<string name="occupancy_standing_only">standing only</string>
+	<string name="occupancy_crowded">crowded</string>
+	<string name="occupancy_full">full</string>
+	<string name="occupancy_wont_let">won’t let in</string>
+	<string name="no_map_app">No maps app installed</string>
+	<string name="departure_headsign_content_description">towards %1$s</string>
+	<string name="departure_momentarily">momentarily</string>
+	<string name="departure_departed">departed</string>
+	<string name="departure_now">now</string>
+	<string name="at_time">at %1$02d:%2$02d</string>
+	<string name="at_time_realtime">at %1$02d:%2$02d:%3$02d</string>
+	<string name="on_demand">on demand</string>
+	<string name="no_boarding">no boarding</string>
+	<string name="on_boarding">on-boarding</string>
+	<string name="off_boarding">off-boarding</string>
+	<string name="boarding">can board</string>
+	<string name="line_headsign">» %1$s</string>
+	<string name="line_headsign_content_description">towards %1$s</string>
+	<string name="line_headsigns">%1$s «» %2$s</string>
+	<string name="line_headsigns_content_description">between %1$s and %2$s</string>
+	<string name="stops_nearby">Stops nearby</string>
+	<string name="results_for">Results for ‘%1$s’</string>
+	<string name="bimba_server_address_hint">Server</string>
+	<string name="bimba_server_token_hint">Token</string>
+	<string name="bimba_server_continue_button">Continue</string>
+	<string name="realtime_content_description">departure is realtime</string>
+	<string name="wheelchair_content_description">vehicle is wheelchair accessible</string>
+	<string name="air_condition_content_description">air conditioning</string>
+	<string name="bicycles_allowed_content_description">bicycles allowed</string>
+	<string name="voice_announcements_content_description">voice announcements</string>
+	<string name="tickets_sold_content_description">tickets sold on board</string>
+	<string name="usb_charging_content_description">USB charging</string>
+	<string name="show_departures">Show departures</string>
+	<string name="open_in_maps_app">Open in maps app</string>
+	<string name="stop_content_description">stop</string>
+	<string name="seatbelts_everyone">Seatbelts, everyone!</string> <!-- taken from ‘Magic School Bus’. Should be translated like in the series. It’s the first words of the intro song -->
+	<string name="onboarding_question">How would you like to start?</string>
+	<string name="onboarding_simple">Simple</string>
+	<string name="onboarding_simple_action">choose localities</string>
+	<string name="onboarding_advanced">Advanced</string>
+	<string name="onboarding_advanced_action">choose server</string>
+	<string name="cancel">Cancel</string>
+	<string name="error">Error</string>
+	<string name="rate_limit">Rate limit</string>
+	<string name="server_rate_limited_question">This server is rate-limited and no token was given. Do you want to continue?</string>
+	<string name="server_private_question">This server is private and no token was given</string>
+	<string name="last_update">Last update: %1$s</string>
+	<string name="title_feeds">Timetables</string>
+	<string name="title_servers">Servers</string>
+	<string name="title_cities">Localities</string>
+	<string name="error_url">Malformed URL provided</string>
+	<string name="error_traffic_spec">Cannot verify server</string>
+	<string name="stops_near_code">Stops near %1$s</string>
+	<string name="code_is_not_full">Code is not full</string>
+	<string name="choose_server">Choose server flavour</string>
+	<string name="ok">OK</string>
+	<string name="no_location_access">Location access not given</string>
+	<string name="no_location_message">Permission to use location is needed to find nearby stops and show current position on map. Other features will work without it. It can be enabled and disabled in system settings any time.</string>
+	<string name="stop_stub_on_demand_in_zone">Stop on demand in zone %1$s</string>
+	<string name="stop_stub_on_demand">Stop on demand</string>
+	<string name="stop_stub_in_zone">Stop in zone %1$s</string>
+	<string name="vehicle_headsign_content_description">%1$s towards %2$s</string>
+	<string name="departure_headsign">» %1$s</string>
+	<string name="credits">Font yellowcircle8 (https://git.apiote.xyz/yellowcircle8.git) based on Railway Sans © Greg Fleming, OFL-1.1 https://github.com/davelab6/Railway-Sans\n\n Mastodon icon (https://github.com/mastodon/joinmastodon) © Mastodon contributors, AGPL-3.0-or-later\n\n Bimba logo created by https://github.com/tebriz159\n\n Material icons © Google, Apache-2.0\n\n Map data © OpenStreetMap contributors (https://www.openstreetmap.org/copyright), ODbL-1.0</string>
+	<string name="title_about">About</string>
+	<string name="translation_button_description">link to translations service</string>
+	<string name="app_description">FLOSS public transport passenger companion; a timetable in your pocket.</string>
+	<string name="website_button_description">link to website</string>
+	<string name="code_button_description">link to source code</string>
+	<string name="mastodon_button_description">link to Mastodon</string>
+	<string name="use_online_feed">Use online feed</string>
+	<string name="information_may_be_outdated">Information may be outdated</string>
+	<string name="current_timetable_validity">Current timetable valid: %1$s to %2$s</string>
+	<string name="error_406">App version is not compatible with the server</string>
+	<string name="filter_localities">filter localities</string>
+	<string name="error_41">This locality is not supported by the server</string>
+	<string name="stop_from_qr_code">QR code stop</string>
+	<string name="departures_snackbar">Last update: %1$s</string>
+	<string name="title_select_date">Select day of departures</string>
+	<string name="title_select_line">Select line</string>
+	<string name="clear_date_selection">Clear</string>
+	<string name="title_filter">Filter</string>
+	<string name="title_filter_byline">Filter by line</string>
+	<string name="title_filter_bytime">Filter by time</string>
+	<string name="title_select_time_start">Select start time</string>
+	<string name="title_select_time_end">Select end time</string>
+	<string name="more">More</string>
+	<string name="alert_header">Status updates</string>
+	<string name="map_attribution"><![CDATA[© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors]]></string>
+	<string name="favourite_content_description">Save as favorite</string>
+	<string name="favourite">Favorite</string>
+	<string name="filtered">Filtered</string>
+	<string name="unfiltered">Unfiltered</string>
+	<string name="cannot_save_favourite">Couldn’t save the favorite</string>
+	<string name="no_next_departures">no more departures</string>
+	<string name="error_44">No more departures</string>
+	<string name="loading">loading…</string>
+	<string name="favourite_deleted">Favorite deleted</string>
+	<string name="undo">Undo</string>
+	<string name="title_activity_settings">SettingsActivity</string>
+	<string name="units_title">Unit system</string>
+	<string name="units_locale_based">Locale based</string>
+	<string name="units_metric">Metric (SI)</string>
+	<string name="units_imperial">Imperial (UK)</string>
+	<string name="units_customary">US Customary</string>
+	<string name="units_tgm10">TGM (base 10)</string>
+	<string name="units_tgm12">TGM (base 12)</string>
+	<string name="title_settings">Settings</string>
+</resources>




diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index df879f01ea8436856a0eed72136b1a4b85951084..76ae82dae9074ecb926e61f518f36d54cef017d4 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -1,4 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
+
+SPDX-License-Identifier: GPL-3.0-or-later
+-->
 <resources>
     <string name="app_name">Bimba</string>
     <string name="title_home">Accueil</string>
@@ -49,7 +54,7 @@     Dernière mise à jour : %1$s
     <string name="title_filter">Filtrer</string>
     <string name="cancel">Annuler</string>
     <string name="more">Plus</string>
-    <string name="title_voyage">Voyage</string>
+    <string name="title_journey">Voyage</string>
     <string name="title_activity_results">Résultats</string>
     <string name="title_map">Carte</string>
     <string name="no_departures">Aucun départ</string>
@@ -68,7 +73,7 @@     Prochainement
     <string name="error_offline">Vous êtes hors ligne. Connectez-vous à Internet</string>
     <string name="off_boarding">Débarquement</string>
     <string name="error_gps">Impossible d\'obtenir la position actuelle</string>
-    <string name="speed_in_km_per_h">%1$.3f km/h</string>
+    <string name="speed_in_km_per_h">%1$s km/h</string>
     <string name="occupancy_unknown">Inconnu</string>
     <string name="occupancy_few_seats">Peu de sièges</string>
     <string name="occupancy_crowded">Encombré</string>




diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index a7ad7ccc620202f1698b8fa2859f47bb1c5276ce..b82bcc3ef26310d03d67a6b5eab3bcf46aac22da 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-SPDX-FileCopyrightText: Adam Evyčędo
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
 
 SPDX-License-Identifier: GPL-3.0-or-later
 --><resources>
     <string name="app_name">Bimba</string>
     <string name="title_home">Casa</string>
     <string name="title_map">Cartina</string>
-    <string name="title_voyage">Viaggio</string>
+    <string name="title_journey">Viaggio</string>
     <string name="home_fab_description">icona GPS</string>
     <string name="search_placeholder">fermate, linee o codici OLC</string>
     <string name="title_activity_results">Risultati</string>




diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml
index 4c87604b47f664e0663bbc07cdf7d3db1016c94b..a29ad3303af3a290263427ff3950ee82602572bf 100644
--- a/app/src/main/res/values-nb-rNO/strings.xml
+++ b/app/src/main/res/values-nb-rNO/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-SPDX-FileCopyrightText: Adam Evyčędo
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
 
 SPDX-License-Identifier: GPL-3.0-or-later
 -->




diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 1f933108d6c66a0dabfa1dd07ac8ddf53f05fc9f..0a7a5bad3e665dddd97dc286915c2260f548725a 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-SPDX-FileCopyrightText: Adam Evyčędo
+SPDX-FileCopyrightText: Adam Evyčędo and contributors using Weblate
 
 SPDX-License-Identifier: GPL-3.0-or-later
 --><resources>
     <string name="app_name">Bimba</string>
     <string name="title_home">Dom</string>
     <string name="title_map">Mapa</string>
-    <string name="title_voyage">Podróż</string>
+    <string name="title_journey">Podróż</string>
     <string name="home_fab_description">ikona lokalizacji</string>
     <string name="search_placeholder">przystanki, linie lub kody OLC</string>
     <string name="title_activity_results">Wyniki</string>