Merge branch 'master' of ssh://github.com/osmandapp/Osmand into js_voice_routing

This commit is contained in:
PaulStets 2018-08-04 08:42:02 +03:00
commit 405e63d4a3
10 changed files with 264 additions and 80 deletions

View file

@ -5,6 +5,10 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -13,4 +17,18 @@
android:paddingBottom="@dimen/list_view_bottom_padding" android:paddingBottom="@dimen/list_view_bottom_padding"
android:scrollbars="vertical"/> android:scrollbars="vertical"/>
<Button
android:id="@+id/open_osmand_btn"
style="@style/DialogActionButtonActive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="@dimen/content_padding_big"
android:drawableLeft="@drawable/ic_action_osmand_plus"
android:drawablePadding="@dimen/content_padding_standard"
android:drawableStart="@drawable/ic_action_osmand_plus"
android:text="@string/open_osmand"/>
</FrameLayout>
</LinearLayout> </LinearLayout>

View file

@ -1,4 +1,5 @@
<resources> <resources>
<string name="open_osmand">Open OsmAnd</string>
<string name="shared_string_live">Live</string> <string name="shared_string_live">Live</string>
<string name="shared_string_bot">Bot</string> <string name="shared_string_bot">Bot</string>
<string name="get_telegram_title">Registration in Telegram</string> <string name="get_telegram_title">Registration in Telegram</string>

View file

@ -7,7 +7,6 @@ import org.drinkless.td.libcore.telegram.Client
import org.drinkless.td.libcore.telegram.Client.ResultHandler import org.drinkless.td.libcore.telegram.Client.ResultHandler
import org.drinkless.td.libcore.telegram.TdApi import org.drinkless.td.libcore.telegram.TdApi
import org.drinkless.td.libcore.telegram.TdApi.AuthorizationState import org.drinkless.td.libcore.telegram.TdApi.AuthorizationState
import org.json.JSONObject
import java.io.File import java.io.File
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@ -28,6 +27,9 @@ class TelegramHelper private constructor() {
private const val UPDATE_LIVE_MESSAGES_INTERVAL_SEC = 30L private const val UPDATE_LIVE_MESSAGES_INTERVAL_SEC = 30L
private const val MESSAGE_ACTIVE_TIME_SEC = 24 * 60 * 60 // 24 hours private const val MESSAGE_ACTIVE_TIME_SEC = 24 * 60 * 60 // 24 hours
private const val DEVICE_PREFIX = "Device: "
private const val LOCATION_PREFIX = "Location: "
// min and max values for the Telegram API // min and max values for the Telegram API
const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 61 const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 61
const val MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 60 * 60 * 24 - 1 // one day const val MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 60 * 60 * 24 - 1 // one day
@ -83,6 +85,7 @@ class TelegramHelper private constructor() {
var listener: TelegramListener? = null var listener: TelegramListener? = null
private val incomingMessagesListeners = HashSet<TelegramIncomingMessagesListener>() private val incomingMessagesListeners = HashSet<TelegramIncomingMessagesListener>()
private val fullInfoUpdatesListeners = HashSet<FullInfoUpdatesListener>()
fun addIncomingMessagesListener(listener: TelegramIncomingMessagesListener) { fun addIncomingMessagesListener(listener: TelegramIncomingMessagesListener) {
incomingMessagesListeners.add(listener) incomingMessagesListeners.add(listener)
@ -92,6 +95,14 @@ class TelegramHelper private constructor() {
incomingMessagesListeners.remove(listener) incomingMessagesListeners.remove(listener)
} }
fun addFullInfoUpdatesListener(listener: FullInfoUpdatesListener) {
fullInfoUpdatesListeners.add(listener)
}
fun removeFullInfoUpdatesListener(listener: FullInfoUpdatesListener) {
fullInfoUpdatesListeners.remove(listener)
}
fun getChatList(): TreeSet<OrderedChat> { fun getChatList(): TreeSet<OrderedChat> {
synchronized(chatList) { synchronized(chatList) {
return TreeSet(chatList.filter { !it.isChannel }) return TreeSet(chatList.filter { !it.isChannel })
@ -128,9 +139,21 @@ class TelegramHelper private constructor() {
return res return res
} }
fun getBasicGroupFullInfo(id: Int) = basicGroupsFullInfo[id] fun getBasicGroupFullInfo(id: Int): TdApi.BasicGroupFullInfo? {
val res = basicGroupsFullInfo[id]
if (res == null) {
requestBasicGroupFullInfo(id)
}
return res
}
fun getSupergroupFullInfo(id: Int) = supergroupsFullInfo[id] fun getSupergroupFullInfo(id: Int): TdApi.SupergroupFullInfo? {
val res = supergroupsFullInfo[id]
if (res == null) {
requestSupergroupFullInfo(id)
}
return res
}
fun isGroup(chat: TdApi.Chat): Boolean { fun isGroup(chat: TdApi.Chat): Boolean {
return chat.type is TdApi.ChatTypeSupergroup || chat.type is TdApi.ChatTypeBasicGroup return chat.type is TdApi.ChatTypeSupergroup || chat.type is TdApi.ChatTypeBasicGroup
@ -178,6 +201,11 @@ class TelegramHelper private constructor() {
fun updateLocationMessages() fun updateLocationMessages()
} }
interface FullInfoUpdatesListener {
fun onBasicGroupFullInfoUpdated(groupId: Int, info: TdApi.BasicGroupFullInfo)
fun onSupergroupFullInfoUpdated(groupId: Int, info: TdApi.SupergroupFullInfo)
}
interface TelegramAuthorizationRequestListener { interface TelegramAuthorizationRequestListener {
fun onRequestTelegramAuthenticationParameter(parameterType: TelegramAuthenticationParameterType) fun onRequestTelegramAuthenticationParameter(parameterType: TelegramAuthenticationParameterType)
fun onTelegramAuthorizationRequestError(code: Int, message: String) fun onTelegramAuthorizationRequestError(code: Int, message: String)
@ -253,6 +281,19 @@ class TelegramHelper private constructor() {
} }
} }
fun getOsmAndBotDeviceName(message: TdApi.Message): String {
var deviceName = ""
if (message.replyMarkup is TdApi.ReplyMarkupInlineKeyboard) {
val replyMarkup = message.replyMarkup as TdApi.ReplyMarkupInlineKeyboard
try {
deviceName = replyMarkup.rows[0][1].text.split("\\s".toRegex())[1]
} catch (e: Exception) {
}
}
return deviceName
}
fun isOsmAndBot(userId: Int) = users[userId]?.username == OSMAND_BOT_USERNAME fun isOsmAndBot(userId: Int) = users[userId]?.username == OSMAND_BOT_USERNAME
fun isBot(userId: Int) = users[userId]?.type is TdApi.UserTypeBot fun isBot(userId: Int) = users[userId]?.type is TdApi.UserTypeBot
@ -351,6 +392,42 @@ class TelegramHelper private constructor() {
listener?.onTelegramChatsRead() listener?.onTelegramChatsRead()
} }
private fun requestBasicGroupFullInfo(id: Int) {
client?.send(TdApi.GetBasicGroupFullInfo(id)) { obj ->
when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
listener?.onTelegramError(error.code, error.message)
}
}
TdApi.BasicGroupFullInfo.CONSTRUCTOR -> {
val info = obj as TdApi.BasicGroupFullInfo
basicGroupsFullInfo[id] = info
fullInfoUpdatesListeners.forEach { it.onBasicGroupFullInfoUpdated(id, info) }
}
}
}
}
private fun requestSupergroupFullInfo(id: Int) {
client?.send(TdApi.GetSupergroupFullInfo(id)) { obj ->
when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
listener?.onTelegramError(error.code, error.message)
}
}
TdApi.SupergroupFullInfo.CONSTRUCTOR -> {
val info = obj as TdApi.SupergroupFullInfo
supergroupsFullInfo[id] = info
fullInfoUpdatesListeners.forEach { it.onSupergroupFullInfoUpdated(id, info) }
}
}
}
}
private fun requestCurrentUser(){ private fun requestCurrentUser(){
client?.send(TdApi.GetMe()) { obj -> client?.send(TdApi.GetMe()) { obj ->
when (obj.constructor) { when (obj.constructor) {
@ -384,6 +461,9 @@ class TelegramHelper private constructor() {
val oldContent = message.content val oldContent = message.content
if (oldContent is TdApi.MessageText) { if (oldContent is TdApi.MessageText) {
message.content = parseOsmAndBotLocation(oldContent.text.text) message.content = parseOsmAndBotLocation(oldContent.text.text)
} else if (oldContent is TdApi.MessageLocation &&
(isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) {
message.content = parseOsmAndBotLocation(message)
} }
removeOldMessages(message.senderUserId, message.chatId) removeOldMessages(message.senderUserId, message.chatId)
usersLocationMessages[message.id] = message usersLocationMessages[message.id] = message
@ -627,51 +707,54 @@ class TelegramHelper private constructor() {
val content = content val content = content
return when (content) { return when (content) {
is TdApi.MessageLocation -> true is TdApi.MessageLocation -> true
is TdApi.MessageText -> { is TdApi.MessageText -> isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId)
if (content.text.text.startsWith("{")) {
// TODO: get user from library if null
if (isOsmAndBot(senderUserId)) {
return true
}
}
false
}
else -> false else -> false
} }
} }
private fun parseOsmAndBotLocation(json: String): MessageOsmAndBotLocation { private fun parseOsmAndBotLocation(message: TdApi.Message): MessageOsmAndBotLocation {
val obj = JSONObject(json) val messageLocation = message.content as TdApi.MessageLocation
return MessageOsmAndBotLocation( val res = MessageOsmAndBotLocation()
obj.optString("name", ""), res.name = getOsmAndBotDeviceName(message)
obj.optDouble("lat", -1.0), res.lat = messageLocation.location.latitude
obj.optDouble("lon", -1.0), res.lon = messageLocation.location.longitude
obj.optDouble("alt", -1.0), return res
obj.optDouble("azi", -1.0),
obj.optDouble("spd", -1.0),
obj.optInt("updAgo", -1),
obj.optInt("locAgo", -1),
obj.optInt("updId", -1),
obj.optInt("updTime", -1)
)
} }
class MessageOsmAndBotLocation internal constructor( private fun parseOsmAndBotLocation(text: String): MessageOsmAndBotLocation {
val name: String, val res = MessageOsmAndBotLocation()
val lat: Double, for (s in text.lines()) {
val lon: Double, when {
val alt: Double, s.startsWith(DEVICE_PREFIX) -> {
val azi: Double, res.name = s.removePrefix(DEVICE_PREFIX)
val spd: Double, }
val updAgo: Int, s.startsWith(LOCATION_PREFIX) -> {
val locAgo: Int, val locStr = s.removePrefix(LOCATION_PREFIX)
val updId: Int, try {
val updTime: Int val (latS, lonS) = locStr.split(" ")
) : TdApi.MessageContent() { res.lat = latS.dropLast(1).toDouble()
res.lon = lonS.toDouble()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
return res
}
class MessageOsmAndBotLocation : TdApi.MessageContent() {
var name: String = ""
internal set
var lat: Double = Double.NaN
internal set
var lon: Double = Double.NaN
internal set
override fun getConstructor() = -1 override fun getConstructor() = -1
fun isValid() = name != "" && lat != -1.0 && lon != -1.0 fun isValid() = name != "" && lat != Double.NaN && lon != Double.NaN
} }
class OrderedChat internal constructor(internal val order: Long, internal val chatId: Long, internal val isChannel: Boolean) : Comparable<OrderedChat> { class OrderedChat internal constructor(internal val order: Long, internal val chatId: Long, internal val isChannel: Boolean) : Comparable<OrderedChat> {
@ -881,6 +964,9 @@ class TelegramHelper private constructor() {
val newContent = updateMessageContent.newContent val newContent = updateMessageContent.newContent
message.content = if (newContent is TdApi.MessageText) { message.content = if (newContent is TdApi.MessageText) {
parseOsmAndBotLocation(newContent.text.text) parseOsmAndBotLocation(newContent.text.text)
} else if (newContent is TdApi.MessageLocation &&
(isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) {
parseOsmAndBotLocation(message)
} else { } else {
newContent newContent
} }
@ -989,11 +1075,21 @@ class TelegramHelper private constructor() {
} }
TdApi.UpdateBasicGroupFullInfo.CONSTRUCTOR -> { TdApi.UpdateBasicGroupFullInfo.CONSTRUCTOR -> {
val updateBasicGroupFullInfo = obj as TdApi.UpdateBasicGroupFullInfo val updateBasicGroupFullInfo = obj as TdApi.UpdateBasicGroupFullInfo
basicGroupsFullInfo[updateBasicGroupFullInfo.basicGroupId] = updateBasicGroupFullInfo.basicGroupFullInfo val id = updateBasicGroupFullInfo.basicGroupId
if (basicGroupsFullInfo.containsKey(id)) {
val info = updateBasicGroupFullInfo.basicGroupFullInfo
basicGroupsFullInfo[id] = info
fullInfoUpdatesListeners.forEach { it.onBasicGroupFullInfoUpdated(id, info) }
}
} }
TdApi.UpdateSupergroupFullInfo.CONSTRUCTOR -> { TdApi.UpdateSupergroupFullInfo.CONSTRUCTOR -> {
val updateSupergroupFullInfo = obj as TdApi.UpdateSupergroupFullInfo val updateSupergroupFullInfo = obj as TdApi.UpdateSupergroupFullInfo
supergroupsFullInfo[updateSupergroupFullInfo.supergroupId] = updateSupergroupFullInfo.supergroupFullInfo val id = updateSupergroupFullInfo.supergroupId
if (supergroupsFullInfo.containsKey(id)) {
val info = updateSupergroupFullInfo.supergroupFullInfo
supergroupsFullInfo[id] = info
fullInfoUpdatesListeners.forEach { it.onSupergroupFullInfoUpdated(id, info) }
}
} }
} }
} }

View file

@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import net.osmand.Location import net.osmand.Location
@ -18,6 +19,7 @@ import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.TelegramHelper.* import net.osmand.telegram.helpers.TelegramHelper.*
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem import net.osmand.telegram.helpers.TelegramUiHelper.ChatItem
@ -33,7 +35,7 @@ private const val CHAT_VIEW_TYPE = 0
private const val LOCATION_ITEM_VIEW_TYPE = 1 private const val LOCATION_ITEM_VIEW_TYPE = 1
class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessagesListener, class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessagesListener,
TelegramLocationListener, TelegramCompassListener { FullInfoUpdatesListener, TelegramLocationListener, TelegramCompassListener {
private val app: TelegramApplication private val app: TelegramApplication
get() = activity?.application as TelegramApplication get() = activity?.application as TelegramApplication
@ -67,6 +69,12 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
} }
}) })
} }
mainView.findViewById<Button>(R.id.open_osmand_btn).setOnClickListener {
val intent = activity?.packageManager?.getLaunchIntentForPackage(OsmandAidlHelper.OSMAND_PACKAGE_NAME)
if (intent != null) {
startActivity(intent)
}
}
return mainView return mainView
} }
@ -75,12 +83,14 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
locationViewCache = app.uiUtils.getUpdateLocationViewCache() locationViewCache = app.uiUtils.getUpdateLocationViewCache()
updateList() updateList()
telegramHelper.addIncomingMessagesListener(this) telegramHelper.addIncomingMessagesListener(this)
telegramHelper.addFullInfoUpdatesListener(this)
startLocationUpdate() startLocationUpdate()
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
telegramHelper.removeIncomingMessagesListener(this) telegramHelper.removeIncomingMessagesListener(this)
telegramHelper.removeFullInfoUpdatesListener(this)
stopLocationUpdate() stopLocationUpdate()
} }
@ -130,6 +140,14 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
override fun updateLocationMessages() {} override fun updateLocationMessages() {}
override fun onBasicGroupFullInfoUpdated(groupId: Int, info: TdApi.BasicGroupFullInfo) {
app.runInUIThread { updateList() }
}
override fun onSupergroupFullInfoUpdated(groupId: Int, info: TdApi.SupergroupFullInfo) {
app.runInUIThread { updateList() }
}
override fun updateLocation(location: Location?) { override fun updateLocation(location: Location?) {
val loc = this.location val loc = this.location
val newLocation = loc == null && location != null val newLocation = loc == null && location != null
@ -299,8 +317,9 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
item.privateChat -> "" // FIXME item.privateChat -> "" // FIXME
else -> { else -> {
val live = getString(R.string.shared_string_live) val live = getString(R.string.shared_string_live)
// val all = getString(R.string.shared_string_all) val all = getString(R.string.shared_string_all)
"$live ${item.liveMembersCount}" val liveStr = "$live ${item.liveMembersCount}"
if (item.membersCount > 0) "$liveStr$all ${item.membersCount}" else liveStr
} }
} }
} }

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><resources> <?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="switch_to_raster_map_to_see">Off-line vektorové mapy toto místo neobsahují. Mapová data můžete stáhnout v \'Nastavení\' (\'Stáhnout mapy\'), nebo se přepněte na modul \'Online mapy\'.</string> <string name="switch_to_raster_map_to_see">Off-line vektorové mapy toto místo neobsahují. Mapová data můžete stáhnout v \'Nastavení\' (\'Stáhnout mapy\'), nebo se přepněte na modul \'Online mapy\'.</string>
<string name="send_files_to_osm">Nahrát GPX soubory do OSM?</string> <string name="send_files_to_osm">Nahrát GPX soubory do OSM?</string>
@ -2516,7 +2517,7 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="import_track">Import trasy</string> <string name="import_track">Import trasy</string>
<string name="import_track_desc">Soubor %$1s neobsahuje body trasy, importovat jako trasu?</string> <string name="import_track_desc">Soubor %$1s neobsahuje body trasy, importovat jako trasu?</string>
<string name="move_point">Přesunout bod</string> <string name="move_point">Přesunout bod</string>
<string name="add_segment_to_the_track">Přidat do GPX trasy</string> <string name="add_segment_to_the_track">Přidat do GPX souboru</string>
<string name="move_all_to_history">Přesunout vše do historie</string> <string name="move_all_to_history">Přesunout vše do historie</string>
<string name="show_direction">Indikace vzdálenosti</string> <string name="show_direction">Indikace vzdálenosti</string>
@ -2686,7 +2687,7 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="osmand_extended_description_part1">OsmAnd (OSM Automated Navigation Directions) je mapová a navigační aplikace s přístupem k volným a kvalitním celosvětovým údajům z OpenStreetMap (OSM). <string name="osmand_extended_description_part1">OsmAnd (OSM Automated Navigation Directions) je mapová a navigační aplikace s přístupem k volným a kvalitním celosvětovým údajům z OpenStreetMap (OSM).
\n \n
\nVyužívejte hlasovou a optickou navigaci, zobrazení POI (bodů zájmu), vytváření a správu GPX tras, znázornění vrstevnic a nadmořské výšky (pomocí doplňkového modulu), výběr z režimů auto, cyklista a pěší, editaci OSM a mnoho dalšího.</string> \nVyužívejte hlasovou a optickou navigaci, zobrazení POI (bodů zájmu), vytváření a správu GPX tras, znázornění vrstevnic a nadmořské výšky (pomocí doplňkového modulu), výběr z režimů auto, cyklista a pěší, editaci OSM a mnoho dalšího.</string>
<string name="toast_empty_name_error">Místo nemá žádný název</string> <string name="toast_empty_name_error">Bezejmenné místo</string>
<string name="tunnel_warning">Blíží se tunel</string> <string name="tunnel_warning">Blíží se tunel</string>
<string name="show_tunnels">Tunely</string> <string name="show_tunnels">Tunely</string>
<string name="make_as_start_point">Nastavit toto jako počáteční bod</string> <string name="make_as_start_point">Nastavit toto jako počáteční bod</string>
@ -2709,8 +2710,8 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="optional_point_name">Volitelný název bodu</string> <string name="optional_point_name">Volitelný název bodu</string>
<string name="transport_nearby_routes_within">Trasy v okruhu</string> <string name="transport_nearby_routes_within">Trasy v okruhu</string>
<string name="transport_nearby_routes">POBLÍŽ</string> <string name="transport_nearby_routes">POBLÍŽ</string>
<string name="distance_farthest">Vzdálenost: Nejvzdálenější jako první</string> <string name="distance_farthest">Vzdálenost: nejvzdálenější jako první</string>
<string name="distance_nearest">Vzdálenost: Nejbližší jako první</string> <string name="distance_nearest">Vzdálenost: nejbližší jako první</string>
<string name="rendering_attr_whiteWaterSports_name">Divoká voda</string> <string name="rendering_attr_whiteWaterSports_name">Divoká voda</string>
<string name="osmand_extended_description_part2">GPS navigace <string name="osmand_extended_description_part2">GPS navigace
\n• Můžete si vybrat mezi offline režimem (bez roamingových poplatků v zahraničí) a online režimem (rychlejší) \n• Můžete si vybrat mezi offline režimem (bez roamingových poplatků v zahraničí) a online režimem (rychlejší)
@ -2761,7 +2762,7 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="unlock_all_features">Odemknout všechny funkce OsmAnd</string> <string name="unlock_all_features">Odemknout všechny funkce OsmAnd</string>
<string name="purchase_dialog_title">Vyberte si předplatné</string> <string name="purchase_dialog_title">Vyberte si předplatné</string>
<string name="purchase_dialog_travel_description">Chcete-li číst články o cestování offline, je třeba koupit jednu z následujících položek:</string> <string name="purchase_dialog_travel_description">Chcete-li dostávat offline články o cestování, je třeba koupit jednu z následujících položek:</string>
<string name="purchase_dialog_subtitle">Vyberte vhodnou položku:</string> <string name="purchase_dialog_subtitle">Vyberte vhodnou položku:</string>
<string name="shared_string_dont">Nedělat</string> <string name="shared_string_dont">Nedělat</string>
<string name="shared_string_do">Dělat</string> <string name="shared_string_do">Dělat</string>
@ -2775,18 +2776,18 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="online_webpage_warning">Stránka je k dispozici pouze online. Chcete ji otevřít v prohlížeči?</string> <string name="online_webpage_warning">Stránka je k dispozici pouze online. Chcete ji otevřít v prohlížeči?</string>
<string name="images_cache">Mezipaměť obrázků</string> <string name="images_cache">Mezipaměť obrázků</string>
<string name="delete_search_history">Vymazat historii hledání</string> <string name="delete_search_history">Vymazat historii hledání</string>
<string name="download_images">Zobrazit obrázky</string> <string name="download_images">Stáhnout obrázky</string>
<string name="download_maps_travel">Cestovní průvodce</string> <string name="download_maps_travel">Cestovní průvodce</string>
<string name="shared_string_wikivoyage">Wikivoyage</string> <string name="shared_string_wikivoyage">Wikivoyage</string>
<string name="article_removed">Článek odstraněn</string> <string name="article_removed">Článek odstraněn</string>
<string name="wikivoyage_search_hint">Vyhledávání: Stát, město, kraj</string> <string name="wikivoyage_search_hint">Vyhledávání: stát, město, kraj</string>
<string name="shared_string_read">Číst</string> <string name="shared_string_read">Číst</string>
<string name="saved_articles">Články v záložkách</string> <string name="saved_articles">Články v záložkách</string>
<string name="shared_string_explore">Prozkoumat</string> <string name="shared_string_explore">Prozkoumat</string>
<string name="shared_string_contents">Obsah</string> <string name="shared_string_contents">Obsah</string>
<string name="index_item_world_wikivoyage">Celosvětové články Wikivoyage</string> <string name="index_item_world_wikivoyage">Celosvětové články Wikivoyage</string>
<string name="contour_lines_hillshade_maps">Vrstevnice &amp; stínování terénu</string> <string name="contour_lines_hillshade_maps">Vrstevnice &amp; stínování terénu</string>
<string name="shared_string_restart">Restartovat</string> <string name="shared_string_restart">Restartovat aplikaci</string>
<string name="show_images">Zobrazit obrázky</string> <string name="show_images">Zobrazit obrázky</string>
<string name="purchase_cancelled_dialog_descr">Obnovte předplatné, abyste nadále mohli využívat všechny funkce:</string> <string name="purchase_cancelled_dialog_descr">Obnovte předplatné, abyste nadále mohli využívat všechny funkce:</string>
@ -2798,8 +2799,8 @@ Zobrazená oblast: %1$s x %2$s</string>
<string name="download_file">Stáhnout soubor</string> <string name="download_file">Stáhnout soubor</string>
<string name="start_editing">Začít s úpravami</string> <string name="start_editing">Začít s úpravami</string>
<string name="get_unlimited_access">Získejte neomezený přístup</string> <string name="get_unlimited_access">Získejte neomezený přístup</string>
<string name="monthly_map_updates">Aktualizace map: <b>Každý měsíc</b></string> <string name="monthly_map_updates">Aktualizace map: <b>každý měsíc</b></string>
<string name="daily_map_updates">Aktualizace map: <b>Každou hodinu</b></string> <string name="daily_map_updates">Aktualizace map: <b>každou hodinu</b></string>
<string name="download_wikipedia_description">Stáhnout články Wikipedie pro %1$s a číst je v režimu offline.</string> <string name="download_wikipedia_description">Stáhnout články Wikipedie pro %1$s a číst je v režimu offline.</string>
<string name="download_wikipedia_label">Stahování dat z Wikipedie</string> <string name="download_wikipedia_label">Stahování dat z Wikipedie</string>
<string name="open_in_browser_wiki">Otevřít článek online</string> <string name="open_in_browser_wiki">Otevřít článek online</string>

View file

@ -3086,4 +3086,8 @@ Abgedeckte Fläche: %1$s x %2$s</string>
\n • Bootnavigation: Unterstützung für Fahrrinnen \n • Bootnavigation: Unterstützung für Fahrrinnen
\n \n
\n • Andere Fehlerbehebungen</string> \n • Andere Fehlerbehebungen</string>
<string name="thank_you_for_feedback">Danke für Ihre Rückmeldung</string>
<string name="poi_cannot_be_found">Knoten oder Weg kann nicht gefunden werden.</string>
<string name="search_no_results_feedback">Keine Suchergebnisse?
\nGeben Sie uns eine Rückmeldung</string>
</resources> </resources>

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><resources><string name="add_opening_hours">Lisa lahioleku ajad</string> <?xml version='1.0' encoding='UTF-8'?>
<resources><string name="add_opening_hours">Lisa lahioleku ajad</string>
<string name="description">Kirjeldus</string> <string name="description">Kirjeldus</string>
<string name="contact_info">Kontakti info</string> <string name="contact_info">Kontakti info</string>
@ -171,4 +172,42 @@
<string name="quick_action_showhide_osmbugs_title">Näita/peida OSM Notes</string> <string name="quick_action_showhide_osmbugs_title">Näita/peida OSM Notes</string>
<string name="quick_action_osmbugs_show">Näita OSM Notes</string> <string name="quick_action_osmbugs_show">Näita OSM Notes</string>
<string name="quick_action_osmbugs_hide">Peida OSM Notes</string> <string name="quick_action_osmbugs_hide">Peida OSM Notes</string>
<string name="thank_you_for_feedback">Täname tagasiside eest</string>
<string name="poi_cannot_be_found">Sõlme või teed ei leitud.</string>
<string name="search_no_results_feedback">Otsingutulemused puuduvad? Anna meile tagasisidet</string>
<string name="increase_search_radius_to">Suurenda otsingu raadiust kuni %1$s</string>
<string name="send_search_query">Saada otsingu päring?</string>
<string name="shared_string_world">Maailm</string>
<string name="point_deleted">Punkt %1$s kustutatud</string>
<string name="coord_input_edit_point">Muuda punkti</string>
<string name="coord_input_add_point">Lisa punkt</string>
<string name="coord_input_save_as_track">Salvesta jäljena</string>
<string name="coord_input_save_as_track_descr">Lisasid %1$s punkti. Sisesta faili nimi ja vajuta \"Salvesta\".</string>
<string name="error_notification_desc">Palun saada ekraanipilt sellest teatest aadressil support@osmand.net</string>
<string name="quick_action_edit_actions">Muuda tegevusi</string>
<string name="shared_string_bookmark">Järjehoidja</string>
<string name="hide_full_description">Peida täielik kirjeldus</string>
<string name="show_full_description">Näita täielikku kirjeldust</string>
<string name="open_wikipedia_link_online">Ava Wikipedia link veebis</string>
<string name="open_wikipedia_link_online_description">Link avatakse brauseris.</string>
<string name="how_to_open_link">Kuidas link avada?</string>
<string name="read_wikipedia_offline">Loe Wikipediat ilma võrguühenduseta</string>
<string name="download_all">Lae kõik alla</string>
<string name="shared_string_restart">Rakenduse taaskäivitamine</string>
<string name="show_images">Näita pilte</string>
<string name="maps_you_need">Kaardid, mida vajad</string>
<string name="osmand_team">OsmAnd meeskond</string>
<string name="popular_destinations">Populaarsed sihtkohad</string>
<string name="paid_app">Makstud rakendus</string>
<string name="paid_plugin">Makstud lisa</string>
<string name="update_is_available">Uuendus saadaval</string>
<string name="download_file">Lae fail alla</string>
<string name="start_editing">Alusta muutmist</string>
<string name="get_unlimited_access">Hangi piiramatu ligipääs</string>
<string name="monthly_map_updates">Kaardiuuendused: <b>iga kuu</b></string>
<string name="daily_map_updates">Kaardiuuendused: <b>iga tund</b></string>
<string name="in_app_purchase">Rakenduse sisene ost</string>
<string name="in_app_purchase_desc">Ühekordne makse</string>
<string name="purchase_unlim_title">Osta - %1$s</string>
<string name="purchase_subscription_title">Liitu - %1$s</string>
</resources> </resources>

View file

@ -618,7 +618,7 @@
<string name="poi_harbour_basin">حوضه بندرگاه</string> <string name="poi_harbour_basin">حوضه بندرگاه</string>
<string name="poi_seamark_harbour">بندرگاه</string> <string name="poi_seamark_harbour">بندرگاه</string>
<string name="poi_landmark">لندمارک</string> <string name="poi_landmark">لندمارک</string>
<string name="poi_seamark_light">]چراغ دریایی</string> <string name="poi_seamark_light">چراغ دریایی</string>
<string name="poi_seamark_light_major">چراغ بزرگ دریایی</string> <string name="poi_seamark_light_major">چراغ بزرگ دریایی</string>
<string name="poi_seamark_light_minor">چراغ کوچک دریایی</string> <string name="poi_seamark_light_minor">چراغ کوچک دریایی</string>
<string name="poi_seamark_light_float">چراغ شناور دریایی</string> <string name="poi_seamark_light_float">چراغ شناور دریایی</string>

View file

@ -738,7 +738,7 @@
<string name="fav_export_confirmation">قبلاً از نقاط برگزیده یک خروجی تهیه کرده‌اید و فایلش وجود دارد. خروجی جدید را جایگزین آن می‌کنید؟</string> <string name="fav_export_confirmation">قبلاً از نقاط برگزیده یک خروجی تهیه کرده‌اید و فایلش وجود دارد. خروجی جدید را جایگزین آن می‌کنید؟</string>
<string name="osmand_development_plugin_description">به‌وسیلهٔ این افزونه می‌توانید تنظیمات توسعه‌ای و امکانات عیب‌یابی را مشاهده کنید؛ مانند شبیه‌سازی مسیریابی، آزمایش عملکرد رندرینگ یا امتحان‌کردن پیام‌های صوتی. <string name="osmand_development_plugin_description">به‌وسیلهٔ این افزونه می‌توانید تنظیمات توسعه‌ای و امکانات عیب‌یابی را مشاهده کنید؛ مانند شبیه‌سازی مسیریابی، آزمایش عملکرد رندر یا امتحان‌کردن پیام‌های صوتی.
\nاین تنظیمات برای توسعه‌دهندگان فراهم شده است و به‌کار کاربران عادی نمی‌آید.</string> \nاین تنظیمات برای توسعه‌دهندگان فراهم شده است و به‌کار کاربران عادی نمی‌آید.</string>
<string name="animate_route_off">پایان شبیه‌سازی</string> <string name="animate_route_off">پایان شبیه‌سازی</string>
<string name="animate_route">شروع شبیه‌سازی</string> <string name="animate_route">شروع شبیه‌سازی</string>
@ -892,7 +892,7 @@
<string name="monitoring_control_start">GPX</string> <string name="monitoring_control_start">GPX</string>
<string name="rendering_attr_noPolygons_description">همهٔ عوارض زمین را روی نقشه ناپدید کنید.</string> <string name="rendering_attr_noPolygons_description">همهٔ عوارض زمین را روی نقشه ناپدید کنید.</string>
<string name="rendering_attr_noPolygons_name">چندضلعی‌ها</string> <string name="rendering_attr_noPolygons_name">چندضلعی‌ها</string>
<string name="rendering_attr_appMode_name">حالت رندرکردن</string> <string name="rendering_attr_appMode_name">حالت رندرگیری</string>
<string name="rendering_attr_appMode_description">بهینه‌سازی نقشه برای</string> <string name="rendering_attr_appMode_description">بهینه‌سازی نقشه برای</string>
<string name="rendering_attr_contourLines_description">از این زوم نمایان شود (نیازمند داده‌های منحنی تراز):</string> <string name="rendering_attr_contourLines_description">از این زوم نمایان شود (نیازمند داده‌های منحنی تراز):</string>
<string name="rendering_attr_contourLines_name">نشان‌دادن منحنی‌های تراز</string> <string name="rendering_attr_contourLines_name">نشان‌دادن منحنی‌های تراز</string>
@ -1170,8 +1170,8 @@
<string name="local_index_no_items_to_do">هیچ‌موردی برای %1$s وجود ندارد</string> <string name="local_index_no_items_to_do">هیچ‌موردی برای %1$s وجود ندارد</string>
<string name="local_index_action_do">دارید %2$s مورد را %1$s می‌کنید. ادامه می‌دهید؟</string> <string name="local_index_action_do">دارید %2$s مورد را %1$s می‌کنید. ادامه می‌دهید؟</string>
<string name="trace_rendering">اطلاعات عیب‌یابی رندرینگ</string> <string name="trace_rendering">اطلاعات عیب‌یابی رندرگیری</string>
<string name="trace_rendering_descr">عملکرد رندرینگ را نمایش می‌دهد.</string> <string name="trace_rendering_descr">عملکرد رندرگیری را نمایش می‌دهد.</string>
<string name="choose_audio_stream_descr">بلندگوی پخش راهنمای صوتی را انتخاب کنید.</string> <string name="choose_audio_stream_descr">بلندگوی پخش راهنمای صوتی را انتخاب کنید.</string>
<string name="voice_stream_voice_call">منبع صدای تماس تلفنی (همچنین برای وقفه‌انداختن در دستگاه پخش خودرو)</string> <string name="voice_stream_voice_call">منبع صدای تماس تلفنی (همچنین برای وقفه‌انداختن در دستگاه پخش خودرو)</string>
@ -1195,11 +1195,11 @@
<string name="send_location_email_pattern">برای مشاهدهٔ مکان، پیوند اینترنتی %1$s یا پیوند اندرویدی %2$s را باز کنید</string> <string name="send_location_email_pattern">برای مشاهدهٔ مکان، پیوند اینترنتی %1$s یا پیوند اندرویدی %2$s را باز کنید</string>
<string name="amenity_type_geocache">Geocache</string> <string name="amenity_type_geocache">Geocache</string>
<string name="continuous_rendering_descr">به‌جای نمایش یکبارهٔ تصویر از رندرینگ پیوسته استفاده شود.</string> <string name="continuous_rendering_descr">به‌جای نمایش یکبارهٔ تصویر از رندرکردن پیوسته استفاده شود.</string>
<string name="renderer_load_sucess">رندرکننده بارگذاری شد</string> <string name="renderer_load_sucess">رندرکننده بارگذاری شد</string>
<string name="renderer_load_exception">بارگذاری رندرکننده ناموفق بود</string> <string name="renderer_load_exception">بارگذاری رندرکننده ناموفق بود</string>
<string name="renderers">رسم‌کنندهٔ بُرداری</string> <string name="renderers">رندرکنندهٔ بُرداری</string>
<string name="renderers_descr">شکل‌وشمایل رندر را انتخاب نمایید.</string> <string name="renderers_descr">شکل‌وشمایل رندرگیری را انتخاب نمایید.</string>
<string name="download_type_to_filter">فیلتر</string> <string name="download_type_to_filter">فیلتر</string>
<string name="transport_context_menu">جست‌وجوی وسیلهٔ حمل‌ونقل در ایستگاه</string> <string name="transport_context_menu">جست‌وجوی وسیلهٔ حمل‌ونقل در ایستگاه</string>
<string name="rotate_map_to_bearing_descr">نحوهٔ چرخش نقشه را انتخاب کنید.</string> <string name="rotate_map_to_bearing_descr">نحوهٔ چرخش نقشه را انتخاب کنید.</string>
@ -1751,8 +1751,8 @@
<string name="download_tab_downloads">همهٔ دانلودها</string> <string name="download_tab_downloads">همهٔ دانلودها</string>
<string name="download_tab_updates">به‌روز‌رسانی‌ها</string> <string name="download_tab_updates">به‌روز‌رسانی‌ها</string>
<string name="shared_string_dismiss">بی‌خیال</string> <string name="shared_string_dismiss">بی‌خیال</string>
<string name="use_opengl_render">استفاده از رندرینگ OpenGL</string> <string name="use_opengl_render">استفاده از رندرگیری OpenGL</string>
<string name="use_opengl_render_descr">از رندرینگ سرعت‌یافتهٔ سخت‌افزاری OpenGL استفاده کن (شاید مصرف باتری افزایش یابد یا روی دستگاه‌های خیلی قدیمی کار نکند).</string> <string name="use_opengl_render_descr">از رندرگیری سرعت‌یافتهٔ سخت‌افزاری OpenGL استفاده کن (شاید مصرف باتری افزایش یابد یا روی دستگاه‌های خیلی قدیمی کار نکند).</string>
<string name="lock_screen_request_explanation">%1$s به این مجوز نیاز دارد تا برای صرفه‌جویی در انرژی، بتواند نمایشگر را خاموش کند.</string> <string name="lock_screen_request_explanation">%1$s به این مجوز نیاز دارد تا برای صرفه‌جویی در انرژی، بتواند نمایشگر را خاموش کند.</string>
<string name="wake_on_voice_descr">قبل از رسیدن به پیچ، نمایشگر روشن شود (اگر خاموش است).</string> <string name="wake_on_voice_descr">قبل از رسیدن به پیچ، نمایشگر روشن شود (اگر خاموش است).</string>
<string name="shared_string_never">هرگز</string> <string name="shared_string_never">هرگز</string>
@ -2241,7 +2241,7 @@
<string name="active_markers">نشانه‌های فعال</string> <string name="active_markers">نشانه‌های فعال</string>
<string name="map_markers">نشانه‌های نقشه</string> <string name="map_markers">نشانه‌های نقشه</string>
<string name="map_marker">نشانهٔ نقشه</string> <string name="map_marker">نشانهٔ نقشه</string>
<string name="consider_turning_polygons_off">توصیه می‌کنیم رسم چندضلعی‌ها را غیرفعال کنید.</string> <string name="consider_turning_polygons_off">توصیه می‌کنیم رندرشدن چندضلعی‌ها را غیرفعال کنید.</string>
<string name="rendering_attr_showMtbRoutes_name">نمایش مسیرهای دوچرخه‌سواری کوهستانی (MTB)</string> <string name="rendering_attr_showMtbRoutes_name">نمایش مسیرهای دوچرخه‌سواری کوهستانی (MTB)</string>
<string name="show_polygons">چندضلعی‌ها را نشان بده</string> <string name="show_polygons">چندضلعی‌ها را نشان بده</string>
<string name="shared_string_status">وضعیت</string> <string name="shared_string_status">وضعیت</string>

View file

@ -2969,12 +2969,14 @@ Zodpovedá oblasti: %1$s x %2$s</string>
\n \n
\n • Mapové značky: opravené zapínanie a vypínanie skupín, možnosť skryť značky z mapy \n • Mapové značky: opravené zapínanie a vypínanie skupín, možnosť skryť značky z mapy
\n \n
\n • Úpravy OSM: Možnosť meniť značky nebodových objektov, oprava chýbajúcich komentárov na poznámkach, záloha úprav \n • Úpravy OSM: Možnosť meniť značky nebodových objektov a ciest, oprava chýbajúcich komentárov na poznámkach, záloha úprav
\n \n
\n • Vylepšené čítanie Wikipédie a Wikivoyage, aktualizované súbory sú už k dispozícii \n • Vylepšené čítanie Wikipédie a Wikivoyage, aktualizované súbory sú už k dispozícii
\n \n
\n • Kontextové menu: opravené farby znakov ciest v nočnom režime, opravené doplnkové veľkosti menu \n • Kontextové menu: opravené farby znakov ciest v nočnom režime, opravené doplnkové veľkosti menu
\n \n
\n • Navigácia lodí: podpora pre vodné cesty
\n
\n • Opravy ďalších chýb \n • Opravy ďalších chýb
\n \n
\n</string> \n</string>
@ -2983,4 +2985,8 @@ Zodpovedá oblasti: %1$s x %2$s</string>
<string name="search_no_results_description">Žiadne výsledky? <string name="search_no_results_description">Žiadne výsledky?
\nPovedzte nám o tom.</string> \nPovedzte nám o tom.</string>
<string name="send_search_query">Odoslať vyhľadávaciu požiadavku?</string> <string name="send_search_query">Odoslať vyhľadávaciu požiadavku?</string>
<string name="thank_you_for_feedback">Ďakujeme za vašu spätnú väzbu</string>
<string name="poi_cannot_be_found">Nebol nájdený bod ani cesta.</string>
<string name="search_no_results_feedback">Žiadne výsledky vyhľadávania?
\nDajte nám spätnú väzbu</string>
</resources> </resources>