diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index ecde2e9132bd..f8c92c9849a8 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -337,6 +337,7 @@ dependencies {
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.arrow)
+ implementation(libs.arrow.optics)
implementation(libs.arrow.resilience)
implementation(libs.compose.constrainlayout)
implementation(libs.compose.foundation)
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 92471124665d..28d6a17ed1f6 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -106,5 +106,11 @@
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
index 6af9ff57cb02..e4722094f9ae 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
@@ -11,6 +11,8 @@ import net.mullvad.mullvadvpn.lib.model.BuildVersion
import net.mullvad.mullvadvpn.lib.shared.AccountRepository
import net.mullvad.mullvadvpn.lib.shared.ConnectionProxy
import net.mullvad.mullvadvpn.lib.shared.DeviceRepository
+import net.mullvad.mullvadvpn.lib.shared.LocaleRepository
+import net.mullvad.mullvadvpn.lib.shared.RelayLocationTranslationRepository
import net.mullvad.mullvadvpn.lib.shared.VpnPermissionRepository
import org.koin.android.ext.koin.androidContext
import org.koin.core.qualifier.named
@@ -32,5 +34,7 @@ val appModule = module {
single { AccountRepository(get(), get(), MainScope()) }
single { DeviceRepository(get()) }
single { VpnPermissionRepository(androidContext()) }
- single { ConnectionProxy(get(), get()) }
+ single { ConnectionProxy(get(), get(), get()) }
+ single { LocaleRepository(get()) }
+ single { RelayLocationTranslationRepository(get(), get(), MainScope()) }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
index 6494cbb16758..929d1e3b9981 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
@@ -117,7 +117,7 @@ val uiModule = module {
single { MullvadProblemReport(get()) }
single { RelayOverridesRepository(get()) }
single { CustomListsRepository(get()) }
- single { RelayListRepository(get()) }
+ single { RelayListRepository(get(), get()) }
single { RelayListFilterRepository(get()) }
single { VoucherRepository(get(), get()) }
single { SplitTunnelingRepository(get()) }
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt
new file mode 100644
index 000000000000..8969ffd14c16
--- /dev/null
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/LocaleChangedBroadcastReceiver.kt
@@ -0,0 +1,18 @@
+package net.mullvad.mullvadvpn.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import net.mullvad.mullvadvpn.lib.shared.LocaleRepository
+import org.koin.core.component.KoinComponent
+import org.koin.core.component.inject
+
+class LocaleChangedBroadcastReceiver : BroadcastReceiver(), KoinComponent {
+ private val localeRepository by inject()
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+ if (intent?.action == Intent.ACTION_LOCALE_CHANGED) {
+ localeRepository.refreshLocale()
+ }
+ }
+}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt
index ea017339f6c2..6d308e3b267f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt
@@ -55,3 +55,6 @@ fun List.getRelayItemsByCodes(
): List =
this.filter { codes.contains(it.id) } +
this.flatMap { it.descendants() }.filter { codes.contains(it.id) }
+
+fun List.sortedByName() =
+ this.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name })
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt
index ce41b57c4ca4..69a35c406ba0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/RelayListRepository.kt
@@ -1,11 +1,15 @@
package net.mullvad.mullvadvpn.repository
+import arrow.optics.Every
+import arrow.optics.copy
+import arrow.optics.dsl.every
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -17,18 +21,45 @@ import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayItemId
import net.mullvad.mullvadvpn.lib.model.WireguardConstraints
import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData
+import net.mullvad.mullvadvpn.lib.model.cities
+import net.mullvad.mullvadvpn.lib.model.name
+import net.mullvad.mullvadvpn.lib.shared.RelayLocationTranslationRepository
import net.mullvad.mullvadvpn.relaylist.findByGeoLocationId
+import net.mullvad.mullvadvpn.relaylist.sortedByName
class RelayListRepository(
private val managementService: ManagementService,
+ private val translationRepository: RelayLocationTranslationRepository,
dispatcher: CoroutineDispatcher = Dispatchers.IO
) {
val relayList: StateFlow> =
- managementService.relayCountries.stateIn(
- CoroutineScope(dispatcher),
- SharingStarted.WhileSubscribed(),
- emptyList()
- )
+ combine(managementService.relayCountries, translationRepository.translations) {
+ countries,
+ translations ->
+ countries.translateRelays(translations)
+ }
+ .stateIn(CoroutineScope(dispatcher), SharingStarted.WhileSubscribed(), emptyList())
+
+ private fun List.translateRelays(
+ translations: Map
+ ): List {
+ if (translations.isEmpty()) {
+ return this
+ }
+
+ return Every.list()
+ .modify(this) {
+ it.copy {
+ RelayItem.Location.Country.name set translations.getOrDefault(it.name, it.name)
+ RelayItem.Location.Country.cities.every(Every.list()).name transform
+ { cityName ->
+ translations.getOrDefault(cityName, cityName)
+ }
+ RelayItem.Location.Country.cities transform { cities -> cities.sortedByName() }
+ }
+ }
+ .sortedByName()
+ }
val wireguardEndpointData: StateFlow =
managementService.wireguardEndpointData.stateIn(
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GeoIpLocation.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GeoIpLocation.kt
index 3334b458d7a7..d312382a0209 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GeoIpLocation.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GeoIpLocation.kt
@@ -1,7 +1,9 @@
package net.mullvad.mullvadvpn.lib.model
+import arrow.optics.optics
import java.net.InetAddress
+@optics
data class GeoIpLocation(
val ipv4: InetAddress?,
val ipv6: InetAddress?,
@@ -10,4 +12,6 @@ data class GeoIpLocation(
val latitude: Double,
val longitude: Double,
val hostname: String?,
-)
+) {
+ companion object
+}
diff --git a/android/lib/resource/src/main/res/xml-da/relay_locations.xml b/android/lib/resource/src/main/res/xml-da/relay_locations.xml
new file mode 100644
index 000000000000..beba43aed514
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-da/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albanien
+ Amsterdam
+ Ashburn, VA
+ Athen
+ Atlanta, GA
+ Auckland
+ Australien
+ Østrig
+ Bangkok
+ Barcelona
+ Belgien
+ Beograd
+ Berlin
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasilien
+ Brisbane
+ Bruxelles
+ Bukarest
+ Budapest
+ Bulgarien
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chisinau
+ Cleveland, OH
+ Colombia
+ København
+ Kroatien
+ Tjekkiet
+ Dallas, TX
+ Danmark
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Düsseldorf
+ Estland
+ Finland
+ Frankrig
+ Frankfurt
+ Tyskland
+ Glasgow
+ Gøteborg
+ Grækenland
+ Helsingborg
+ Helsinki
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Ungarn
+ Indien
+ Indonesien
+ Irland
+ Israel
+ Italien
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiev
+ Kyiv
+ Letland
+ Lissabon
+ Ljubljana
+ London
+ Los Angeles, Californien
+ Louisville, KY
+ Luxembourg
+ Madrid
+ Malmø
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexico
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldova
+ Montreal
+ Holland
+ New York, NY
+ New Zealand
+ Nis
+ Nordmakedonien
+ Norge
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polen
+ Portland, OR
+ Portugal
+ Prag
+ Pune
+ Queretaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Rumænien
+ Rom
+ Salt Lake City, UT
+ San Francisco, Californien
+ San Jose, Californien
+ Santiago
+ Sao Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbien
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakiet
+ Slovenien
+ Sofia
+ Sydafrika
+ Spanien
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Sverige
+ Schweiz
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Tokyo
+ Toronto
+ UK
+ USA
+ Ukraine
+ Forenede Arabiske Emirater
+ Valencia
+ Vancouver
+ Wien
+ Warszawa
+ Washington DC
+ Wien
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-de/relay_locations.xml b/android/lib/resource/src/main/res/xml-de/relay_locations.xml
new file mode 100644
index 000000000000..26bf0eab00ab
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-de/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albanien
+ Amsterdam
+ Ashburn, VA
+ Athen
+ Atlanta, GA
+ Auckland
+ Australien
+ Österreich
+ Bangkok
+ Barcelona
+ Belgien
+ Belgrad
+ Berlin
+ Bogotá
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasilien
+ Brisbane
+ Brüssel
+ Bukarest
+ Budapest
+ Bulgarien
+ Calgary
+ Kanada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chișinău
+ Cleveland, OH
+ Kolumbien
+ Kopenhagen
+ Kroatien
+ Tschechien
+ Dallas, TX
+ Dänemark
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Düsseldorf
+ Estland
+ Finnland
+ Frankreich
+ Frankfurt am Main
+ Deutschland
+ Glasgow
+ Göteborg
+ Griechenland
+ Helsingborg
+ Helsinki
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Ungarn
+ Indien
+ Indonesien
+ Irland
+ Israel
+ Italien
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiew
+ Kiew
+ Lettland
+ Lissabon
+ Ljubljana
+ London
+ Los Angeles, CA
+ Louisville, KY
+ Luxemburg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexiko
+ Miami, FL
+ Mailand
+ Milwaukee, WI
+ Minneapolis/St. Paul Flgh. , MN
+ Republik Moldau
+ Montreal
+ Niederlande
+ New York City, NY
+ Neuseeland
+ Niš
+ Nordmazedonien
+ Norwegen
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polen
+ Portland, OR
+ Portugal
+ Prag
+ Pune
+ Santiago de Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Rumänien
+ Rom
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbien
+ Singapur
+ Sioux Falls, SD
+ Skopje
+ Slowakei
+ Slowenien
+ Sofia
+ Südafrika
+ Spanien
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Schweden
+ Schweiz
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Präfektur Tokio
+ Toronto
+ Vereinigtes Königreich
+ Vereinigte Staaten
+ Ukraine
+ Vereinigte Arabische Emirate
+ Valencia
+ Vancouver
+ Wien
+ Warschau
+ Washington DC
+ Wien
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-es/relay_locations.xml b/android/lib/resource/src/main/res/xml-es/relay_locations.xml
new file mode 100644
index 000000000000..56414443b3f7
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-es/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albania
+ Ámsterdam
+ Ashburn, VA
+ Atenas
+ Atlanta, GA
+ Auckland
+ Australia
+ Austria
+ Bangkok
+ Barcelona
+ Bélgica
+ Belgrado
+ Berlín
+ Bogotá
+ Burdeos
+ Boston, MA
+ Bratislava
+ Brasil
+ Brisbane
+ Bruselas
+ Bucarest
+ Budapest
+ Bulgaria
+ Calgary
+ Canadá
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chisináu
+ Cleveland, OH
+ Colombia
+ Copenhague
+ Croacia
+ República Checa
+ Dallas, TX
+ Dinamarca
+ Denver, CO
+ Detroit, MI
+ Dubái
+ Dublín
+ Düsseldorf
+ Estonia
+ Finlandia
+ Francia
+ Fráncfort
+ Alemania
+ Glasgow
+ Gotemburgo
+ Grecia
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, Texas
+ Hungría
+ India
+ Indonesia
+ Irlanda
+ Israel
+ Italia
+ Jackson, MS
+ Yakarta
+ Japón
+ Johannesburgo
+ Kiev
+ Kiev
+ Letonia
+ Lisboa
+ Liubliana
+ Londres
+ Los Ángeles, CA
+ Louisville, KY
+ Luxemburgo
+ Madrid
+ Malmö
+ Manchester
+ Marsella
+ McAllen, TX
+ Melbourne
+ México
+ Miami, FL
+ Milán
+ Milwaukee, WI
+ Minneapolis/St Paul Apt, MN
+ Moldavia
+ Montreal
+ Países Bajos
+ Nueva York, NY
+ Nueva Zelanda
+ Niš
+ Macedonia del Norte
+ Noruega
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ París
+ Perth
+ Filadelfia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polonia
+ Portland, OR
+ Portugal
+ Praga
+ Pune
+ Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Rumanía
+ Roma
+ Salt Lake City, UT
+ San Francisco, CA
+ San José, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapur
+ Sioux Falls, SD
+ Skopie
+ Eslovaquia
+ Eslovenia
+ Sofía
+ Sudáfrica
+ España
+ San Luis, MO
+ Stamford, CT
+ Stavanger
+ Estocolmo
+ Suecia
+ Suiza
+ Sídney
+ Tallin
+ Tel Aviv
+ Tailandia
+ Tirana
+ Tokio
+ Toronto
+ Reino Unido
+ Estados Unidos
+ Ucrania
+ Emiratos Árabes Unidos
+ Valencia
+ Vancouver
+ Viena
+ Varsovia
+ Washington DC
+ Viena
+ Zagreb
+ Zúrich
+
diff --git a/android/lib/resource/src/main/res/xml-fi/relay_locations.xml b/android/lib/resource/src/main/res/xml-fi/relay_locations.xml
new file mode 100644
index 000000000000..1adb4cbd7ef7
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-fi/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albania
+ Amsterdam
+ Ashburn, VA
+ Ateena
+ Atlanta, GA
+ Auckland
+ Australia
+ Itävalta
+ Bangkok
+ Barcelona
+ Belgia
+ Belgrad
+ Berliini
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasilia
+ Brisbane
+ Bryssel
+ Bukarest
+ Budapest
+ Bulgaria
+ Calgary
+ Kanada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chisinau
+ Cleveland, OH
+ Kolumbia
+ Kööpenhamina
+ Kroatia
+ Tšekki
+ Dallas, TX
+ Tanska
+ Denver, CO
+ Detroit, Michigan
+ Dubai
+ Dublin
+ Düsseldorf
+ Viro
+ Suomi
+ Ranska
+ Frankfurt
+ Saksa
+ Glasgow
+ Göteborg
+ Kreikka
+ Helsingborg
+ Helsinki
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Unkari
+ Intia
+ Indonesia
+ Irlanti
+ Israel
+ Italia
+ Jackson, MS
+ Jakarta
+ Japani
+ Johannesburg
+ Kiova
+ Kiova
+ Latvia
+ Lissabon
+ Ljubljana
+ Lontoo
+ Los Angeles, CA
+ Louisville, KY
+ Luxemburg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Meksiko
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldova
+ Montreal
+ Alankomaat
+ New York, NY
+ Uusi-Seelanti
+ Nis
+ Pohjois-Makedonia
+ Norja
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Pariisi
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Puola
+ Portland, OR
+ Portugali
+ Praha
+ Pune
+ Queretaro
+ Raleigh, NC
+ Richmond, VA
+ Riika
+ Romania
+ Rooma
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakia
+ Slovenia
+ Sofia
+ Etelä-Afrikka
+ Espanja
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Tukholma
+ Ruotsi
+ Sveitsi
+ Sydney
+ Tallinna
+ Tel Aviv
+ Thaimaa
+ Tirana
+ Tokio
+ Toronto
+ Iso-Britannia
+ Yhdysvallat
+ Ukraina
+ Yhdistyneet Arabiemiirikunnat
+ Valencia
+ Vancouver
+ Wien
+ Varsova
+ Washington DC
+ Wien
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-fr/relay_locations.xml b/android/lib/resource/src/main/res/xml-fr/relay_locations.xml
new file mode 100644
index 000000000000..cebc852c138b
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-fr/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adélaïde
+ Albanie
+ Amsterdam
+ Ashburn, VA
+ Athènes
+ Atlanta, GA
+ Auckland
+ Australie
+ Autriche
+ Bangkok
+ Barcelone
+ Belgique
+ Belgrade
+ Berlin
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brésil
+ Brisbane
+ Bruxelles
+ Bucarest
+ Budapest
+ Bulgarie
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chili
+ Chișinău
+ Cleveland, OH
+ Colombie
+ Copenhague
+ Croatie
+ République tchèque
+ Dallas, TX
+ Danemark
+ Denver, CO
+ Detroit, MI
+ Dubaï
+ Dublin
+ Düsseldorf
+ Estonie
+ Finlande
+ France
+ Francfort-sur-le-Main
+ Allemagne
+ Glasgow
+ Göteborg
+ Grèce
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Hongrie
+ Inde
+ Indonésie
+ Irlande
+ Israël
+ Italie
+ Jackson, MS
+ Jakarta
+ Japon
+ Johannesbourg
+ Kiev
+ Kiev
+ Lettonie
+ Lisbonne
+ Ljubljana
+ Londres
+ Los Angeles, CA
+ Louisville, KY
+ Luxembourg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexique
+ Miami, FL
+ Milan
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldavie
+ Montréal
+ Pays-Bas
+ New York, NY
+ Nouvelle-Zélande
+ Niš
+ Macédoine du Nord
+ Norvège
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palerme
+ Paris
+ Perth
+ Philadelphie, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Pologne
+ Portland, OR
+ Portugal
+ Prague
+ Pune
+ Santiago de Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Roumanie
+ Rome
+ Salt Lake City, UT
+ San Francisco, CA
+ San José, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbie
+ Singapour
+ Sioux Falls, SD
+ Skopje
+ Slovaquie
+ Slovénie
+ Sofia
+ Afrique du Sud
+ Espagne
+ Saint-Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Suède
+ Suisse
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thaïlande
+ Tirana
+ Tokyo
+ Toronto
+ Royaume-Uni
+ États-Unis
+ Ukraine
+ Émirats arabes unis
+ Valence
+ Vancouver
+ Vienne
+ Varsovie
+ Washington DC
+ Vienne
+ Zagreb
+ Zurich
+
diff --git a/android/lib/resource/src/main/res/xml-it/relay_locations.xml b/android/lib/resource/src/main/res/xml-it/relay_locations.xml
new file mode 100644
index 000000000000..070246b9c5fe
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-it/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albania
+ Amsterdam
+ Ashburn, VA
+ Atene
+ Atlanta, GA
+ Auckland
+ Australia
+ Austria
+ Bangkok
+ Barcellona
+ Belgio
+ Belgrado
+ Berlino
+ Bogotà
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasile
+ Brisbane
+ Bruxelles
+ Bucarest
+ Budapest
+ Bulgaria
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Cile
+ Chisinau
+ Cleveland, OH
+ Colombia
+ Copenaghen
+ Croazia
+ Repubblica Ceca
+ Dallas, TX
+ Danimarca
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublino
+ Dusseldorf
+ Estonia
+ Finlandia
+ Francia
+ Francoforte sul Meno
+ Germania
+ Glasgow
+ Göteborg
+ Grecia
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Ungheria
+ India
+ Indonesia
+ Irlanda
+ Israele
+ Italia
+ Jackson, MS
+ Giacarta
+ Giappone
+ Johannesburg
+ Kiev
+ Kiev
+ Lettonia
+ Lisbona
+ Lubiana
+ Londra
+ Los Angeles, CA
+ Louisville, KY
+ Lussemburgo
+ Madrid
+ Malmö
+ Manchester
+ Marsiglia
+ McAllen, TX
+ Melbourne
+ Messico
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldavia
+ Montréal
+ Paesi Bassi
+ New York, NY
+ Nuova Zelanda
+ Nis
+ Macedonia del Nord
+ Norvegia
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Parigi
+ Perth
+ Filadelfia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polonia
+ Portland, OR
+ Portogallo
+ Praga
+ Pune
+ Santiago de Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Romania
+ Roma
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ San Paolo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakia
+ Slovenia
+ Sofia
+ Sudafrica
+ Spagna
+ Saint Louis, MO
+ Stamford, CT
+ Stavanger
+ Stoccolma
+ Svezia
+ Svizzera
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailandia
+ Tirana
+ Tokyo
+ Toronto
+ Regno Unito
+ Stati Uniti d\'America
+ Ucraina
+ Emirati Arabi Uniti
+ Valencia
+ Vancouver
+ Vienna
+ Varsavia
+ Washington DC
+ Vienna
+ Zagabria
+ Zurigo
+
diff --git a/android/lib/resource/src/main/res/xml-ja/relay_locations.xml b/android/lib/resource/src/main/res/xml-ja/relay_locations.xml
new file mode 100644
index 000000000000..b68b5be6872d
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-ja/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ アデレード
+ アルバニア
+ アムステルダム
+ アッシュバーン、VA
+ アテネ
+ アトランタ、GA
+ オークランド
+ オーストラリア
+ オーストリア
+ バンコク
+ バルセロナ
+ ベルギー
+ ベオグラード
+ ベルリン
+ ボゴタ
+ ボルドー
+ ボストン、MA
+ ブラチスラバ
+ ブラジル
+ ブリスベン
+ ブリュッセル
+ ブカレスト
+ ブダペスト
+ ブルガリア
+ カルガリー
+ カナダ
+ キャンベラ
+ シャーロット、NC
+ シカゴ、IL
+ チリ
+ キシナウ
+ クリーブランド、OH
+ コロンビア
+ コペンハーゲン
+ クロアチア
+ チェコ
+ ダラス、TX
+ デンマーク
+ デンバー、CO
+ デトロイト、MI
+ ドバイ
+ ダブリン
+ デュッセルドルフ
+ エストニア
+ フィンランド
+ フランス
+ フランクフルト
+ ドイツ
+ グラスゴー
+ ヨーテボリ
+ ギリシャ
+ ヘルシンボリ
+ ヘルシンキ
+ 香港
+ ホノルル、HI
+ ヒューストン、TX
+ ハンガリー
+ インド
+ インドネシア
+ アイルランド
+ イスラエル
+ イタリア
+ ジャクソン、MS
+ ジャカルタ
+ 日本
+ ヨハネスブルグ
+ キエフ
+ キエフ
+ ラトビア
+ リスボン
+ リュブリャナ
+ ロンドン
+ ロサンゼルス、CA
+ ルイビル、KY
+ ルクセンブルク
+ マドリード
+ マルメ
+ マンチェスター
+ マルセイユ
+ マッカレン、TX
+ メルボルン
+ メキシコ
+ マイアミ、FL
+ ミラノ
+ ミルウォーキー、WI
+ ミネアポリス/セントポール国際空港、MN
+ モルドバ
+ モントリオール
+ オランダ
+ ニューヨーク、NY
+ ニュージーランド
+ ニシュ
+ 北マケドニア
+ ノルウェー
+ オクラホマシティ、OK
+ 大阪
+ オスロ
+ パレルモ
+ パリ
+ パース
+ フィラデルフィア、PA
+ フェニックス、AZ
+ ピスカタウェイ、NJ
+ ポーランド
+ ポートランド、OR
+ ポルトガル
+ プラハ
+ プネー
+ ケレタロ
+ ローリー、NC
+ リッチモンド、VA
+ リガ
+ ルーマニア
+ ローマ
+ ソルトレイクシティ、UT
+ サンフランシスコ、CA
+ サンノゼ、CA
+ サンチャゴ
+ サンパウロ
+ シアトル、WA
+ セコーカス、NJ
+ セルビア
+ シンガポール
+ スーフォールズ、SD
+ スコピエ
+ スロバキア
+ スロベニア
+ ソフィア
+ 南アフリカ
+ スペイン
+ セントルイス、MO
+ スタンフォード、CT
+ スタヴァンゲル
+ ストックホルム
+ スウェーデン
+ スイス
+ シドニー
+ タリン
+ テルアビブ
+ タイ
+ ティラナ
+ 東京
+ トロント
+ イギリス
+ アメリカ合衆国
+ ウクライナ
+ アラブ首長国連邦
+ バレンシア
+ バンクーバー
+ ウィーン
+ ワルシャワ
+ ワシントン DC
+ ウィーン
+ ザグレブ
+ チューリッヒ
+
diff --git a/android/lib/resource/src/main/res/xml-ko/relay_locations.xml b/android/lib/resource/src/main/res/xml-ko/relay_locations.xml
new file mode 100644
index 000000000000..3d807440a1f5
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-ko/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ 애들레이드
+ 알바니아
+ 암스테르담
+ 애쉬번, 버지니아 주
+ 아테네
+ 애틀랜타, GA
+ 오클랜드
+ 오스트레일리아
+ 오스트리아
+ 방콕
+ 바르셀로나
+ 벨기에
+ 베오그라드
+ 베를린
+ 보고타
+ 보르도
+ 보스톤, MA
+ 브라티슬라바
+ 브라질
+ 브리즈번
+ 브뤼셀
+ 부쿠레슈티
+ 부다페스트
+ 불가리아
+ 캘거리
+ 캐나다
+ 캔버라
+ 샬롯, NC
+ 시카고, IL
+ 칠레
+ 키시나우
+ 클리블랜드, OH
+ 콜롬비아
+ 코펜하겐
+ 크로아티아
+ 체코
+ 댈러스, TX
+ 덴마크
+ 덴버, CO
+ 미시간주 디트로이트
+ 두바이
+ 더블린
+ 뒤셀도르프
+ 에스토니아
+ 핀란드
+ 프랑스
+ 프랑크푸르트
+ 독일
+ 글래스고
+ 예테보리
+ 그리스
+ 헬싱보리
+ 헬싱키
+ 홍콩
+ 호놀룰루, HI
+ 휴스턴, 텍사스
+ 헝가리
+ 인도
+ 인도네시아
+ 아일랜드
+ 이스라엘
+ 이탈리아
+ 잭슨, MS
+ 자카르타
+ 일본
+ 요하네스버그
+ 키예프
+ 키예프
+ 라트비아
+ 리스본
+ 류블랴나
+ 런던
+ 로스앤젤레스, CA
+ 루이빌, KY
+ 룩셈부르크
+ 마드리드
+ 말뫼
+ 맨체스터
+ 마르세이유
+ 맥앨런, 텍사스
+ 멜버른
+ 멕시코
+ 마이애미, FL
+ 밀라노
+ 밀워키, WI
+ 미니애폴리스/세인트 폴 공항, MN
+ 몰도바
+ 몬트리올
+ 네덜란드
+ 뉴욕, NY
+ 뉴질랜드
+ 니시
+ 북마케도니아
+ 노르웨이
+ 오클라호마 시티, OK
+ 오사카
+ 오슬로
+ 팔레르모
+ 파리
+ 퍼스
+ 필라델피아, PA
+ 피닉스, AZ
+ 피스카타웨이, NJ
+ 폴란드
+ 포틀랜드, OR
+ 포르투갈
+ 프라하
+ 푸네
+ 케레타로
+ 노스캐롤라이나, 롤리
+ 리치몬드, VA
+ 리가
+ 루마니아
+ 로마
+ 솔트레이크시티, UT
+ 샌프란시스코, CA
+ 산호세, CA
+ 산티아고
+ 상파울루
+ 시애틀, WA
+ 세코커스, NJ
+ 세르비아
+ 싱가포르
+ 수 폴스, SD
+ 스코페
+ 슬로바키아
+ 슬로베니아
+ 소피아
+ 남아프리카 공화국
+ 스페인
+ 세인트루이스, MO
+ 스탬포드, CT
+ 스타방에르
+ 스톡홀름
+ 스웨덴
+ 스위스
+ 시드니
+ 탈린
+ 텔아비브
+ 태국
+ 티라나
+ 도쿄
+ 토론토
+ 영국
+ 미국
+ 우크라이나
+ 아랍에미리트
+ 발렌시아
+ 밴쿠버
+ 비엔나
+ 바르샤바
+ 워싱턴 DC
+ 빈
+ 자그레브
+ 취리히
+
diff --git a/android/lib/resource/src/main/res/xml-my/relay_locations.xml b/android/lib/resource/src/main/res/xml-my/relay_locations.xml
new file mode 100644
index 000000000000..d93745bdbdac
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-my/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ အက်ဒလိတ်
+ အယ်လ်ဘေးနီးယား
+ အမ်စတာဒမ်
+ Ashburn, VA
+ အေသင်
+ အတ္တလန်တာ၊ ဂျော်ဂျီယာ
+ အော့ကလန်
+ သြစတြေးလျ
+ သြစတြီးယား
+ ဘန်ကောက်
+ ဘာစီလိုနာ
+ ဘယ်လ်ဂျီယံ
+ ဘဲလ်ဂရိတ်
+ ဘာလင်
+ ဘိုဂိုတာ
+ ဘော်ဒို
+ ဘော်စတွန်၊ မက်ဆာချူးဆက်
+ Bratislava
+ ဘရာဇီး
+ ဘရစ်စဘိန်း
+ ဘရပ်ဆဲလ်
+ ဘူခါရက်စ်
+ ဘူဒါပက်
+ ဘူလ်ဂေးရီးယား
+ ကယ်ဂယ်ရီ
+ ကနေဒါ
+ ကင်ဘာရာ
+ ရှားလော့၊ မြောက်ကာရိုလိုင်းနား
+ ချီကာဂို၊ အီလီနွိုက်
+ ချီလီ
+ ခိရှီနို
+ ကလိဗ်လန့် ၊ အိုဟိုင်းယိုး
+ ကိုလံဘီယာ
+ ကိုပင်ဟေဂင်
+ ခရိုအေးရှား
+ ချက်သမ္မတနိုင်ငံ
+ ဒဲလ်လက်စ်၊ တက္ကဆက်
+ ဒိန်းမတ်
+ ဒန်ဗာ၊ ကော်လိုရာဒို
+ ဒီထရိုက်၊ MI
+ ဒူဘိုင်း
+ ဒါဘလင်
+ ဒူဆင်ဒေါ့ဖ်
+ အက်စ်တိုးနီးယား
+ ဖင်လန်
+ ပြင်သစ်
+ ဖရန့်ဖတ်
+ ဂျာမနီ
+ ဂလပ်စဂို
+ ဂိုသန်ဘက်
+ ဂရိ
+ ဟယ်ဆင်းဘော့
+ ဟယ်လ်စင်ကီ
+ ဟောင်ကောင်
+ ဟိုနိုလူလူ၊ ဟာဝိုင်ယီ
+ Houston, TX
+ ဟန်ဂေရီ
+ အိန္ဒိယ
+ အင်ဒိုနီးရှား
+ အိုင်ယာလန်
+ အစ္စရေး
+ အီတလီ
+ ဂျက်ဆင်၊ မစ္စစ္စပီ
+ ဂျာကာတာ
+ ဂျပန်
+ ဂျိုဟန်နက်စ်ဘတ်
+ ကိယက်ဗ်
+ ကိယက်ဗ်
+ လတ်ဗီးယား
+ လစ္စဘွန်း
+ လစ်ဘီယာနာ
+ လန်ဒန်
+ လော့စ်အိန်ဂျလိစ်၊ ကယ်လီဖိုးနီးယား
+ လူဝီဗေးလ်၊ ကင်တပ်ကီ
+ လူဇင်ဘတ်
+ မက်ဒရစ်
+ မယ်မို
+ မန်ချက်စတာ
+ မာဆေး
+ McAllen, TX
+ မဲလ်ဘုန်း
+ မက္ကဆီကို
+ မိုင်ယာမီ၊ ဖလော်ရီဒါ
+ မီလန်
+ မီဝါကီ၊ ဝစ္စကန်ဆင်
+ မင်နီယာပိုလစ်/စိန့်ပေါလ် လေဆိပ်၊ မင်နီဆိုးတား
+ မော်လ်ဒိုဗာ
+ မွန်ထရီရယ်
+ နယ်သာလန်
+ နယူးယောက်
+ နယူးဇီလန်
+ နိစ်
+ မြောက်မက်ဆီဒိုးနီးယား
+ နော်ဝေး
+ အိုကလာဟိုးမားစီးတီး၊ အိုကလာဟိုးမား
+ အိုဆာကာ
+ အော်စလို
+ Palermo
+ ပဲရစ်
+ ပါ့သ်
+ ဖီလဒဲလ်ဖီးယား၊ ပန်ဆဲလ်ဗေးနီးယား
+ ဖီးနစ်၊ အရီဇိုးနား
+ ပစ်စ်ကာတာဝေး၊ နယူးဂျာစီ
+ ပိုလန်
+ ပို့တ်လန်၊ အော်ရီဂွန်
+ ပေါ်တူဂီ
+ ပရာ့ဂ်
+ ပူနာ
+ ကီရင်တာရို (Queretaro)
+ ရာလီ၊ မြောက်ကာရိုလိုင်းနား
+ ရစ်ချ်မန်၊ ဗာဂျီးနီးယား
+ ရီဂါ
+ ရိုမေးနီးယား
+ ရောမ
+ ဆော့တ်လိတ်ခ်စီးတီး၊ ယူတာ
+ ဆန်ဖရန်စစ္စကို၊ ကယ်လီဖိုးနီးယား
+ ဆန်ဟိုဆေး၊ ကယ်လီဖိုးနီးယား
+ ဆန်တီယာဂို
+ ဆောပိုလို
+ ဆီယက်တဲလ်၊ ဝါရှင်တန်
+ ဆီကောကတ်စ်၊ နယူးဂျာစီ
+ ဆားဘီးယား
+ စင်ကာပူ
+ ဆူးဖော၊ တောင်ဒါကိုတာ
+ စကော့ပ်ရာ
+ Slovakia
+ ဆလိုဗေးနီးယား
+ ဆိုဖီယာ
+ တောင်အာဖရိက
+ စပိန်
+ စိန့်လူးဝစ်၊ မစ်ဆူရီ
+ စတမ်းဖို့၊ ကော်နက်တီကပ်
+ Stavanger
+ စတော့ဟုမ်း
+ ဆွီဒင်
+ ဆွစ်ဇာလန်
+ ဆစ်ဒနီ
+ တောလ်လင်း
+ တဲလ်အဗစ်
+ ထိုင်း
+ တေရားနား
+ တိုကျို
+ တိုရွန်တို
+ UK
+ USA
+ ယူကရိန်း
+ အာရတ်စော်ဘွားများ ပြည်ထောင်စု
+ ဗလန်စီယာ
+ ဗန်ကူးဗား
+ ဗီယင်နာ
+ ဝါဆော
+ ဝါရှင်တန်ဒီစီ
+ ဗင်း
+ ဇက်ဂ်ရက်ဘ်
+ ဇူးရစ်ချ်
+
diff --git a/android/lib/resource/src/main/res/xml-nb/relay_locations.xml b/android/lib/resource/src/main/res/xml-nb/relay_locations.xml
new file mode 100644
index 000000000000..3a200eebc0df
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-nb/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albania
+ Amsterdam
+ Ashburn, VA
+ Athen
+ Atlanta, GA
+ Auckland
+ Australia
+ Østerrike
+ Bangkok
+ Barcelona
+ Belgia
+ Beograd
+ Berlin
+ Bogotá
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasil
+ Brisbane
+ Brussel
+ București
+ Budapest
+ Bulgaria
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chișinău
+ Cleveland, OH
+ Colombia
+ København
+ Kroatia
+ Tsjekkia
+ Dallas, TX
+ Danmark
+ Denver, CO
+ Detroit i Michigan
+ Dubai
+ Dublin
+ Düsseldorf
+ Estland
+ Finland
+ Frankrike
+ Frankfurt
+ Tyskland
+ Glasgow
+ Göteborg
+ Hellas
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Ungarn
+ India
+ Indonesia
+ Irland
+ Israel
+ Italia
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiev
+ Kyiv
+ Latvia
+ Lisboa
+ Ljubljana
+ London
+ Los Angeles, CA
+ Louisville, KY
+ Luxembourg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexico
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldova
+ Montreal
+ Nederland
+ New York, NY
+ New Zealand
+ Niš
+ Nord-Makedonia
+ Norge
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polen
+ Portland, OR
+ Portugal
+ Praha
+ Pune
+ Queretaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Romania
+ Roma
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ Sao Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakia
+ Slovenia
+ Sofia
+ Sør-Afrika
+ Spania
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Sverige
+ Sveits
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Tokyo
+ Toronto
+ Storbritannia
+ USA
+ Ukraina
+ De forente arabiske emirater
+ Valencia
+ Vancouver
+ Wien
+ Warszawa
+ Washington DC
+ Wien
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-nl/relay_locations.xml b/android/lib/resource/src/main/res/xml-nl/relay_locations.xml
new file mode 100644
index 000000000000..c15b4c4c5aa2
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-nl/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albanië
+ Amsterdam
+ Ashburn, VA
+ Athene
+ Atlanta, GA
+ Auckland
+ Australië
+ Oostenrijk
+ Bangkok
+ Barcelona
+ België
+ Belgrado
+ Berlijn
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brazilië
+ Brisbane
+ Brussel
+ Boekarest
+ Boedapest
+ Bulgarije
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chili
+ Chisinau
+ Cleveland, OH
+ Colombia
+ Kopenhagen
+ Kroatië
+ Tsjechië
+ Dallas, TX
+ Denemarken
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Düsseldorf
+ Estland
+ Finland
+ Frankrijk
+ Frankfurt am Main
+ Duitsland
+ Glasgow
+ Göteborg
+ Griekenland
+ Helsingborg
+ Helsinki
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Hongarije
+ India
+ Indonesië
+ Ierland
+ Israël
+ Italië
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiev
+ Kiev
+ Letland
+ Lissabon
+ Ljubljana
+ Londen
+ Los Angeles, CA
+ Louisville, KY
+ Luxemburg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexico
+ Miami, FL
+ Milaan
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldavië
+ Montreal
+ Nederland
+ New York, NY
+ Nieuw-Zeeland
+ Niš
+ Noord-Macedonië
+ Noorwegen
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Parijs
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polen
+ Portland, OR
+ Portugal
+ Praag
+ Pune
+ Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Roemenië
+ Rome
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Servië
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slowakije
+ Slovenië
+ Sofia
+ Zuid-Afrika
+ Spanje
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Zweden
+ Zwitserland
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Tokio
+ Toronto
+ Verenigd Koninkrijk
+ Verenigde Staten van Amerika
+ Oekraïne
+ Verenigde Arabische Emiraten
+ Valencia
+ Vancouver
+ Wenen
+ Warschau
+ Washington DC
+ Wenen
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-pl/relay_locations.xml b/android/lib/resource/src/main/res/xml-pl/relay_locations.xml
new file mode 100644
index 000000000000..3d6a23f9d9b5
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-pl/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelajda
+ Albania
+ Amsterdam
+ Ashburn, VA
+ Ateny
+ Atlanta, GA
+ Auckland
+ Australia
+ Austria
+ Bangkok
+ Barcelona
+ Belgia
+ Belgrad
+ Berlin
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratysława
+ Brazylia
+ Brisbane
+ Bruksela
+ Bukareszt
+ Budapeszt
+ Bułgaria
+ Calgary
+ Kanada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Kiszyniów
+ Cleveland, OH
+ Kolumbia
+ Kopenhaga
+ Chorwacja
+ Czechy
+ Dallas, TX
+ Dania
+ Denver, CO
+ Detroit, MI
+ Dubaj
+ Dublin
+ Düsseldorf
+ Estonia
+ Finlandia
+ Francja
+ Frankfurt
+ Niemcy
+ Glasgow
+ Göteborg
+ Grecja
+ Helsingborg
+ Helsinki
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Węgry
+ Indie
+ Indonezja
+ Irlandia
+ Izrael
+ Włochy
+ Jackson, MS
+ Dżakarta
+ Japonia
+ Johannesburg
+ Kijów
+ Kijów
+ Łotwa
+ Lizbona
+ Lublana
+ Londyn
+ Los Angeles, CA
+ Louisville, KY
+ Luksemburg
+ Madryt
+ Malmö
+ Manchester
+ Marsylia
+ McAllen, TX
+ Melbourne
+ Meksyk
+ Miami, FL
+ Mediolan
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Mołdawia
+ Montreal
+ Holandia
+ Nowy Jork, NY
+ Nowa Zelandia
+ Nisz
+ Macedonia Północna
+ Norwegia
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paryż
+ Perth
+ Filadelfia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polska
+ Portland, OR
+ Portugalia
+ Praga
+ Pune
+ Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Ryga
+ Rumunia
+ Rzym
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapur
+ Sioux Falls, SD
+ Skopje
+ Słowacja
+ Słowenia
+ Sofia
+ Republika Południowej Afryki
+ Hiszpania
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Sztokholm
+ Szwecja
+ Szwajcaria
+ Sydney
+ Tallin
+ Tel Awiw
+ Tajlandia
+ Tirana
+ Tokio
+ Toronto
+ Wielka Brytania
+ Stany Zjednoczone
+ Ukraina
+ Zjednoczone Emiraty Arabskie
+ Walencja
+ Vancouver
+ Wiedeń
+ Warszawa
+ Waszyngton, DC
+ Wiedeń
+ Zagrzeb
+ Zurych
+
diff --git a/android/lib/resource/src/main/res/xml-pt/relay_locations.xml b/android/lib/resource/src/main/res/xml-pt/relay_locations.xml
new file mode 100644
index 000000000000..c1576f85a8e7
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-pt/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albânia
+ Amesterdão
+ Ashburn, VA
+ Atenas
+ Atlanta, GA
+ Auckland
+ Austrália
+ Áustria
+ Banguecoque
+ Barcelona
+ Bélgica
+ Belgrado
+ Berlim
+ Bogotá
+ Bordéus
+ Boston, MA
+ Bratislava
+ Brasil
+ Brisbane
+ Bruxelas
+ Bucareste
+ Budapeste
+ Bulgária
+ Calgary
+ Canadá
+ Camberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chişinău
+ Cleveland, OH
+ Colômbia
+ Copenhaga
+ Croácia
+ República Checa
+ Dallas, TX
+ Dinamarca
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Dusseldorf
+ Estónia
+ Finlândia
+ França
+ Frankfurt
+ Alemanha
+ Glasgow
+ Gotemburgo
+ Grécia
+ Helsingborg
+ Helsínquia
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Hungria
+ Índia
+ Indonésia
+ República da Irlanda
+ Israel
+ Itália
+ Jackson, MS
+ Jacarta
+ Japão
+ Joanesburgo
+ Kiev
+ Kiev
+ Letónia
+ Lisboa
+ Ljubljana
+ Londres
+ Los Angeles, CA
+ Louisville, KY
+ Luxemburgo
+ Madrid
+ Malmö
+ Manchester
+ Marselha
+ McAllen, TX
+ Melbourne
+ México
+ Miami, FL
+ Milão
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldávia
+ Montreal
+ Países Baixos
+ Nova Iorque, NY
+ Nova Zelândia
+ Niš
+ Macedónia do Norte
+ Noruega
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Filadélfia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polónia
+ Portland, OR
+ Portugal
+ Praga
+ Pune
+ Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Roménia
+ Roma
+ Salt Lake City, UT
+ São Francisco, CA
+ Puerto San José, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Sérvia
+ Singapura
+ Sioux Falls, SD
+ Skopje
+ Eslováquia
+ Eslovénia
+ Sófia
+ África do Sul
+ Espanha
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Estocolmo
+ Suécia
+ Suíça
+ Sydney
+ Tallinn
+ Telavive
+ Tailândia
+ Tirana
+ Tóquio
+ Toronto
+ Reino Unido
+ Estados Unidos
+ Ucrânia
+ Emirados Árabes Unidos
+ Valência
+ Vancouver
+ Viena
+ Varsóvia
+ Washington DC
+ Viena
+ Zagreb
+ Zurique
+
diff --git a/android/lib/resource/src/main/res/xml-ru/relay_locations.xml b/android/lib/resource/src/main/res/xml-ru/relay_locations.xml
new file mode 100644
index 000000000000..d658f846fc96
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-ru/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Аделаида
+ Албания
+ Амстердам
+ Эшберн, Вирджиния
+ Афины
+ Атланта, GA
+ Окленд
+ Австралия
+ Австрия
+ Бангкок
+ Барселона
+ Бельгия
+ Белград
+ Берлин
+ Богота
+ Бордо
+ Бостон, MA
+ Братислава
+ Бразилия
+ Брисбен
+ Брюссель
+ Бухарест
+ Будапешт
+ Болгария
+ Калгари
+ Канада
+ Канберра
+ Шарлотт, NC
+ Чикаго, IL
+ Чили
+ Кишинёв
+ Кливленд, OH
+ Колумбия
+ Копенгаген
+ Хорватия
+ Чехия
+ Даллас, TX
+ Дания
+ Денвер, CO
+ Детройт, Мичиган
+ Дубай
+ Дублин
+ Дюссельдорф
+ Эстония
+ Финляндия
+ Франция
+ Франкфурт-на-Майне
+ Германия
+ Глазго
+ Гётеборг
+ Греция
+ Хельсингборг
+ Хельсинки
+ Гонконг
+ Гонолулу, HI
+ Хьюстон, Техас
+ Венгрия
+ Индия
+ Индонезия
+ Ирландия
+ Израиль
+ Италия
+ Джексон, MS
+ Джакарта
+ Япония
+ Йоханнесбург
+ Киев
+ Киев
+ Латвия
+ Лиссабон
+ Любляна
+ Лондон
+ Лос-Анджелес, CA
+ Луисвилл, KY
+ Люксембург
+ Мадрид
+ Мальмё
+ Манчестер
+ Марсель
+ Мак-Аллен, Техас
+ Мельбурн
+ Мексика
+ Майами, FL
+ Милан
+ Милуоки, WI
+ Аэропорт Миннеаполис/Сент-Пол, MN
+ Молдова
+ Монреаль
+ Нидерланды
+ Нью-Йорк, NY
+ Новая Зеландия
+ Ниш
+ Северная Македония
+ Норвегия
+ Оклахома-Сити, OK
+ Осака
+ Осло
+ Палермо
+ Париж
+ Перт
+ Филадельфия, PA
+ Финикс, AZ
+ Пискатауэй, NJ
+ Польша
+ Портленд, OR
+ Португалия
+ Прага
+ Пуна
+ Сантьяго-де-Керетаро
+ Роли, NC
+ Ричмонд, VA
+ Рига
+ Румыния
+ Рим
+ Солт-Лейк-Сити, UT
+ Сан-Франциско, CA
+ Сан-Хосе, CA
+ Сантьяго
+ Сан-Паулу
+ Сиэтл, WA
+ Секаукус, NJ
+ Сербия
+ Сингапур
+ Су-Фолс, SD
+ Скопье
+ Словакия
+ Словения
+ София
+ Южно-Африканская Республика
+ Испания
+ Сент-Луис, MO
+ Стамфорд, CT
+ Ставангер
+ Стокгольм
+ Швеция
+ Швейцария
+ Сидней
+ Таллин
+ Тель-Авив
+ Таиланд
+ Тирана
+ Токио
+ Торонто
+ Великобритания
+ Соединённые Штаты Америки
+ Украина
+ Объединённые Арабские Эмираты
+ Валенсия
+ Ванкувер
+ Вена
+ Варшава
+ Вашингтон, округ Колумбия
+ Вена
+ Загреб
+ Цюрих
+
diff --git a/android/lib/resource/src/main/res/xml-sv/relay_locations.xml b/android/lib/resource/src/main/res/xml-sv/relay_locations.xml
new file mode 100644
index 000000000000..9943c452e223
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-sv/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albanien
+ Amsterdam
+ Ashburn, VA
+ Aten
+ Atlanta, GA
+ Auckland
+ Australien
+ Österrike
+ Bangkok
+ Barcelona
+ Belgien
+ Belgrad
+ Berlin
+ Bogotá
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brasilien
+ Brisbane
+ Bryssel
+ Bukarest
+ Budapest
+ Bulgarien
+ Calgary
+ Kanada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chișinău
+ Cleveland, OH
+ Colombia
+ Köpenhamn
+ Kroatien
+ Tjeckien
+ Dallas, TX
+ Danmark
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Düsseldorf
+ Estland
+ Finland
+ Frankrike
+ Frankfurt am Main
+ Tyskland
+ Glasgow
+ Göteborg
+ Grekland
+ Helsingborg
+ Helsingfors
+ Hongkong
+ Honolulu, HI
+ Houston, TX
+ Ungern
+ Indien
+ Indonesien
+ Irland
+ Israel
+ Italien
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiev
+ Kiev
+ Lettland
+ Lissabon
+ Ljubljana
+ London
+ Los Angeles, CA
+ Louisville, KY
+ Luxemburg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexiko
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldavien
+ Montréal
+ Nederländerna
+ New York, NY
+ Nya Zeeland
+ Niš
+ Nordmakedonien
+ Norge
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polen
+ Portland, OR
+ Portugal
+ Prag
+ Pune
+ Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Rumänien
+ Rom
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbien
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakien
+ Slovenien
+ Sofia
+ Sydafrika
+ Spanien
+ Saint Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Sverige
+ Schweiz
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Tokyo
+ Toronto
+ Storbritannien
+ USA
+ Ukraina
+ Förenade Arabemiraten
+ Valencia
+ Vancouver
+ Wien
+ Warszawa
+ Washington DC
+ Wien
+ Zagreb
+ Zürich
+
diff --git a/android/lib/resource/src/main/res/xml-th/relay_locations.xml b/android/lib/resource/src/main/res/xml-th/relay_locations.xml
new file mode 100644
index 000000000000..e6aaf1e3e1c2
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-th/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ แอดิเลด
+ แอลเบเนีย
+ อัมสเตอร์ดัม
+ แอชเบิร์น รัฐเวอร์จิเนีย
+ เอเธนส์
+ แอตแลนตา รัฐจอร์เจีย
+ ออกแลนด์
+ ออสเตรเลีย
+ ออสเตรีย
+ กรุงเทพ
+ บาร์เซโลนา
+ เบลเยียม
+ เบลเกรด
+ เบอร์ลิน
+ โบโกตา
+ บอร์โด
+ บอสตัน รัฐแมสซาชูเซตส์
+ บราติสลาวา
+ บราซิล
+ บริสเบน
+ บรัสเซลส์
+ บูคาเรสต์
+ บูดาเปสต์
+ บัลแกเรีย
+ แคลกะรี
+ แคนาดา
+ แคนเบอร์รา
+ ชาร์ลอตต์ รัฐนอร์ทแคโรไลนา
+ ชิคาโก รัฐอิลลินอยส์
+ ชิลี
+ คีชีเนา
+ คลีฟแลนด์ รัฐโอไฮโอ
+ โคลอมเบีย
+ โคเปนเฮเกน
+ โครเอเชีย
+ สาธารณรัฐเช็ก
+ แดลลัส รัฐเท็กซัส
+ เดนมาร์ก
+ เดนเวอร์ รัฐโคโลราโด
+ ดีทรอยต์, มิชิแกน
+ ดูไบ
+ ดับลิน
+ ดึสเซิลดอร์ฟ
+ เอสโตเนีย
+ ฟินแลนด์
+ ฝรั่งเศส
+ แฟรงก์เฟิร์ต
+ เยอรมนี
+ กลาสโกว์
+ กอเทนเบิร์ก
+ กรีซ
+ เฮลซิงบอรย์
+ เฮลซิงกิ
+ ฮ่องกง
+ โฮโนลูลู รัฐฮาวาย
+ ฮิวสตัน เท็กซัส
+ ฮังการี
+ อินเดีย
+ อินโดนีเซีย
+ ไอร์แลนด์
+ อิสราเอล
+ อิตาลี
+ แจ็กสัน รัฐมิสซิสซิปปี
+ จาการ์ตา
+ ญี่ปุ่น
+ โจฮันเนสเบิร์ก
+ เคียฟ
+ เคียฟ
+ ลัตเวีย
+ ลิสบอน
+ ลูบลิยานา
+ ลอนดอน
+ ลอสแอนเจลิส รัฐแคลิฟอร์เนีย
+ ลุยส์วิลล์ รัฐเคนทักกี
+ ลักเซมเบิร์ก
+ มาดริด
+ มัลเมอ
+ แมนเชสเตอร์
+ มาร์แซย์
+ แมคอัลเลน เท็กซัส
+ เมลเบิร์น
+ เม็กซิโก
+ ไมแอมี รัฐฟลอริดา
+ มิลาน
+ มิลวอกี รัฐวิสคอนซิน
+ มินนีแอโพลิส/เซนต์พอล รัฐมินนิโซตา
+ มอลโดวา
+ มอนทรีออล
+ เนเธอร์แลนด์
+ นิวยอร์ก รัฐนิวยอร์ก
+ นิวซีแลนด์
+ นีช
+ นอร์ทมาซิโดเนีย
+ นอร์เวย์
+ โอคลาโฮมาซิตี รัฐโอคลาโฮมา
+ โอซากะ
+ ออสโล
+ ปาแลร์โม
+ ปารีส
+ เพิร์ท
+ ฟิลาเดลเฟีย รัฐเพนซิลเวเนีย
+ ฟีนิกซ์ รัฐแอริโซนา
+ พิสแกตาเวย์ รัฐนิวเจอร์ซีย์
+ โปแลนด์
+ พอร์ตแลนด์ รัฐออริกอน
+ โปรตุเกส
+ ปราก
+ ปูเน
+ เกเรตาโร
+ ราลี นอร์ทแคโรไลนา
+ ริชมอนด์ รัฐเวอร์จิเนีย
+ รีกา
+ โรมาเนีย
+ โรม
+ ซอลต์เลกซิตี รัฐยูทาห์
+ ซานฟรานซิสโก รัฐแคลิฟอร์เนีย
+ แซนโฮเซ รัฐแคลิฟอร์เนีย
+ ซันติอาโก
+ เซาเปาโล
+ ซีแอตเทิล รัฐวอชิงตัน
+ ซีคอคัส รัฐนิวเจอร์ซีย์
+ เซอร์เบีย
+ สิงคโปร์
+ ซูฟอลส์ รัฐเซาท์ดาโคตา
+ สโกเปีย
+ สโลวาเกีย
+ สโลวีเนีย
+ โซเฟีย
+ แอฟริกาใต้
+ สเปน
+ เซนต์หลุยส์ รัฐมิสซูรี
+ สแตมเฟิร์ด รัฐคอนเนตทิคัต
+ สตาวังเงอร์
+ สต็อกโฮล์ม
+ สวีเดน
+ สวิตเซอร์แลนด์
+ ซิดนีย์
+ ทาลลินน์
+ เทลอาวีฟ
+ ไทย
+ ติรานา
+ โตเกียว
+ โทรอนโต
+ สหราชอาณาจักร
+ สหรัฐอเมริกา
+ ยูเครน
+ สหรัฐอาหรับเอมิเรตส์
+ บาเลนเซีย
+ แวนคูเวอร์
+ เวียนนา
+ วอร์ซอ
+ วอชิงตัน ดี.ซี.
+ วีน
+ ซาเกร็บ
+ ซือริช
+
diff --git a/android/lib/resource/src/main/res/xml-tr/relay_locations.xml b/android/lib/resource/src/main/res/xml-tr/relay_locations.xml
new file mode 100644
index 000000000000..c3f0d62b952d
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-tr/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Arnavutluk
+ Amsterdam
+ Ashburn, VA
+ Atina
+ Atlanta, GA
+ Auckland
+ Avustralya
+ Avusturya
+ Bangkok
+ Barselona
+ Belçika
+ Belgrad
+ Berlin
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brezilya
+ Brisbane
+ Brüksel
+ Bükreș
+ Budapeşte
+ Bulgaristan
+ Calgary
+ Kanada
+ Canberra
+ Charlotte, NC
+ Şikago, IL
+ Şili
+ Kişinev
+ Cleveland, OH
+ Kolombiya
+ Kopenhag
+ Hırvatistan
+ Çek Cumhuriyeti
+ Dallas, TX
+ Danimarka
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Düsseldorf
+ Estonya
+ Finlandiya
+ Fransa
+ Frankfurt
+ Almanya
+ Glasgow
+ Göteborg
+ Yunanistan
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Macaristan
+ Hindistan
+ Endonezya
+ İrlanda
+ İsrail
+ İtalya
+ Jackson, MS
+ Cakarta
+ Japonya
+ Johannesburg
+ Kiev
+ Kiev
+ Letonya
+ Lizbon
+ Ljubljana
+ Londra
+ Los Angeles, CA
+ Louisville, KY
+ Lüksemburg
+ Madrid
+ Malmö
+ Manchester
+ Marsilya
+ McAllen, Teksas
+ Melbourne
+ Meksika
+ Miami, FL
+ Milano
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldova
+ Montreal
+ Hollanda
+ New York, NY
+ Yeni Zelanda
+ Niş
+ Kuzey Makedonya
+ Norveç
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Polonya
+ Portland, OR
+ Portekiz
+ Prag
+ Pune
+ Santiago de Querétaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Romanya
+ Roma
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ São Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Sırbistan
+ Singapur
+ Sioux Falls, SD
+ Skopje
+ Slovakya
+ Slovenya
+ Sofya
+ Güney Afrika Cumhuriyeti
+ İspanya
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ İsveç
+ İsviçre
+ Sidney
+ Tallinn
+ Tel Aviv
+ Tayland
+ Tiran
+ Tokyo
+ Toronto
+ Birleşik Krallık
+ Amerika Birleşik Devletleri
+ Ukrayna
+ Birleşik Arap Emirlikleri
+ Valensiya
+ Vancouver
+ Viyana
+ Varşova
+ Washington DC
+ Viyana
+ Zagreb
+ Zürih
+
diff --git a/android/lib/resource/src/main/res/xml-zh-rCN/relay_locations.xml b/android/lib/resource/src/main/res/xml-zh-rCN/relay_locations.xml
new file mode 100644
index 000000000000..4df5d38faa62
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-zh-rCN/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ 阿德莱德
+ 阿尔巴尼亚
+ 阿姆斯特丹
+ 弗吉尼亚州阿什本
+ 雅典
+ 佐治亚州亚特兰大
+ 奥克兰
+ 澳大利亚
+ 奥地利
+ 曼谷
+ 巴塞罗那
+ 比利时
+ 贝尔格莱德
+ 柏林
+ 波哥大
+ 波尔多
+ 马萨诸塞州波士顿
+ 布拉迪斯拉发
+ 巴西
+ 布里斯班
+ 布鲁塞尔
+ 布加勒斯特
+ 布达佩斯
+ 保加利亚
+ 卡尔加里
+ 加拿大
+ 堪培拉
+ 北卡罗来纳州夏洛特
+ 伊利诺伊州芝加哥
+ 智利
+ 基希讷乌
+ 俄亥俄州克里夫兰
+ 哥伦比亚
+ 哥本哈根
+ 克罗地亚
+ 捷克
+ 德克萨斯州达拉斯
+ 丹麦
+ 科罗拉多州丹佛
+ 密歇根州底特律
+ 迪拜
+ 都柏林
+ 杜塞尔多夫
+ 爱沙尼亚
+ 芬兰
+ 法国
+ 法兰克福
+ 德国
+ 格拉斯哥
+ 哥德堡
+ 希腊
+ 赫尔辛堡
+ 赫尔辛基
+ 香港
+ 夏威夷州檀香山
+ 德克萨斯州休斯敦
+ 匈牙利
+ 印度
+ 印度尼西亚
+ 爱尔兰
+ 以色列
+ 意大利
+ 密西西比州杰克逊
+ 雅加达
+ 日本
+ 约翰内斯堡
+ 基辅
+ 基辅
+ 拉脱维亚
+ 里斯本
+ 卢布尔雅那
+ 伦敦
+ 加利福尼亚州洛杉矶
+ 肯塔基州路易斯维尔
+ 卢森堡
+ 马德里
+ 马尔默
+ 曼彻斯特
+ 马赛
+ 得克萨斯州麦卡伦
+ 墨尔本
+ 墨西哥
+ 佛罗里达州迈阿密
+ 米兰
+ 威斯康星州密尔沃基
+ 明尼苏达州明尼阿波利斯/圣保罗机场
+ 摩尔多瓦
+ 蒙特利尔
+ 荷兰
+ 纽约州纽约
+ 新西兰
+ 尼斯
+ 北马其顿
+ 挪威
+ 俄克拉何马州俄克拉何马城
+ 大阪
+ 奥斯陆
+ Palermo
+ 巴黎
+ 珀斯
+ 宾夕法尼亚州费城
+ 亚利桑那州菲尼克斯
+ 新泽西州皮斯卡特维
+ 波兰
+ 俄勒冈州波特兰
+ 葡萄牙
+ 布拉格
+ 浦那
+ 克雷塔罗
+ 罗利,北卡罗来纳州
+ 弗吉尼亚州里士满
+ 里加
+ 罗马尼亚
+ 罗马
+ 犹他州盐湖城
+ 加利福尼亚州旧金山
+ 加利福尼亚州圣何塞
+ 圣地亚哥
+ 圣保罗
+ 华盛顿州西雅图
+ 新泽西州锡考克斯
+ 塞尔维亚
+ 新加坡
+ 南达科他州苏瀑
+ 斯科普里
+ 斯洛伐克
+ 斯洛文尼亚
+ 索非亚
+ 南非
+ 西班牙
+ 密苏里州圣路易斯
+ 康涅狄格州斯坦福
+ 斯塔万格
+ 斯德哥尔摩
+ 瑞典
+ 瑞士
+ 悉尼
+ 塔林
+ 特拉维夫
+ 泰国
+ 地拉那
+ 东京
+ 多伦多
+ 英国
+ 美国
+ 乌克兰
+ 阿拉伯联合酋长国
+ 瓦伦西亚
+ 温哥华
+ 维也纳
+ 华沙
+ 华盛顿特区
+ 维也纳
+ 萨格勒布
+ 苏黎世
+
diff --git a/android/lib/resource/src/main/res/xml-zh-rTW/relay_locations.xml b/android/lib/resource/src/main/res/xml-zh-rTW/relay_locations.xml
new file mode 100644
index 000000000000..5e4742b1ca21
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml-zh-rTW/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ 阿得雷德
+ 阿爾巴尼亞
+ 阿姆斯特丹
+ 維吉尼亞州阿什本
+ 雅典
+ 喬治亞州,亞特蘭大
+ 奧克蘭
+ 澳大利亞
+ 奧地利
+ 曼谷
+ 巴塞隆納
+ 比利時
+ 貝爾格勒
+ 柏林
+ 波哥大
+ 波爾多
+ 麻州,波士頓
+ 布拉提斯拉瓦
+ 巴西
+ 布利斯班
+ 布魯塞爾
+ 布加勒斯特
+ 布達佩斯
+ 保加利亞
+ 卡加利
+ 加拿大
+ 坎培拉
+ 北卡羅來納州,夏洛特
+ 伊利諾州,芝加哥
+ 智利
+ 奇西瑙
+ 俄亥俄州,克利夫蘭
+ 哥倫比亞
+ 哥本哈根
+ 克羅埃西亞
+ 捷克共和國
+ 德州,達拉斯
+ 丹麥
+ 科羅拉多州,丹佛
+ 密西根州底特律
+ 杜拜
+ 都柏林
+ 杜塞道夫
+ 愛沙尼亞
+ 芬蘭
+ 法國
+ 法蘭克福
+ 德國
+ 格拉斯哥
+ 哥特堡
+ 希臘
+ 赫爾辛堡
+ 赫爾辛基
+ 香港
+ 夏威夷州,檀香山
+ 德克薩斯州休士頓
+ 匈牙利
+ 印度
+ 印尼
+ 愛爾蘭
+ 以色列
+ 義大利
+ 密西西比州,傑克遜
+ 雅加達
+ 日本
+ 約翰尼斯堡
+ 基輔
+ 基輔
+ 拉脫維亞
+ 里斯本
+ 盧比安納
+ 倫敦
+ 加州,洛杉磯
+ 肯塔基州,路易維爾
+ 盧森堡
+ 馬德里
+ 馬爾默
+ 曼徹斯特
+ 馬賽
+ 德州麥克亞連
+ 墨爾本
+ 墨西哥
+ 佛羅里達州,邁阿密
+ 米蘭
+ 威斯康辛州,密爾瓦基
+ 明尼蘇達州,明尼亞波利斯/聖保羅機場
+ 摩爾多瓦
+ 蒙特婁
+ 荷蘭
+ 紐約州,紐約市
+ 紐西蘭
+ 尼斯
+ 北馬其頓
+ 挪威
+ 奧克拉荷馬州,奧克拉荷馬市
+ 大阪
+ 奧斯陸
+ Palermo
+ 巴黎
+ 伯斯
+ 賓夕法尼亞州,費城
+ 亞利桑那州,鳳凰城
+ 紐澤西州,皮斯卡特維
+ 波蘭
+ 俄勒岡州,波特蘭
+ 葡萄牙
+ 布拉格
+ 浦那
+ 克雷塔羅
+ 羅利,NC
+ 維吉尼亞州,里奇蒙
+ 里加
+ 羅馬尼亞
+ 羅馬
+ 猶他州,鹽湖城
+ 加州,舊金山
+ 加州,聖荷西
+ 聖地亞哥
+ 聖保羅
+ 華盛頓州,西雅圖
+ 紐澤西州,錫考克斯
+ 塞爾維亞
+ 新加坡
+ 南達科他州,蘇瀑
+ 斯高彼亞
+ 斯洛伐克
+ 斯洛維尼亞
+ 索菲亞
+ 南非
+ 西班牙
+ 密蘇里州,聖路易
+ 康乃狄克州,斯坦福
+ 斯塔萬格
+ 斯德哥爾摩
+ 瑞典
+ 瑞士
+ 雪梨
+ 塔林
+ 特拉維夫
+ 泰國
+ 地拉那
+ 東京
+ 多倫多
+ 英國
+ 美國
+ 烏克蘭
+ 阿拉伯聯合大公國
+ 瓦倫西亞
+ 溫哥華
+ 維也納
+ 華沙
+ 華盛頓特區
+ 維也納
+ 薩格勒布
+ 蘇黎世
+
diff --git a/android/lib/resource/src/main/res/xml/relay_locations.xml b/android/lib/resource/src/main/res/xml/relay_locations.xml
new file mode 100644
index 000000000000..e11438dccd56
--- /dev/null
+++ b/android/lib/resource/src/main/res/xml/relay_locations.xml
@@ -0,0 +1,158 @@
+
+
+ Adelaide
+ Albania
+ Amsterdam
+ Ashburn, VA
+ Athens
+ Atlanta, GA
+ Auckland
+ Australia
+ Austria
+ Bangkok
+ Barcelona
+ Belgium
+ Belgrade
+ Berlin
+ Bogota
+ Bordeaux
+ Boston, MA
+ Bratislava
+ Brazil
+ Brisbane
+ Brussels
+ Bucharest
+ Budapest
+ Bulgaria
+ Calgary
+ Canada
+ Canberra
+ Charlotte, NC
+ Chicago, IL
+ Chile
+ Chisinau
+ Cleveland, OH
+ Colombia
+ Copenhagen
+ Croatia
+ Czech Republic
+ Dallas, TX
+ Denmark
+ Denver, CO
+ Detroit, MI
+ Dubai
+ Dublin
+ Dusseldorf
+ Estonia
+ Finland
+ France
+ Frankfurt
+ Germany
+ Glasgow
+ Gothenburg
+ Greece
+ Helsingborg
+ Helsinki
+ Hong Kong
+ Honolulu, HI
+ Houston, TX
+ Hungary
+ India
+ Indonesia
+ Ireland
+ Israel
+ Italy
+ Jackson, MS
+ Jakarta
+ Japan
+ Johannesburg
+ Kiev
+ Kyiv
+ Latvia
+ Lisbon
+ Ljubljana
+ London
+ Los Angeles, CA
+ Louisville, KY
+ Luxembourg
+ Madrid
+ Malmö
+ Manchester
+ Marseille
+ McAllen, TX
+ Melbourne
+ Mexico
+ Miami, FL
+ Milan
+ Milwaukee, WI
+ Minneapolis/St. Paul Apt, MN
+ Moldova
+ Montreal
+ Netherlands
+ New York, NY
+ New Zealand
+ Nis
+ North Macedonia
+ Norway
+ Oklahoma City, OK
+ Osaka
+ Oslo
+ Palermo
+ Paris
+ Perth
+ Philadelphia, PA
+ Phoenix, AZ
+ Piscataway, NJ
+ Poland
+ Portland, OR
+ Portugal
+ Prague
+ Pune
+ Queretaro
+ Raleigh, NC
+ Richmond, VA
+ Riga
+ Romania
+ Rome
+ Salt Lake City, UT
+ San Francisco, CA
+ San Jose, CA
+ Santiago
+ Sao Paulo
+ Seattle, WA
+ Secaucus, NJ
+ Serbia
+ Singapore
+ Sioux Falls, SD
+ Skopje
+ Slovakia
+ Slovenia
+ Sofia
+ South Africa
+ Spain
+ St. Louis, MO
+ Stamford, CT
+ Stavanger
+ Stockholm
+ Sweden
+ Switzerland
+ Sydney
+ Tallinn
+ Tel Aviv
+ Thailand
+ Tirana
+ Tokyo
+ Toronto
+ UK
+ USA
+ Ukraine
+ United Arab Emirates
+ Valencia
+ Vancouver
+ Vienna
+ Warsaw
+ Washington DC
+ Wien
+ Zagreb
+ Zurich
+
diff --git a/android/lib/shared/build.gradle.kts b/android/lib/shared/build.gradle.kts
index 68078c0a6aaf..a6cb6ef37194 100644
--- a/android/lib/shared/build.gradle.kts
+++ b/android/lib/shared/build.gradle.kts
@@ -28,6 +28,7 @@ android {
}
dependencies {
+ implementation(projects.lib.resource)
implementation(projects.lib.common)
implementation(projects.lib.daemonGrpc)
implementation(projects.lib.model)
diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt
index 6ea373e4260c..13d668b65bb7 100644
--- a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt
+++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxy.kt
@@ -3,14 +3,36 @@ package net.mullvad.mullvadvpn.lib.shared
import arrow.core.Either
import arrow.core.raise.either
import arrow.core.raise.ensure
+import kotlinx.coroutines.flow.combine
import net.mullvad.mullvadvpn.lib.daemon.grpc.ManagementService
import net.mullvad.mullvadvpn.lib.model.ConnectError
+import net.mullvad.mullvadvpn.lib.model.GeoIpLocation
+import net.mullvad.mullvadvpn.lib.model.TunnelState
class ConnectionProxy(
private val managementService: ManagementService,
+ translationRepository: RelayLocationTranslationRepository,
private val vpnPermissionRepository: VpnPermissionRepository
) {
- val tunnelState = managementService.tunnelState
+ val tunnelState =
+ combine(managementService.tunnelState, translationRepository.translations) {
+ tunnelState,
+ translations ->
+ tunnelState.translateLocations(translations)
+ }
+
+ private fun TunnelState.translateLocations(translations: Map): TunnelState {
+ return when (this) {
+ is TunnelState.Connecting -> copy(location = location?.translate(translations))
+ is TunnelState.Disconnected -> copy(location = location?.translate(translations))
+ is TunnelState.Disconnecting -> this
+ is TunnelState.Error -> this
+ is TunnelState.Connected -> copy(location = location?.translate(translations))
+ }
+ }
+
+ private fun GeoIpLocation.translate(translations: Map): GeoIpLocation =
+ copy(city = translations[city] ?: city, country = translations[country] ?: country)
suspend fun connect(): Either = either {
ensure(vpnPermissionRepository.hasVpnPermission()) { ConnectError.NoVpnPermission }
diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt
new file mode 100644
index 000000000000..4e5628d214cb
--- /dev/null
+++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/LocaleRepository.kt
@@ -0,0 +1,19 @@
+package net.mullvad.mullvadvpn.lib.shared
+
+import android.content.res.Resources
+import co.touchlab.kermit.Logger
+import java.util.Locale
+import kotlin.also
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+
+class LocaleRepository(val resources: Resources) {
+ private val _currentLocale = MutableStateFlow(getLocale())
+ val currentLocale: StateFlow = _currentLocale
+
+ private fun getLocale(): Locale? = resources.configuration.locales.get(0)
+
+ fun refreshLocale() {
+ _currentLocale.value = getLocale().also { Logger.d("New locale: $it") }
+ }
+}
diff --git a/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt
new file mode 100644
index 000000000000..edaa0c1ebc41
--- /dev/null
+++ b/android/lib/shared/src/main/kotlin/net/mullvad/mullvadvpn/lib/shared/RelayLocationTranslationRepository.kt
@@ -0,0 +1,61 @@
+package net.mullvad.mullvadvpn.lib.shared
+
+import android.content.Context
+import android.content.res.XmlResourceParser
+import co.touchlab.kermit.Logger
+import java.util.Locale
+import kotlin.collections.set
+import kotlin.collections.toMap
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+typealias Translations = Map
+
+class RelayLocationTranslationRepository(
+ val context: Context,
+ val localeRepository: LocaleRepository,
+ externalScope: CoroutineScope = MainScope(),
+ val dispatcher: CoroutineDispatcher = Dispatchers.IO
+) {
+ val translations: StateFlow =
+ localeRepository.currentLocale
+ .filterNotNull()
+ .map { loadTranslations(it) }
+ .stateIn(externalScope, SharingStarted.Eagerly, emptyMap())
+
+ private suspend fun loadTranslations(locale: Locale): Translations =
+ withContext(dispatcher) {
+ Logger.d("Updating translations based on $locale")
+ if (locale.language == DEFAULT_LANGUAGE) emptyMap()
+ else {
+ // Load current translations
+ val xml = context.resources.getXml(R.xml.relay_locations)
+ xml.loadRelayTranslation()
+ }
+ }
+
+ private fun XmlResourceParser.loadRelayTranslation(): Map {
+ val translation = mutableMapOf()
+ while (this.eventType != XmlResourceParser.END_DOCUMENT) {
+ if (this.eventType == XmlResourceParser.START_TAG && this.name == "string") {
+ val key = this.getAttributeValue(null, "name")
+ val value = this.nextText()
+ translation[key] = value
+ }
+ this.next()
+ }
+ return translation.toMap()
+ }
+
+ companion object {
+ private const val DEFAULT_LANGUAGE = "en"
+ }
+}
diff --git a/android/lib/shared/src/test/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxyTest.kt b/android/lib/shared/src/test/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxyTest.kt
index 74ab4f6b6453..138d0f5a41d9 100644
--- a/android/lib/shared/src/test/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxyTest.kt
+++ b/android/lib/shared/src/test/kotlin/net/mullvad/mullvadvpn/lib/shared/ConnectionProxyTest.kt
@@ -13,11 +13,14 @@ class ConnectionProxyTest {
private val mockManagementService: ManagementService = mockk(relaxed = true)
private val mockVpnPermissionRepository: VpnPermissionRepository = mockk()
+ private val mockTranslationRepository: RelayLocationTranslationRepository =
+ mockk(relaxed = true)
private val connectionProxy: ConnectionProxy =
ConnectionProxy(
managementService = mockManagementService,
- vpnPermissionRepository = mockVpnPermissionRepository
+ vpnPermissionRepository = mockVpnPermissionRepository,
+ translationRepository = mockTranslationRepository
)
@Test
diff --git a/android/translations-converter/src/main.rs b/android/translations-converter/src/main.rs
index afb760f8991e..7a340d748338 100644
--- a/android/translations-converter/src/main.rs
+++ b/android/translations-converter/src/main.rs
@@ -35,6 +35,7 @@ mod android;
mod gettext;
mod normalize;
+use crate::gettext::MsgValue;
use crate::normalize::Normalize;
use std::{
collections::HashMap,
@@ -121,8 +122,8 @@ fn main() {
for message in template {
match message.value {
- gettext::MsgValue::Invariant(_) => missing_translations.remove(&message.id.normalize()),
- gettext::MsgValue::Plural { .. } => missing_plurals.remove(&message.id.normalize()),
+ MsgValue::Invariant(_) => missing_translations.remove(&message.id.normalize()),
+ MsgValue::Plural { .. } => missing_plurals.remove(&message.id.normalize()),
};
}
@@ -182,7 +183,7 @@ fn main() {
gettext::MsgEntry {
id,
- value: gettext::MsgValue::Plural {
+ value: MsgValue::Plural {
plural_id,
values: vec![gettext::MsgString::empty(), gettext::MsgString::empty()],
},
@@ -191,6 +192,65 @@ fn main() {
)
.expect("Failed to append missing plural translations to message template file");
}
+
+ // Generate all relay locale files
+
+ let relay_template_path = locale_dir.join("relay-locations.pot");
+
+ let default_translations = gettext::Messages::from_file(&relay_template_path)
+ .expect("Failed to load translations for a locale");
+
+ let resources_dir = Path::new("../lib/resource/src/main/res");
+
+ let relay_locations_path = resources_dir.join("xml/relay_locations.xml");
+
+ let mut localized_strings = android::StringResources::new();
+ for translation in default_translations {
+ match translation.value {
+ MsgValue::Invariant(_) => {
+ if !translation.id.is_empty() {
+ localized_strings.push(android::StringResource::new(
+ translation.id.normalize(),
+ &translation.id.normalize(),
+ ));
+ }
+ }
+ MsgValue::Plural { .. } => {}
+ }
+ }
+
+ localized_strings.sort();
+
+ fs::write(relay_locations_path, localized_strings.to_string())
+ .expect("Failed to create Android locale file");
+
+ let relay_locale_files = fs::read_dir(locale_dir)
+ .expect("Failed to open root locale directory")
+ .filter_map(|dir_entry_result| dir_entry_result.ok())
+ .map(|dir_entry| dir_entry.path())
+ .filter(|dir_entry_path| dir_entry_path.is_dir())
+ .map(|dir_path| dir_path.join("relay-locations.po"))
+ .filter(|file_path| file_path.exists());
+
+ for relay_file in relay_locale_files {
+ let locale = relay_file
+ .parent()
+ .unwrap()
+ .file_name()
+ .unwrap()
+ .to_str()
+ .unwrap();
+ let destination_dir = resources_dir.join(android_xml_directory(locale));
+
+ if !destination_dir.exists() {
+ fs::create_dir(&destination_dir).expect("Failed to create Android locale directory");
+ }
+
+ let translations = gettext::Messages::from_file(&relay_file)
+ .expect("Failed to load translations for a locale");
+
+ generate_relay_translations(translations, destination_dir.join("relay_locations.xml"));
+ }
}
/// Determines the localized value resources directory name based on a locale specification.
@@ -211,6 +271,49 @@ fn android_locale_directory(locale: &str) -> String {
directory
}
+/// Determines the localized value resources directory name based on a locale specification.
+///
+/// This just makes sure a locale such as `en-US' gets correctly mapped to the directory name
+/// `xml-en-rUS`.
+fn android_xml_directory(locale: &str) -> String {
+ let mut directory = String::from("xml-");
+ let mut parts = locale.split('-');
+
+ directory.push_str(parts.next().unwrap());
+
+ if let Some(region) = parts.next() {
+ directory.push_str("-r");
+ directory.push_str(region);
+ }
+
+ directory
+}
+
+/// Generate translated Android relay resource strings for a locale.
+fn generate_relay_translations(
+ translations: gettext::Messages,
+ strings_output_path: impl AsRef,
+) {
+ let mut localized_strings = android::StringResources::new();
+
+ for translation in translations {
+ match translation.value {
+ MsgValue::Invariant(translation_value) => {
+ localized_strings.push(android::StringResource::new(
+ translation.id.normalize(),
+ &translation_value.normalize(),
+ ));
+ }
+ MsgValue::Plural { .. } => {}
+ }
+ }
+
+ localized_strings.sort();
+
+ fs::write(strings_output_path, localized_strings.to_string())
+ .expect("Failed to create Android locale file");
+}
+
/// Generate translated Android resource strings for a locale.
///
/// Based on the gettext translated message entries, it finds the messages with message IDs that
@@ -238,7 +341,7 @@ fn generate_translations(
for translation in translations {
match translation.value {
- gettext::MsgValue::Invariant(translation_value) => {
+ MsgValue::Invariant(translation_value) => {
if let Some(android_key) = known_strings.remove(&translation.id.normalize()) {
localized_strings.push(android::StringResource::new(
android_key,
@@ -246,7 +349,7 @@ fn generate_translations(
));
}
}
- gettext::MsgValue::Plural { values, .. } => {
+ MsgValue::Plural { values, .. } => {
if let Some(android_key) = known_plurals.remove(&translation.id.normalize()) {
let values = values.into_iter().map(|message| message.normalize());