kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
update in-app language picker (#538)
rodzic
8dca9ea8b6
commit
c9a81c72e0
|
@ -37,7 +37,7 @@ android {
|
||||||
storePassword keystoreProperties['storePassword']
|
storePassword keystoreProperties['storePassword']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileSdkVersion 32
|
compileSdkVersion 33
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.geeksville.mesh"
|
applicationId "com.geeksville.mesh"
|
||||||
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
|
||||||
|
@ -65,7 +65,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// We have to list all translated languages here, because some of our libs have bogus languages that google play
|
// We have to list all translated languages here, because some of our libs have bogus languages that google play
|
||||||
// doesn't like and we need to strip them (gr)
|
// doesn't like and we need to strip them (gr)
|
||||||
resConfigs "cs", "de", "el", "en", "es", "fi", "fr", "ga", "ht", "it", "ja", "ko-rKR", "nl", "no", "pl", "pt", "pt-rBR", "ro", "ru", "sk", "sl", "sq", "sv", "tr", "zh"
|
resConfigs "cs", "de", "el", "en", "es", "fi", "fr", "fr-rHT", "ga", "hu", "it", "ja", "ko", "nl", "nb", "pl", "pt", "pt-rBR", "ro", "ru", "sk", "sl", "sq", "sv", "tr", "zh", "uk"
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
// abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
// abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
|
@ -125,7 +125,11 @@ protobuf {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation 'androidx.appcompat:appcompat:1.5.0'
|
def appcompat_version = '1.6.0-rc01'
|
||||||
|
implementation "androidx.appcompat:appcompat:$appcompat_version"
|
||||||
|
// For loading and tinting drawables on older versions of the platform
|
||||||
|
implementation "androidx.appcompat:appcompat-resources:$appcompat_version"
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.8.0'
|
implementation 'androidx.core:core-ktx:1.8.0'
|
||||||
implementation 'androidx.fragment:fragment-ktx:1.5.2'
|
implementation 'androidx.fragment:fragment-ktx:1.5.2'
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation 'androidx.cardview:cardview:1.0.0'
|
||||||
|
|
|
@ -81,11 +81,8 @@
|
||||||
android:roundIcon="@mipmap/ic_launcher2_round"
|
android:roundIcon="@mipmap/ic_launcher2_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme"
|
||||||
|
android:localeConfig="@xml/locales_config">
|
||||||
<meta-data
|
|
||||||
android:name="com.mixpanel.android.MPConfig.DisableViewCrawler"
|
|
||||||
android:value="true" />
|
|
||||||
|
|
||||||
<!-- Default crash collection and analytics off until we (possibly) turn it on in application.onCreate -->
|
<!-- Default crash collection and analytics off until we (possibly) turn it on in application.onCreate -->
|
||||||
<meta-data
|
<meta-data
|
||||||
|
@ -112,6 +109,15 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||||
|
android:enabled="false"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data
|
||||||
|
android:name="autoStoreLocales"
|
||||||
|
android:value="true" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<!-- zxing for QR Code scanning: lock portrait orientation -->
|
<!-- zxing for QR Code scanning: lock portrait orientation -->
|
||||||
<activity
|
<activity
|
||||||
android:name="com.journeyapps.barcodescanner.CaptureActivity"
|
android:name="com.journeyapps.barcodescanner.CaptureActivity"
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package com.geeksville.mesh
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import com.geeksville.mesh.android.Logging
|
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
open class BaseActivity: AppCompatActivity(), Logging {
|
|
||||||
|
|
||||||
override fun attachBaseContext(newBase: Context) {
|
|
||||||
val res = newBase.resources
|
|
||||||
val config = res.configuration
|
|
||||||
|
|
||||||
// get chosen language from preference
|
|
||||||
val prefs = UIViewModel.getPreferences(newBase)
|
|
||||||
val langCode: String = prefs.getString("lang","zz") ?: ""
|
|
||||||
debug("langCode is $langCode")
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 17) {
|
|
||||||
val locale = if (langCode == "zz")
|
|
||||||
Locale.getDefault()
|
|
||||||
else
|
|
||||||
createLocale(langCode)
|
|
||||||
config.setLocale(locale)
|
|
||||||
|
|
||||||
if(Build.VERSION.SDK_INT > 24) {
|
|
||||||
//Using createNewConfigurationContext will cause CompanionDeviceManager to crash
|
|
||||||
applyOverrideConfiguration(config)
|
|
||||||
super.attachBaseContext(newBase)
|
|
||||||
}else {
|
|
||||||
super.attachBaseContext(newBase.createConfigurationContext(config))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.attachBaseContext(newBase)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createLocale(language: String): Locale {
|
|
||||||
val langArray = language.split("_")
|
|
||||||
return if (langArray.size == 2) {
|
|
||||||
Locale(langArray[0], langArray[1])
|
|
||||||
} else {
|
|
||||||
Locale(langArray[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
@ -42,6 +43,7 @@ import com.geeksville.mesh.repository.radio.SerialInterface
|
||||||
import com.geeksville.mesh.service.*
|
import com.geeksville.mesh.service.*
|
||||||
import com.geeksville.mesh.ui.*
|
import com.geeksville.mesh.ui.*
|
||||||
import com.geeksville.mesh.util.Exceptions
|
import com.geeksville.mesh.util.Exceptions
|
||||||
|
import com.geeksville.mesh.util.LanguageUtils
|
||||||
import com.geeksville.mesh.util.exceptionReporter
|
import com.geeksville.mesh.util.exceptionReporter
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
@ -106,7 +108,7 @@ eventually:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : BaseActivity(), Logging {
|
class MainActivity : AppCompatActivity(), Logging {
|
||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
|
||||||
|
@ -200,6 +202,11 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
if (!prefs.getBoolean("app_intro_completed", false)) {
|
if (!prefs.getBoolean("app_intro_completed", false)) {
|
||||||
startActivity(Intent(this, AppIntroduction::class.java))
|
startActivity(Intent(this, AppIntroduction::class.java))
|
||||||
}
|
}
|
||||||
|
// First run: migrate in-app language prefs to appcompat
|
||||||
|
if (prefs.getString("lang", LanguageUtils.SYSTEM_DEFAULT) != LanguageUtils.SYSTEM_MANAGED) {
|
||||||
|
LanguageUtils.migrateLanguagePrefs(prefs)
|
||||||
|
}
|
||||||
|
info("in-app language is ${LanguageUtils.getLocale()}")
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
@ -843,7 +850,6 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
editor.putInt("theme", 0)
|
editor.putInt("theme", 0)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
|
||||||
delegate.applyDayNight()
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
1 -> {
|
1 -> {
|
||||||
|
@ -851,15 +857,13 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
editor.putInt("theme", 1)
|
editor.putInt("theme", 1)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
|
||||||
delegate.applyDayNight()
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
2 -> {
|
else -> {
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
editor.putInt("theme", 2)
|
editor.putInt("theme", 2)
|
||||||
editor.apply()
|
editor.apply()
|
||||||
|
|
||||||
delegate.applyDayNight()
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,34 +879,23 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
/// If nothing is found set FOLLOW SYSTEM option
|
/// If nothing is found set FOLLOW SYSTEM option
|
||||||
|
|
||||||
when (prefs.getInt("theme", 2)) {
|
when (prefs.getInt("theme", 2)) {
|
||||||
0 -> {
|
0 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
1 -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||||
delegate.applyDayNight()
|
else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
|
||||||
delegate.applyDayNight()
|
|
||||||
}
|
|
||||||
2 -> {
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
|
||||||
delegate.applyDayNight()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chooseLangDialog() {
|
private fun chooseLangDialog() {
|
||||||
|
|
||||||
/// Prepare dialog and its items
|
/// Prepare dialog and its items
|
||||||
val builder = MaterialAlertDialogBuilder(this)
|
val builder = MaterialAlertDialogBuilder(this)
|
||||||
builder.setTitle(getString(R.string.preferences_language))
|
builder.setTitle(getString(R.string.preferences_language))
|
||||||
|
|
||||||
val languageLabels by lazy { resources.getStringArray(R.array.language_entries) }
|
val languageTags = LanguageUtils.getLanguageTags(this)
|
||||||
val languageValues by lazy { resources.getStringArray(R.array.language_values) }
|
val languageLabels = languageTags.map { it.first }.toTypedArray()
|
||||||
|
val languageValues = languageTags.map { it.second }
|
||||||
|
|
||||||
/// Load preferences and its value
|
/// Load preferences and its value
|
||||||
val prefs = UIViewModel.getPreferences(this)
|
val lang = LanguageUtils.getLocale()
|
||||||
val editor: SharedPreferences.Editor = prefs.edit()
|
|
||||||
val lang = prefs.getString("lang", "zz")
|
|
||||||
debug("Lang from prefs: $lang")
|
debug("Lang from prefs: $lang")
|
||||||
|
|
||||||
builder.setSingleChoiceItems(
|
builder.setSingleChoiceItems(
|
||||||
|
@ -911,8 +904,7 @@ class MainActivity : BaseActivity(), Logging {
|
||||||
) { dialog, which ->
|
) { dialog, which ->
|
||||||
val selectedLang = languageValues[which]
|
val selectedLang = languageValues[which]
|
||||||
debug("Set lang pref to $selectedLang")
|
debug("Set lang pref to $selectedLang")
|
||||||
editor.putString("lang", selectedLang)
|
LanguageUtils.setLocale(selectedLang)
|
||||||
editor.apply()
|
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package com.geeksville.mesh.ui
|
|
||||||
|
|
||||||
import com.geeksville.mesh.android.Logging
|
|
||||||
|
|
||||||
|
|
||||||
object UILog : Logging
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.geeksville.mesh.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.core.os.LocaleListCompat
|
||||||
|
import com.geeksville.mesh.android.Logging
|
||||||
|
import com.geeksville.mesh.R
|
||||||
|
import org.xmlpull.v1.XmlPullParser
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
object LanguageUtils : Logging {
|
||||||
|
|
||||||
|
const val SYSTEM_DEFAULT = "zz"
|
||||||
|
const val SYSTEM_MANAGED = "appcompat"
|
||||||
|
|
||||||
|
fun getLocale(): String {
|
||||||
|
return AppCompatDelegate.getApplicationLocales().toLanguageTags().ifEmpty { SYSTEM_DEFAULT }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setLocale(lang: String) {
|
||||||
|
AppCompatDelegate.setApplicationLocales(
|
||||||
|
if (lang == SYSTEM_DEFAULT) LocaleListCompat.getEmptyLocaleList()
|
||||||
|
else LocaleListCompat.forLanguageTags(lang)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun migrateLanguagePrefs(prefs: SharedPreferences) {
|
||||||
|
val currentLang = prefs.getString("lang", SYSTEM_DEFAULT) ?: SYSTEM_DEFAULT
|
||||||
|
debug("Migrating in-app language prefs: $currentLang")
|
||||||
|
prefs.edit { putString("lang", SYSTEM_MANAGED) }
|
||||||
|
setLocale(currentLang)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a list from locales_config.xml
|
||||||
|
* of native language names paired to its Locale tag (ex: "English", "en")
|
||||||
|
*/
|
||||||
|
fun getLanguageTags(context: Context): List<Pair<String, String>> {
|
||||||
|
val languageTags = mutableListOf(SYSTEM_DEFAULT)
|
||||||
|
try {
|
||||||
|
context.resources.getXml(R.xml.locales_config).use {
|
||||||
|
while (it.eventType != XmlPullParser.END_DOCUMENT) {
|
||||||
|
if (it.eventType == XmlPullParser.START_TAG && it.name == "locale") {
|
||||||
|
languageTags += it.getAttributeValue(0)
|
||||||
|
}
|
||||||
|
it.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
errormsg("Error parsing locale_config.xml ${e.message}")
|
||||||
|
}
|
||||||
|
fun getDisplayLanguage(tag: String): String {
|
||||||
|
val loc = Locale(tag)
|
||||||
|
return when (tag) {
|
||||||
|
SYSTEM_DEFAULT -> context.getString(R.string.preferences_system_default)
|
||||||
|
"fr-HT" -> context.getString(R.string.fr_HT)
|
||||||
|
"pt-BR" -> context.getString(R.string.pt_BR)
|
||||||
|
else -> loc.getDisplayLanguage(loc)
|
||||||
|
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(loc) else it.toString() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return languageTags.map { getDisplayLanguage(it) to it }
|
||||||
|
}
|
||||||
|
}
|
|
@ -68,7 +68,7 @@
|
||||||
<string name="modem_config_slow_short">단거리 (저속)</string>
|
<string name="modem_config_slow_short">단거리 (저속)</string>
|
||||||
<string name="modem_config_slow_medium">중거리 (저속)</string>
|
<string name="modem_config_slow_medium">중거리 (저속)</string>
|
||||||
<string name="modem_config_slow_long">장거리 (저속)</string>
|
<string name="modem_config_slow_long">장거리 (저속)</string>
|
||||||
<string name="preferences_language">언어 (restart needed)</string>
|
<string name="preferences_language">언어</string>
|
||||||
<string name="preferences_system_default">시스템 기본값</string>
|
<string name="preferences_system_default">시스템 기본값</string>
|
||||||
<string name="debug_panel">디버그 패널</string>
|
<string name="debug_panel">디버그 패널</string>
|
||||||
<string name="debug_last_messages">500 last messages</string>
|
<string name="debug_last_messages">500 last messages</string>
|
|
@ -126,7 +126,7 @@
|
||||||
<string name="why_background_required">W przypadku tej funkcji musisz przyznać opcję uprawnień lokalizacji „Zezwalaj przez cały czas”.</string>
|
<string name="why_background_required">W przypadku tej funkcji musisz przyznać opcję uprawnień lokalizacji „Zezwalaj przez cały czas”.</string>
|
||||||
<string name="cancel_no_radio">Anuluj (brak dostępu do radia)</string>
|
<string name="cancel_no_radio">Anuluj (brak dostępu do radia)</string>
|
||||||
<string name="allow_will_show">Zezwól (pokaże okno dialogowe)</string>
|
<string name="allow_will_show">Zezwól (pokaże okno dialogowe)</string>
|
||||||
<string name="preferences_language">Język (wymagany restart)</string>
|
<string name="preferences_language">Język</string>
|
||||||
<string name="preferences_system_default">Domyślny systemu</string>
|
<string name="preferences_system_default">Domyślny systemu</string>
|
||||||
<string name="preferences_map_style">Typ map</string>
|
<string name="preferences_map_style">Typ map</string>
|
||||||
<string name="resend">Ponów</string>
|
<string name="resend">Ponów</string>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<string name="unset">Não definido</string>
|
<string name="unset">Não definido</string>
|
||||||
<string name="connection_status">Status da conexão</string>
|
<string name="connection_status">Status da conexão</string>
|
||||||
<string name="application_icon">icone da aplicação</string>
|
<string name="application_icon">icone da aplicação</string>
|
||||||
<string name="unknown_username">Nome de usuário desconhecido</string>
|
<string name="unknown_username">Nome desconhecido</string>
|
||||||
<string name="user_avatar">Avatar do usuário</string>
|
<string name="user_avatar">Avatar do usuário</string>
|
||||||
<string name="sample_message">ei, encontrei o esconderijo, está aqui ao lado do tigre grande. estou um pouco assustado.</string>
|
<string name="sample_message">ei, encontrei o esconderijo, está aqui ao lado do tigre grande. estou um pouco assustado.</string>
|
||||||
<string name="send_text">Enviar Texto</string>
|
<string name="send_text">Enviar Texto</string>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<string name="unset">Não Definido</string>
|
<string name="unset">Não Definido</string>
|
||||||
<string name="connection_status">Estado da Conexão</string>
|
<string name="connection_status">Estado da Conexão</string>
|
||||||
<string name="application_icon">icone da aplicação</string>
|
<string name="application_icon">icone da aplicação</string>
|
||||||
<string name="unknown_username">Nome Desconhecido</string>
|
<string name="unknown_username">Nome desconhecido</string>
|
||||||
<string name="user_avatar">Avatar do Usuário</string>
|
<string name="user_avatar">Avatar do Usuário</string>
|
||||||
<string name="sample_message">Hey, encontrei o cache, está aqui ao lado do grande tigre. Estou um pouco assustado.</string>
|
<string name="sample_message">Hey, encontrei o cache, está aqui ao lado do grande tigre. Estou um pouco assustado.</string>
|
||||||
<string name="send_text">Enviar Texto</string>
|
<string name="send_text">Enviar Texto</string>
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
<string name="download_region_dialog_title">Завантажити регіон</string>
|
<string name="download_region_dialog_title">Завантажити регіон</string>
|
||||||
<string name="download_region_connection_alert">Ви не підключені до Інтернету, ви не можете завантажити офлайн-карту</string>
|
<string name="download_region_connection_alert">Ви не підключені до Інтернету, ви не можете завантажити офлайн-карту</string>
|
||||||
<string name="download_failed">Не вдалося завантажити пакет стилів</string>
|
<string name="download_failed">Не вдалося завантажити пакет стилів</string>
|
||||||
<string name="preferences_language">Мова (потрібне перезавантаження)</string>
|
<string name="preferences_language">Мова</string>
|
||||||
<string name="preferences_system_default">Системні налаштунки за умовчанням</string>
|
<string name="preferences_system_default">Системні налаштунки за умовчанням</string>
|
||||||
<string name="preferences_map_style">Джерело карти</string>
|
<string name="preferences_map_style">Джерело карти</string>
|
||||||
<string name="resend">Перенадіслати</string>
|
<string name="resend">Перенадіслати</string>
|
||||||
|
|
|
@ -1,94 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string-array name="language_entries" translatable="false">
|
|
||||||
<!-- zz -->
|
|
||||||
<item>@string/preferences_system_default</item>
|
|
||||||
<!-- en -->
|
|
||||||
<item>English</item>
|
|
||||||
<!-- cs -->
|
|
||||||
<item>Čeština</item>
|
|
||||||
<!-- zh -->
|
|
||||||
<item>Chinese 中文 </item>
|
|
||||||
<!-- de -->
|
|
||||||
<item>Deutsch</item>
|
|
||||||
<!-- es -->
|
|
||||||
<item>Español</item>
|
|
||||||
<!-- fr -->
|
|
||||||
<item>Français</item>
|
|
||||||
<!-- ga -->
|
|
||||||
<item>Gaeilge</item>
|
|
||||||
<!-- el -->
|
|
||||||
<item>Greek ελληνικά</item>
|
|
||||||
<!-- ht -->
|
|
||||||
<item>Haiti</item>
|
|
||||||
<!-- it -->
|
|
||||||
<item>Italiano</item>
|
|
||||||
<!-- ja -->
|
|
||||||
<item>Japanese 日本語</item>
|
|
||||||
<!-- ko-rKR -->
|
|
||||||
<item>Korean 한국어</item>
|
|
||||||
<!-- hu -->
|
|
||||||
<item>Magyar</item>
|
|
||||||
<!-- nl -->
|
|
||||||
<item>Nederlands</item>
|
|
||||||
<!-- no -->
|
|
||||||
<item>Norge</item>
|
|
||||||
<!-- pl -->
|
|
||||||
<item>Polski</item>
|
|
||||||
<!-- pt -->
|
|
||||||
<item>Português</item>
|
|
||||||
<!-- pt_BR -->
|
|
||||||
<item>Português do Brasil</item>
|
|
||||||
<!-- ro -->
|
|
||||||
<item>Română</item>
|
|
||||||
<!-- ru -->
|
|
||||||
<item>Russian Pусский</item>
|
|
||||||
<!-- sq -->
|
|
||||||
<item>Shqip</item>
|
|
||||||
<!-- sk -->
|
|
||||||
<item>Slovenský</item>
|
|
||||||
<!-- sl -->
|
|
||||||
<item>Slovenščina</item>
|
|
||||||
<!-- fi -->
|
|
||||||
<item>Suomi</item>
|
|
||||||
<!-- sv -->
|
|
||||||
<item>Svenska</item>
|
|
||||||
<!-- tr -->
|
|
||||||
<item>Türkçe</item>
|
|
||||||
<!-- uk -->
|
|
||||||
<item>Українська</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="language_values" translatable="false">
|
|
||||||
<item>zz</item>
|
|
||||||
<item>en</item>
|
|
||||||
<item>cs</item>
|
|
||||||
<item>zh</item>
|
|
||||||
<item>de</item>
|
|
||||||
<item>es</item>
|
|
||||||
<item>fr</item>
|
|
||||||
<item>ga</item>
|
|
||||||
<item>el</item>
|
|
||||||
<item>ht</item>
|
|
||||||
<item>it</item>
|
|
||||||
<item>ja</item>
|
|
||||||
<item>ko_KR</item>
|
|
||||||
<item>hu</item>
|
|
||||||
<item>nl</item>
|
|
||||||
<item>no</item>
|
|
||||||
<item>pl</item>
|
|
||||||
<item>pt</item>
|
|
||||||
<item>pt_BR</item>
|
|
||||||
<item>ro</item>
|
|
||||||
<item>ru</item>
|
|
||||||
<item>sq</item>
|
|
||||||
<item>sk</item>
|
|
||||||
<item>sl</item>
|
|
||||||
<item>fi</item>
|
|
||||||
<item>sv</item>
|
|
||||||
<item>tr</item>
|
|
||||||
<item>uk</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="map_styles">
|
<string-array name="map_styles">
|
||||||
<item>OpenStreetMap</item>
|
<item>OpenStreetMap</item>
|
||||||
<item>USGS TOPO</item>
|
<item>USGS TOPO</item>
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
<resources>
|
<resources>
|
||||||
|
// Language tags native names (not available via .getDisplayLanguage)
|
||||||
|
<string name="fr_HT" translatable="false">Kreyòl ayisyen</string>
|
||||||
|
<string name="pt_BR" translatable="false">Português do Brasil</string>
|
||||||
|
|
||||||
<string name="app_name" translatable="false">Meshtastic</string>
|
<string name="app_name" translatable="false">Meshtastic</string>
|
||||||
<string name="action_settings">Settings</string>
|
<string name="action_settings">Settings</string>
|
||||||
<string name="channel_name">Channel Name</string>
|
<string name="channel_name">Channel Name</string>
|
||||||
|
@ -129,7 +133,7 @@
|
||||||
<string name="download_region_dialog_title">Download Region</string>
|
<string name="download_region_dialog_title">Download Region</string>
|
||||||
<string name="download_region_connection_alert">You are not connected to the internet, you cannot download an offline map</string>
|
<string name="download_region_connection_alert">You are not connected to the internet, you cannot download an offline map</string>
|
||||||
<string name="download_failed">Unable to download style pack</string>
|
<string name="download_failed">Unable to download style pack</string>
|
||||||
<string name="preferences_language">Language (restart needed)</string>
|
<string name="preferences_language">Language</string>
|
||||||
<string name="preferences_system_default">System default</string>
|
<string name="preferences_system_default">System default</string>
|
||||||
<string name="preferences_map_style">Map Source</string>
|
<string name="preferences_map_style">Map Source</string>
|
||||||
<string name="resend">Resend</string>
|
<string name="resend">Resend</string>
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<locale android:name="en"/> <!-- English (ultimate fallback locale) -->
|
||||||
|
<locale android:name="cs"/> <!-- Czech -->
|
||||||
|
<locale android:name="zh"/> <!-- Chinese -->
|
||||||
|
<locale android:name="de"/> <!-- German -->
|
||||||
|
<locale android:name="es"/> <!-- Spanish (Spain) -->
|
||||||
|
<locale android:name="fr"/> <!-- French (France) -->
|
||||||
|
<locale android:name="ga"/> <!-- Irish -->
|
||||||
|
<locale android:name="el"/> <!-- Greek -->
|
||||||
|
<locale android:name="fr-HT"/> <!-- Haitian Creole -->
|
||||||
|
<locale android:name="it"/> <!-- Italian -->
|
||||||
|
<locale android:name="ja"/> <!-- Japanese -->
|
||||||
|
<locale android:name="ko"/> <!-- Korean -->
|
||||||
|
<locale android:name="hu"/> <!-- Hungarian -->
|
||||||
|
<locale android:name="nl"/> <!-- Dutch -->
|
||||||
|
<locale android:name="nb"/> <!-- Norwegian -->
|
||||||
|
<locale android:name="pl"/> <!-- Polish -->
|
||||||
|
<locale android:name="pt"/> <!-- Portuguese -->
|
||||||
|
<locale android:name="pt-BR"/> <!-- Portuguese (Brazil) -->
|
||||||
|
<locale android:name="ro"/> <!-- Romanian -->
|
||||||
|
<locale android:name="ru"/> <!-- Russian -->
|
||||||
|
<locale android:name="sq"/> <!-- Albanian -->
|
||||||
|
<locale android:name="sk"/> <!-- Slovak -->
|
||||||
|
<locale android:name="sl"/> <!-- Slovenian -->
|
||||||
|
<locale android:name="fi"/> <!-- Finnish -->
|
||||||
|
<locale android:name="sv"/> <!-- Swedish -->
|
||||||
|
<locale android:name="tr"/> <!-- Turkish -->
|
||||||
|
<locale android:name="uk"/> <!-- Ukrainian -->
|
||||||
|
</locale-config>
|
Ładowanie…
Reference in New Issue