Compare commits

...

38 commits

Author SHA1 Message Date
Neel Doshi
0e980e9dfb
Merge ffae85b18c into 0024e72a2e 2025-05-03 17:41:46 +00:00
translatewiki.net
0024e72a2e
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-05-01 14:01:50 +02:00
translatewiki.net
60aca9a5e3
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-04-28 14:01:51 +02:00
translatewiki.net
d0f6c16878
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-04-24 14:02:11 +02:00
Yusuke Matsubara
8fded5ef6e
Change back some variable names that were accidentally changed (#6297) 2025-04-24 20:16:03 +09:00
Yusuke Matsubara
329a68216e
Improve credit line in image list (#6295)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
- When author is not uploader, show both.
- When failing to parse author from HTML, use structured data.
2025-04-23 23:23:09 +09:00
translatewiki.net
30762971db
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-04-21 14:01:47 +02:00
Khushbu Khemchandani
7479d96675
Code Enhancement (Explore Map) (#6293)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
* Exclude past locations (P585) from Nearby query

* "Send" button text should be white

* Custom picker: logic

* Revert back changes

* Enhancement :- Explore Map information

* Enhancement :- Explore Map information

* Style

---------

Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
2025-04-21 14:49:15 +09:00
translatewiki.net
ed42d85f67
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-04-17 14:01:53 +02:00
Sonal Yadav
78d29bcf20
FIX : Custom picker detect images that is already in commons (#6288)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
* Fix: Exclude specific text from being posted in WikidataFeedback

* Add detection logic for images already on Commons in custom picker
2025-04-15 13:53:26 +10:00
Ritika Pahwa
1a13cb3383
Add v5.3.0 to CHANGELOG.md
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-15 02:43:33 +05:30
Khushbu Khemchandani
9289dcc42c
UI enhancement Issue(#6285) (#6287)
* Exclude past locations (P585) from Nearby query

* "Send" button text should be white
2025-04-14 22:58:28 +09:00
translatewiki.net
efdc9c5548
Localisation updates from https://translatewiki.net.
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-14 14:01:44 +02:00
Khushbu Khemchandani
69b3544107
Exclude past locations (P585) from Nearby query (#6284)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-14 10:54:29 +09:00
Ritika Pahwa
5b5aeead88
Bump up version code to 1050
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-13 13:09:19 +05:30
Prinuel
4bacac1f8b
BookmarkLocationsFragment.kt:fix android studio warnings for this file, : Eliminated three unused imports, and changed calls to object: FilePicker.HandleActivityResult to use lamda (#6283)
Co-authored-by: bethel-m <bethelcletus87@gmail.com>
2025-04-13 14:39:14 +09:00
samimshoaib01
6aeb3c07cc
ui: make recenter FAB theme-aware using Material attributes (#6281)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-12 21:05:42 +05:30
Sonal Yadav
2c41176a6e
Mark for closed locations (P3999) in Nearby (#6273)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
* Exclude closed locations (P3999) from Nearby query

* feat: Show  for P3999 items (official closure)

* revert changes

* Add P3999 (date of closure) support for non-existent places

* Typo fixing

* fix-typo

* .

---------

Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
2025-04-11 18:00:47 +09:00
translatewiki.net
e3dd00bcfa
Localisation updates from https://translatewiki.net.
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-10 14:01:48 +02:00
Jason-Whitmore
262efe4d8c
ExploreMapFragment.java: fix removeMarker() to remove the correct marker (#6279)
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
Before this change, the removeMarker() method would determine the correct overlay to remove
by comparing an overlay's Place coordinates with the target BaseMarker's Place coordinates.
If two different markers had the same Place coordinates, the incorrect marker would be removed,
leading to more than one green label appearing on the screen.

After this change, the removeMarker() method now compares an overlay's title with the BaseMarker's
Place name. removeMarker() will work properly as long as all BaseMarker's Place names are unique.
Also, null checks were added to removeMarker().
2025-04-10 14:19:31 +09:00
Dmitry Brant
2eed441462
Enable EmailAuth support. (#6277)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-04-08 20:59:28 +09:00
translatewiki.net
56fa8ceb5a
Localisation updates from https://translatewiki.net.
Some checks are pending
Android CI / Run tests and generate APK (push) Waiting to run
2025-04-07 14:01:50 +02:00
Rohit Verma
7bf9276d1a
fix: resolve IndexOutOfBounds error when removing images from top card (#6124)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
replace deprecated onBackPressed with onBackPressedCallback

remove unit test for deprecated onBackPressed method

remove if-check before deleting picture to prevent hiding top thumbnail card

hide the thumbnail card on fragments other than MediaDetailFragment

Co-authored-by: Nicolas Raoul <nicolas.raoul@gmail.com>
2025-04-05 22:47:27 +09:00
Prinuel
51da9e4dd6
FooterAdapter.kt: changed enum access of FooterItem, from FooterItem.values to FooterItem.entries, this is the more efficient way of accessing Enum values as introduced in kotlin 1.9 (#6271)
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
Co-authored-by: bethel-m <bethelcletus87@gmail.com>
2025-04-03 21:10:41 +09:00
translatewiki.net
731ff62faf
Localisation updates from https://translatewiki.net. 2025-04-03 14:01:45 +02:00
translatewiki.net
fdfd7781e9
Localisation updates from https://translatewiki.net.
Some checks failed
Android CI / Run tests and generate APK (push) Has been cancelled
2025-03-31 14:01:52 +02:00
Jason-Whitmore
6e090c8d7a
ExploreMapFragment.java: fix marker labels in Explore map fragment to display the username (#6260)
Before this change, the labels that would appear on the marker when tapped did not include
the author or username. Instead, it displayed "Unknown".

After this change, the labels now display the author name. If the author name is not
available, the username will be displayed. If both are unavailable, the default value
of "Unknown" will be displayed. To improve the readability of the text, any HTML text
is removed from the username/author.
2025-03-31 17:49:06 +09:00
Ritika Pahwa
44966645ca
Add v5.2.0 to CHANGELOG.md 2025-03-29 13:21:03 +05:30
translatewiki.net
669f3043ae
Localisation updates from https://translatewiki.net. 2025-03-27 13:01:54 +01:00
translatewiki.net
5a5e660a43
Localisation updates from https://translatewiki.net. 2025-03-24 13:01:43 +01:00
Ritika Pahwa
2e05a58e8b
Bump up version code to 1049 2025-03-22 14:07:51 +05:30
translatewiki.net
f1f4e8baff
Localisation updates from https://translatewiki.net. 2025-03-20 13:01:41 +01:00
Sonal Yadav
828f69fc46
Update Privacy Policy Link to GitHub.io (#6255)
* "moved privacy policy"

* Update PRIVACY_POLICY_URL to https://commons-app.github.io/privacy-policy as suggested

* Use BuildConfig.PRIVACY_POLICY_URL in launchPrivacyPolicy function
2025-03-20 07:21:33 +09:00
Ritika Pahwa
954a7aee91
Bump up version code and name (#6250)
* Bump up version code and name

* Remove unintended change
2025-03-18 23:28:19 +09:00
translatewiki.net
fa0bdf5747
Localisation updates from https://translatewiki.net. 2025-03-17 13:01:37 +01:00
Sonal Yadav
67ac92ff57
Fix NullPointerException in onBackPressed() (#6249) 2025-03-17 07:53:58 +09:00
Neel Doshi
ffae85b18c Test : Removed the test which are longer used. 2024-12-26 21:00:02 +05:30
Neel Doshi
614892c5cb Migrated from Rxjava to Retroift, added MVVM Architecture. 2024-12-26 20:21:52 +05:30
88 changed files with 1772 additions and 636 deletions

View file

@ -1,5 +1,46 @@
# Wikimedia Commons for Android
## v5.3.0
### What's changed
* Enable EmailAuth support
* Explore map images no longer show "Unknown"
* Fix crash when removing last two images of multiupload
* Mark ❌ for closed locations (P3999) in Nearby
* Fix two pin labels staying visible at the same time in Explore map
* Refactoring and minor UI improvements
## v5.2.0
v5.2.0 boasts several new functionalities like:
* A new refresh button lets you quickly reload the Nearby map
* Bookmarks now support categories
* Improved feedback and consistency in the user interface
* Bug fixes and performance improvements
### What's changed
* Implement "Refresh" button to clear the cache and reload the Nearby map.
* `CommonsApplication` migrate to kotlin & some lint fixes.
* Revert back to MainScope for database and UI updates and make database operations thread safe.
* Hide edit options for logged-out users in Explore screen.
* Introduced a button to delete the current folder in custom selector.
* Improve Unique File Name Search.
* Migration of several modules from Java to Kotlin.
* Fix modification on bottom sheet's data when coming from Nearby Banner and clicked on other pins.
* Bug fixes and enhancement of Achievements screen.
* Show where file is being used on Commons and other wikis.
* Migrate android.media.ExifInterface to androidx.exifinterface.media.ExifInterface as android.media.ExifInterface had security flaws on older devices.
* Make dialogs modal and always show the upload icon.
* Fix unintentional deletion of subfolders and non-images by custom selector.
* Bookmark categories.
* Add pull down to refresh in the Contributions screen.
* Fix race condition and lag when loading pin details, faster overlay management.
* Show cached pins in Nearby even when internet is unavailable
Full changelog with the list of contributors: [`v5.1.2...v5.2.0`](https://github.com/commons-app/apps-android-commons/compare/v5.1.2...v5.2.0).
## v5.1.2
### What's changed

View file

@ -53,11 +53,26 @@ dependencies {
implementation 'androidx.compose.ui:ui-tooling-preview'
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
def lifecycle_version = "2.8.7"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// ViewModel utilities for Compose
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
// Lifecycle utilities for Compose
implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// Annotation processor
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// Jetpack Compose
def composeBom = platform('androidx.compose:compose-bom:2024.11.00')
implementation "androidx.activity:activity-compose:1.9.3"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.4"
implementation (composeBom)
implementation "androidx.compose.runtime:runtime"
implementation "androidx.compose.ui:ui"
@ -212,8 +227,8 @@ android {
defaultConfig {
//applicationId 'fr.free.nrw.commons'
versionCode 1046
versionName '5.1.3'
versionCode 1050
versionName '5.3.0'
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
minSdkVersion 21
@ -318,7 +333,7 @@ android {
buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\""
buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes\""
buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.org/wiki/Special:PasswordReset\""
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\""
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\""
buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\""
buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons\""
buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.contributions.contentprovider\""
@ -333,6 +348,7 @@ android {
buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\""
buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\""
buildConfigField "String", "DEPICTS_PROPERTY", "\"P180\""
buildConfigField "String", "CREATOR_PROPERTY", "\"P170\""
dimension 'tier'
}
@ -355,7 +371,7 @@ android {
buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\""
buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Main_Page&welcome=yes\""
buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/Special:PasswordReset\""
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\""
buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\""
buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\""
buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons.beta\""
buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.beta.contributions.contentprovider\""
@ -370,6 +386,7 @@ android {
buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\""
buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\""
buildConfigField "String", "DEPICTS_PROPERTY", "\"P245962\""
buildConfigField "String", "CREATOR_PROPERTY", "\"P253075\""
dimension 'tier'
}
}

View file

@ -53,6 +53,7 @@ class Media constructor(
*/
var author: String? = null,
var user: String? = null,
var creatorName: String? = null,
/**
* Gets the categories the file falls under.
* @return file categories as an ArrayList of Strings
@ -66,6 +67,7 @@ class Media constructor(
var captions: Map<String, String> = emptyMap(),
var descriptions: Map<String, String> = emptyMap(),
var depictionIds: List<String> = emptyList(),
var creatorIds: List<String> = emptyList(),
/**
* This field was added to find non-hidden categories
* Stores the mapping of category title to hidden attribute
@ -130,6 +132,7 @@ class Media constructor(
* returns user
* @return Author or User
*/
@Deprecated("Use user for uploader username. Use attributedAuthor() for attribution. Note that the uploader may not be the creator/author.")
fun getAuthorOrUser(): String? {
return if (!author.isNullOrEmpty()) {
author
@ -138,6 +141,19 @@ class Media constructor(
}
}
/**
* Returns author if it's not null or empty, otherwise
* returns creator name
* @return name of author or creator
*/
fun getAttributedAuthor(): String? {
return if (!author.isNullOrEmpty()) {
author
} else{
creatorName
}
}
/**
* Gets media display title
* @return Media title

View file

@ -1,7 +1,7 @@
package fr.free.nrw.commons
import androidx.core.text.HtmlCompat
import fr.free.nrw.commons.media.IdAndCaptions
import fr.free.nrw.commons.media.IdAndLabels
import fr.free.nrw.commons.media.MediaClient
import fr.free.nrw.commons.media.PAGE_ID_PREFIX
import io.reactivex.Single
@ -29,7 +29,17 @@ class MediaDataExtractor
it
.entities()
.mapValues { entry -> entry.value.labels().mapValues { it.value.value() } }
}.map { it.map { (key, value) -> IdAndCaptions(key, value) } }
}.map { it.map { (key, value) -> IdAndLabels(key, value) } }
.onErrorReturn { emptyList() }
fun fetchCreatorIdsAndLabels(media: Media) =
mediaClient
.getEntities(media.creatorIds)
.map {
it
.entities()
.mapValues { entry -> entry.value.labels().mapValues { it.value.value() } }
}.map { it.map { (key, value) -> IdAndLabels(key, value) } }
.onErrorReturn { emptyList() }
fun checkDeletionRequestExists(media: Media) = mediaClient.checkPageExistsUsingTitle("Commons:Deletion_requests/" + media.filename)

View file

@ -65,6 +65,7 @@ class LoginActivity : AccountAuthenticatorActivity() {
private val delegate: AppCompatDelegate by lazy {
AppCompatDelegate.create(this, null)
}
private var lastLoginResult: LoginResult? = null
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -271,6 +272,7 @@ class LoginActivity : AccountAuthenticatorActivity() {
showLoggingProgressBar()
loginClient.doLogin(username,
password,
lastLoginResult,
twoFactorCode,
Locale.getDefault().language,
object : LoginCallback {
@ -280,9 +282,17 @@ class LoginActivity : AccountAuthenticatorActivity() {
onLoginSuccess(loginResult)
}
override fun twoFactorPrompt(caught: Throwable, token: String?) = runOnUiThread {
override fun twoFactorPrompt(loginResult: LoginResult, caught: Throwable, token: String?) = runOnUiThread {
Timber.d("Requesting 2FA prompt")
progressDialog!!.dismiss()
lastLoginResult = loginResult
askUserForTwoFactorAuth()
}
override fun emailAuthPrompt(loginResult: LoginResult, caught: Throwable, token: String?) {
Timber.d("Requesting email auth prompt")
progressDialog!!.dismiss()
lastLoginResult = loginResult
askUserForTwoFactorAuth()
}
@ -341,12 +351,13 @@ class LoginActivity : AccountAuthenticatorActivity() {
progressDialog!!.dismiss()
with(binding!!) {
twoFactorContainer.visibility = View.VISIBLE
twoFactorContainer.hint = getString(if (lastLoginResult is LoginResult.EmailAuthResult) R.string.email_auth_code else R.string._2fa_code)
loginTwoFactor.visibility = View.VISIBLE
loginTwoFactor.requestFocus()
}
val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY)
showMessageAndCancelDialog(R.string.login_failed_2fa_needed)
showMessageAndCancelDialog(getString(if (lastLoginResult is LoginResult.EmailAuthResult) R.string.login_failed_email_auth_needed else R.string.login_failed_2fa_needed))
}
@VisibleForTesting

View file

@ -32,7 +32,7 @@ class CsrfTokenClient(
try {
if (retry > 0) {
// Log in explicitly
loginClient.loginBlocking(userName, password, "")
loginClient.loginBlocking(userName, password)
}
// Get CSRFToken response off the main thread.
@ -92,6 +92,8 @@ class CsrfTokenClient(
override fun failure(caught: Throwable?) = retryWithLogin(cb) { caught }
override fun twoFactorPrompt() = cb.twoFactorPrompt()
override fun emailAuthPrompt() = cb.emailAuthPrompt()
},
)
@ -165,10 +167,17 @@ class CsrfTokenClient(
}
override fun twoFactorPrompt(
loginResult: LoginResult,
caught: Throwable,
token: String?,
) = callback.twoFactorPrompt()
override fun emailAuthPrompt(
loginResult: LoginResult,
caught: Throwable,
token: String?,
) = callback.emailAuthPrompt()
// Should not happen here, but call the callback just in case.
override fun passwordResetPrompt(token: String?) = callback.failure(LoginFailedException("Logged in with temporary password."))
@ -190,6 +199,8 @@ class CsrfTokenClient(
fun failure(caught: Throwable?)
fun twoFactorPrompt()
fun emailAuthPrompt()
}
companion object {

View file

@ -4,6 +4,13 @@ interface LoginCallback {
fun success(loginResult: LoginResult)
fun twoFactorPrompt(
loginResult: LoginResult,
caught: Throwable,
token: String?,
)
fun emailAuthPrompt(
loginResult: LoginResult,
caught: Throwable,
token: String?,
)

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.auth.login
import android.text.TextUtils
import fr.free.nrw.commons.auth.login.LoginResult.EmailAuthResult
import fr.free.nrw.commons.auth.login.LoginResult.OAuthResult
import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
import fr.free.nrw.commons.wikidata.WikidataConstants.WIKIPEDIA_URL
@ -51,6 +52,7 @@ class LoginClient(
password,
null,
null,
null,
response.body()!!.query()!!.loginToken(),
userLanguage,
cb,
@ -75,6 +77,7 @@ class LoginClient(
password: String,
retypedPassword: String?,
twoFactorCode: String?,
emailAuthCode: String?,
loginToken: String?,
userLanguage: String,
cb: LoginCallback,
@ -82,7 +85,7 @@ class LoginClient(
this.userLanguage = userLanguage
loginCall =
if (twoFactorCode.isNullOrEmpty() && retypedPassword.isNullOrEmpty()) {
if (twoFactorCode.isNullOrEmpty() && emailAuthCode.isNullOrEmpty() && retypedPassword.isNullOrEmpty()) {
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
} else {
loginInterface.postLogIn(
@ -90,6 +93,7 @@ class LoginClient(
password,
retypedPassword,
twoFactorCode,
emailAuthCode,
loginToken,
userLanguage,
true,
@ -112,10 +116,18 @@ class LoginClient(
when (loginResult) {
is OAuthResult ->
cb.twoFactorPrompt(
loginResult,
LoginFailedException(loginResult.message),
loginToken,
)
is EmailAuthResult ->
cb.emailAuthPrompt(
loginResult,
LoginFailedException(loginResult.message),
loginToken
)
is ResetPasswordResult -> cb.passwordResetPrompt(loginToken)
is LoginResult.Result ->
@ -147,6 +159,7 @@ class LoginClient(
fun doLogin(
username: String,
password: String,
lastLoginResult: LoginResult?,
twoFactorCode: String,
userLanguage: String,
loginCallback: LoginCallback,
@ -159,7 +172,10 @@ class LoginClient(
) = if (response.isSuccessful) {
val loginToken = response.body()?.query()?.loginToken()
loginToken?.let {
login(username, password, null, twoFactorCode, it, userLanguage, loginCallback)
login(username, password, null,
if (lastLoginResult is OAuthResult) twoFactorCode else null,
if (lastLoginResult is EmailAuthResult) twoFactorCode else null,
it, userLanguage, loginCallback)
} ?: run {
loginCallback.error(IOException("Failed to retrieve login token"))
}
@ -181,7 +197,8 @@ class LoginClient(
fun loginBlocking(
userName: String,
password: String,
twoFactorCode: String?,
twoFactorCode: String? = null,
emailAuthCode: String? = null
) {
val tokenResponse = getLoginToken().execute()
if (tokenResponse
@ -195,7 +212,7 @@ class LoginClient(
val loginToken = tokenResponse.body()?.query()?.loginToken()
val tempLoginCall =
if (twoFactorCode.isNullOrEmpty()) {
if (twoFactorCode.isNullOrEmpty() && emailAuthCode.isNullOrEmpty()) {
loginInterface.postLogIn(userName, password, loginToken, userLanguage, WIKIPEDIA_URL)
} else {
loginInterface.postLogIn(
@ -203,6 +220,7 @@ class LoginClient(
password,
null,
twoFactorCode,
emailAuthCode,
loginToken,
userLanguage,
true,
@ -214,7 +232,7 @@ class LoginClient(
val loginResult = loginResponse.toLoginResult(password) ?: throw IOException("Unexpected response when logging in.")
if ("UI" == loginResult.status) {
if (loginResult is OAuthResult) {
if (loginResult is OAuthResult || loginResult is EmailAuthResult) {
// TODO: Find a better way to boil up the warning about 2FA
throw LoginFailedException(loginResult.message)
}

View file

@ -35,7 +35,8 @@ interface LoginInterface {
@Field("password") pass: String?,
@Field("retype") retypedPass: String?,
@Field("OATHToken") twoFactorCode: String?,
@Field("logintoken") token: String?,
@Field("token") emailAuthToken: String?,
@Field("logintoken") loginToken: String?,
@Field("uselang") userLanguage: String?,
@Field("logincontinue") loginContinue: Boolean,
): Call<LoginResponse?>

View file

@ -2,6 +2,7 @@ package fr.free.nrw.commons.auth.login
import com.google.gson.annotations.SerializedName
import fr.free.nrw.commons.auth.login.LoginResult.OAuthResult
import fr.free.nrw.commons.auth.login.LoginResult.EmailAuthResult
import fr.free.nrw.commons.auth.login.LoginResult.ResetPasswordResult
import fr.free.nrw.commons.auth.login.LoginResult.Result
import fr.free.nrw.commons.wikidata.mwapi.MwServiceError
@ -27,11 +28,13 @@ internal class ClientLogin {
fun toLoginResult(password: String): LoginResult {
var userMessage = message
if ("UI" == status) {
if (requests != null) {
for (req in requests) {
if ("MediaWiki\\Extension\\OATHAuth\\Auth\\TOTPAuthenticationRequest" == req.id()) {
requests?.forEach { request ->
request.id()?.let {
if (it.endsWith("TOTPAuthenticationRequest")) {
return OAuthResult(status, userName, password, message)
} else if ("MediaWiki\\Auth\\PasswordAuthenticationRequest" == req.id()) {
} else if (it.endsWith("EmailAuthAuthenticationRequest")) {
return EmailAuthResult(status, userName, password, message)
} else if (it.endsWith("PasswordAuthenticationRequest")) {
return ResetPasswordResult(status, userName, password, message)
}
}
@ -49,7 +52,7 @@ internal class Request {
private val required: String? = null
private val provider: String? = null
private val account: String? = null
private val fields: Map<String, RequestField>? = null
internal val fields: Map<String, RequestField>? = null
fun id(): String? = id
}
@ -57,5 +60,5 @@ internal class Request {
internal class RequestField {
private val type: String? = null
private val label: String? = null
private val help: String? = null
internal val help: String? = null
}

View file

@ -24,6 +24,13 @@ sealed class LoginResult(
message: String?,
) : LoginResult(status, userName, password, message)
class EmailAuthResult(
status: String,
userName: String?,
password: String?,
message: String?,
) : LoginResult(status, userName, password, message)
class ResetPasswordResult(
status: String,
userName: String?,

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.bookmarks.locations
import android.Manifest.permission
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -9,15 +8,12 @@ import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import dagger.android.support.DaggerFragment
import fr.free.nrw.commons.R
import fr.free.nrw.commons.contributions.ContributionController
import fr.free.nrw.commons.databinding.FragmentBookmarksLocationsBinding
import fr.free.nrw.commons.filepicker.FilePicker
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.nearby.fragments.CommonPlaceClickActions
import fr.free.nrw.commons.nearby.fragments.PlaceAdapter
@ -41,9 +37,8 @@ class BookmarkLocationsFragment : DaggerFragment() {
private val cameraPickLauncherForResult =
registerForActivityResult(StartActivityForResult()) { result ->
contributionController.handleActivityResultWithCallback(
requireActivity(),
object: FilePicker.HandleActivityResult {
override fun onHandleActivityResult(callbacks: FilePicker.Callbacks) {
requireActivity()
) { callbacks ->
contributionController.onPictureReturnedFromCamera(
result,
requireActivity(),
@ -51,15 +46,12 @@ class BookmarkLocationsFragment : DaggerFragment() {
)
}
}
)
}
private val galleryPickLauncherForResult =
registerForActivityResult(StartActivityForResult()) { result ->
contributionController.handleActivityResultWithCallback(
requireActivity(),
object: FilePicker.HandleActivityResult {
override fun onHandleActivityResult(callbacks: FilePicker.Callbacks) {
requireActivity()
) { callbacks ->
contributionController.onPictureReturnedFromGallery(
result,
requireActivity(),
@ -67,8 +59,6 @@ class BookmarkLocationsFragment : DaggerFragment() {
)
}
}
)
}
companion object {
fun newInstance(): BookmarkLocationsFragment {

View file

@ -8,23 +8,29 @@ import androidx.appcompat.app.AlertDialog
import androidx.recyclerview.widget.RecyclerView
import com.facebook.imagepipeline.request.ImageRequest
import com.facebook.imagepipeline.request.ImageRequestBuilder
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.utils.MediaAttributionUtil
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.R
import fr.free.nrw.commons.databinding.LayoutContributionBinding
import fr.free.nrw.commons.media.MediaClient
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.io.File
class ContributionViewHolder internal constructor(
private val parent: View, private val callback: ContributionsListAdapter.Callback,
private val mediaClient: MediaClient
parent: View,
private val callback: ContributionsListAdapter.Callback,
private val compositeDisposable: CompositeDisposable,
private val mediaClient: MediaClient,
private val mediaDataExtractor: MediaDataExtractor
) : RecyclerView.ViewHolder(parent) {
var binding: LayoutContributionBinding = LayoutContributionBinding.bind(parent)
private var position = 0
private var contribution: Contribution? = null
private val compositeDisposable = CompositeDisposable()
private var isWikipediaButtonDisplayed = false
private val pausingPopUp: AlertDialog
var imageRequest: ImageRequest? = null
@ -54,7 +60,7 @@ an upload might take a dozen seconds. */
this.contribution = contribution
this.position = position
binding.contributionTitle.text = contribution.media.mostRelevantCaption
binding.authorView.text = contribution.media.getAuthorOrUser()
setAuthorText(contribution.media)
//Removes flicker of loading image.
binding.contributionImage.hierarchy.fadeDuration = 0
@ -93,6 +99,30 @@ an upload might take a dozen seconds. */
checkIfMediaExistsOnWikipediaPage(contribution)
}
fun updateAttribution() {
if (contribution != null) {
val media = contribution!!.media
if (!media.getAttributedAuthor().isNullOrEmpty()) {
return
}
compositeDisposable.addAll(
mediaDataExtractor.fetchCreatorIdsAndLabels(media)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ idAndLabels ->
media.creatorName = MediaAttributionUtil.getCreatorName(idAndLabels)
setAuthorText(media)
},
{ t: Throwable? -> Timber.e(t) })
)
}
}
private fun setAuthorText(media: Media) {
binding.authorView.text = MediaAttributionUtil.getTagLine(media, itemView.context)
}
/**
* Checks if a media exists on the corresponding Wikipedia article Currently the check is made
* for the device's current language Wikipedia

View file

@ -4,21 +4,26 @@ import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.paging.PagedListAdapter
import androidx.recyclerview.widget.DiffUtil
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.R
import fr.free.nrw.commons.media.MediaClient
import io.reactivex.disposables.CompositeDisposable
/**
* Represents The View Adapter for the List of Contributions
*/
class ContributionsListAdapter internal constructor(
private val callback: Callback,
private val mediaClient: MediaClient
private val mediaClient: MediaClient,
private val mediaDataExtractor: MediaDataExtractor,
private val compositeDisposable: CompositeDisposable
) : PagedListAdapter<Contribution, ContributionViewHolder>(DIFF_CALLBACK) {
/**
* Initializes the view holder with contribution data
*/
override fun onBindViewHolder(holder: ContributionViewHolder, position: Int) {
holder.init(position, getItem(position))
holder.updateAttribution()
}
fun getContributionForPosition(position: Int): Contribution? {
@ -36,7 +41,7 @@ class ContributionsListAdapter internal constructor(
val viewHolder = ContributionViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.layout_contribution, parent, false),
callback, mediaClient
callback, compositeDisposable, mediaClient, mediaDataExtractor
)
return viewHolder
}

View file

@ -27,6 +27,7 @@ import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver
import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener
import androidx.recyclerview.widget.SimpleItemAnimator
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.R
import fr.free.nrw.commons.Utils
import fr.free.nrw.commons.auth.SessionManager
@ -63,6 +64,10 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
@Inject
var mediaClient: MediaClient? = null
@JvmField
@Inject
var mediaDataExtractor: MediaDataExtractor? = null
@JvmField
@Named(NetworkingModule.NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
@Inject
@ -231,7 +236,7 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
}
private fun initAdapter() {
adapter = ContributionsListAdapter(this, mediaClient!!)
adapter = ContributionsListAdapter(this, mediaClient!!, mediaDataExtractor!!, compositeDisposable)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -387,37 +387,42 @@ after opening the app.
}
override fun onBackPressed() {
if (contributionsFragment != null && activeFragment == ActiveFragment.CONTRIBUTIONS) {
when (activeFragment) {
ActiveFragment.CONTRIBUTIONS -> {
// Means that contribution fragment is visible
if (!contributionsFragment!!.backButtonClicked()) { //If this one does not wan't to handle
if (contributionsFragment?.backButtonClicked() != true) { //If this one does not want to handle
// the back press, let the activity do so
super.onBackPressed()
}
} else if (nearbyParentFragment != null && activeFragment == ActiveFragment.NEARBY) {
}
ActiveFragment.NEARBY -> {
// Means that nearby fragment is visible
/* If function nearbyParentFragment.backButtonClick() returns false, it means that the bottomsheet is
not expanded. So if the back button is pressed, then go back to the Contributions tab */
if (!nearbyParentFragment!!.backButtonClicked()) {
supportFragmentManager.beginTransaction().remove(nearbyParentFragment!!)
.commit()
if (nearbyParentFragment?.backButtonClicked() != true) {
nearbyParentFragment?.let {
supportFragmentManager.beginTransaction().remove(it).commit()
}
setSelectedItemId(NavTab.CONTRIBUTIONS.code())
}
} else if (exploreFragment != null && activeFragment == ActiveFragment.EXPLORE) {
// Means that explore fragment is visible
if (!exploreFragment!!.onBackPressed()) {
if (applicationKvStore!!.getBoolean("login_skipped")) {
}
ActiveFragment.EXPLORE -> {
// Explore Fragment is visible
if (exploreFragment?.onBackPressed() != true) {
if (applicationKvStore?.getBoolean("login_skipped") == true) {
super.onBackPressed()
} else {
setSelectedItemId(NavTab.CONTRIBUTIONS.code())
}
}
} else if (bookmarkFragment != null && activeFragment == ActiveFragment.BOOKMARK) {
}
ActiveFragment.BOOKMARK -> {
// Means that bookmark fragment is visible
bookmarkFragment!!.onBackPressed()
} else {
bookmarkFragment?.onBackPressed()
}
else -> {
super.onBackPressed()
}
}
}
override fun onBackStackChanged() {
//initBackButton();

View file

@ -26,6 +26,7 @@ import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.TreeMap
import kotlin.collections.ArrayList
@ -342,46 +343,37 @@ class ImageAdapter(
numberOfSelectedImagesMarkedAsNotForUpload--
}
notifyItemChanged(position, ImageUnselected())
// Getting index from all images index when switch is on
val indexes =
if (showAlreadyActionedImages) {
ImageHelper.getIndexList(selectedImages, images)
// Getting index from actionable images when switch is off
} else {
ImageHelper.getIndexList(selectedImages, ArrayList(actionableImagesMap.values))
}
for (index in indexes) {
notifyItemChanged(index, ImageSelectedOrUpdated())
}
} else {
val image = images[position]
scope.launch(ioDispatcher) {
val imageSHA1 = imageLoader.getSHA1(image, defaultDispatcher)
withContext(Dispatchers.Main) {
if (holder.isItemUploaded()) {
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
} else {
return@withContext
}
if (imageSHA1.isNotEmpty() && imageLoader.getFromUploaded(imageSHA1) != null) {
holder.itemUploaded()
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
return@withContext
}
if (!holder.isItemUploaded() && imageSHA1.isNotEmpty() && imageLoader.getFromUploaded(imageSHA1) != null) {
Toast.makeText(context, R.string.custom_selector_already_uploaded_image_text, Toast.LENGTH_SHORT).show()
}
if (holder.isItemNotForUpload()) {
numberOfSelectedImagesMarkedAsNotForUpload++
}
selectedImages.add(image)
notifyItemChanged(position, ImageSelectedOrUpdated())
// Getting index from all images index when switch is on
val indexes: ArrayList<Int> =
if (showAlreadyActionedImages) {
selectedImages.add(images[position])
ImageHelper.getIndexList(selectedImages, images)
// Getting index from actionable images when switch is off
} else {
selectedImages.add(ArrayList(actionableImagesMap.values)[position])
ImageHelper.getIndexList(selectedImages, ArrayList(actionableImagesMap.values))
}
for (index in indexes) {
notifyItemChanged(index, ImageSelectedOrUpdated())
}
}
}
imageSelectListener.onSelectedImagesChanged(selectedImages, numberOfSelectedImagesMarkedAsNotForUpload)
}
}
}
}
/**
* Initialize the data set.

View file

@ -638,17 +638,20 @@ class CustomSelectorActivity :
finishPickImages(arrayListOf())
return
}
var i = 0
while (i < selectedImages.size) {
val path = selectedImages[i].path
val file = File(path)
if (!file.exists()) {
selectedImages.removeAt(i)
i--
scope.launch(ioDispatcher) {
val uniqueImages = selectedImages.distinctBy { image ->
CustomSelectorUtils.getImageSHA1(
image.uri,
ioDispatcher,
fileUtilsWrapper,
contentResolver
)
}
withContext(Dispatchers.Main) {
finishPickImages(ArrayList(uniqueImages))
}
i++
}
finishPickImages(selectedImages)
}
/**

View file

@ -25,6 +25,7 @@ import fr.free.nrw.commons.media.PageMediaInterface
import fr.free.nrw.commons.media.WikidataMediaInterface
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
import fr.free.nrw.commons.mwapi.UserInterface
import fr.free.nrw.commons.network.APIService
import fr.free.nrw.commons.notification.NotificationInterface
import fr.free.nrw.commons.review.ReviewInterface
import fr.free.nrw.commons.upload.UploadInterface
@ -42,6 +43,8 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Level
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import timber.log.Timber
import java.io.File
import java.util.concurrent.TimeUnit
@ -295,6 +298,32 @@ class NetworkingModule {
fun provideLanguageWikipediaSite(): WikiSite =
WikiSite.forDefaultLocaleLanguageCode()
@Provides
@Named("tool_wmflabs_base_url")
fun provideToolWmflabsBaseUrl() : HttpUrl =
"https://tools.wmflabs.org/commons-android-app/tool-commons-android-app/".toHttpUrlOrNull()!!
@Singleton
@Provides
@Named("tool_wmflabs_retrofit")
fun provideToolWmflabsBaseUrlRetrofit(
@Named("tool_wmflabs_base_url") baseUrl: HttpUrl,
okHttpClient: OkHttpClient
) : Retrofit {
return Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
// .addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
}
@Provides
@Singleton
fun provideAPIService(
@Named("tool_wmflabs_retrofit") retrofit: Retrofit
): APIService = retrofit.create(APIService::class.java)
companion object {
private const val WIKIDATA_SPARQL_QUERY_URL = "https://query.wikidata.org/sparql"
private const val TOOLS_FORGE_URL =

View file

@ -708,8 +708,29 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
GeoPoint point = new GeoPoint(
nearbyBaseMarker.getPlace().location.getLatitude(),
nearbyBaseMarker.getPlace().location.getLongitude());
OverlayItem item = new OverlayItem(nearbyBaseMarker.getPlace().name, null,
point);
Media markerMedia = this.getMediaFromImageURL(nearbyBaseMarker.getPlace().pic);
String authorUser = null;
if (markerMedia != null) {
authorUser = markerMedia.getAuthorOrUser();
// HTML text is sometimes part of the author string and needs to be removed
authorUser = Html.fromHtml(authorUser, Html.FROM_HTML_MODE_LEGACY).toString();
}
String title = nearbyBaseMarker.getPlace().name;
// Remove "File:" if present at start
if (title.startsWith("File:")) {
title = title.substring(5);
}
// Remove extensions like .jpg, .jpeg, .png, .svg (case insensitive)
title = title.replaceAll("(?i)\\.(jpg|jpeg|png|svg)$", "");
title = title.replace("_", " ");
//Truncate if too long because it doesn't fit the screen
if (title.length() > 43) {
title = title.substring(0, 40) + "";
}
OverlayItem item = new OverlayItem(title, authorUser, point);
item.setMarker(d);
items.add(item);
ItemizedOverlayWithFocus overlay = new ItemizedOverlayWithFocus(items,
@ -740,13 +761,37 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
}
}
/**
* Retrieves the specific Media object from the mediaList field.
* @param url The specific Media's image URL.
* @return The Media object that matches the URL or null if it could not be found.
*/
private Media getMediaFromImageURL(String url) {
if (mediaList == null || url == null) {
return null;
}
for (int i = 0; i < mediaList.size(); i++) {
if (mediaList.get(i) != null && mediaList.get(i).getImageUrl() != null
&& mediaList.get(i).getImageUrl().equals(url)) {
return mediaList.get(i);
}
}
return null;
}
/**
* Removes a marker from the map based on the specified NearbyBaseMarker.
*
* @param nearbyBaseMarker The NearbyBaseMarker object representing the marker to be removed.
*/
private void removeMarker(BaseMarker nearbyBaseMarker) {
Place place = nearbyBaseMarker.getPlace();
if (nearbyBaseMarker == null || nearbyBaseMarker.getPlace().getName() == null) {
return;
}
String target = nearbyBaseMarker.getPlace().getName();
List<Overlay> overlays = binding.mapView.getOverlays();
ItemizedOverlayWithFocus item;
@ -755,8 +800,7 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment
item = (ItemizedOverlayWithFocus) overlays.get(i);
OverlayItem overlayItem = item.getItem(0);
if (place.location.getLatitude() == overlayItem.getPoint().getLatitude()
&& place.location.getLongitude() == overlayItem.getPoint().getLongitude()) {
if (overlayItem.getTitle().equals(target)) {
binding.mapView.getOverlays().remove(i);
binding.mapView.invalidate();
break;

View file

@ -18,6 +18,12 @@ import javax.inject.Inject
class MediaConverter
@Inject
constructor() {
/**
* Creating Media object from MWQueryPage.
*
* @param page response from the API
* @return Media object
*/
fun convert(
page: MwQueryPage,
entity: Entities.Entity,
@ -40,24 +46,17 @@ class MediaConverter
metadata.prefixedLicenseUrl,
getAuthor(metadata),
imageInfo.getUser(),
null,
MediaDataExtractorUtil.extractCategoriesFromList(metadata.categories()),
metadata.latLng,
entity.labels().mapValues { it.value.value() },
entity.descriptions().mapValues { it.value.value() },
entity.depictionIds(),
entity.creatorIds(),
myMap,
)
}
/**
* Creating Media object from MWQueryPage.
* Earlier only basic details were set for the media object but going forward,
* a full media object(with categories, descriptions, coordinates etc) can be constructed using this method
*
* @param page response from the API
* @return Media object
*/
private fun safeParseDate(dateStr: String): Date? =
try {
CommonsDateUtil.getMediaSimpleDateFormat().parse(dateStr)
@ -66,24 +65,32 @@ class MediaConverter
}
/**
* This method extracts the Commons Username from the artist HTML information
* This method extracts the Commons Username from the artist HTML information.
* When the HTML is in customized formatting, it may fail to parse and return null.
* @param metadata
* @return
*/
private fun getAuthor(metadata: ExtMetadata): String? {
return try {
val authorHtml = metadata.artist()
val anchorStartTagTerminalChars = "\">"
val anchorStartTagTerminalString = "\">"
val anchorCloseTag = "</a>"
return authorHtml.substring(
authorHtml.indexOf(anchorStartTagTerminalChars) +
anchorStartTagTerminalChars
.length,
return if (!authorHtml.contains("<") && !authorHtml.contains(">") ) {
authorHtml.trim()
} else if (!authorHtml.contains(anchorStartTagTerminalString) || !authorHtml.endsWith(anchorCloseTag)) {
null
} else {
val authorText = authorHtml.substring(
authorHtml.indexOf(anchorStartTagTerminalString) +
anchorStartTagTerminalString.length,
authorHtml.indexOf(anchorCloseTag),
)
} catch (ex: java.lang.Exception) {
""
if (authorText.contains("<") || authorText.contains(">")) {
null
} else {
authorText
}
}
}
}
@ -92,6 +99,10 @@ private fun Entities.Entity.depictionIds() =
this[WikidataProperties.DEPICTS]?.mapNotNull { (it.mainSnak.dataValue as? DataValue.EntityId)?.value?.id }
?: emptyList()
private fun Entities.Entity.creatorIds() =
this[WikidataProperties.CREATOR]?.mapNotNull { (it.mainSnak.dataValue as? DataValue.EntityId)?.value?.id }
?: emptyList()
private val ExtMetadata.prefixedLicenseUrl: String
get() =
licenseUrl().let {

View file

@ -4,16 +4,18 @@ import android.content.Context
import android.os.Bundle
import android.view.View
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.R
import fr.free.nrw.commons.category.CategoryImagesCallback
import fr.free.nrw.commons.explore.paging.BasePagingFragment
import fr.free.nrw.commons.media.MediaDetailPagerFragment.MediaDetailProvider
import javax.inject.Inject
abstract class PageableMediaFragment :
BasePagingFragment<Media>(),
MediaDetailProvider {
override val pagedListAdapter by lazy {
PagedMediaAdapter(categoryImagesCallback::onMediaClicked)
PagedMediaAdapter(categoryImagesCallback::onMediaClicked, mediaDataExtractor)
}
override val errorTextId: Int = R.string.error_loading_images
@ -22,6 +24,9 @@ abstract class PageableMediaFragment :
lateinit var categoryImagesCallback: CategoryImagesCallback
@Inject
lateinit var mediaDataExtractor: MediaDataExtractor
override fun onAttach(context: Context) {
super.onAttach(context)
if (parentFragment != null) {

View file

@ -5,13 +5,22 @@ import android.view.ViewGroup
import androidx.paging.PagedListAdapter
import androidx.recyclerview.widget.DiffUtil
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.utils.MediaAttributionUtil
import fr.free.nrw.commons.R
import fr.free.nrw.commons.databinding.LayoutCategoryImagesBinding
import fr.free.nrw.commons.explore.paging.BaseViewHolder
import fr.free.nrw.commons.explore.paging.inflate
import fr.free.nrw.commons.media.IdAndLabels
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
class PagedMediaAdapter(
private val onImageClicked: (Int) -> Unit,
private val mediaDataExtractor: MediaDataExtractor,
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
) : PagedListAdapter<Media, SearchImagesViewHolder>(
object : DiffUtil.ItemCallback<Media>() {
override fun areItemsTheSame(
@ -25,6 +34,7 @@ class PagedMediaAdapter(
) = oldItem.pageId == newItem.pageId
},
) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
@ -37,7 +47,24 @@ class PagedMediaAdapter(
holder: SearchImagesViewHolder,
position: Int,
) {
holder.bind(getItem(position)!! to position)
val media = getItem(position) ?: return
holder.bind(media to position)
if (!media.getAttributedAuthor().isNullOrEmpty()) {
return
}
compositeDisposable.addAll(
mediaDataExtractor.fetchCreatorIdsAndLabels(media)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ idAndLabels ->
media.creatorName = MediaAttributionUtil.getCreatorName(idAndLabels);
holder.setAuthorText(media)
},
{ t: Throwable? -> Timber.e(t) })
)
}
}
@ -52,7 +79,10 @@ class SearchImagesViewHolder(
binding.categoryImageView.setOnClickListener { onImageClicked(item.second) }
binding.categoryImageTitle.text = media.mostRelevantCaption
binding.categoryImageView.setImageURI(media.thumbUrl)
binding.categoryImageAuthor.text =
containerView.context.getString(R.string.image_uploaded_by, media.getAuthorOrUser())
setAuthorText(media)
}
fun setAuthorText(media: Media) {
binding.categoryImageAuthor.text = MediaAttributionUtil.getTagLine(media, containerView.context)
}
}

View file

@ -32,7 +32,7 @@ class FooterAdapter(
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
) = when (FooterItem.values()[viewType]) {
) = when (FooterItem.entries[viewType]) {
FooterItem.LoadingItem ->
LoadingViewHolder(
parent.inflate(R.layout.list_item_progress),

View file

@ -1,6 +0,0 @@
package fr.free.nrw.commons.media
data class IdAndCaptions(
val id: String,
val captions: Map<String, String>,
)

View file

@ -0,0 +1,18 @@
package fr.free.nrw.commons.media
data class IdAndLabels(
val id: String,
val labels: Map<String, String>,
) {
// if a label is available in user's locale, return it
// if not then check for english, else show any available.
fun getLocalizedLabel(locale: String): String? {
if (labels[locale] != null) {
return labels[locale]
}
if (labels["en"] != null) {
return labels["en"]
}
return labels.values.firstOrNull() ?: id
}
}

View file

@ -16,7 +16,6 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.ViewTreeObserver.OnGlobalLayoutListener
import android.widget.ArrayAdapter
import android.widget.Button
@ -622,10 +621,9 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ idAndCaptions: List<IdAndCaptions> -> onDepictionsLoaded(idAndCaptions) },
{ idAndCaptions: List<IdAndLabels> -> onDepictionsLoaded(idAndCaptions) },
{ t: Throwable? -> Timber.e(t) })
)
// compositeDisposable.add(disposable);
}
private fun onDiscussionLoaded(discussion: String) {
@ -655,7 +653,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C
}
}
private fun onDepictionsLoaded(idAndCaptions: List<IdAndCaptions>) {
private fun onDepictionsLoaded(idAndCaptions: List<IdAndLabels>) {
binding.depictsLayout.visibility = View.VISIBLE
binding.depictionsEditButton.visibility = View.VISIBLE
buildDepictionList(idAndCaptions)
@ -865,24 +863,24 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C
* Populates media details fragment with depiction list
* @param idAndCaptions
*/
private fun buildDepictionList(idAndCaptions: List<IdAndCaptions>) {
private fun buildDepictionList(idAndCaptions: List<IdAndLabels>) {
binding.mediaDetailDepictionContainer.removeAllViews()
// Create a mutable list from the original list
val mutableIdAndCaptions = idAndCaptions.toMutableList()
if (mutableIdAndCaptions.isEmpty()) {
// Create a placeholder IdAndCaptions object and add it to the list
// Create a placeholder IdAndLabels object and add it to the list
mutableIdAndCaptions.add(
IdAndCaptions(
IdAndLabels(
id = media?.pageId ?: "", // Use an empty string if media?.pageId is null
captions = mapOf(Locale.getDefault().language to getString(R.string.detail_panel_cats_none)) // Create a Map with the language as the key and the message as the value
labels = mapOf(Locale.getDefault().language to getString(R.string.detail_panel_cats_none)) // Create a Map with the language as the key and the message as the value
)
)
}
val locale: String = Locale.getDefault().language
for (idAndCaption: IdAndCaptions in mutableIdAndCaptions) {
for (idAndCaption in mutableIdAndCaptions) {
binding.mediaDetailDepictionContainer.addView(
buildDepictLabel(
getDepictionCaption(idAndCaption, locale),
@ -894,16 +892,16 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C
}
private fun getDepictionCaption(idAndCaption: IdAndCaptions, locale: String): String? {
private fun getDepictionCaption(idAndCaption: IdAndLabels, locale: String): String? {
// Check if the Depiction Caption is available in user's locale
// if not then check for english, else show any available.
if (idAndCaption.captions[locale] != null) {
return idAndCaption.captions[locale]
if (idAndCaption.labels[locale] != null) {
return idAndCaption.labels[locale]
}
if (idAndCaption.captions["en"] != null) {
return idAndCaption.captions["en"]
if (idAndCaption.labels["en"] != null) {
return idAndCaption.labels["en"]
}
return idAndCaption.captions.values.iterator().next()
return idAndCaption.labels.values.iterator().next()
}
private fun onMediaDetailLicenceClicked() {

View file

@ -153,7 +153,10 @@ public class Place implements Parcelable {
.build(),
item.getPic().getValue(),
// Checking if the place exists or not
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == ""), entityId);
(item.getDestroyed().getValue() == "") && (item.getEndTime().getValue() == "")
&& (item.getDateOfOfficialClosure().getValue() == "")
&& (item.getPointInTime().getValue()==""),
entityId);
}
/**

View file

@ -18,6 +18,8 @@ class NearbyResultItem(
@field:SerializedName("description") private val description: ResultTuple?,
@field:SerializedName("endTime") private val endTime: ResultTuple?,
@field:SerializedName("monument") private val monument: ResultTuple?,
@field:SerializedName("dateOfOfficialClosure") private val dateOfOfficialClosure: ResultTuple?,
@field:SerializedName("pointInTime") private val pointInTime: ResultTuple?,
) {
fun getItem(): ResultTuple = item ?: ResultTuple()
@ -41,6 +43,8 @@ class NearbyResultItem(
fun getDestroyed(): ResultTuple = destroyed ?: ResultTuple()
fun getDateOfOfficialClosure(): ResultTuple = dateOfOfficialClosure ?: ResultTuple()
fun getDescription(): ResultTuple = description ?: ResultTuple()
fun getEndTime(): ResultTuple = endTime ?: ResultTuple()
@ -48,4 +52,7 @@ class NearbyResultItem(
fun getAddress(): String = address?.value ?: ""
fun getMonument(): ResultTuple? = monument
fun getPointInTime(): ResultTuple = pointInTime ?: ResultTuple()
}

View file

@ -0,0 +1,23 @@
package fr.free.nrw.commons.network
import fr.free.nrw.commons.profile.model.AchievementResponse
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Query
interface APIService {
// https://tools.wmflabs.org/commons-android-app/tool-commons-android-app/uploadsbyuser.py?user=Devanonymous
@GET("uploadsbyuser.py")
suspend fun getImageUploadCount(
@Query("user") username : String
) : Response<Int>
// https://tools.wmflabs.org/commons-android-app/tool-commons-android-app//feedback.py?user=Devanonymous
@GET("feedback.py")
suspend fun getUserAchievements(
@Query("user") username: String
) : Response<AchievementResponse>
}

View file

@ -0,0 +1,41 @@
package fr.free.nrw.commons.profile.achievements
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import fr.free.nrw.commons.profile.model.UserAchievements
import fr.free.nrw.commons.repository.ProfileRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import javax.inject.Inject
class AchievementViewModel @Inject constructor(
private val repository: ProfileRepository
) : ViewModel() {
private val _achievements = MutableStateFlow(UserAchievements(
LevelController.LevelInfo.LEVEL_1,
articlesUsingImagesCount = 0,
thanksReceivedCount = 0,
featuredImagesCount = 0,
qualityImagesCount = 0,
imagesUploadedCount = 0,
revertedCount = 0,
uniqueImagesCount = 0,
imagesEditedBySomeoneElseCount = 0
)
)
val achievements : StateFlow<UserAchievements> = _achievements
private val _loading = MutableStateFlow(true)
val loading : StateFlow<Boolean> = _loading
fun getUserAchievements(username: String){
viewModelScope.launch {
repository.getUserLevel(username = username).collect {
_loading.value = false
_achievements.value = it
}
}
}
}

View file

@ -0,0 +1,23 @@
package fr.free.nrw.commons.profile.achievements
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import javax.inject.Inject
import javax.inject.Provider
/**
* This class extends the ViewModelProvider.Factory and creates a ViewModelFactory class
* for AchievementViewModel
*/
class AchievementViewModelFactory @Inject constructor(
private val viewModelProvider: Provider<AchievementViewModel>
): ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(AchievementViewModel::class.java)) {
(@Suppress("UNCHECKED_CAST")
return viewModelProvider.get() as T)
} else {
throw IllegalArgumentException("Unknown class name")
}
}
}

View file

@ -1,15 +1,16 @@
package fr.free.nrw.commons.profile.achievements
import android.annotation.SuppressLint
import android.net.Uri
import android.os.Bundle
import android.util.DisplayMetrics
import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.widget.Toast
import androidx.appcompat.view.ContextThemeWrapper
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.badge.BadgeUtils
@ -22,21 +23,20 @@ import fr.free.nrw.commons.di.CommonsDaggerSupportFragment
import fr.free.nrw.commons.kvstore.BasicKvStore
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
import fr.free.nrw.commons.profile.ProfileActivity
import fr.free.nrw.commons.profile.achievements.LevelController.LevelInfo.Companion.from
import fr.free.nrw.commons.utils.ConfigUtils.isBetaFlavour
import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog
import fr.free.nrw.commons.utils.ViewUtil.showDismissibleSnackBar
import fr.free.nrw.commons.utils.ViewUtil.showLongToast
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import org.apache.commons.lang3.StringUtils
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import timber.log.Timber
import java.util.Objects
import javax.inject.Inject
class AchievementsFragment : CommonsDaggerSupportFragment(){
private lateinit var levelInfo: LevelController.LevelInfo
@Inject
lateinit var viewModelFactory: AchievementViewModelFactory
lateinit var viewModel: AchievementViewModel
@Inject
lateinit var sessionManager: SessionManager
@ -45,11 +45,8 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
private var _binding: FragmentAchievementsBinding? = null
private val binding get() = _binding!!
// To keep track of the number of wiki edits made by a user
private var numberOfEdits: Int = 0
private var userName: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
@ -64,6 +61,8 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
): View {
_binding = FragmentAchievementsBinding.inflate(inflater, container, false)
viewModel = ViewModelProvider(
this@AchievementsFragment, viewModelFactory)[AchievementViewModel::class.java]
binding.achievementInfo.setOnClickListener { showInfoDialog() }
binding.imagesUploadInfoIcon.setOnClickListener { showUploadInfo() }
binding.imagesRevertedInfoIcon.setOnClickListener { showRevertedInfo() }
@ -73,19 +72,15 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
binding.thanksImageIcon.setOnClickListener { showThanksReceivedInfo() }
binding.qualityImageIcon.setOnClickListener { showQualityImagesInfo() }
// DisplayMetrics used to fetch the size of the screen
val displayMetrics = DisplayMetrics()
requireActivity().windowManager.defaultDisplay.getMetrics(displayMetrics)
val height = displayMetrics.heightPixels
val width = displayMetrics.widthPixels
// Used for the setting the size of imageView at runtime
// TODO REMOVE
val params = binding.achievementBadgeImage.layoutParams as ConstraintLayout.LayoutParams
params.height = (height * BADGE_IMAGE_HEIGHT_RATIO).toInt()
params.width = (width * BADGE_IMAGE_WIDTH_RATIO).toInt()
binding.achievementBadgeImage.requestLayout()
lifecycleScope.launch {
viewModel.loading.collectLatest {
if (it){
binding.progressBar.visibility = View.VISIBLE
} else {
binding.progressBar.visibility = View.GONE
}
}
}
setHasOptionsMenu(true)
if (sessionManager.userName == null || sessionManager.userName == userName) {
@ -100,8 +95,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
return binding.root
}
setWikidataEditCount()
setAchievements()
return binding.root
@ -145,72 +138,56 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
* which then calls parseJson when results are fetched
*/
@SuppressLint("SetTextI18n")
private fun setAchievements() {
binding.progressBar.visibility = View.VISIBLE
if (checkAccount()) {
try {
compositeDisposable.add(
okHttpJsonApiClient
.getAchievements(userName ?: return)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ response ->
if (response != null) {
setUploadCount(Achievements.from(response))
} else {
Timber.d("Success")
// TODO Create a Method to Hide all the Statistics
// binding.layoutImageReverts.visibility = View.INVISIBLE
// binding.achievementBadgeImage.visibility = View.INVISIBLE
// If the number of edits made by the user are more than 150,000
// in some cases such high number of wiki edit counts cause the
// achievements calculator to fail in some cases, for more details
// refer Issue: #3295
if (numberOfEdits <= 150_000) {
showSnackBarWithRetry(false)
} else {
showSnackBarWithRetry(true)
}
}
},
{ throwable ->
Timber.e(throwable, "Fetching achievements statistics failed")
if (numberOfEdits <= 150_000) {
showSnackBarWithRetry(false)
} else {
showSnackBarWithRetry(true)
}
}
)
)
} catch (e: Exception) {
Timber.d("Exception: ${e.message}")
}
}
}
viewModel.getUserAchievements(username = userName.toString())
/**
* To call the API to fetch the count of wiki data edits
* in the form of JavaRx Single object<JSONobject>
</JSONobject> */
lifecycleScope.launch {
viewModel.achievements.collect{
private fun setWikidataEditCount() {
if (StringUtils.isBlank(userName)) {
return
}
compositeDisposable.add(
okHttpJsonApiClient
.getWikidataEdits(userName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ edits: Int ->
numberOfEdits = edits
showBadgesWithCount(view = binding.wikidataEditsIcon, count = edits)
}, { e: Throwable ->
Timber.e("Error:$e")
})
binding.achievementLevel.text = getString(R.string.level,it.level.levelNumber)
val store = BasicKvStore(requireContext(), userName)
store.putString("userAchievementsLevel", it.level.levelNumber.toString())
binding.achievementBadgeImage.setImageDrawable(
VectorDrawableCompat.create(
resources, R.drawable.badge,
ContextThemeWrapper(activity, it.level.levelStyle).theme
)
)
binding.achievementBadgeText.text = it.level.levelNumber.toString()
// TODO(use String Format)
binding.imageUploadedTVCount.text =
it.imagesUploadedCount.toString() + "/" + it.level.maxUploadCount
binding.imagesUploadedProgressbar.progress =
100 * it.imagesUploadedCount / it.level.maxUploadCount
// Revert
binding.imageRevertTVCount.text = it.revertedCount.toString() + "%"
binding.imageRevertsProgressbar.progress = it.revertedCount
binding.imagesRevertLimitText.text =
resources.getString(R.string.achievements_revert_limit_message) + it.level.minNonRevertPercentage + "%"
// Images Used
binding.imagesUsedProgressbar.progress = (100 * it.uniqueImagesCount) / it.level.maxUniqueImages
binding.imagesUsedCount.text = (it.uniqueImagesCount.toString() + "/"
+ it.level.maxUniqueImages)
// Thanks Received Badge
showBadgesWithCount(view = binding.thanksImageIcon, count = it.thanksReceivedCount)
// Featured Images Badge
showBadgesWithCount(view = binding.featuredImageIcon, count = it.featuredImagesCount)
// Quality Images Badge
showBadgesWithCount(view = binding.qualityImageIcon, count = it.qualityImagesCount)
showBadgesWithCount(view = binding.wikidataEditsIcon, count = it.imagesEditedBySomeoneElseCount)
}
}
}
}
/**
@ -253,49 +230,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
binding.progressBar.visibility = View.GONE
}
/**
* used to the count of images uploaded by user
*/
private fun setUploadCount(achievements: Achievements) {
if (checkAccount()) {
compositeDisposable.add(okHttpJsonApiClient
.getUploadCount(Objects.requireNonNull<String>(userName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ uploadCount: Int? ->
setAchievementsUploadCount(
achievements,
uploadCount ?:0
)
},
{ t: Throwable? ->
Timber.e(t, "Fetching upload count failed")
onError()
}
))
}
}
/**
* used to set achievements upload count and call hideProgressbar
* @param uploadCount
*/
private fun setAchievementsUploadCount(achievements: Achievements, uploadCount: Int) {
// Create a new instance of Achievements with updated imagesUploaded
val updatedAchievements = Achievements(
achievements.uniqueUsedImages,
achievements.articlesUsingImages,
achievements.thanksReceived,
achievements.featuredImages,
achievements.qualityImages,
uploadCount, // Update imagesUploaded with new value
achievements.revertCount
)
hideProgressBar(updatedAchievements)
}
/**
* used to the uploaded images progressbar
@ -306,9 +240,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
setZeroAchievements()
} else {
binding.imagesUploadedProgressbar.visibility = View.VISIBLE
binding.imagesUploadedProgressbar.progress =
100 * uploadCount / levelInfo.maxUploadCount
binding.imageUploadedTVCount.text = uploadCount.toString() + "/" + levelInfo.maxUploadCount
}
}
@ -325,7 +256,7 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
getString(R.string.ok),
{}
)
binding.layout.visibility = View.INVISIBLE
// binding.imagesUploadedProgressbar.setVisibility(View.INVISIBLE);
// binding.imageRevertsProgressbar.setVisibility(View.INVISIBLE);
// binding.imagesUsedByWikiProgressBar.setVisibility(View.INVISIBLE);
@ -335,52 +266,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
binding.imagesUploadTextParam.setText(R.string.no_image_uploaded)
}
/**
* used to set the non revert image percentage
* @param notRevertPercentage
*/
private fun setImageRevertPercentage(notRevertPercentage: Int) {
binding.imageRevertsProgressbar.visibility = View.VISIBLE
binding.imageRevertsProgressbar.progress = notRevertPercentage
val revertPercentage = notRevertPercentage.toString()
binding.imageRevertTVCount.text = "$revertPercentage%"
binding.imagesRevertLimitText.text =
resources.getString(R.string.achievements_revert_limit_message) + levelInfo.minNonRevertPercentage + "%"
}
/**
* Used the inflate the fetched statistics of the images uploaded by user
* and assign badge and level. Also stores the achievements level of the user in BasicKvStore to display in menu
* @param achievements
*/
private fun inflateAchievements(achievements: Achievements) {
// Thanks Received Badge
showBadgesWithCount(view = binding.thanksImageIcon, count = achievements.thanksReceived)
// Featured Images Badge
showBadgesWithCount(view = binding.featuredImageIcon, count = achievements.featuredImages)
// Quality Images Badge
showBadgesWithCount(view = binding.qualityImageIcon, count = achievements.qualityImages)
binding.imagesUsedByWikiProgressBar.progress =
100 * achievements.uniqueUsedImages / levelInfo.maxUniqueImages
binding.imagesUsedCount.text = (achievements.uniqueUsedImages.toString() + "/"
+ levelInfo.maxUniqueImages)
binding.achievementLevel.text = getString(R.string.level,levelInfo.levelNumber)
binding.achievementBadgeImage.setImageDrawable(
VectorDrawableCompat.create(
resources, R.drawable.badge,
ContextThemeWrapper(activity, levelInfo.levelStyle).theme
)
)
binding.achievementBadgeText.text = levelInfo.levelNumber.toString()
val store = BasicKvStore(requireContext(), userName)
store.putString("userAchievementsLevel", levelInfo.levelNumber.toString())
}
/**
* This function is used to show badge on any view (button, imageView, etc)
* @param view The View on which the badge will be displayed eg (button, imageView, etc)
@ -425,22 +310,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
})
}
/**
* to hide progressbar
*/
private fun hideProgressBar(achievements: Achievements) {
if (binding.progressBar != null) {
levelInfo = from(
achievements.imagesUploaded,
achievements.uniqueUsedImages,
achievements.notRevertPercentage
)
inflateAchievements(achievements)
setUploadProgress(achievements.imagesUploaded)
setImageRevertPercentage(achievements.notRevertPercentage)
binding.progressBar.visibility = View.GONE
}
}
fun showUploadInfo() {
launchAlertWithHelpLink(
@ -546,9 +415,6 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){
companion object{
private const val BADGE_IMAGE_WIDTH_RATIO = 0.4
private const val BADGE_IMAGE_HEIGHT_RATIO = 0.3
/**
* Help link URLs
*/

View file

@ -0,0 +1,34 @@
package fr.free.nrw.commons.profile.model
import com.google.gson.annotations.SerializedName
data class AchievementResponse(
@SerializedName("articlesUsingImages")
val articlesUsingImages: Int,
@SerializedName("database")
val database: String,
@SerializedName("deletedUploads")
val deletedUploads: Int,
@SerializedName("featuredImages")
val featuredImages: FeaturedImages,
@SerializedName("imagesEditedBySomeoneElse")
val imagesEditedBySomeoneElse: Int,
@SerializedName("labs")
val labs: Boolean,
@SerializedName("status")
val status: String,
@SerializedName("thanksReceived")
val thanksReceived: Int,
@SerializedName("uniqueUsedImages")
val uniqueUsedImages: Int,
@SerializedName("user")
val user: String
)
data class FeaturedImages(
@SerializedName("Featured_pictures_on_Wikimedia_Commons")
val featuredPicturesOnWikimediaCommons: Int,
@SerializedName("Quality_images")
val qualityImages: Int
)

View file

@ -0,0 +1,15 @@
package fr.free.nrw.commons.profile.model
import fr.free.nrw.commons.profile.achievements.LevelController
data class UserAchievements(
val level: LevelController.LevelInfo,
val articlesUsingImagesCount: Int = 0,
val thanksReceivedCount: Int = 0,
val featuredImagesCount: Int = 0,
val qualityImagesCount: Int = 0,
val imagesUploadedCount: Int = 0,
val revertedCount: Int = 0,
val uniqueImagesCount: Int = 0,
val imagesEditedBySomeoneElseCount: Int = 0
)

View file

@ -0,0 +1,53 @@
package fr.free.nrw.commons.repository
import fr.free.nrw.commons.network.APIService
import fr.free.nrw.commons.profile.achievements.LevelController
import fr.free.nrw.commons.profile.model.UserAchievements
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import timber.log.Timber
import javax.inject.Inject
class ProfileRepository @Inject constructor(private val apiService: APIService) {
fun getUserLevel(username: String) : Flow<UserAchievements> = flow {
try {
val uploadCountResponse = apiService.getImageUploadCount(username)
val imagesUploaded = uploadCountResponse.body() ?:0
val achievementResponse = apiService.getUserAchievements(username)
val uniqueImages = achievementResponse.body()?.uniqueUsedImages ?: 0
val articlesUsingImages = achievementResponse.body()?.articlesUsingImages ?: 0
val thanksReceived = achievementResponse.body()?.thanksReceived ?: 0
val featuredImages = achievementResponse.body()?.featuredImages?.featuredPicturesOnWikimediaCommons ?:0
val qualityImages = achievementResponse.body()?.featuredImages?.qualityImages ?: 0
val deletedUploads = achievementResponse.body()?.deletedUploads ?:0
val revertCount = (imagesUploaded - deletedUploads) * 100 / imagesUploaded
val imagesEditedBySomeoneElse = achievementResponse.body()?.imagesEditedBySomeoneElse ?:0
val level = LevelController.LevelInfo.from(
imagesUploaded = imagesUploaded,
uniqueImagesUsed = uniqueImages,
nonRevertRate = revertCount)
emit(
UserAchievements(
level = level,
articlesUsingImagesCount = articlesUsingImages,
featuredImagesCount = featuredImages,
imagesUploadedCount = imagesUploaded,
qualityImagesCount = qualityImages,
revertedCount = revertCount,
thanksReceivedCount = thanksReceived,
uniqueImagesCount = uniqueImages,
imagesEditedBySomeoneElseCount = imagesEditedBySomeoneElse
)
)
}
catch(e : Exception) {
Timber.e(e.printStackTrace().toString())
}
}
}

View file

@ -14,6 +14,7 @@ import android.os.Bundle
import android.provider.Settings
import android.view.View
import android.widget.CheckBox
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
@ -122,7 +123,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
/**
* Set the value of the showPermissionDialog variable.
*
* @param showPermissionsDialog `true` to indicate to show
* @property isShowPermissionsDialog `true` to indicate to show
* Permissions Dialog if permissions are missing, `false` otherwise.
*/
/**
@ -166,6 +167,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
private var _binding: ActivityUploadBinding? = null
private val binding: ActivityUploadBinding get() = _binding!!
private lateinit var onBackPressedCallback: OnBackPressedCallback
@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -173,6 +176,23 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
_binding = ActivityUploadBinding.inflate(layoutInflater)
setContentView(binding.root)
// Overrides the back button to make sure the user is prepared to lose their progress
onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
showAlertDialog(
this@UploadActivity,
getString(R.string.back_button_warning),
getString(R.string.back_button_warning_desc),
getString(R.string.back_button_continue),
getString(R.string.back_button_warning),
null
) {
finish()
}
}
}
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
/*
If Configuration of device is changed then get the new fragments
created by the system and populate the fragments ArrayList
@ -187,7 +207,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
}
init()
binding.rlContainerTitle.setOnClickListener { v: View? -> onRlContainerTitleClicked() }
binding.rlContainerTitle.setOnClickListener { _: View? -> onRlContainerTitleClicked() }
nearbyPopupAnswers = mutableMapOf()
//getting the current dpi of the device and if it is less than 320dp i.e. overlapping
//threshold, thumbnails automatically minimizes
@ -201,7 +221,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
}
locationManager!!.requestLocationUpdatesFromProvider(LocationManager.GPS_PROVIDER)
locationManager!!.requestLocationUpdatesFromProvider(LocationManager.NETWORK_PROVIDER)
store = BasicKvStore(this, storeNameForCurrentUploadImagesSize).apply {
store = BasicKvStore(this, STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE).apply {
clearAll()
}
checkStoragePermissions()
@ -241,7 +261,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
override fun onPageSelected(position: Int) {
currentSelectedPosition = position
if (position >= uploadableFiles!!.size) {
if (position >= uploadableFiles.size) {
binding.cvContainerTopCard.visibility = View.GONE
} else {
thumbnailsAdapter!!.notifyDataSetChanged()
@ -274,7 +294,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter { result: Boolean? -> result!! }
.subscribe { result: Boolean? ->
.subscribe { _: Boolean? ->
showAlertDialog(
this,
getString(R.string.block_notification_title),
@ -284,7 +304,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
})
}
fun checkStoragePermissions() {
private fun checkStoragePermissions() {
// Check if all required permissions are granted
val hasAllPermissions = hasPermission(this, PERMISSIONS_STORAGE)
val hasPartialAccess = hasPartialAccess(this)
@ -355,7 +375,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
showLongToast(this, messageResourceId)
}
override fun getUploadableFiles(): List<UploadableFile>? {
override fun getUploadableFiles(): List<UploadableFile> {
return uploadableFiles
}
@ -367,6 +387,14 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
override fun onUploadMediaDeleted(index: Int) {
fragments!!.removeAt(index) //Remove the corresponding fragment
uploadableFiles.removeAt(index) //Remove the files from the list
val isMediaDetailFragment = fragments!!.getOrNull(currentSelectedPosition)?.let {
it is UploadMediaDetailFragment
} ?: false
if(!isMediaDetailFragment) {
// Should hide the top card current fragment is not the media detail fragment
showHideTopCard(false)
}
thumbnailsAdapter!!.notifyItemRemoved(index) //Notify the thumbnails adapter
uploadImagesAdapter!!.notifyDataSetChanged() //Notify the ViewPager
}
@ -375,8 +403,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
binding.tvTopCardTitle.text = resources
.getQuantityString(
R.plurals.upload_count_title,
uploadableFiles!!.size,
uploadableFiles!!.size
uploadableFiles.size,
uploadableFiles.size
)
}
@ -444,15 +472,16 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
receiveInternalSharedItems()
}
if (uploadableFiles == null || uploadableFiles!!.isEmpty()) {
if (uploadableFiles.isEmpty()) {
handleNullMedia()
} else {
//Show thumbnails
if (uploadableFiles!!.size > 1) {
if (!defaultKvStore.getBoolean("hasAlreadyLaunchedCategoriesDialog")) { //If there is only file, no need to show the image thumbnails
if (uploadableFiles.size > 1) {
if (!defaultKvStore.getBoolean("hasAlreadyLaunchedCategoriesDialog")) {
// If there is only file, no need to show the image thumbnails
showAlertDialogForCategories()
}
if (uploadableFiles!!.size > 3 &&
if (uploadableFiles.size > 3 &&
!defaultKvStore.getBoolean("hasAlreadyLaunchedBigMultiupload")
) {
showAlertForBattery()
@ -464,8 +493,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
binding.tvTopCardTitle.text = resources
.getQuantityString(
R.plurals.upload_count_title,
uploadableFiles!!.size,
uploadableFiles!!.size
uploadableFiles.size,
uploadableFiles.size
)
@ -474,7 +503,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
}
for (uploadableFile in uploadableFiles!!) {
for (uploadableFile in uploadableFiles) {
val uploadMediaDetailFragment = UploadMediaDetailFragment()
if (!uploadIsOfAPlace) {
@ -497,8 +526,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
object : UploadMediaDetailFragmentCallback {
override fun deletePictureAtIndex(index: Int) {
store!!.putInt(
keyForCurrentUploadImagesSize,
(store!!.getInt(keyForCurrentUploadImagesSize) - 1)
KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE,
(store!!.getInt(KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE) - 1)
)
presenter!!.deletePictureAtIndex(index)
}
@ -576,11 +605,11 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
fragments!!.add(mediaLicenseFragment!!)
} else {
for (i in 1 until fragments!!.size) {
fragments!![i]!!.callback = object : UploadBaseFragment.Callback {
fragments!![i].callback = object : UploadBaseFragment.Callback {
override fun onNextButtonClicked(index: Int) {
if (index < fragments!!.size - 1) {
binding.vpUpload.setCurrentItem(index + 1, false)
fragments!![index + 1]!!.onBecameVisible()
fragments!![index + 1].onBecameVisible()
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
.scrollToPositionWithOffset(
if ((index > 0)) index - 1 else 0,
@ -594,7 +623,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
override fun onPreviousButtonClicked(index: Int) {
if (index != 0) {
binding.vpUpload.setCurrentItem(index - 1, true)
fragments!![index - 1]!!.onBecameVisible()
fragments!![index - 1].onBecameVisible()
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
.scrollToPositionWithOffset(
if ((index > 3)) index - 2 else 0,
@ -632,11 +661,12 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
binding.vpUpload.offscreenPageLimit = fragments!!.size
}
// Saving size of uploadableFiles
store!!.putInt(keyForCurrentUploadImagesSize, uploadableFiles!!.size)
store!!.putInt(KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE, uploadableFiles.size)
}
/**
* Changes current image when one image upload is cancelled, to highlight next image in the top thumbnail.
* Changes current image when one image upload is cancelled, to highlight next image in the top
* thumbnail.
* Fixes: [Issue](https://github.com/commons-app/apps-android-commons/issues/5511)
*
* @param index Index of image to be removed
@ -771,7 +801,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
override fun onNextButtonClicked(index: Int) {
if (index < fragments!!.size - 1) {
binding.vpUpload.setCurrentItem(index + 1, false)
fragments!![index + 1]!!.onBecameVisible()
fragments!![index + 1].onBecameVisible()
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
.scrollToPositionWithOffset(if ((index > 0)) index - 1 else 0, 0)
if (index < fragments!!.size - 4) {
@ -786,10 +816,10 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
override fun onPreviousButtonClicked(index: Int) {
if (index != 0) {
binding.vpUpload.setCurrentItem(index - 1, true)
fragments!![index - 1]!!.onBecameVisible()
fragments!![index - 1].onBecameVisible()
(binding.rvThumbnails.layoutManager as LinearLayoutManager)
.scrollToPositionWithOffset(if ((index > 3)) index - 2 else 0, 0)
if ((index != 1) && ((index - 1) < uploadableFiles!!.size)) {
if ((index != 1) && ((index - 1) < uploadableFiles.size)) {
// Shows the top card if it was hidden because of the last image being deleted and
// now the user has hit previous button to go back to the media details
showHideTopCard(true)
@ -797,7 +827,10 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
}
}
override fun onThumbnailDeleted(position: Int) = presenter!!.deletePictureAtIndex(position)
override fun onThumbnailDeleted(position: Int) {
presenter!!.deletePictureAtIndex(position)
thumbnailsAdapter?.notifyDataSetChanged()
}
/**
* The adapter used to show image upload intermediate fragments
@ -824,11 +857,11 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
}
fun onRlContainerTitleClicked() {
private fun onRlContainerTitleClicked() {
binding.rvThumbnails.visibility =
if (isTitleExpanded) View.GONE else View.VISIBLE
isTitleExpanded = !isTitleExpanded
binding.ibToggleTopCard.rotation = binding.ibToggleTopCard.rotation + 180
binding.ibToggleTopCard.rotation += 180
}
override fun onDestroy() {
@ -845,21 +878,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
if (uploadCategoriesFragment != null) {
uploadCategoriesFragment!!.callback = null
}
}
/**
* Overrides the back button to make sure the user is prepared to lose their progress
*/
@SuppressLint("MissingSuperCall")
override fun onBackPressed() {
showAlertDialog(
this,
getString(R.string.back_button_warning),
getString(R.string.back_button_warning_desc),
getString(R.string.back_button_continue),
getString(R.string.back_button_warning),
null
) { finish() }
onBackPressedCallback.remove()
}
/**
@ -879,7 +898,7 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
.setView(view)
.setTitle(getString(R.string.multiple_files_depiction_header))
.setMessage(getString(R.string.multiple_files_depiction))
.setPositiveButton("OK") { dialog: DialogInterface?, which: Int ->
.setPositiveButton("OK") { _: DialogInterface?, _: Int ->
if (checkBox.isChecked) {
// Save the user's choice to not show the dialog again
defaultKvStore.putBoolean("hasAlreadyLaunchedCategoriesDialog", true)
@ -958,7 +977,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
Also, location information is discarded if the difference between
current location and location recorded just before capturing the image
is greater than 100 meters */
if (isLocationTagUnchecked || locationDifference > 100 || !defaultKvStore.getBoolean("inAppCameraLocationPref")
if (isLocationTagUnchecked || locationDifference > 100
|| !defaultKvStore.getBoolean("inAppCameraLocationPref")
|| !isInAppCameraUpload
) {
currLocation = null
@ -979,8 +999,8 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C
@JvmField
var nearbyPopupAnswers: MutableMap<Place, Boolean>? = null
const val keyForCurrentUploadImagesSize: String = "CurrentUploadImagesSize"
const val storeNameForCurrentUploadImagesSize: String = "CurrentUploadImageQualities"
const val KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE: String = "CurrentUploadImagesSize"
const val STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE: String = "CurrentUploadImageQualities"
/**
* Sets the flag indicating whether the upload is of a specific place.

View file

@ -146,11 +146,7 @@ class UploadPresenter @Inject internal constructor(
override fun deletePictureAtIndex(index: Int) {
val uploadableFiles = view.getUploadableFiles()
if (index == uploadableFiles!!.size - 1) {
// If the next fragment to be shown is not one of the MediaDetailsFragment
// lets hide the top card so that it doesn't appear on the other fragments
view.showHideTopCard(false)
}
uploadableFiles?.let {
view.setImageCancelled(true)
repository.deletePicture(uploadableFiles[index].getFilePath())
if (uploadableFiles.size == 1) {
@ -175,6 +171,7 @@ class UploadPresenter @Inject internal constructor(
//In case lets update the number of uploadable media
view.updateTopCardTitle()
}
}
override fun onAttachView(view: UploadContract.View) {
this.view = view

View file

@ -532,7 +532,7 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
basicKvStore!!.putBoolean(keyForShowingAlertDialog, false)
if (isInternetConnectionEstablished(requireActivity())) {
val sizeOfUploads = basicKvStore!!.getInt(
UploadActivity.keyForCurrentUploadImagesSize
UploadActivity.KEY_FOR_CURRENT_UPLOAD_IMAGE_SIZE
)
for (i in indexOfFragment until sizeOfUploads) {
presenter.getImageQuality(

View file

@ -310,7 +310,7 @@ class UploadMediaPresenter @Inject constructor(
private fun storeImageQuality(
imageResult: Int, uploadItemIndex: Int, activity: Activity, uploadItem: UploadItem
) {
val store = BasicKvStore(activity, UploadActivity.storeNameForCurrentUploadImagesSize)
val store = BasicKvStore(activity, UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE)
val value = store.getString(UPLOAD_QUALITIES_KEY, null)
try {
val jsonObject = value.asJsonObject().apply {
@ -339,8 +339,10 @@ class UploadMediaPresenter @Inject constructor(
*/
override fun checkImageQuality(uploadItem: UploadItem, index: Int) {
if ((uploadItem.imageQuality != IMAGE_OK) && (uploadItem.imageQuality != IMAGE_KEEP)) {
val value = basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
val value = basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
?.getString(UPLOAD_QUALITIES_KEY, null)
try {
val imageQuality = value.asJsonObject()["UploadItem$index"] as Int
view.showProgress(false)
@ -363,8 +365,9 @@ class UploadMediaPresenter @Inject constructor(
* @param index Index of the UploadItem which was deleted
*/
override fun updateImageQualitiesJSON(size: Int, index: Int) {
val value = basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
val value = basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
?.getString(UPLOAD_QUALITIES_KEY, null)
try {
val jsonObject = value.asJsonObject().apply {
for (i in index until (size - 1)) {
@ -372,7 +375,8 @@ class UploadMediaPresenter @Inject constructor(
}
remove("UploadItem" + (size - 1))
}
basicKvStoreFactory?.let { it(UploadActivity.storeNameForCurrentUploadImagesSize) }
basicKvStoreFactory?.let { it(UploadActivity.STORE_NAME_FOR_CURRENT_UPLOAD_IMAGE_SIZE) }
?.putString(UPLOAD_QUALITIES_KEY, jsonObject.toString())
} catch (e: Exception) {
Timber.e(e)

View file

@ -0,0 +1,39 @@
package fr.free.nrw.commons.utils
import android.content.Context
import android.icu.text.ListFormatter
import android.os.Build
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.R
import fr.free.nrw.commons.media.IdAndLabels
import java.util.Locale
object MediaAttributionUtil {
fun getTagLine(media: Media, context: Context): String {
val uploader = media.user
val author = media.getAttributedAuthor()
return if (author.isNullOrEmpty()) {
context.getString(R.string.image_uploaded_by, uploader)
} else if (author == uploader) {
context.getString(R.string.image_tag_line_created_and_uploaded_by, author)
} else {
context.getString(
R.string.image_tag_line_created_by_and_uploaded_by,
author,
uploader
)
}
}
fun getCreatorName(idAndLabels: List<IdAndLabels>): String? {
val locale = Locale.getDefault()
val names = idAndLabels.map{ x -> x.getLocalizedLabel(locale.language)}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val formatter = ListFormatter.getInstance(locale)
return formatter.format(names)
} else {
return names.joinToString(", ")
}
}
}

View file

@ -1,9 +1,8 @@
package fr.free.nrw.commons.utils
import android.os.Build
import android.text.Html
import android.text.Spanned
import android.text.SpannedString
import androidx.core.text.HtmlCompat
object StringUtil {
@ -26,12 +25,6 @@ object StringUtil {
.replace("&#8207;", "\u200F")
.replace("&amp;", "&")
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(processedSource, Html.FROM_HTML_MODE_LEGACY)
} else {
//noinspection deprecation
@Suppress("DEPRECATION")
Html.fromHtml(processedSource)
}
return HtmlCompat.fromHtml(processedSource, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
}

View file

@ -7,6 +7,7 @@ enum class WikidataProperties(
) {
IMAGE("P18"),
DEPICTS(BuildConfig.DEPICTS_PROPERTY),
CREATOR(BuildConfig.CREATOR_PROPERTY),
COMMONS_CATEGORY("P373"),
INSTANCE_OF("P31"),
MEDIA_LEGENDS("P2096"),

View file

@ -1,7 +1,6 @@
package fr.free.nrw.commons.wikidata.model.gallery
import com.google.gson.annotations.SerializedName
import org.apache.commons.lang3.StringUtils
class ExtMetadata {
@SerializedName("DateTime") private val dateTime: Values? = null

View file

@ -146,6 +146,7 @@
android:layout_marginEnd="@dimen/standard_gap"
android:layout_marginRight="@dimen/standard_gap"
android:layout_marginBottom="@dimen/standard_gap"
android:hint="@string/_2fa_code"
android:visibility="gone"
app:passwordToggleEnabled="false"
tools:visibility="visible">
@ -154,9 +155,7 @@
android:id="@+id/login_two_factor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/_2fa_code"
android:imeOptions="flagNoExtractUi"
android:inputType="number"
android:visibility="gone"
tools:visibility="visible" />

View file

@ -102,6 +102,7 @@
android:layout_marginEnd="8dp"
android:text="SEND"
android:visibility="visible"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/textHeader"
app:layout_constraintHorizontal_bias="1.0"

View file

@ -43,7 +43,7 @@
android:id="@+id/achievement_badge_image"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginTop="16dp"
android:layout_marginTop="100dp"
android:background="@drawable/badge"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
@ -263,7 +263,7 @@
app:layout_constraintTop_toBottomOf="@+id/images_used_tv">
<ProgressBar
android:id="@+id/images_used_by_wiki_progress_bar"
android:id="@+id/images_used_progressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -362,7 +362,7 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintHorizontal_bias="0.5"
android:visibility="gone"/>
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -26,10 +26,11 @@
android:clickable="true"
android:focusable="true"
android:visibility="visible"
app:backgroundTint="@color/main_background_light"
app:backgroundTint="?attr/colorSurface"
app:elevation="@dimen/dimen_6"
app:fabSize="normal"
app:srcCompat="@drawable/ic_my_location_black_24dp"
app:tint="?attr/colorOnSurface"
app:useCompatPadding="true" />
<View

View file

@ -168,6 +168,7 @@
<string name="login_failed_throttled">الكثير من المحاولات غير الناجحة. الرجاء المحاولة مرة أخرى في بضع دقائق.</string>
<string name="login_failed_blocked">عذراً، لقد تم منع هذا المستخدم على كومنز</string>
<string name="login_failed_2fa_needed">يجب توفير رمز التحقق المزدوج.</string>
<string name="login_failed_email_auth_needed">تم إرسال رمز التحقق إلى بريدك الإلكتروني. يُرجى إدخال الرمز لتسجيل الدخول.</string>
<string name="login_failed_generic">فشل تسجيل الدخول</string>
<string name="share_upload_button">ارفع</string>
<string name="multiple_share_base_title">اسم هذه المجموعة</string>
@ -273,6 +274,7 @@
<string name="become_a_tester_title">انضم لمختبري اصدارات Beta (بيتا)</string>
<string name="become_a_tester_description">يمكنك الاشتراك في القناة التجريبية على جوجل بلاي والحصول على إمكانية الوصول المبكر إلى الميزات الجديدة وإصلاحات الأخطاء</string>
<string name="_2fa_code">رمز التحقق المزدوج 2FA</string>
<string name="email_auth_code">رمز التحقق من البريد الإلكتروني</string>
<string name="logout_verification">أترغب فعلا في الخروج؟</string>
<string name="mediaimage_failed">صورة الوسائط فشلت</string>
<string name="no_subcategory_found">لم يتم العثور على تصنيفات فرعية.</string>
@ -887,4 +889,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">مبروك، جميع الصور الموجودة في هذا الألبوم تم تحميلها أو تم وضع علامة عليها بأنها غير قابلة للتحميل.</string>
<string name="show_in_explore">عرض في استكشاف</string>
<string name="show_in_nearby">عرض في المناطق القريبة</string>
<string name="image_tag_line_created_and_uploaded_by">تم الإنشاء والتحميل بواسطة: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">تم إنشاؤه بواسطة %1$s وتم تحميله بواسطة %2$s</string>
</resources>

View file

@ -2,6 +2,7 @@
<!-- Authors:
* Aftabuzzaman
* Bellayet
* Bodhisattwa
* Borhan
* Elias Ahmmad
* Leemon2010
@ -418,7 +419,11 @@
<string name="category_edit_helper_edit_message_else">বিষয়শ্রেণী হালনাগাদ করা সম্ভব হয়নি।</string>
<string name="category_edit_button_text">বিষয়শ্রেণীগুলি হালনাগাদ করুন</string>
<string name="depictions_edit_helper_show_edit_title">চিত্রণ সম্পাদনা</string>
<string name="coordinates_edit_helper_show_edit_title">স্থানাঙ্ক হালনাগাদ</string>
<string name="description_edit_helper_show_edit_title">বিবরণ হালনাগাদ</string>
<string name="coordinates_edit_helper_show_edit_title_success">সফল</string>
<string name="coordinates_edit_helper_show_edit_message">স্থানাঙ্ক %1$s যোগ করা হয়েছে।</string>
<string name="description_edit_helper_show_edit_message">বর্ণনা যোগ করা হয়েছে।</string>
<string name="you_have_no_achievements_yet">আপনি এখনও কোনও অবদান রাখেন নি</string>
<string name="account_created">অ্যাকাউন্ট তৈরি করা হয়েছে!</string>
<string name="some_error">একটি ত্রুটি হয়েছে!</string>
@ -470,6 +475,9 @@
<string name="limited_connection_enabled">সীমিত সংযোগ মোড সক্রিয় করা হয়েছে!</string>
<string name="limited_connection_mode">সীমিত সংযোগ মোড</string>
<string name="statistics_quality">মানসম্মত ছবি</string>
<string name="resuming_upload">আপলোড আবার শুরু হচ্ছে...</string>
<string name="pausing_upload">আপলোড থামানো হচ্ছে...</string>
<string name="cancelling_upload">আপলোড বাতিল করা হচ্ছে…</string>
<string name="cancel_upload">আপলোড বাতিল করুন</string>
<string name="limited_connection_explanation">আপনি সীমিত সংযোগ মোড সক্রিয় করেছেন। সমস্ত আপলোডকে এখন বিরাম দেওয়া হয়েছে ও আপনি এই মোডটি নিষ্ক্রিয় করলে আপলোড পুনরায় শুরু করা হবে।</string>
<string name="license_step_title">মিডিয়ার লাইসেন্স</string>

View file

@ -83,8 +83,10 @@
<item quantity="many">%1$d nahrání</item>
<item quantity="other">%1$d nahrání</item>
</plurals>
<plurals name="receiving_shared_content" fuzzy="true">
<plurals name="receiving_shared_content">
<item quantity="one">Probíhá příjem sdíleného obsahu. Zpracování obrázku může chvíli trvat v závislosti na velikosti obrázku a vašem zařízení</item>
<item quantity="few">Probíhá příjem sdíleného obsahu. Zpracování obrázků může chvíli trvat v závislosti na velikosti obrázků a vašem zařízení</item>
<item quantity="many">Probíhá příjem sdíleného obsahu. Zpracování obrázků může chvíli trvat v závislosti na velikosti obrázků a vašem zařízení</item>
<item quantity="other">Probíhá příjem sdíleného obsahu. Zpracování obrázků může chvíli trvat v závislosti na velikosti obrázků a vašem zařízení</item>
</plurals>
<string name="navigation_item_explore">Objevit</string>
@ -107,10 +109,14 @@
<string name="updating_caption_title">Nahrávání titulků a popisů</string>
<string name="updating_caption_message">Čekejte prosím…</string>
<string name="login_success">Úspěšně přihlášeni!</string>
<string name="login_failed" fuzzy="true">Přihlášení se nezdařilo!</string>
<string name="login_failed">Přihlášení se nezdařilo!</string>
<string name="upload_failed">Soubor nebyl nalezen. Prosím, zkuste jiný soubor.</string>
<string name="authentication_failed" fuzzy="true">Ověření se nezdařilo, prosím přihlaste se znovu</string>
<string name="retry_limit_reached">Byl dosažen maximální limit opakování! Zrušte prosím nahrávání a zkuste to znovu</string>
<string name="unrestricted_battery_mode">Vypnout optimalizaci baterie?</string>
<string name="suggest_unrestricted_mode">Nahrávání více než 3 obrázků funguje spolehlivě při vypnuté optimalizaci baterie. Pro bezproblémové nahrávání prosím vypněte pro aplikaci Commons optimalizaci baterie.\n\nMožné kroky pro vypnutí optimalizace baterie:\n\nKrok 1: Klepněte na tlačítko „Nastavení“ níže.\n\nKrok 2: Přepněte kategorii z „Neomezeno“ na „Všechny aplikace“.\n\nKrok 3: Vyhledejte aplikaci „Commons“ nebo „fr.free.nrw.commons“.\n\nKrok 4: Klepněte na ni a vyberte „Neomezeno“.\n\nKrok 5: Klepněte na „Hotovo“.</string>
<string name="authentication_failed">Ověření se nezdařilo. Přihlaste se prosím znovu.</string>
<string name="uploading_started">Nahrávání začalo!</string>
<string name="uploading_queued">Nahrávání je ve frontě (zapnut režim omezeného připojení)</string>
<string name="upload_completed_notification_title">%1$s nahráno!</string>
<string name="upload_completed_notification_text">Klepnutím zobrazíte upload</string>
<string name="upload_progress_notification_title_start">Načítání souboru: %s</string>
@ -129,31 +135,41 @@
<string name="menu_from_camera">Vyfotit</string>
<string name="menu_nearby">Poblíž</string>
<string name="provider_contributions">Moje obrázky</string>
<string name="menu_copy_link">Kopírovat odkaz</string>
<string name="menu_link_copied">Odkaz byl zkopírován do schránky</string>
<string name="menu_share">Sdílet</string>
<string name="menu_view_file_page">Zobrazit stránku souboru</string>
<string name="share_title_hint">Název (povinný)</string>
<string name="add_caption_toast">Prosím, zadejte titulek pro tento soubor</string>
<string name="add_caption_toast">Zadejte prosím titulek pro tento soubor</string>
<string name="share_description_hint">Popis</string>
<string name="share_caption_hint" fuzzy="true">Popisek (max. 255 znaků)</string>
<string name="login_failed_network" fuzzy="true">Nelze se přihlásit - selhání sítě</string>
<string name="share_caption_hint">Titulek</string>
<string name="login_failed_network">Nelze se přihlásit selhání sítě</string>
<string name="login_failed_throttled">Příliš mnoho neúspěšných pokusů. Zkuste to prosím znovu za několik minut.</string>
<string name="login_failed_blocked">Omlouváme se, tento uživatel byl na Commons zablokován</string>
<string name="login_failed_2fa_needed">Prosím vložte kód pro své dvoufázové ověření.</string>
<string name="login_failed_generic" fuzzy="true">Přihlášení se nezdařilo</string>
<string name="login_failed_email_auth_needed">Ověřovací kód byl odeslán na vaši e-mailovou adresu. Pro přihlášení prosím zadejte kód.</string>
<string name="login_failed_generic">Přihlášení se nezdařilo</string>
<string name="share_upload_button">Nahrát</string>
<string name="multiple_share_base_title">Pojmenujte tuto sadu</string>
<string name="provider_modifications">Úpravy</string>
<string name="menu_upload_single">Načíst</string>
<string name="categories_search_text_hint">Hledání kategorií</string>
<string name="depicts_search_text_hint">Hledat položky, které váš multimediální soubor zobrazuje (hora, Tádž Mahal atd.)</string>
<string name="menu_save_categories">Uložit</string>
<string name="menu_overflow_desc">Rozbalovací nabídka</string>
<string name="refresh_button">Obnovit</string>
<string name="display_list_button">Seznam</string>
<string name="contributions_subtitle_zero">(Žádné nahrané soubory)</string>
<string name="categories_not_found">Žádné kategorie neodpovídají „%1$s“</string>
<string name="depictions_not_found">Nenalezeny žádné položky Wikidata odpovídající %1$s</string>
<string name="no_child_classes">%1$s nemá žádné podřazené třídy</string>
<string name="no_parent_classes">%1$s nemá žádné nadřazené třídy</string>
<string name="categories_skip_explanation">Přidejte kategorie, aby bylo vaše obrázky možno na Wikimedia Commons najít.</string>
<string name="categories_activity_title">Kategorie</string>
<string name="title_activity_settings">Nastavení</string>
<string name="title_activity_signup">Zaregistrovat se</string>
<string name="title_activity_featured_images">Nejlepší obrázky</string>
<string name="title_activity_custom_selector">Vlastní výběr</string>
<string name="title_activity_category_details">Kategorie</string>
<string name="title_activity_review">Kontrola</string>
<string name="menu_about">O aplikaci</string>
@ -216,13 +232,17 @@
<string name="read_storage_permission_rationale">Požadované oprávnění: Čtení externího úložiště. Bez něj nemůže aplikace číst vaši galerii.</string>
<string name="write_storage_permission_rationale">Požadované oprávnění: Zapisování do externího úložiště. Bez něj nemůže aplikace používat vaši kameru/galerii.</string>
<string name="location_permission_title">Požadavek na přístup k poloze</string>
<string name="in_app_camera_location_permission_title">Poloha záznamu pro snímky v aplikaci</string>
<string name="in_app_camera_location_switch_pref_summary">Povolte pro zaznamenání polohy u snímků v aplikaci v případě, že ji fotoaparát zařízení nezaznamená</string>
<string name="ok">OK</string>
<string name="warning">Upozornění</string>
<string name="duplicate_file_name">Nalezen duplicitní název souboru</string>
<string name="upload">Nahrát</string>
<string name="yes">Ano</string>
<string name="no">Ne</string>
<string name="media_detail_caption">Titulek</string>
<string name="media_detail_title">Název</string>
<string name="media_detail_depiction">Znázornění</string>
<string name="media_detail_description">Popis</string>
<string name="media_detail_discussion">Diskuse</string>
<string name="media_detail_author">Autor</string>
@ -233,6 +253,7 @@
<string name="become_a_tester_title">Staňte se beta testery</string>
<string name="become_a_tester_description">Přihlásit se do našeho beta kanálu na Google Play a dostávat včasný přístup k novinkám a opravám chyb</string>
<string name="_2fa_code">Kód pro dvoufázové ověření (2FA)</string>
<string name="email_auth_code">Ověřovací kód z e-mailu</string>
<string name="logout_verification">Opravdu se chcete odhlásit?</string>
<string name="mediaimage_failed">Obrázek</string>
<string name="no_subcategory_found">Nebyly nalezeny podkategorie</string>
@ -253,6 +274,7 @@
<string name="navigation_item_about">O aplikaci</string>
<string name="navigation_item_settings">Nastavení</string>
<string name="navigation_item_feedback">Zpětná vazba</string>
<string name="navigation_item_feedback_github">Zpětná vazba přes GitHub</string>
<string name="navigation_item_logout">Odhlášení</string>
<string name="navigation_item_info">Průvodce</string>
<string name="navigation_item_notification">Upozornění</string>
@ -262,6 +284,7 @@
<string name="nearby_info_menu_wikidata_article">Položka Wikidat</string>
<string name="nearby_info_menu_wikipedia_article">Článek na Wikipedii</string>
<string name="description_info">Popište prosím obrázek, jak jen to je možné: Kde byl pořízen? Co znázorňuje? Jaký je kontext obrázku? Popisujte prosím významné předměty nebo osoby na obrázku a nezapomeňte na informace, které není možné snadno odhadnout ze samotného obrázku, jako je například denní doba, pokud jde o krajinu. Pokud je na obrázku něco neobvyklého, popište, co to dělá neobvyklým.</string>
<string name="caption_info">Napište prosím stručný popis obrázku. První titulek bude použit jako název obrázku. Maximálně 255 znaků.</string>
<string name="upload_problem_exist">Potenciální problémy s tímto obrázkem:</string>
<string name="upload_problem_image_dark">Obrázek je příliš tmavý.</string>
<string name="upload_problem_image_blurry">Obrázek je rozmazaný.</string>
@ -269,9 +292,12 @@
<string name="upload_problem_different_geolocation">Tento obrázek byl pořízen na jiném místě.</string>
<string name="upload_problem_fbmd">Prosíme, nahrávejte pouze obrázky, které jste sami pořídili. Nenahrávejte obrázky, které jste našli na něčím Facebookovém profilu.</string>
<string name="upload_problem_do_you_continue">Pořád chcete tento obrázek nahrát?</string>
<string name="upload_connection_error_alert_title">Chyba připojení</string>
<string name="upload_connection_error_alert_detail">Proces nahrávání vyžaduje aktivní přístup k internetu. Zkontrolujte prosím své internetové připojení.</string>
<string name="upload_problem_image">V obrázku byly nalezeny problémy</string>
<string name="internet_downloaded">Prosíme, nahrávejte pouze obrázky, které jste sami vytvořili. Nenahrávejte obrázky, které jste našli na internetu.</string>
<string name="use_external_storage" fuzzy="true">Použít externí úložiště</string>
<string name="use_external_storage_summary" fuzzy="true">Uložit obrázky pořízené fotoaparátem, jenž je součástí této aplikace</string>
<string name="use_external_storage">Uložit snímky z aplikace</string>
<string name="use_external_storage_summary">Uložit obrázky pořízené fotoaparátem v aplikaci do úložiště vašeho zařízení</string>
<string name="login_to_your_account">Přihlásit se k účtu</string>
<string name="send_log_file">Odeslat log</string>
<string name="send_log_file_description">Odeslat log vývojářům e-mailem za účelem odstranění problémů s aplikací. Poznámka: Logy mohou obsahovat identifikační údaje.</string>
@ -282,19 +308,23 @@
<string name="nominated_see_more">Zobrazit webovou stránku pro více informací</string>
<string name="skip_login">Přeskočit</string>
<string name="navigation_item_login">Přihlásit se</string>
<string name="skip_login_title" fuzzy="true">Opravdu chcete přeskočit přihlášení?</string>
<string name="skip_login_message" fuzzy="true">Budete-li chtít nahrát obrázky v budoucnu, musíte se přihlásit.</string>
<string name="skip_login_title">Opravdu chcete přeskočit přihlášení?</string>
<string name="skip_login_message">Budete-li chtít nahrát obrázky v budoucnu, musíte se přihlásit.</string>
<string name="login_alert_message">K použití této funkce se musíte přihlásit</string>
<string name="copy_wikicode">Zkopírovat wikitext do schránky</string>
<string name="wikicode_copied">Wikitext byl zkopírován do schránky</string>
<string name="nearby_location_not_available">Funkce Poblíž nemusí pracovat správně, poloha není dostupná.</string>
<string name="nearby_showing_pins_offline">Internet není dostupný. Zobrazuji místa z mezipaměti.</string>
<string name="upload_location_access_denied">Přístup k poloze zamítnut. Pro používání této funkce prosím nastavte svoji polohu ručně.</string>
<string name="location_permission_rationale_nearby">Vyžadováno povolení k zobrazení seznamu míst v okolí</string>
<string name="location_permission_rationale_explore">K zobrazení seznamu obrázků v okolí je vyžadováno oprávnění</string>
<string name="nearby_directions">Trasa</string>
<string name="nearby_wikidata">Wikidata</string>
<string name="nearby_wikipedia">Wikipedie</string>
<string name="nearby_commons">Commons</string>
<string name="about_rate_us">Ohodnoťte nás</string>
<string name="about_faq">Často kladené otázky</string>
<string name="user_guide">Uživatelská příručka</string>
<string name="welcome_skip_button">Přeskočit úvod</string>
<string name="no_internet">Internet je nedostupný</string>
<string name="error_notifications">Při načítání upozornění došlo k chybě</string>
@ -321,12 +351,15 @@
<string name="title_activity_search">Hledat</string>
<string name="search_recent_header">Nedávná hledání:</string>
<string name="provider_searches">Nedávno hledané dotazy</string>
<string name="provider_recent_languages">Pořadí nejnovějších jazyků</string>
<string name="error_loading_categories">Chyba při načítání kategorií.</string>
<string name="error_loading_depictions">Během načítání znázornění došlo k chybě.</string>
<string name="search_tab_title_media">Mediální soubory</string>
<string name="search_tab_title_categories">Kategorie</string>
<string name="search_tab_title_depictions">Položky</string>
<string name="explore_tab_title_featured">Nejlepší</string>
<string name="explore_tab_title_mobile">Nahrané z mobilu</string>
<string name="explore_tab_title_map">Mapa</string>
<string name="successful_wikidata_edit">Obrázek byl přidán do položky %1$s na Wikidatech!</string>
<string name="wikidata_edit_failure">Nepodařilo se aktualizovat příslušnou položku na Wikidatech!</string>
<string name="menu_set_wallpaper">Nastavit jako pozadí</string>
@ -344,27 +377,34 @@
<string name="construction_event_answer">Obrázky s technickou či kulturní tematikou jsou na Commons vítány.</string>
<string name="congratulatory_message_quiz">Zodpověděli jste správně %1$s otázek. Gratulujeme!</string>
<string name="warning_for_no_answer">Vyberte správnou možnost</string>
<string name="user_not_logged_in" fuzzy="true">Došlo k odhlášení, prosím přihlašte se.</string>
<string name="user_not_logged_in">Přihlášení vypršelo. Přihlaste se prosím znovu.</string>
<string name="quiz_result_share_message">Sdílejte váš kvíz s přáteli!</string>
<string name="continue_message">Pokračovat</string>
<string name="correct">Správná odpověď</string>
<string name="wrong">Nesprávná odpověď</string>
<string name="quiz_screenshot_question">Je v pořádku nahrát tento snímek obrazovky?</string>
<string name="share_app_title">Sdílet aplikaci</string>
<string name="error_fetching_nearby_places" fuzzy="true">Nastala chyba při hledání míst v okolí.</string>
<string name="rotate">Otočit</string>
<string name="error_fetching_nearby_places">Nepodařilo se načíst místa v okolí</string>
<string name="no_pictures_in_this_area">Žádné obrázky v této oblasti</string>
<string name="no_nearby_places_around">Nenalezena žádná místa v okolí</string>
<string name="error_fetching_nearby_monuments">Chyba při načítání míst v okolí.</string>
<string name="no_recent_searches">Zatím žádné vyhledávání</string>
<string name="delete_recent_searches_dialog">Opravdu chcete vyčistit historii vašeho hledání?</string>
<string name="cancel_upload_dialog">Opravdu chcete zrušit toto nahrávání?</string>
<string name="delete_search_dialog">Chcete odstranit toto hledání?</string>
<string name="search_history_deleted">Historie hledání byla odstraněna</string>
<string name="nominate_delete">Navrhnout na smazání</string>
<string name="delete">Smazat</string>
<string name="Achievements">Dosažené úspěchy</string>
<string name="Profile">Profil</string>
<string name="badges">Odznaky</string>
<string name="statistics">Statistiky</string>
<string name="statistics_thanks">Obdržená poděkování</string>
<string name="statistics_featured">Nejlepší obrázky</string>
<string name="statistics_wikidata_edits">Obrázky přes „Místa v okolí“</string>
<string name="level" fuzzy="true">Úroveň</string>
<string name="level">Úroveň %d</string>
<string name="profileLevel">%s (úroveň %s)</string>
<string name="images_uploaded">Nahrané obrázky</string>
<string name="image_reverts">Nerevertované obrázky</string>
<string name="images_used_by_wiki">Použitých obrázků</string>
@ -376,15 +416,15 @@
<string name="images_used_explanation">Počet obrázků, které jste nahrál/a na Commons a jsou použity v projektech Wikimedia</string>
<string name="error_occurred">Chyba!</string>
<string name="notifications_channel_name_all">Upozornění z Commons</string>
<string name="preference_author_name_toggle">Použít vlastní název autora</string>
<string name="preference_author_name_toggle">Použít vlastní jméno autora</string>
<string name="preference_author_name_toggle_summary">Při nahrávání fotografií používejte vlastní jméno autora namísto uživatelského jména</string>
<string name="preference_author_name">Vlastní název autora</string>
<string name="preference_author_name">Vlastní jméno autora</string>
<string name="contributions_fragment">Příspěvky</string>
<string name="nearby_fragment">Poblíž</string>
<string name="notifications">Upozornění</string>
<string name="read_notifications">Upozornění (přečtená)</string>
<string name="display_nearby_notification">Zobrazit upozornění v okolí</string>
<string name="display_nearby_notification_summary" fuzzy="true">Klepnutím sem zobrazíte nejbližší místo, které potřebuje obrázky</string>
<string name="display_nearby_notification_summary">Zobrazit oznámení v aplikaci pro nejbližší místo, které potřebuje obrázky</string>
<string name="list_sheet">Seznam</string>
<string name="storage_permission">Povolení k ukládání</string>
<string name="write_storage_permission_rationale_for_image_share">Potřebujeme povolení k přístupu k externí paměti vašeho zařízení, abychom mohli nahrávat obrázky.</string>
@ -392,10 +432,11 @@
<string name="step_count">Krok %1$d z %2$d: %3$s</string>
<string name="next">Další</string>
<string name="previous">Předchozí</string>
<string name="upload_title_duplicate" fuzzy="true">Soubor s názvem %1$s již existuje. Opravdu chcete pokračovat?</string>
<string name="upload_title_duplicate">Soubor s názvem %1$s již existuje. Opravdu chcete pokračovat?\n\nPoznámka: k názvu souboru bude automaticky připojena správná přípona.</string>
<string name="map_application_missing">Na vašem zařízení nebyla nalezena žádná kompatibilní aplikace poskytující mapy. Pro použití této funkce nainstalujte aplikaci poskytující mapy.</string>
<string name="title_page_bookmarks_pictures">Obrázky</string>
<string name="title_page_bookmarks_locations">Místa</string>
<string name="title_page_bookmarks_categories">Kategorie</string>
<string name="menu_bookmark">Přidat/Odstranit ze záložek</string>
<string name="provider_bookmarks">Záložky</string>
<string name="bookmark_empty">Nemáte zatím žádné záložky</string>
@ -410,20 +451,36 @@
<string name="no_uploads">Vítejte na Commons!\n\nNahrajte svá první média klepnutím na tlačítko přidat.</string>
<string name="no_categories_selected">Nebyly vybrány žádné kategorie</string>
<string name="no_categories_selected_warning_desc">Obrázky bez kategorií jsou používány jen zřídka. Opravdu chcete nahrát obrázek bez výběru kategorií?</string>
<string name="upload_flow_all_images_in_set" fuzzy="true">(Pro všechny snímky v sadě)</string>
<string name="no_depictions_selected">Nebyla vybrána žádná znázornění</string>
<string name="no_depictions_selected_warning_desc">Obrázky se znázorněními lze lépe nalézt a je větší šance, že budou použity. Opravdu chcete pokračovat bez vybrání znázornění?</string>
<string name="back_button_warning">Zrušit nahrávání</string>
<string name="back_button_warning_desc">Použitím tlačítka zpět zrušíte toto nahrávání a ztratíte svůj postup.</string>
<string name="back_button_continue">Pokračovat v nahrávání</string>
<string name="upload_flow_all_images_in_set">(Pro všechny snímky v sadě)</string>
<string name="search_this_area">Prohledat tuto oblast</string>
<string name="nearby_card_permission_title">Je požadováno oprávnění</string>
<string name="nearby_card_permission_explanation">Chtěli byste, abychom pomocí aktuální polohy zobrazili nejbližší místo, které potřebuje obrázky?</string>
<string name="unable_to_display_nearest_place">Nelze zobrazit nejbližší místo, které potřebuje snímky bez oprávnění k umístění</string>
<string name="never_ask_again">Znovu nezobrazovat</string>
<string name="display_location_permission_title" fuzzy="true">Zobrazit oprávnění k umístění</string>
<string name="display_location_permission_title">Požádat o oprávnění k poloze</string>
<string name="display_location_permission_explanation">Požádejte o oprávnění k umístění, pokud je zapotřebí pro funkci zobrazení pohledu v blízkosti.</string>
<string name="achievements_fetch_failed">Nastala neočekávaná chyba. Nemohli jsme načíst vaše úspěchy</string>
<string name="achievements_fetch_failed_ultimate_achievement">Vytvořili jste tolik příspěvků, že je náš systém výpočtu úspěchů nedokáže zvládnout. Toto je nejvyšší možný úspěch.</string>
<string name="ends_on">Končí:</string>
<string name="display_campaigns">Zobrazovat kampaně</string>
<string name="display_campaigns_explanation">Podívejte se na probíhající kampaně</string>
<string name="in_app_camera_location_access_explanation">Povolte aplikaci zjišťovat polohu v případě, že ji fotoaparát nezaznamenává. Některé fotoaparáty zařízení nezaznamenávají polohu. V takových případech je užitečnější nechat aplikaci samotnou polohu zjistit a připojit. Tuto možnost lze kdykoli změnit v Nastavení</string>
<string name="option_allow">Povolit</string>
<string name="option_dismiss">Zavřít</string>
<string name="in_app_camera_needs_location">Zapněte prosím v nastavení přístup k poloze a zkuste to znovu.\n\nPoznámka: nahrání nemusí mít polohu, pokud ji aplikace nemohla během krátké doby získat ze zařízení.</string>
<string name="in_app_camera_location_permission_rationale">Fotoaparát v aplikaci potřebuje přístup k poloze, aby ji přiložil k vašem obrázkům, pokud nejsou dostupné v metadatech EXIF. Povolte prosím aplikaci přístup k vaší poloze a zkuste to znovu.\n\nPoznámka: nahrání nemusí mít polohu, pokud ji aplikace nemohla během krátké doby získat ze zařízení.</string>
<string name="in_app_camera_location_permission_denied">Aplikace nezaznamenala polohu spolu s fotkami z důvodu chybějícího oprávnění k poloze</string>
<string name="in_app_camera_location_unavailable">Aplikace nezaznamenala polohu spolu s fotkami z důvodu vypnutého zjišťování polohy</string>
<string name="open_document_photo_picker_title">Použít výběr fotky založený na dokumentech</string>
<string name="open_document_photo_picker_explanation">Nový nástroj pro výběr fotek systému Android může ztrácet informace o poloze. Povolte, pokud jej používáte.</string>
<string name="location_loss_warning">Vypnutí může vést spuštění nového nástroje pro výběr fotek systému Android. Riskujete tím ztrátu informací o poloze.\n\nKlepněte na „Zjistit více“ pro více informací.</string>
<string name="nearby_campaign_dismiss_message">Kampaně již neuvidíte. Toto oznámení však můžete znovu zapnout v Nastavení.</string>
<string name="this_function_needs_network_connection" fuzzy="true">Tato funkce vyžaduje připojení k síti, zkontrolujte prosím nastavení připojení.</string>
<string name="this_function_needs_network_connection">Tato funkce vyžaduje připojení k síti. Zkontrolujte prosím nastavení připojení.</string>
<string name="error_processing_image">Během zpracování obrázku došlo k chybě. Prosím zkuste to znovu!</string>
<string name="getting_edit_token">Probíhá získávání tokenu pro editaci</string>
<string name="check_category_adding_template">Probíhá přidávání šablony na zkontrolování kategorie</string>
@ -454,13 +511,14 @@
<string name="review_thanks_yes_button_text">Další obrázek</string>
<string name="review_thanks_no_button_text">Ano, proč ne</string>
<string name="skip_image_explanation">Kliknutím na toto tlačítko se zobrazí další nedávno nahraný obrázek z Wikimedia Commons</string>
<string name="review_image_explanation" fuzzy="true">Můžete kontrolovat obrázky a zlepšit kvalitu Wikimedia Commons.\n\nTři aspekty, které se posuzují:\n  - Je tento obrázek v pořádku?\n  - Dodržuje tento obrázok pravidla autorských práv?\n  - Je tento obrázek správně kategorizován?\n\nPokud je vše v pořádku, autorovi můžete poděkovat.</string>
<string name="review_image_explanation">Můžete kontrolovat obrázky a zlepšit kvalitu Wikimedia Commons.\nTři aspekty, které se posuzují:\n\n- Dodržuje tento obrázek téma?\nPokud klepnete na Ne (mimo téma), přidáte k tomuto obrázku šablonu nominace na smazání.\n\n- Dodržuje tento obrázek pravidla autorských práv?\nPokud klepnete na Ne (nedodržuje pravidla autorských práv), přidáte k tomuto obrázku šablonu nominace na smazání.\n\n- Je tento obrázek správně kategorizován?\nPokud klepnete na Ne (není správně kategorizován), přidáte k tomuto obrázku šablonu nominace na kategorizaci.\n\nPokud je vše v pořádku, nebude k obrázku přidána žádná šablona a autorovi budete moci poděkovat.</string>
<string name="no_image">Nejsou použity žádné obrázky</string>
<string name="no_image_reverted">Žádné revertované obrázky</string>
<string name="no_image_uploaded">Žádné nahrané obrázky</string>
<string name="no_notification">Nemáte žádná nepřečtená upozornění</string>
<string name="no_read_notification">Nemáte žádná přečtená upozornění</string>
<string name="share_logs_using">Sdílet logy pomocí</string>
<string name="check_your_email_inbox">Zkontrolujte svou e-mailovou schránku</string>
<string name="menu_option_read">Zobrazit přečtené</string>
<string name="menu_option_unread">Zobrazit nepřečtené</string>
<string name="error_occurred_in_picking_images">Nastala chyba při vybírání obrázků</string>
@ -483,10 +541,13 @@
<string name="exif_tag_name_lensModel">Model objektivu</string>
<string name="exif_tag_name_serialNumbers">Sériová čísla</string>
<string name="exif_tag_name_software">Software</string>
<string name="media_location_permission_denied">Přístup k poloze médií odmítnut</string>
<string name="add_location_manually">Možná nebudeme schopni automaticky získat údaje o poloze z obrázků, které nahrajete. Před odesláním prosím přidejte odpovídající polohu ke každému obrázku</string>
<string name="share_text">Nahrávejte fotky na Wikimedia Commons přímo s vašeho mobilu. Stáhněte si aplikaci: %1$s</string>
<string name="share_via">Sdílet aplikaci pomocí…</string>
<string name="image_info">Informace o obrázku</string>
<string name="no_categories_found">Nebyly nalezeny žádné kategorie</string>
<string name="no_depiction_found">Nenalezena žádná znázornění</string>
<string name="upload_cancelled">Nahrání zrušeno</string>
<string name="previous_image_title_description_not_found">Neexistují žádné údaje k titulku a popisu předcházejícího obrázku</string>
<string name="dialog_box_text_nomination">Proč by měl být soubor %1$s smazán?</string>
@ -497,15 +558,50 @@
<string name="delete_helper_show_deletion_message_if">Soubor %1$s byl nominován na smazání.</string>
<string name="delete_helper_show_deletion_title_failed">Chyba</string>
<string name="delete_helper_show_deletion_message_else">Nepodařilo se požádat o smazání.</string>
<string name="delete_helper_ask_spam_selfie" fuzzy="true">Selfie</string>
<string name="delete_helper_ask_spam_blurry" fuzzy="true">Rozmazané</string>
<string name="delete_helper_ask_spam_nonsense" fuzzy="true">Nesmysl</string>
<string name="delete_helper_ask_spam_selfie">selfie, které není použito v žádném článku</string>
<string name="delete_helper_ask_spam_blurry">úplně rozmazané</string>
<string name="delete_helper_ask_spam_nonsense">nesmysl, naprosto nepoužitelné v jakémkoli článku</string>
<string name="delete_helper_ask_reason_copyright_press_photo">Tisková fotka</string>
<string name="delete_helper_ask_reason_copyright_internet_photo">Náhodná fotka z internetu</string>
<string name="delete_helper_ask_reason_copyright_logo">Logo</string>
<string name="delete_helper_ask_reason_copyright_no_freedom_of_panorama">Porušení svobody panoramatu</string>
<string name="delete_helper_ask_alert_set_positive_button_reason">Pretože to je</string>
<string name="category_edit_helper_make_edit_toast">Pokouším se aktualizovat kategorie.</string>
<string name="category_edit_helper_show_edit_title">Aktualizace kategorií</string>
<string name="category_edit_helper_show_edit_title_success">Úspěch</string>
<plurals name="category_edit_helper_show_edit_message_if">
<item quantity="one">Byla přidána kategorie %1$s.</item>
<item quantity="few">Byly přidány kategorie %1$s.</item>
<item quantity="many">Byly přidány kategorie %1$s.</item>
<item quantity="other">Byly přidány kategorie %1$s.</item>
</plurals>
<string name="category_edit_helper_edit_message_else">Nepodařilo se přidat kategorie.</string>
<string name="category_edit_button_text">Aktualizovat kategorie</string>
<string name="depictions_edit_helper_make_edit_toast">Pokouším se aktualizovat znázornění.</string>
<string name="depictions_edit_helper_show_edit_title">Upravit znázornění</string>
<plurals name="depictions_edit_helper_show_edit_message_if">
<item quantity="one">Bylo přidáno znázornění %1$s.</item>
<item quantity="few">Byla přidána znázornění %1$s.</item>
<item quantity="many">Byla přidána znázornění %1$s.</item>
<item quantity="other">Byla přidána znázornění %1$s.</item>
</plurals>
<string name="depictions_edit_helper_edit_message_else">Nepodařilo se přidat znázornění.</string>
<string name="coordinates_edit_helper_make_edit_toast">Pokouším se aktualizovat souřadnice.</string>
<string name="coordinates_edit_helper_show_edit_title">Aktualizace souřadnicí</string>
<string name="description_edit_helper_show_edit_title">Aktualizace popisu</string>
<string name="caption_edit_helper_show_edit_title">Aktualizace titulku</string>
<string name="coordinates_edit_helper_show_edit_title_success">Úspěch</string>
<string name="coordinates_edit_helper_show_edit_message">Souřadnice %1$s byly přidány.</string>
<string name="description_edit_helper_show_edit_message">Popisy byly přidány.</string>
<string name="caption_edit_helper_show_edit_message">Titulek byl přidán.</string>
<string name="coordinates_edit_helper_edit_message_else">Nepodařilo se přidat souřadnice.</string>
<string name="description_edit_helper_edit_message_else">Nepodařilo se přidat popisy.</string>
<string name="caption_edit_helper_edit_message_else">Nepodařilo se přidat titulek.</string>
<string name="coordinates_picking_unsuccessful">Souřadnice obrázku nebyly aktualizovány</string>
<string name="descriptions_picking_unsuccessful">Nepodařilo se získat popisy.</string>
<string name="description_activity_title">Upravit popisy a titulky</string>
<string name="share_image_via">Sdílet obrázek pomocí</string>
<string name="you_have_no_achievements_yet">Zatím nemáte žádné příspěvky</string>
<string name="no_achievements_yet">Zatím nemáte žádné příspěvky</string>
<string name="account_created">Účet byl založen!</string>
<string name="text_copy">Text byl zkopírován do schránky.</string>
@ -516,9 +612,13 @@
<string name="place_state_needs_photo">Potřebuje fotku</string>
<string name="place_type">Typ místa:</string>
<string name="nearby_search_hint">Most, muzeum, hotel atd.</string>
<string name="you_must_reset_your_passsword" fuzzy="true">Při přihlášení nastala chyba, musíte si resetovat vaše heslo!</string>
<string name="you_must_reset_your_passsword">Při přihlášení nastala chyba. Musíte si resetovat vaše heslo!</string>
<string name="title_for_media">MÉDIA</string>
<string name="title_for_child_classes">PODŘAZENÉ TŘÍDY</string>
<string name="title_for_parent_classes">NADŘAZENÉ TŘÍDY</string>
<string name="upload_nearby_place_found_title">Místo v okolí nalezeno</string>
<string name="upload_nearby_place_found_description_singular" fuzzy="true">Je toto fotka místa %1$s?</string>
<string name="upload_nearby_place_found_description_plural">Je na těchto obrázcích %1$s?</string>
<string name="upload_nearby_place_found_description_singular">Je toto obrázek místa %1$s?</string>
<string name="title_app_shortcut_bookmark">Záložky</string>
<string name="title_app_shortcut_setting">Nastavení</string>
<string name="remove_bookmark">Odebráno ze záložek</string>
@ -526,15 +626,21 @@
<string name="wallpaper_set_unsuccessfully">Něco se pokazilo. Tapetu se nepodařilo nastavit</string>
<string name="setting_wallpaper_dialog_title">Nastavit jako tapetu</string>
<string name="setting_wallpaper_dialog_message">Nastavování tapety. Prosím, čekejte…</string>
<string name="theme_default_name">Podle systému</string>
<string name="theme_dark_name">Tmavý</string>
<string name="theme_light_name">Světlý</string>
<string name="cannot_open_location_settings">Nepodařilo se otevřít nastavení polohy. Zapněte prosím polohu ručně</string>
<string name="recommend_high_accuracy_mode">Pro nejpřesnější výsledky zvolte režim vysoké přesnosti.</string>
<string name="ask_to_turn_location_on">Zapnout lokaci?</string>
<string name="ask_to_turn_location_on_text">Zapněte prosím funkci polohy, aby mohla aplikace zobrazovat vaší aktuální polohu</string>
<string name="nearby_needs_location">Funkce Poblíž potřebuje pro správné fungování povolenou polohu</string>
<string name="explore_map_needs_location">Používání mapy vyžaduje oprávnění k poloze pro zobrazení obrázků v okolí</string>
<string name="upload_map_location_access">Pro automatické nastavení polohy musíte udělit přístup k poloze.</string>
<string name="use_location_from_similar_image">Pořídili jste tyto dva obrázky na stejném místě? Chcete použít zeměpisnou šířku/délku obrázku vpravo?</string>
<string name="load_more">Načíst další</string>
<string name="nearby_no_results">Nebyla nalezená žádná místa, zkuste změnit kritéria vyhledávání.</string>
<string name="todo_improve">Navrhovaná vylepšení:</string>
<string name="missing_category">- Přidejte kategorie k tomuto obrázku pro zlepšení použitelnosti.</string>
<string name="missing_article">Přidejte tento obrázek do přidruženého článku na Wikipedii, který neobsahuje žádné obrázky.</string>
<string name="add_picture_to_wikipedia_article_title">Přidat obrázek na Wikipedii</string>
<string name="add_picture_to_wikipedia_article_desc">Chcete přidat tento obrázek do článku na %1$s Wikipedii?</string>
@ -545,11 +651,14 @@
<string name="wikipedia_instructions_step_3">3. Najděte v článku odpovídající sekci pro Váš obrázek</string>
<string name="wikipedia_instructions_step_4">4. Klikněte na ikonu Editovat (ikona tužky) pro danou sekci.</string>
<string name="wikipedia_instructions_step_5">5. Vložte wikitext na vhodné místo.</string>
<string name="wikipedia_instructions_step_6">6. Pokud je to nutné, upravte wikitext pro vhodné umístění. Pro více informací se podívejte &lt;a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\"&gt;sem&lt;/a&gt;.</string>
<string name="wikipedia_instructions_step_7">7. Zveřejněte článek</string>
<string name="copy_wikicode_to_clipboard">Zkopírujte wikitext</string>
<string name="pause">pozastavit</string>
<string name="resume">pokračovat</string>
<string name="paused">Pozastaveno</string>
<string name="more">Další</string>
<string name="bookmarks">Záložky</string>
<string name="achievements_tab_title">Dosažené úspěchy</string>
<string name="leaderboard_tab_title">Žebříček</string>
<string name="rank_prefix">Pořadí</string>
@ -564,6 +673,190 @@
<string name="menu_set_avatar">Nastavit jako avatar</string>
<string name="leaderboard_yearly">Ročně</string>
<string name="leaderboard_weekly">Týdně</string>
<string name="leaderboard_all_time">Celou dobu</string>
<string name="leaderboard_upload">Nahrát</string>
<string name="leaderboard_nearby">Poblíž</string>
<string name="leaderboard_used">Použito</string>
<string name="leaderboard_my_rank_button_text">Moje pořadí</string>
<string name="limited_connection_enabled">Režim omezeného připojení zapnut!</string>
<string name="limited_connection_disabled">Režim omezeného připojení vypnut. Čekající nahrávání budou nyní pokračovat.</string>
<string name="limited_connection_mode">Režim omezeného připojení</string>
<string name="statistics_quality">Kvalitní obrázky</string>
<string name="quality_images_info">Kvalitní obrázky jsou diagramy nebo fotografie, které splňují určité standardy kvality (obvykle technického charakteru) a jsou hodnotné pro projekty Wikimedia</string>
<string name="resuming_upload">Pokračování v nahrávání…</string>
<string name="pausing_upload">Pozastavování nahrávání…</string>
<string name="cancelling_upload">Přerušování nahrávání…</string>
<string name="cancel_upload">Zrušit nahrávání</string>
<string name="limited_connection_explanation">Zapnuli jste režim omezeného připojení. Všechna nahrávání jsou pozastavena a budou pokračovat po vypnutí tohoto režimu.</string>
<string name="limited_connection_is_on">Režim omezeného připojení je zapnutý.</string>
<string name="media_details_tooltip">Napište prosím krátký titulek, který shrnuje obsah obrázku. Do popisu napište, čím je obrázek zajímavý, typický nebo zvláštní a popište kontext, ať už je viditelný, či nikoli. Pokuste se co nejvíce používat přesnou terminologii.</string>
<string name="depicts_tooltip">Najděte a vyberte všechny koncepty, které tento obrázek zobrazuje. Buďte co nejvíce konkrétní. Pokud obrázek zobrazuje více položek, vyberte všechny v rozumné míře. Nevybírejte obecné štítky, pokud jsou dostupné konkrétnější.</string>
<string name="categories_tooltip">Vyberte prosím všechny příslušné kategorie. Na rozdíl od znázornění jsou kategorie pouze v angličtině.</string>
<string name="license_tooltip">Díky Commons může váš obrázek kdykoli kdokoli znovu použít a přizpůsobit. Chcete se vzdát všech práv? Chcete, aby vám bylo vždy připsáno autorství? Chcete, aby úpravy používaly stejnou licenci?</string>
<string name="depicts_step_title">Znázornění</string>
<string name="license_step_title">Licence média</string>
<string name="media_detail_step_title">Podrobnosti o médiu</string>
<string name="menu_view_category_page">Zobrazit stránku kategorie</string>
<string name="menu_view_item_page">Zobrazit stránku položky</string>
<string name="app_ui_language">Jazyk rozhraní aplikace</string>
<string name="remove">Odstraní titulek a popisek</string>
<string name="read_help_link">Číst dál</string>
<string name="media_detail_in_all_languages">Ve všech jazycích</string>
<string name="choose_a_location">Vybrat polohu</string>
<string name="pan_and_zoom_to_adjust">Posuňte a přibližte pro úpravu</string>
<string name="select_location_location_picker">Vybrat umístění</string>
<string name="show_in_map_app">Zobrazit v mapové aplikaci</string>
<string name="modify_location">Upravit umístění</string>
<string name="location_picker_image_view">Zobrazení obrázku výběru polohy</string>
<string name="location_picker_image_view_shadow">\n Stín zobrazení obrázku výběru polohy</string>
<string name="image_location">Umístění obrázku</string>
<string name="check_whether_location_is_correct">Zkontrolujte, zda je umístění správné</string>
<string name="label">Štítek</string>
<string name="description">Popis</string>
<string name="title_page_bookmarks_items">Položky</string>
<string name="custom_selector_title">Vlastní výběr</string>
<string name="custom_selector_empty_text">Žádné obrázky</string>
<string name="done">Hotovo</string>
<string name="back">Zpět</string>
<string name="welcome_custom_picture_selector_text">Vítejte ve výběru vlastních obrázků</string>
<string name="custom_selector_info_text1">Tento výběr zobrazuje, které obrázky jste již nahráli do Commons.</string>
<string name="custom_selector_info_text2">Na rozdíl od obrázku nalevo má obrázek napravo logo Commons, které značí, že byl již nahrán.\n Klepněte a podržte pro náhled obrázku.</string>
<string name="welcome_custom_selector_ok">Skvělé</string>
<string name="custom_selector_already_uploaded_image_text">Tento obrázek byl již nahrán do Commons.</string>
<string name="custom_selector_over_limit_warning">Z technických důvodů nedokáže aplikace spolehlivě nahrát více než %1$d obrázků naráz. Limit %1$d byl překročen o %2$d.</string>
<string name="custom_selector_dismiss_limit_warning_button_text">Zavřít</string>
<string name="custom_selector_button_limit_text">Maximum: %1$d</string>
<string name="custom_selector_limit_error_desc">Chyba: překročen limit nahrání</string>
<string name="wlm_upload_info">Tento obrázek bude zařazen do soutěže Wiki miluje památky</string>
<string name="display_monuments">Zobrazit památky</string>
<string name="wlm_month_message">Je měsíc soutěže Wiki miluje památky!</string>
<string name="learn_more">ZJISTIT VÍCE</string>
<string name="wlm_campaign_description">Wiki miluje památky je mezinárodní soutěž týkající se památek, organizovaná Wikimedií</string>
<string name="need_permission">Je vyžadováno oprávnění</string>
<string name="read_phone_state_permission_message">Mapy v okolí potřebují ke správné funkčnosti číst STAV TELEFONU</string>
<string name="contributions_of_user">Příspěvky uživatele: %s</string>
<string name="achievements_of_user">Úspěchy uživatele: %s</string>
<string name="menu_view_user_page">Zobrazit profil uživatele</string>
<string name="edit_depictions">Upravit znázornění</string>
<string name="edit_categories">Upravit kategorie</string>
<string name="advanced_options">Pokročilé možnosti</string>
<string name="advanced_query_info_text">Dotaz na objekty v okolí si můžete přizpůsobit. Pokud se objeví chyby, možnost resetujte.</string>
<string name="apply">Použít</string>
<string name="reset">Resetovat</string>
<string name="location_message">Údaje o poloze pomáhají editorům Wiki najít váš obrázek, díky čemuž je mnohem užitečnější.\nVaše nedávná nahrání nemají žádnou polohu.\nDoporučujeme zapnout polohu v nastavení aplikace fotoaparátu.\nDěkujeme, že nahráváte!</string>
<string name="no_location_found_title">Nenalezena žádná poloha</string>
<string name="no_location_found_message">Co takhle přidat místo, kde byl tento obrázek pořízen?\nÚdaje o poloze pomáhají editorům Wiki najít váš obrázek, díky čemuž je mnohem užitečnější.\nDěkujeme!</string>
<string name="add_location">Přidat polohu</string>
<string name="feedback_sharing_data_alert">Odstraňte prosím z tohoto e-mailu všechny informace, které nechcete sdílet veřejně. Mějte také na paměti, že e-mailová adresa, kterou používáte, a související jméno a profilový obrázek, budou veřejně zobrazeny.</string>
<string name="explore_map_details">Podrobnosti</string>
<string name="achievements_unavailable_beta">Úspěchy jsou dostupné pouze v produkční verzi. Více informací viz dokumentace pro vývojáře.</string>
<string name="leaderboard_unavailable_beta">Žebříček je dostupný pouze v produkční verzi. Více informací viz dokumentace pro vývojáře.</string>
<string name="copyright_popup">Nahrávejte pouze obrázky, které jste sami pořídili. Uživatelé, kteří nahrají obrázky chráněné autorským právem, budou zablokováni. To platí i pro beta verzi. Děkujeme za testování aplikace!</string>
<string name="select_feedback_data_choice">Zrušte zaškrtnutí všech informací, které nechcete sdílet veřejně.</string>
<string name="api_level">Úroveň API</string>
<string name="android_version">Verze systému Android</string>
<string name="device_manufacturer">Výrobce zařízení</string>
<string name="device_model">Model zařízení</string>
<string name="device_name">Název zařízení</string>
<string name="network_type">Typ sítě</string>
<string name="thanks_feedback">Děkujeme za odeslání zpětné vazby</string>
<string name="error_feedback">Chyba při odesílání zpětné vazby</string>
<string name="enter_description">Jaká je vaše zpětná vazba?</string>
<string name="your_feedback">Vaše zpětná vazba</string>
<string name="mark_as_not_for_upload">Označit jako neurčené k nahrání</string>
<string name="unmark_as_not_for_upload">Zrušit označení jako neurčené k nahrání</string>
<string name="marking_as_not_for_upload">Označování jako neurčené k nahrání</string>
<string name="unmarking_as_not_for_upload">Rušení označení jako neurčené k nahrání</string>
<string name="show_already_actioned_pictures">Zobrazit již zpracované obrázky</string>
<string name="hiding_already_actioned_pictures">Skrývání již zpracovaných obrázků</string>
<string name="no_more_images_found">Nenalezeny žádné další obrázky</string>
<string name="this_image_is_already_uploaded">Tento obrázek byl již nahrán</string>
<string name="can_not_select_this_image_for_upload">Tento obrázek nelze vybrat k nahrání</string>
<string name="image_selected">Obrázek vybrán</string>
<string name="image_marked_as_not_for_upload">Obrázek označen jako neurčen k nahrání</string>
<string name="menu_view_report">Nahlásit</string>
<string name="menu_view_set_white_background">Nastavit bílé pozadí</string>
<string name="menu_view_set_black_background">Nastavit černé pozadí</string>
<string name="report_violation">Nahlásit porušení podmínek</string>
<string name="report_user">Nahlásit tohoto uživatele</string>
<string name="report_content">Nahlásit tento obsah</string>
<string name="request_user_block">Požádat o zablokování tohoto uživatele</string>
<string name="welcome_to_full_screen_mode_text">Vítejte v celoobrazovkovém režimu výběru</string>
<string name="full_screen_mode_zoom_info">Použijte dva prsty pro přiblížení a oddálení.</string>
<string name="full_screen_mode_features_info">Rychlým a dlouhým přejetím prstem provedete tyto akce: \n- Doleva/doprava: Přejít na předchozí/další \n- Nahoru: Vybrat\n- Dolů: Označit jako neurčené k nahrání.</string>
<string name="set_up_avatar_toast_string">Pro nastavení vašeho avatara v žebříčku klepněte na tlačítko „Nastavit jako avatar“ v rozbalovací nabídce u jakéhokoli obrázku.</string>
<string name="similar_coordinate_description_auto_set">Souřadnice nejsou přesné souřadnice, ale osoba, která nahrála tento obrázek, si myslí, že jsou dostatečně blízko.</string>
<string name="storage_permissions_denied">Přístup k úložišti zamítnut</string>
<string name="unable_to_share_upload_item">Tuto položku nelze sdílet</string>
<string name="permissions_are_required_for_functionality">Pro funkčnost jsou vyžadována oprávnění</string>
<string name="learn_how_to_write_a_useful_description">Naučte se, jak psát užitečný popis</string>
<string name="learn_how_to_write_a_useful_caption">Naučte se, jak psát užitečný popis</string>
<string name="see_your_achievements">Podívejte se na své úspěchy</string>
<string name="edit_image">Upravit obrázek</string>
<string name="edit_location">Upravit polohu</string>
<string name="location_updated">Poloha aktualizována!</string>
<string name="remove_location">Odstranit polohu</string>
<string name="remove_location_warning_title">Odstranit varování o poloze</string>
<string name="remove_location_warning_desc">Díky poloze jsou obrázky užitečnější a lze je lépe najít. Opravdu chcete polohu z tohoto obrázku odebrat?</string>
<string name="location_removed">Poloha odebrána!</string>
<string name="send_thanks_to_author">Poděkovat autorovi</string>
<string name="error_sending_thanks">Chyba při děkování autorovi.</string>
<string name="invalid_login_message">Vaše přihlášení vypršelo. Přihlaste se prosím znovu.</string>
<string name="no_application_available_to_open_gpx_files">Není dostupná žádná aplikace k otevření souborů GPX</string>
<string name="file_saved_successfully">Soubor úspěšně uložen</string>
<string name="do_you_want_to_open_gpx_file">Chcete otevřít soubor GPX?</string>
<string name="do_you_want_to_open_kml_file">Chcete otevřít soubor KML?</string>
<string name="failed_to_save_kml_file">Nepodařilo se uložit soubor KML.</string>
<string name="failed_to_save_gpx_file">Nepodařilo se uložit soubor GPX.</string>
<string name="saving_kml_file">Ukládání souboru KML</string>
<string name="saving_gpx_file">Ukládání souboru GPX</string>
<plurals name="custom_picker_images_selected_title_appendix">
<item quantity="one">Vybrán %d obrázek</item>
<item quantity="few">Vybrány %d obrázky</item>
<item quantity="many">Vybráno %d obrázků</item>
<item quantity="other">Vybráno %d obrázků</item>
</plurals>
<string name="multiple_files_depiction">Nezapomeňte, že všechny obrázky ve hromadném nahrání získají stejné kategorie a znázornění. Pokud obrázky nesdílí znázornění a kategorie, nahrajte je prosím zvlášť.</string>
<string name="multiple_files_depiction_header">Informace o hromadných nahráních</string>
<string name="nearby_wikitalk">Nahlásit problém s touto položkou do Wikidat</string>
<string name="please_enter_some_comments">Zadejte prosím komentář</string>
<string name="talk">Diskuze</string>
<string name="write_something_about_the_item">Napište komentář o položce „%1$s“. Bude veřejně viditelný.</string>
<string name="does_not_exist_anymore_no_picture_can_ever_be_taken_of_it">„%1$s“ již neexistuje, nelze z něj již tedy pořídit obrázek.</string>
<string name="is_at_a_different_place_please_specify_the_correct_place_below_if_possible_tell_us_the_correct_latitude_longitude">„%1$s“ je na jiném místě. Zadejte prosím správné místo, a pokud je to možné, napište správnou zeměpisnou šířku a délku.</string>
<string name="other_problem_or_information_please_explain_below">Jiný problém nebo informace (vysvětlete prosím níže).</string>
<string name="feedback_destination_note">Vaše zpětná vazba bude zveřejněna na následující stránce wiki: &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\"&gt;Commons:Mobile app/Feedback&lt;/a&gt;</string>
<string name="are_you_sure_that_you_want_cancel_all_the_uploads">Opravdu chcete zrušit všechna nahrávání?</string>
<string name="cancelling_all_the_uploads">Rušení všech nahrávání…</string>
<string name="uploads">Nahrávání</string>
<string name="pending">Čekající</string>
<string name="failed">Selhaná</string>
<string name="could_not_load_place_data">Nepodařilo se načíst údaje o místě</string>
<string name="custom_selector_delete_folder">Smazat složku</string>
<string name="custom_selector_confirm_deletion_title">Potvrďte smazání</string>
<string name="custom_selector_confirm_deletion_message">Opravdu chcete smazat složku %1$s obsahující %2$d položek?</string>
<string name="custom_selector_delete">Smazat</string>
<string name="custom_selector_cancel">Zrušit</string>
<string name="custom_selector_folder_deleted_success">Složka %1$s úspěšně smazána</string>
<string name="custom_selector_folder_deleted_failure">Nepodařilo se smazat složku %1$s</string>
<string name="custom_selector_error_trashing_folder_contents">Chyba při vyhazování obsahu složky: %1$s</string>
<string name="custom_selector_folder_not_found_error">Nepodařilo se načíst cestu ke složce pro ID bucketu: %1$d</string>
<string name="red_pin">Toto místo zatím nemá žádný obrázek, vyfoťte jej!</string>
<string name="green_pin">Toto místo již má obrázek.</string>
<string name="grey_pin">Kontrola, zda má toto místo obrázek.</string>
<string name="error_while_loading">Chyba při načítání</string>
<string name="no_usages_found">Nenalezena žádná použití</string>
<string name="usages_on_commons_heading">Commons</string>
<string name="usages_on_other_wikis_heading">Jiné wiki</string>
<string name="file_usages_container_heading">Použití souboru</string>
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
<string name="account">Účet</string>
<string name="vanish_account">Nechat zmizet účet</string>
<string name="account_vanish_request_confirm_title">Varování o zmizení účtu</string>
<string name="account_vanish_request_confirm">Zmizení je &lt;b&gt;poslední možností&lt;/b&gt; a mělo by se &lt;b&gt;používat pouze tehdy, když si přejete navždy přestat editovat&lt;/b&gt; a také skrýt co nejvíce svých minulých asociací.&lt;br/&gt;&lt;br/&gt;Smazání účtu na Wikimedia Commons se provádí změnou jména účtu tak, aby ostatní nemohli rozpoznat vaše příspěvky, v procesu nazývaném zmizení účtu. &lt;b&gt;Zmizení nezaručuje úplnou anonymitu ani neodstraní příspěvky do projektů&lt;/b&gt;.</string>
<string name="caption">Titulek</string>
<string name="caption_copied_to_clipboard">Titulek zkopírován do schránky</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Gratulujeme, všechny obrázky v tomto albu byly buď nahrány, nebo označeny jako neurčené k nahrání.</string>
<string name="show_in_explore">Zobrazit v kartě Objevit</string>
<string name="show_in_nearby">Zobrazit v kartě Poblíž</string>
</resources>

View file

@ -119,6 +119,7 @@
<string name="login_failed_throttled">For mange mislykkede forsøg. Prøv igen om et par minutter.</string>
<string name="login_failed_blocked">Beklager, denne bruger er blevet blokeret på Commons</string>
<string name="login_failed_2fa_needed">Du skal angive din tofaktorgodkendelseskode.</string>
<string name="login_failed_email_auth_needed">En login-bekræftelseskode er blevet sendt til din e-mailadresse. Angiv koden for at logge ind.</string>
<string name="login_failed_generic">Login mislykkedes</string>
<string name="share_upload_button">Upload</string>
<string name="multiple_share_base_title">Navngiv dette sæt</string>
@ -224,6 +225,7 @@
<string name="become_a_tester_title">Bliv betatester</string>
<string name="become_a_tester_description">Registrer dig på vores betakanal på Google Play og få tidlig adgang til nye funktioner og fejlrettelser</string>
<string name="_2fa_code">2FA-kode</string>
<string name="email_auth_code">E-mail-bekræftelseskode</string>
<string name="logout_verification">Ønsker du at logge ud?</string>
<string name="mediaimage_failed">Mediebillede mislykkedes</string>
<string name="no_subcategory_found">Ingen underkategorier fundet</string>
@ -823,4 +825,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Tillykke, alle billeder i dette album er enten blevet uploadet eller markeret som ikke til upload.</string>
<string name="show_in_explore">Vis i Udforsk</string>
<string name="show_in_nearby">Vis i I nærheden</string>
<string name="image_tag_line_created_and_uploaded_by">Oprettet og uploadet af: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Oprettet af %1$s og uploadet af %2$s</string>
</resources>

View file

@ -16,6 +16,7 @@
* Justman10000
* Kghbln
* Killarnee
* Laserlicht
* ManuelFranz
* Mcliquid
* Metalhead64
@ -140,6 +141,8 @@
<string name="menu_from_camera">Foto schießen</string>
<string name="menu_nearby">In der Nähe</string>
<string name="provider_contributions">Meine hochgeladenen Dateien</string>
<string name="menu_copy_link">Link kopieren</string>
<string name="menu_link_copied">Der Link wurde in die Zwischenablage kopiert.</string>
<string name="menu_share">Teilen</string>
<string name="menu_view_file_page">Dateiseite anzeigen</string>
<string name="share_title_hint">Titel (erforderlich)</string>
@ -150,6 +153,7 @@
<string name="login_failed_throttled">Zu viele erfolglose Versuche. Bitte in einigen Minuten erneut versuchen.</string>
<string name="login_failed_blocked">Dieser Benutzer wurde leider auf Commons gesperrt</string>
<string name="login_failed_2fa_needed">Du musst deinen Code zur Zwei-Faktor-Authentifizierung angeben.</string>
<string name="login_failed_email_auth_needed">Ein Login-Code wurde an Ihre E-Mail-Adresse gesendet. Bitte geben Sie den Code ein, um sich anzumelden.</string>
<string name="login_failed_generic">Anmeldung fehlgeschlagen</string>
<string name="share_upload_button">Hochladen</string>
<string name="multiple_share_base_title">Benenne dieses Set</string>
@ -254,6 +258,7 @@
<string name="become_a_tester_title">Beta-Tester werden</string>
<string name="become_a_tester_description">Melde dich bei unserem Beta-Kanal auf Google Play an und erhalte frühen Zugriff auf neue Funktionen und Fehlerbehebungen</string>
<string name="_2fa_code">2FA-Code</string>
<string name="email_auth_code">E-Mail-Bestätigungscode</string>
<string name="logout_verification">Möchtest du dich wirklich abmelden?</string>
<string name="mediaimage_failed">Medienbild fehlgeschlagen</string>
<string name="no_subcategory_found">Keine Unterkategorien gefunden</string>
@ -398,11 +403,13 @@
<string name="delete">Löschen</string>
<string name="Achievements">Errungenschaften</string>
<string name="Profile">Profil</string>
<string name="badges">Auszeichnungen</string>
<string name="statistics">Statistiken</string>
<string name="statistics_thanks">Erhaltene Dankeschöns</string>
<string name="statistics_featured">Vorgestellte Bilder</string>
<string name="statistics_wikidata_edits">Bilder über „Orte in der Nähe“</string>
<string name="level" fuzzy="true">Niveau</string>
<string name="level">Level %d</string>
<string name="profileLevel">%s (Level %s)</string>
<string name="images_uploaded">Hochgeladene Bilder</string>
<string name="image_reverts">Bilder nicht zurückgesetzt</string>
<string name="images_used_by_wiki">Verwendete Bilder</string>
@ -434,6 +441,7 @@
<string name="map_application_missing">Auf deinem Gerät konnte keine kompatible Karten-App gefunden werden. Bitte installiere eine Karten-App, um diese Funktion nutzen zu können.</string>
<string name="title_page_bookmarks_pictures">Bilder</string>
<string name="title_page_bookmarks_locations">Standorte</string>
<string name="title_page_bookmarks_categories">Kategorien</string>
<string name="menu_bookmark">Zu den Lesezeichen hinzufügen/entfernen</string>
<string name="provider_bookmarks">Lesezeichen</string>
<string name="bookmark_empty">Du hast keine Lesezeichen hinzugefügt</string>
@ -696,7 +704,7 @@
<string name="pan_and_zoom_to_adjust">Schwenken und Zoomen zum Anpassen</string>
<string name="select_location_location_picker">Ort auswählen</string>
<string name="show_in_map_app">In Karten-App anzeigen</string>
<string name="modify_location">Standort beabeiten</string>
<string name="modify_location">Standort bearbeiten</string>
<string name="location_picker_image_view">Die Bildansicht der Standortauswahl</string>
<string name="location_picker_image_view_shadow">Der Schatten der Bildansicht der Ortsauswahl</string>
<string name="image_location">Bildstandort</string>
@ -783,7 +791,7 @@
<string name="learn_how_to_write_a_useful_caption">Erfahre, wie man eine nützliche Überschrift schreibt</string>
<string name="see_your_achievements">Deine Erfolge ansehen</string>
<string name="edit_image">Bild bearbeiten</string>
<string name="edit_location">Standort beabeiten</string>
<string name="edit_location">Standort bearbeiten</string>
<string name="location_updated">Standort aktualisiert!</string>
<string name="remove_location">Standort entfernen</string>
<string name="remove_location_warning_title">Standortwarnung entfernen</string>

View file

@ -315,7 +315,7 @@
<string name="share_image_via">Resımi vıla kerê pê</string>
<string name="no_achievements_yet" fuzzy="true">Hewna to iştirak nêkerdo</string>
<string name="account_created">Hesab vıraziya!</string>
<string name="text_copy">Metın kopyayê panoyi biyo</string>
<string name="text_copy">Metın be panoyi ra kopya bi</string>
<string name="notification_mark_read">Pêhesnayışi wanaye nışan bıkerê</string>
<string name="some_error">Yew xeta biye!</string>
<string name="place_state">Weziyetê cayi:</string>

View file

@ -123,6 +123,8 @@
<string name="menu_from_camera">Τραβήξτε φωτογραφία</string>
<string name="menu_nearby">Κοντά</string>
<string name="provider_contributions">Οι μεταφορτώσεις μου</string>
<string name="menu_copy_link">Αντιγραφή συνδέσμου</string>
<string name="menu_link_copied">Ο σύνδεσμος αντιγράφηκε στο πρόχειρο</string>
<string name="menu_share">Κοινοποίηση</string>
<string name="menu_view_file_page">Προβολή σελίδας αρχείου</string>
<string name="share_title_hint">Λεζάντα (Απαιτείται)</string>
@ -237,6 +239,7 @@
<string name="become_a_tester_title">Γίνετε Δοκιμαστής Beta</string>
<string name="become_a_tester_description">Συμμετέχετε στο κανάλι beta στο Google Play και αποκτήστε πρώιμη πρόσβαση σε νέες λειτουργίες και διορθώσεις σφαλμάτων</string>
<string name="_2fa_code">Κωδικός 2FA</string>
<string name="email_auth_code">Κωδικός επαλήθευσης ηλεκτρονικού ταχυδρομείου</string>
<string name="logout_verification">Θέλετε σίγουρα να αποσυνδεθείτε;</string>
<string name="mediaimage_failed">Η εικόνα πολυμέσων απέτυχε</string>
<string name="no_subcategory_found">Δε βρέθηκαν υποκατηγορίες</string>
@ -381,11 +384,13 @@
<string name="delete">Διαγραφή</string>
<string name="Achievements">Επιτεύγματα</string>
<string name="Profile">Προφίλ</string>
<string name="badges">Σήματα</string>
<string name="statistics">Στατιστικά</string>
<string name="statistics_thanks">Ευχαριστίες που έχετε λάβει</string>
<string name="statistics_featured">Προβεβλημμένες εικόνες</string>
<string name="statistics_wikidata_edits">Εικόνες μέσω «Κοντινά μέρη»</string>
<string name="level" fuzzy="true">Επίπεδο</string>
<string name="level">Επίπεδο %d</string>
<string name="profileLevel">%s (Επίπεδο %s)</string>
<string name="images_uploaded">Εικόνες που μεταφορτώθηκαν</string>
<string name="image_reverts">Εικόνες που δεν ανεστράφησαν</string>
<string name="images_used_by_wiki">Εικόνες που χρησιμοποιήθηκαν</string>
@ -417,6 +422,7 @@
<string name="map_application_missing">Δε βρέθηκε καμία συμβατή εφαρμογή χάρτη στη συσκευή σας. Εγκαταστήστε μια εφαρμογή χάρτη για να χρησιμοποιήσετε αυτήν τη δυνατότητα.</string>
<string name="title_page_bookmarks_pictures">Φωτογραφίες</string>
<string name="title_page_bookmarks_locations">Τοποθεσίες</string>
<string name="title_page_bookmarks_categories">Κατηγορίες</string>
<string name="menu_bookmark">Προσθήκη/Κατάργηση σε σελιδοδείκτες</string>
<string name="provider_bookmarks">Σελιδοδείκτες</string>
<string name="bookmark_empty">Δεν έχετε προσθέσει σελιδοδείκτες</string>
@ -498,6 +504,7 @@
<string name="no_notification">Δεν έχετε αδιάβαστες ενημερώσεις</string>
<string name="no_read_notification">Δεν έχετε αδιάβαστες ενημερώσεις</string>
<string name="share_logs_using">Κοινή χρήση αρχείων καταγραφής χρησιμοποιώντας</string>
<string name="check_your_email_inbox">Ελέγξτε τα εισερχόμενα του email σας</string>
<string name="menu_option_read">Προβολή αναγνωσμένων</string>
<string name="menu_option_unread">Προβολή μη αναγνωσμένων</string>
<string name="error_occurred_in_picking_images">Παρουσιάστηκε σφάλμα κατά την επιλογή εικόνων</string>
@ -805,4 +812,20 @@
<string name="pending">Σε εκκρεμότητα</string>
<string name="failed">Απέτυχε</string>
<string name="could_not_load_place_data">Δεν ήταν δυνατή η φόρτωση δεδομένων της θέσης</string>
<string name="custom_selector_delete_folder">Διαγραφή φακέλου</string>
<string name="custom_selector_confirm_deletion_title">Επιβεβαίωση διαγραφής</string>
<string name="custom_selector_confirm_deletion_message">Είστε βέβαιοι ότι θέλετε να διαγράψετε τον φάκελο %1$s που περιέχει %2$d στοιχεία;</string>
<string name="custom_selector_delete">Διαγραφή</string>
<string name="custom_selector_cancel">Ακύρωση</string>
<string name="custom_selector_folder_deleted_success">Ο φάκελος %1$s διαγράφηκε με επιτυχία</string>
<string name="custom_selector_folder_deleted_failure">Αποτυχία διαγραφής του φακέλου %1$s</string>
<string name="red_pin">Αυτό το μέρος δεν έχει ακόμα φωτογραφία, πήγαινε να βγάλεις μία!</string>
<string name="green_pin">Αυτό το μέρος έχει ήδη μια φωτογραφία.</string>
<string name="grey_pin">Τώρα ελέγχεται αν αυτό το μέρος έχει φωτογραφία.</string>
<string name="error_while_loading">Σφάλμα κατά τη φόρτωση</string>
<string name="no_usages_found">Δεν βρέθηκαν χρήσεις</string>
<string name="file_usages_container_heading">Χρήσεις αρχείου</string>
<string name="account">Λογαριασμός</string>
<string name="caption">Λεζάντα</string>
<string name="caption_copied_to_clipboard">Η λεζάντα αντιγράφηκε στο πρόχειρο</string>
</resources>

View file

@ -22,6 +22,7 @@
* Fitoschido
* Gastonsaenz
* Hasley
* HylianAngel
* Ihojose
* JO777
* Jack30
@ -150,6 +151,7 @@
<string name="menu_from_camera">Tomar una foto</string>
<string name="menu_nearby">Cercanos</string>
<string name="provider_contributions">Mis subidas</string>
<string name="menu_copy_link">Copiar enlace</string>
<string name="menu_share">Compartir</string>
<string name="menu_view_file_page">Ver página del archivo</string>
<string name="share_title_hint">Leyenda (requerido)</string>
@ -413,7 +415,7 @@
<string name="statistics_thanks">Agradecimientos recibidos</string>
<string name="statistics_featured">Imágenes destacadas</string>
<string name="statistics_wikidata_edits">Imágenes vía \"Sitios Cercanos\"</string>
<string name="level" fuzzy="true">Nivel</string>
<string name="level">Nivel %d</string>
<string name="images_uploaded">Imágenes subidas</string>
<string name="image_reverts">Imágenes no revertidas</string>
<string name="images_used_by_wiki">Imágenes utilizadas</string>

View file

@ -15,6 +15,7 @@
* Freshman404
* Jeeputer
* Ladsgroup
* Lakzon
* Mardetanha
* Mehdi
* Mjbmr
@ -41,6 +42,14 @@
<string name="submit">ارسال</string>
<string name="add_another_description">توضیح دیگری را بیفزایید</string>
<string name="add_new_contribution">افزودن مشارکت جدید</string>
<string name="add_contribution_from_camera">افزودن مشارکت از دوربین</string>
<string name="add_contribution_from_photos">افزودن مشارکت از تصاویر</string>
<string name="add_contribution_from_contributions_gallery">افزودن مشارکت از گالری مشارکت‌های پیشین</string>
<string name="show_captions">برنگاشت</string>
<string name="row_item_language_description">شرح زبان</string>
<string name="row_item_caption">برنگاشت</string>
<string name="nearby_row_image">تصویر</string>
<string name="nearby_all">همه</string>
<string name="appwidget_img">تصویر روز</string>
<plurals name="uploads_pending_notification_indicator">
<item quantity="one">%1$d پرونده در حال بارگذاری</item>
@ -84,6 +93,7 @@
<string name="signup">ثبت نام</string>
<string name="logging_in_title">واردشدن</string>
<string name="logging_in_message">شکیبا باشید...</string>
<string name="updating_caption_message">لطفاً صبر کنید...</string>
<string name="login_success" fuzzy="true">ورود موفق!</string>
<string name="login_failed" fuzzy="true">ورود ناموفق!</string>
<string name="upload_failed">پرونده یافت نشد لطفاً پرونده دیگری را امتحان کنید.</string>

View file

@ -5,6 +5,7 @@
* Alno
* Assorted-Interests
* BaRaN6161 TURK
* Bananax47
* BlueCamille
* Cigaryno
* Cyclicus
@ -156,6 +157,7 @@
<string name="login_failed_throttled">Trop de tentatives infructueuses. Veuillez réessayer dans quelques minutes.</string>
<string name="login_failed_blocked">Désolé, cet utilisateur a été bloqué sur Commons</string>
<string name="login_failed_2fa_needed">Vous devez fournir votre code dauthentification à deux facteurs.</string>
<string name="login_failed_email_auth_needed">Un code de vérification de connexion a été envoyé à votre adresse e-mail. Veuillez saisir ce code pour vous connecter.</string>
<string name="login_failed_generic">Échec de connexion</string>
<string name="share_upload_button">Téléverser</string>
<string name="multiple_share_base_title">Nommer cet ensemble</string>
@ -261,6 +263,7 @@
<string name="become_a_tester_title">Devenir un bêta-testeur</string>
<string name="become_a_tester_description">Sinscrire à notre canal bêta sur Google Play et obtenir un accès anticipé aux nouvelles fonctionnalités et corrections danomalies</string>
<string name="_2fa_code">Code 2FA</string>
<string name="email_auth_code">Code de vérification par email</string>
<string name="logout_verification">Voulez-vous vraiment vous déconnecter?</string>
<string name="mediaimage_failed">Échec sur limage du média</string>
<string name="no_subcategory_found">Aucune sous-catégorie trouvée</string>
@ -853,8 +856,16 @@
<string name="usages_on_other_wikis_heading">Autres wikis</string>
<string name="bullet_point"></string>
<string name="file_usages_container_heading">Utilisations du fichier</string>
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
<string name="account">Compte</string>
<string name="vanish_account">Faire disparaître le compte</string>
<string name="account_vanish_request_confirm_title">Avertissement de disparition du compte</string>
<string name="account_vanish_request_confirm">La disparition est un &lt;b&gt;dernier recours&lt;/b&gt; et ne devrait être &lt;b&gt;utilisée que quand vous voulez arrêter déditer pour toujours&lt;/b&gt; et aussi pour cacher autant que possible vos associations passées.&lt;br/&gt;&lt;br/&gt;La suppression de compte sur Wikimedia Commons se fait en changeant le nom de votre compte de sorte que les autres ne peuvent pas identifier vos contributions, lors dun processus appelé disparition du compte. &lt;b&gt;La disparition ne garantit pas lanonymat complet ni ne supprime les contributions de vos projets&lt;/b&gt;.</string>
<string name="caption">Légende</string>
<string name="caption_copied_to_clipboard">Légende copiée dans le presse-papier</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Félicitations, toutes les images dans cet album ont été soit téléchargées soit marquées comme non téléchargeables.</string>
<string name="show_in_explore">Afficher dans Explorer</string>
<string name="show_in_nearby">Afficher à proximité</string>
<string name="image_tag_line_created_and_uploaded_by">Crée et publiée par: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Créé par %1$s et publiée par %2$s</string>
</resources>

View file

@ -40,13 +40,13 @@
<item quantity="one">(%1$d)</item>
<item quantity="other">(%1$d)</item>
</plurals>
<plurals name="starting_multiple_uploads" fuzzy="true">
<item quantity="one">Iniciando %1$d carga</item>
<item quantity="other">Iniciando %1$d cargas</item>
<plurals name="starting_multiple_uploads">
<item quantity="one">Procesando %d carga</item>
<item quantity="other">Procesando %d cargas</item>
</plurals>
<plurals name="multiple_uploads_title" fuzzy="true">
<item quantity="one">%1$d carga</item>
<item quantity="other">%1$d cargas</item>
<plurals name="multiple_uploads_title">
<item quantity="one">%d carga</item>
<item quantity="other">%d cargas</item>
</plurals>
<plurals name="share_license_summary">
<item quantity="one">Esta imaxe quedará baixo a licenza %1$s</item>
@ -80,16 +80,16 @@
<string name="updating_caption_title">A actualizar lendas e descricións</string>
<string name="updating_caption_message">Agarde un chisco…</string>
<string name="login_success">Accedeu correctamente!</string>
<string name="login_failed">Erro durante o inició de sesión!</string>
<string name="login_failed">Erro durante o inicio de sesión!</string>
<string name="upload_failed">Ficheiro non atopado. Por favor, probe con outro.</string>
<string name="retry_limit_reached">Alcanzouse o límite máximo de reintentos! Cancele o envío e ténteo de novo</string>
<string name="unrestricted_battery_mode">Desactivar a optimización da batería?</string>
<string name="authentication_failed">Fallou a autenticación. Inicie sesión de novo.</string>
<string name="uploading_started">A carga comezou!</string>
<string name="uploading_queued">Envío en cola (modo de conexión limitado activado)</string>
<string name="upload_completed_notification_title">Cargouse \"%1$s\"!</string>
<string name="upload_completed_notification_title">Subiuse \"%1$s\"!</string>
<string name="upload_completed_notification_text">Prema para ollar a súa carga</string>
<string name="upload_progress_notification_title_start">A enviar ficheiro: %s</string>
<string name="upload_progress_notification_title_start">A subir o ficheiro: %s</string>
<string name="upload_progress_notification_title_in_progress">Cargando \"%1$s\"</string>
<string name="upload_progress_notification_title_finishing">Rematando a carga de \"%1$s\"</string>
<string name="upload_failed_notification_title">Produciuse un erro ao enviar %1$s</string>
@ -352,7 +352,7 @@
<string name="statistics_thanks">Agradecementos recibidos</string>
<string name="statistics_featured">Imaxes destacadas</string>
<string name="statistics_wikidata_edits">Imaxes vía \"Lugares próximos\"</string>
<string name="level" fuzzy="true">Nivel</string>
<string name="level">Nivel %d</string>
<string name="images_uploaded">Imaxes cargadas</string>
<string name="image_reverts">Imaxes non revertidas</string>
<string name="images_used_by_wiki">Imaxes usadas</string>
@ -408,14 +408,14 @@
<string name="never_ask_again">Non volver a preguntar isto nunca</string>
<string name="display_location_permission_title">Solicitar permiso de localización</string>
<string name="display_location_permission_explanation">Pedir permisos de localización cando sexa necesario para a funcionalidade de notificación de proximidade.</string>
<string name="achievements_fetch_failed" fuzzy="true">Algo foi mal, non puidemos obter as túas achegas</string>
<string name="achievements_fetch_failed">Algo foi mal e non puidemos obter os logros</string>
<string name="ends_on">Finaliza o:</string>
<string name="display_campaigns">Amosar campañas</string>
<string name="display_campaigns_explanation">Ver as campañas en curso</string>
<string name="option_allow">Permitir</string>
<string name="option_dismiss">Descartar</string>
<string name="nearby_campaign_dismiss_message">Xa non verá as campañas. Porén, pode volver habilitar esta notificación na configuración.</string>
<string name="this_function_needs_network_connection" fuzzy="true">Esta función require conexión de rede, verifique a súa configuración de conexión.</string>
<string name="this_function_needs_network_connection">Esta función necesita conexión de rede. Verifique a súa configuración de conexión.</string>
<string name="error_processing_image">Houbo un erro ó procesar a imaxe. Por favor, ténteo de novoǃ</string>
<string name="getting_edit_token">Obter un identificador para editar</string>
<string name="check_category_adding_template">Engadir modelo para o control de categoría</string>
@ -462,8 +462,8 @@
<string name="delete_helper_show_deletion_title_failed">Fallou</string>
<string name="delete_helper_show_deletion_message_else">Non foi posíbel solicitar a eliminación.</string>
<string name="delete_helper_ask_spam_selfie">Un autorretrato que non se emprega en ningún artigo</string>
<string name="delete_helper_ask_spam_blurry" fuzzy="true">Borrosa</string>
<string name="delete_helper_ask_spam_nonsense" fuzzy="true">Sen sentido</string>
<string name="delete_helper_ask_spam_blurry">completamente borrosa</string>
<string name="delete_helper_ask_spam_nonsense">sen sentido, totalmente inusable en calquera artigo</string>
<string name="delete_helper_ask_reason_copyright_press_photo">Foto de prensa</string>
<string name="delete_helper_ask_reason_copyright_internet_photo">Foto aleatoria de internet</string>
<string name="delete_helper_ask_reason_copyright_logo">Logo</string>

View file

@ -112,6 +112,7 @@
<string name="login_failed_throttled">Multa sensucesa probi pri konektar. Voluntez probar itere pos kelka minuti.</string>
<string name="login_failed_blocked">Pardonez, ca uzero blokusesis che Commons</string>
<string name="login_failed_2fa_needed">Vu mustas uzar vua autentikigo en du etapi.</string>
<string name="login_failed_email_auth_needed">Kodexo por konfirmar \'\'log in\'\' sendesis a vua e-postal adreso. Voluntez informar la kodexo, por enirar.</string>
<string name="login_failed_generic">Eniro faliis</string>
<string name="share_upload_button">Kargar</string>
<string name="multiple_share_base_title">Nomizes ca ajusto</string>
@ -215,6 +216,7 @@
<string name="become_a_tester_title">Divenez probero di \'\'Beta\'\'-versioni</string>
<string name="become_a_tester_description">Enirez nia kanalo \'\'beta\'\' che Google Play ed anticipez aceso a nova resursi e korektigo di erori</string>
<string name="_2fa_code">Kodexo 2FA</string>
<string name="email_auth_code">Kodexo sendita ad e-postal adreso</string>
<string name="logout_verification">Ka vu deziras ekirar?</string>
<string name="mediaimage_failed">Faliis montrar imajo</string>
<string name="no_subcategory_found">Nula subkategorio trovesis</string>
@ -385,12 +387,16 @@
<string name="notifications">Avizi</string>
<string name="read_notifications">Avizi (lektita)</string>
<string name="display_nearby_notification">Montrez proxima avizo</string>
<string name="display_nearby_notification_summary">Montrar avizo en utensilo \'\'app\'\' pri la maxim proxima loko qua bezonas pikturi</string>
<string name="list_sheet">Listo</string>
<string name="storage_permission">Permiso pri enmagazinigo</string>
<string name="write_storage_permission_rationale_for_image_share">Ni bezonas vua permiso por acesar l\'extera enmagazinigado di vua utensilo, por sendar imaji.</string>
<string name="nearby_notification_dismiss_message">Vu ne pluse vidos la maxim proxima loko qua bezonas fotografuro. Tamen, vu povas kapabligar itere ca avizo en Ajusti (\'\'Settings\'\'), se vu deziros.</string>
<string name="step_count">Etapo %1$d de %2$d: %3$s</string>
<string name="next">Sequanta</string>
<string name="previous">Antea</string>
<string name="upload_title_duplicate">Arkivo kun la nomo %1$s ja existas. Ka vu deziras durigar?\n\nNoto: Sufixo adequata adjuntesos automatale a la nomo dil imajo.</string>
<string name="map_application_missing">Ne trovesis irga \'\'app\'\' por mapi en vua aparato. Voluntez instalar \'\'app\'\' por uzo di mapi, se vu deziras uzar ca resurso.</string>
<string name="title_page_bookmarks_pictures">Imaji</string>
<string name="title_page_bookmarks_locations">Loki</string>
<string name="title_page_bookmarks_categories">Kategorii</string>
@ -409,19 +415,38 @@
<string name="no_categories_selected">Nula kategorio selektita</string>
<string name="no_categories_selected_warning_desc">Imaji sen kategorii rare esas uzebla. Ka vu fakte deziras sendar ol sen selektar irga kategorio?</string>
<string name="no_depictions_selected">Nula deskripturo selektita</string>
<string name="no_depictions_selected_warning_desc">Imaji kun desegni esas plu facile trovebla, e plu probable uzebla. Ka vu fakte deziras durar, sen selektar desegni?</string>
<string name="back_button_warning">Cesar kargajo</string>
<string name="back_button_warning_desc">Kliktanta la butono \"desfacez/retroirar\" nihiligos la sendo dil arkivo</string>
<string name="back_button_continue">Durar kargajo</string>
<string name="upload_flow_all_images_in_set">(Por omna imaji en la grupo)</string>
<string name="search_this_area">Serchez ca areo</string>
<string name="nearby_card_permission_title">Permiso bezonata</string>
<string name="nearby_card_permission_explanation">Ka vu deziras ke ni uzez vua nuna lokizo por montrar vicina loki qui bezonas imaji?</string>
<string name="unable_to_display_nearest_place">Ne esas posibla montrar la maxim proxima loko qua bezonas imajo, se vu ne montros vua lokizo</string>
<string name="never_ask_again">Ne pluse demandez to</string>
<string name="display_location_permission_title">Demandar lokala permiso</string>
<string name="display_location_permission_explanation">Demandez lokala permiso, kande bezonata por uzar karto montranta proximeso.</string>
<string name="achievements_fetch_failed">Ulu faliis, ni ne povis montrar vua sucesi</string>
<string name="achievements_fetch_failed_ultimate_achievement">Vu facis plu multa kontributaji, e nia kalkulo-utensilo ne povis kalkular li. To esis la maxim importanta suceso.</string>
<string name="ends_on">Finas la:</string>
<string name="display_campaigns">Montrez kampanii</string>
<string name="display_campaigns_explanation">Videz la kampanii duranta</string>
<string name="in_app_camera_location_access_explanation">Permisez ke l\'utensilo (\'\'app\'\') lokizez, se la kamero ne enrejistros la lokizo. Kelka kameri ne havas utensilo por enrejistrar lokizo. Cakaze, vua kontributado divenos plu utila se vu permisos ke l\'\'\'app\'\' prenez ed enrejistrez lokizi. Vu povos abrogar ca permiso irgatempe en Ajusti (\'\'Settings\'\')</string>
<string name="option_allow">Permisar</string>
<string name="option_dismiss">Eskartar</string>
<string name="in_app_camera_needs_location">Voluntez kapabligar registrago di lokizo en \'\'Settings\'\', e probez itere.\n\nNoto: l\'arkivo sendanta povas ne havar informo pri lokizo, se l\'\'\'app\'\' ne povas rekuperar l\'informo pri lokizo en kurta intervalo.</string>
<string name="in_app_camera_location_unavailable">Sen kapabligar GPS, l\'enrejistro di la lokizo en la fotografuri ne facesas.</string>
<string name="open_document_photo_picker_title">Uzez selektilo di fotografuri segun dokumenti</string>
<string name="getting_edit_token">Kaptanta \'\'token\'\' por redaktar.</string>
<string name="check_category_adding_template">Adjuntanta shablono por verifikar kategorio</string>
<string name="check_category_notification_title">Demandanta verifiko di kategorio por %1$s</string>
<string name="check_category_edit_summary">Demandanta verifiko di kategorio</string>
<string name="check_category_success_title">Verifiko di kategorio demandita</string>
<string name="check_category_failure_title">Demando pri verifiko di kategorio ne funcionis</string>
<string name="check_category_success_message">Dema%1$sndita verifiko di kategorio por %1$s</string>
<string name="check_category_failure_message">Ne povis demandar verifiko di kategorio por %1$s</string>
<string name="check_category_toast">Demandanta verifiko di kategorio por %1$s</string>
<string name="nominate_for_deletion_done">Facita</string>
<string name="send_thank_success_title">Sendanta danko: Suceso</string>
<string name="send_thank_success_message">Danko sendita sucese a %1$s</string>
@ -430,8 +455,10 @@
<string name="send_thank_toast">Sendanta danko a %1$s</string>
<string name="review_copyright">Ka to obedias la reguli pri autoroyuro?</string>
<string name="review_category">Ka lua kategorio esas korekta?</string>
<string name="review_spam">Ka to apartenas al skopo dil projeto?</string>
<string name="review_thanks">Ka vu deziras dankar la kontributero?</string>
<string name="review_spam_explanation">Kliktez NO por indikar ca imajo por efaco, se ol ne havas irga utileso.</string>
<string name="review_thanks_explanation">Vua opiniono stimulos %1$s</string>
<string name="review_no_category">Ho, to ne mem havas kategorio!</string>
<string name="review_category_explanation">Ca imajo havas %1$s kategorii.</string>
<string name="review_spam_report_question">Ol esas kontre la skopo, nam ol esas</string>
@ -445,16 +472,23 @@
<string name="no_image_uploaded">Nula imajo sendita</string>
<string name="no_notification">Vu havas nul avizi sen lektar</string>
<string name="no_read_notification">Vu ne lektis irga avizo</string>
<string name="share_logs_using">Partigar enrejistruri uzanta</string>
<string name="check_your_email_inbox">Verifikez vua e-postal adreso</string>
<string name="menu_option_read">Vidar lektita</string>
<string name="menu_option_unread">Vidar ne-lektata</string>
<string name="error_occurred_in_picking_images">Eventis eroro dum selekto di imaji</string>
<string name="please_wait">Vartez...</string>
<string name="images_featured_explanation">Imaji saliigita (Angle: \'\'featured\'\') esas fotografuri facita da multe habila fotografisti ed ilustristi, qui selektesis da la komunitato di Wikimedia kom apartenanta a la maxim bona imaji de la retosituo.</string>
<string name="images_via_nearby_explanation">Imaji sendita uzanta resurso \'\'Nearby places\'\' esas imaji sendita pos deskovro di loki en la mapo.</string>
<string name="thanks_received_explanation">Ca utensilo posibligas editeri sendar \'\'danko\'\' ad uzeri qui facis utila redakturi - per sendo di mikra ligilo \"danko\" che historio-pagino o pagino pri diferi.</string>
<string name="copy_image_caption_description">Kopiar a sequanta enmagazinigo-moyeno</string>
<string name="copied_successfully">Kopiita</string>
<string name="welcome_do_upload_content_description">Exempli pri bona imaji por sendar a Commons</string>
<string name="welcome_dont_upload_content_description">Exempli pri imaji por NE SENDAR</string>
<string name="skip_image">Saltez ca imajo</string>
<string name="download_failed_we_cannot_download_the_file_without_storage_permission">Descharjo faliis!! Ni ne povis descharjar l\'arkivo sen permiso pri extera konservo.</string>
<string name="manage_exif_tags">Administrar etiketi EXIF</string>
<string name="manage_exif_tags_summary">Dum sendo di arkivi, selektez quala etiketi EXIF devas mantenesar</string>
<string name="exif_tag_name_author">Autoro</string>
<string name="exif_tag_name_copyright">Autoroyuro</string>
<string name="exif_tag_name_location">Loko</string>
@ -462,13 +496,21 @@
<string name="exif_tag_name_lensModel">Modelo di lenso</string>
<string name="exif_tag_name_serialNumbers">Serio-nombro</string>
<string name="exif_tag_name_software">Software</string>
<string name="media_location_permission_denied">Aceso ad enmagazinigo-moyeno ne permisita</string>
<string name="image_info">Informo pri imajo</string>
<string name="no_categories_found">Nula kategorio trovesis</string>
<string name="upload_cancelled">Kargajo di arkivo cesis</string>
<string name="dialog_box_text_nomination">Pro quo %1$s devas efacesar?</string>
<string name="review_is_uploaded_by">%1$s sendesis da: %2$s</string>
<string name="default_description_language">implicita deskripto-linguo</string>
<string name="delete_helper_show_deletion_title">Indikita por efaco</string>
<string name="delete_helper_show_deletion_title_success">Suceso</string>
<string name="delete_helper_show_deletion_message_if">Indikita %1$s por efaco.</string>
<string name="delete_helper_show_deletion_title_failed">Faliis</string>
<string name="delete_helper_show_deletion_message_else">Ne povis demandar efaco.</string>
<string name="delete_helper_ask_spam_selfie">\'\'selfie\'\'-imajo qua ne uzesas en irga artiklo</string>
<string name="delete_helper_ask_spam_blurry">komplete neklara</string>
<string name="delete_helper_ask_spam_nonsense">sensencajo, qua ne povas uzesar en irga artiklo</string>
<string name="delete_helper_ask_reason_copyright_press_photo">Fotografuro de komunikilaro</string>
<string name="delete_helper_ask_reason_copyright_internet_photo">Hazarda imajo de Interreto</string>
<string name="delete_helper_ask_reason_copyright_logo">Emblemo</string>
@ -533,10 +575,18 @@
<string name="theme_default_name">Sequar sistemo</string>
<string name="theme_dark_name">Koloro obskura</string>
<string name="theme_light_name">Koloro klara</string>
<string name="recommend_high_accuracy_mode">Por plu bona rezulti, selektez modo \"granda exakteso\" (\'\'High Accuracy\'\').</string>
<string name="ask_to_turn_location_on">Kad montrar lokizo?</string>
<string name="load_more">Charjez pluse</string>
<string name="add_picture_to_wikipedia_article_title">Adjuntar imajo a Wikipedio</string>
<string name="add_picture_to_wikipedia_article_desc">Ka vu deziras adjuntar ca imajo al artiklo de Wikipedio en idiomo %1$s?</string>
<string name="confirm">Konfirmez</string>
<string name="instructions_title">Instrucioni</string>
<string name="wikipedia_instructions_step_1">1. Uzez la sequanta wikitexto:</string>
<string name="wikipedia_instructions_step_2">Kliktanta \"konfirmar\" (\'\'Confirm\'\') apertos l\'artiklo che Wikipedio</string>
<string name="wikipedia_instructions_step_3">3. Trovez adequata fako dil artiklo por inkluzar vua imajo</string>
<string name="wikipedia_instructions_step_7">Publikigar l\'artiklo</string>
<string name="copy_wikicode_to_clipboard">Kopiar wikikodexo a transfero-areo di la komputatoro</string>
<string name="pause">pauzar</string>
<string name="resume">durigar</string>
<string name="paused">Pauzita</string>
@ -550,6 +600,7 @@
<string name="leaderboard_column_user">Uzero</string>
<string name="leaderboard_column_count">Quanteso</string>
<string name="setting_avatar_dialog_title">Uzar kom \'\'avatar\'\' di la tabelo pri precipua kunlaboranti</string>
<string name="setting_avatar_dialog_message">Ajustanta kom avataro, voluntez vartar</string>
<string name="avatar_set_successfully">Ajusto di avataro</string>
<string name="avatar_set_unsuccessfully">Eroro dum ajusto di nov avataro, voluntez probar itere</string>
<string name="menu_set_avatar">Uzar kom avataro</string>
@ -560,7 +611,10 @@
<string name="leaderboard_nearby">Vicina</string>
<string name="leaderboard_used">Uzita</string>
<string name="leaderboard_my_rank_button_text">Mea rango</string>
<string name="limited_connection_enabled">Kapabligesis por uzar kun limitizita konekti!</string>
<string name="statistics_quality">Imaji di qualeso</string>
<string name="resuming_upload">Duriganta sendajo...</string>
<string name="pausing_upload">Pauzanta sendajo...</string>
<string name="cancelling_upload">Nuliganta sendajo...</string>
<string name="cancel_upload">Cesar kargajo</string>
<string name="depicts_step_title">Montras</string>
@ -590,8 +644,11 @@
<string name="custom_selector_limit_error_desc">Eroro: Limito pri sendajo transpasita</string>
<string name="wlm_upload_info">Ca imajo partoprenos en konkurso \'\'Wiki Loves Monuments\'\'</string>
<string name="display_monuments">Montrez monumenti</string>
<string name="wlm_month_message">Esas monato di \'\'Wiki Loves Monuments\'\'!</string>
<string name="learn_more">SAVEZ PLUSE</string>
<string name="wlm_campaign_description">\'\'Wiki Loves Monuments\'\' esas internaciona konkurso pri fotografado di monumenti, organizita da Wikimedia</string>
<string name="need_permission">Bezonas permiso</string>
<string name="read_phone_state_permission_message">Mapi di vicina loki mustas lektar la STANDO DI TELEFONO, por funcionar korekte</string>
<string name="contributions_of_user">Kontributadi dil uzero: %s</string>
<string name="achievements_of_user">Sucesi dil uzero: %s</string>
<string name="menu_view_user_page">Vidar profilo dil uzero</string>
@ -617,6 +674,7 @@
<string name="mark_as_not_for_upload">Indikez por ne sendar ol</string>
<string name="unmark_as_not_for_upload">Itere indikez por sendar ol</string>
<string name="marking_as_not_for_upload">Indikanta ke ol ne sendesos</string>
<string name="no_more_images_found">Ne trovesis plusa imaji</string>
<string name="this_image_is_already_uploaded">Ca imajo ja sendesis</string>
<string name="can_not_select_this_image_for_upload">Ne povis selektar ca imajo por sendar (\'\'upload\'\')</string>
<string name="image_selected">Imajo selektita</string>
@ -628,13 +686,19 @@
<string name="report_user">Avizar ca uzero</string>
<string name="report_content">Informar ca kontenajo</string>
<string name="request_user_block">Demandar blokuso di ca uzero</string>
<string name="welcome_to_full_screen_mode_text">Bonveno a selekto di Modo \"tota-skreno\"</string>
<string name="full_screen_mode_zoom_info">Uzez du fingri por augmentar o diminutar \'\'zoom\'\'.</string>
<string name="similar_coordinate_description_auto_set">Koordinati ne esas l\'exakta, tamen l\'individuo qua sendis ca imajo kredas ke la koordinati quin lu informis esas suficante proxima.</string>
<string name="unable_to_share_upload_item">Ne povis partigar ca arkivo</string>
<string name="learn_how_to_write_a_useful_description">Savez quale skribar utila deskripto</string>
<string name="learn_how_to_write_a_useful_caption">Savez quale skribar utila etiketo</string>
<string name="see_your_achievements">Videz vua sucesi</string>
<string name="edit_image">Modifikar imajo</string>
<string name="edit_location">Aktualigar lokizo</string>
<string name="location_updated">Lokizo aktualigita!</string>
<string name="remove_location">Removar lokizo</string>
<string name="remove_location_warning_title">Removar avizo pri lokizo</string>
<string name="remove_location_warning_desc">Imaji kun informi pri lokizo esas plu utila e trovebla. Ka vu fakte deziras removar la lokizo di ca imajo?</string>
<string name="location_removed">Lokizo efacita!</string>
<string name="send_thanks_to_author">Dankar l\'autoro</string>
<string name="error_sending_thanks">Eroro sendanta danki al autoro.</string>
@ -652,6 +716,7 @@
</plurals>
<string name="talk">Diskuto</string>
<string name="write_something_about_the_item">Dicez irgu pri l\'arkivo \'%1$s\'. Ol esos videbla publike.</string>
<string name="cancelling_all_the_uploads">Extinganta la tota sendaji...</string>
<string name="uploads">Arkivi sendita</string>
<string name="pending">Vartanta</string>
<string name="failed">Faliis</string>
@ -663,6 +728,12 @@
<string name="custom_selector_cancel">Nuligez</string>
<string name="custom_selector_folder_deleted_success">Faldilo %1$s sucese efacita</string>
<string name="custom_selector_folder_deleted_failure">Faliis pri efacar faldilo %1$s</string>
<string name="custom_selector_error_trashing_folder_contents">Eroro dum efaco di kontenajo di dokumentaro: %1$s</string>
<string name="custom_selector_folder_not_found_error">Faliis trovar quale rekuperar dokumentaro kun \'\'bucket ID\'\' %1$d</string>
<string name="red_pin">Ankore ne existas fotografuro pr ta loko, facez fotografuro!</string>
<string name="green_pin">Ja existas imajo pri ta loko.</string>
<string name="error_while_loading">Eroro dum kargado</string>
<string name="no_usages_found">Nula uzo trovesis</string>
<string name="usages_on_commons_heading">Commons</string>
<string name="usages_on_other_wikis_heading">Altra wiki</string>
<string name="file_usages_container_heading">Uzi dil arkivo</string>
@ -670,7 +741,10 @@
<string name="account">Konto</string>
<string name="vanish_account">Efacar konto</string>
<string name="account_vanish_request_confirm_title">Avizo pri efaco di konto</string>
<string name="account_vanish_request_confirm">Efaco esas &lt;b&gt;lasta resurso&lt;/b&gt; e devas uzesar &lt;b&gt;nur se vu fakte e definitive ne pluse deziras redaktar&lt;/b&gt;, ed anke celar la maxim multa kam posibla de vua pasinta asocii.&lt;br/&gt;&lt;br/&gt;Efaco di konto che Wikimedia Commons facesas modifikanta la nomo di vua konto, por ke altri ne povas agnoskar vua kontributadi; procedo nomizita Angle \'\'vanishing\'\' (\"desaparo\"). &lt;b&gt;\'\'Vanishing\'\' ne grantas kompleta anonimeso, o removo di kontributadi en la tota projeti&lt;/b&gt;.</string>
<string name="caption">Deskripto-texto</string>
<string name="caption_copied_to_clipboard">Deskripto-texto kopiita a \'\'clipboard\'\'</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Gratuli! Omna imaji en ca albumo sive sendesis, sive indikesis por ne sendar.</string>
<string name="image_tag_line_created_and_uploaded_by">Kreesis e sendesis da: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Kreita da %1$s e sendita da %2$s</string>
</resources>

View file

@ -775,4 +775,6 @@
<string name="file_usages_container_heading">Utilizzi del file</string>
<string name="caption">Didascalia</string>
<string name="caption_copied_to_clipboard">Didascalia copiata negli appunti</string>
<string name="image_tag_line_created_and_uploaded_by">Creato e caricato da: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Creato da %1$s e caricato da %2$s</string>
</resources>

View file

@ -144,6 +144,7 @@
<string name="login_failed_throttled">יותר מדי ניסיונות כניסה כושלים. נא לנסות שוב בעוד כמה דקות.</string>
<string name="login_failed_blocked">סליחה, החשבון הזה חסום בוויקישיתוף</string>
<string name="login_failed_2fa_needed">יש לספק את קוד האימות הדו־שלבי שלך.</string>
<string name="login_failed_email_auth_needed">נשלח קוד אימות כניסה לכתובת הדוא״ל שלך. נא לספק את הקוד כדי להיכנס.</string>
<string name="login_failed_generic">הכניסה נכשלה</string>
<string name="share_upload_button">העלאה</string>
<string name="multiple_share_base_title">שם האוסף</string>
@ -249,6 +250,7 @@
<string name="become_a_tester_title">להפוך לבודק בטא</string>
<string name="become_a_tester_description">להירשם לערוץ הבטא שלנו בחנות גוגל Play ולקבל גישה מוקדמת לאפשרויות חדשות ותיקוני באגים</string>
<string name="_2fa_code">קוד אימות דו־שלבי</string>
<string name="email_auth_code">קוד אימות בדוא״ל</string>
<string name="logout_verification">האם באמת לצאת מהחשבון?</string>
<string name="mediaimage_failed">תמונת המדיה נכשלה</string>
<string name="no_subcategory_found">לא נמצאו תת־קטגוריות</string>
@ -331,7 +333,7 @@
<string name="about_translate_proceed">המשך</string>
<string name="about_translate_cancel">ביטול</string>
<string name="retry">לנסות שוב</string>
<string name="showcase_view_whole_nearby_activity">אלה המקומות בסביבתך שזקוקים לתמונות כדי להמחיש את הערכים שלהם בוויקיפדיה.\n\nלחיצה על חיפוש באזור הזה נועלת את המפה ומתחילה חיפוש סביב המיקום הזה.</string>
<string name="showcase_view_whole_nearby_activity">אלה המקומות בסביבתך שזקוקים לתמונות כדי להמחיש את הערכים שלהם בוויקיפדיה.\n\nלחיצה על \"חיפוש באזור הזה\" נועלת את המפה ומתחילה חיפוש סביב המיקום הזה.</string>
<string name="showcase_view_needs_photo">המקום הזה צריך תמונה.</string>
<string name="showcase_view_has_photo">למקום הזה יש כבר תמונה.</string>
<string name="showcase_view_no_longer_exists">המקום הזה כבר לא קיים.</string>
@ -857,4 +859,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">ברכותינו, כל התמונות באלבום הזה הועלו או שסומנו לא להעלאה.</string>
<string name="show_in_explore">בתצוגת סיור</string>
<string name="show_in_nearby">בתצוגת בסביבה</string>
<string name="image_tag_line_created_and_uploaded_by">נוצר והועלה על־ידי: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">נוצר על־ידי %1$s והועלה על־ידי %2$s</string>
</resources>

View file

@ -119,7 +119,7 @@
<string name="login_failed_network">ログインできません - ネットワークのエラーです</string>
<string name="login_failed_throttled">失敗した回数が多すぎます。数分後にもう一度お試しください。</string>
<string name="login_failed_blocked">申し訳ありませんが、この利用者はコモンズでブロックされています。</string>
<string name="login_failed_2fa_needed">2段階認証コードを入力してください。</string>
<string name="login_failed_2fa_needed">二要素認証コードを入力してください。</string>
<string name="login_failed_generic">ログイン失敗</string>
<string name="share_upload_button">アップロード</string>
<string name="multiple_share_base_title">このセットに名前をつけてください</string>
@ -221,7 +221,7 @@
<string name="media_detail_coordinates_empty">情報なし</string>
<string name="become_a_tester_title">ベータ版テスターになる</string>
<string name="become_a_tester_description">Google Playのベータ版チャンネルにオプトインして、新機能やバグ修正プログラムに早期にアクセス</string>
<string name="_2fa_code">2段階認証コード</string>
<string name="_2fa_code">2FAコード</string>
<string name="logout_verification">ログアウトしてもよろしいですか?</string>
<string name="mediaimage_failed">メディアイメージが失敗しました</string>
<string name="no_subcategory_found">下位カテゴリは見つかりませんでした</string>

View file

@ -16,6 +16,7 @@
* Revi
* Suleiman the Magnificent Television
* Theshinster123
* YeBoy371
* Ykhwong
* YuzaTea
* 그냥기여자
@ -229,7 +230,7 @@
<string name="logout_verification">정말 로그아웃하시겠습니까?</string>
<string name="mediaimage_failed">미디어 그림 실패</string>
<string name="no_subcategory_found">하위 분류가 없습니다</string>
<string name="no_parentcategory_found">부모 분류가 없습니다</string>
<string name="no_parentcategory_found">상위 분류가 없습니다</string>
<string name="welcome_image_mount_zao">자오 연봉</string>
<string name="welcome_image_llamas">라마</string>
<string name="welcome_image_rainbow_bridge">레인보우 브리지</string>
@ -530,7 +531,7 @@
<string name="you_must_reset_your_passsword">로그인에 문제가 생겼습니다, 비밀번호를 재설정해야 합니다!</string>
<string name="title_for_media">미디어</string>
<string name="title_for_child_classes">자식 클래스</string>
<string name="title_for_parent_classes">부모 클래스</string>
<string name="title_for_parent_classes">상위 클래스</string>
<string name="upload_nearby_place_found_title">주변 장소 발견</string>
<string name="upload_nearby_place_found_description_plural">%1$s의 사진이 맞습니까?</string>
<string name="upload_nearby_place_found_description_singular">%1$s의 사진이 맞습니까?</string>

View file

@ -101,6 +101,8 @@
<string name="menu_from_camera">Суратха ал</string>
<string name="menu_nearby">Джуўукъда</string>
<string name="provider_contributions">Джюклегенлерим</string>
<string name="menu_copy_link">Джибериуню копия эт</string>
<string name="menu_link_copied">Джибериу алмашдырыу буферге копия этилгенди</string>
<string name="menu_share">Юлюшле</string>
<string name="menu_view_file_page">Файлны бетине къара</string>
<string name="share_title_hint">Тюб джазыу (Амалсыз)</string>
@ -274,6 +276,7 @@
<string name="copy_wikicode">Викитекстни алмашдырыу буферге копия эт</string>
<string name="wikicode_copied">Викитекст алмашдырыу буферге копия этилди</string>
<string name="nearby_location_not_available">Джууукъдагыла тюз ишлеялмайды, Локация хайырландырылалмайды.</string>
<string name="nearby_showing_pins_offline">Интернет джетишмейди. Къуру кэш этилген джерле кёргюзюледиле.</string>
<string name="upload_location_access_denied">Локациягъа джетишиу уналмады. Бу функцияны хайырланыр ючюн, тилейбиз, локациягъызны къолугъуз бла белгилегиз.</string>
<string name="location_permission_rationale_nearby">Джууукъдагъы джерле тизмени кёргюзюр ючююн, эркинлик берирге керекди</string>
<string name="location_permission_rationale_explore">Джууукъдагъы суратла тизмени кёргюзюр ючююн, эркинлик берирге керекди</string>
@ -357,11 +360,13 @@
<string name="delete">Кетер</string>
<string name="Achievements">Джетишимле</string>
<string name="Profile">Профиль</string>
<string name="badges">Белгичикле</string>
<string name="statistics">Статистика</string>
<string name="statistics_thanks">Бюсюреуле Алындыла</string>
<string name="statistics_featured">Сайланнган Суратла</string>
<string name="statistics_wikidata_edits">\"Джууукъдагъы Джерле\" юсю бла суратла</string>
<string name="level" fuzzy="true">Дараджа</string>
<string name="level">Дараджа %d</string>
<string name="profileLevel">%s (Дараджа %s)</string>
<string name="images_uploaded">Суратла Джюклендиле</string>
<string name="image_reverts">Суратла Кери Алынмадыла</string>
<string name="images_used_by_wiki">Суратла Хайырландыла</string>
@ -393,6 +398,7 @@
<string name="map_application_missing">Девайсыгъызда келишген картография къошакъ табылмады. Тилейбиз, бу энчиликни хайырландырыр ючюн картография къошакъ джюклегиз.</string>
<string name="title_page_bookmarks_pictures">Суратла</string>
<string name="title_page_bookmarks_locations">Локацияла</string>
<string name="title_page_bookmarks_categories">Категорияла</string>
<string name="menu_bookmark">Китаб белгилени къош/къорат</string>
<string name="provider_bookmarks">Китаб белгиле</string>
<string name="bookmark_empty">Алкъын чырт китаб белги къошмадыгъыз</string>
@ -794,4 +800,19 @@
<string name="red_pin">Бу джерни сураты джокъду, хайда бирин эт!</string>
<string name="green_pin">Бу джерни алайсыз да сураты барды.</string>
<string name="grey_pin">Бу джерни сураты болуб-болмагъанын тинте турама.</string>
<string name="error_while_loading">Джюкленнген заманда халат</string>
<string name="no_usages_found">Бир хайырланыучу да табылмады</string>
<string name="usages_on_commons_heading">Гёзен</string>
<string name="usages_on_other_wikis_heading">Башха викиле</string>
<string name="file_usages_container_heading">Файлны хайырланыулары</string>
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
<string name="account">Хыйсаб</string>
<string name="vanish_account">Хыйсабны сюрт</string>
<string name="account_vanish_request_confirm_title">Хыйсаб сюртюуню эсгертиую</string>
<string name="account_vanish_request_confirm">Джокъ этиу — &lt;b&gt;ахыр амалды&lt;/b&gt;, эмда аны &lt;b&gt;тюзетиуню тамамы бла тохтатыргъа излегесиз хайырланыргъа керекди&lt;/b&gt;, неда эскиде ассоциацияланы бир мадар болуб аслам джашырыргъа излесегиз.&lt;br/&gt;&lt;br /&gt;Викигёзенде хыйсабны кетериу, башхала хыйсабны джокъ этиу атны джюрютген процессде сизни кошумугъузну танымазча, хыйсабыгъызны атын тюрлендириу бла этиледи.&lt;b&gt;Джокъ этиу толу анонимликни гарантия этмейди эмда проектде къошумларыгъызны къоратмайды&lt;/b&gt;.</string>
<string name="caption">Тюб джазыу</string>
<string name="caption_copied_to_clipboard">Тюб джазыу алмашдырыу буферге копия этилгенди</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Алгъышлайбыз, бу альбомна бютеу сратла не джюкленнгендиле, неда джюкленирге джораланмагъанлача белгиленнгендиле.</string>
<string name="show_in_explore">Explore-де кёргюз</string>
<string name="show_in_nearby">Nearby-да кёргюз</string>
</resources>

View file

@ -179,7 +179,7 @@
<string name="statistics_thanks">Spasî Hate Wergirtin</string>
<string name="statistics_featured">Wêneyên Bijartî</string>
<string name="statistics_wikidata_edits">Wêneyên bi riya \"Cihên Nêz\"</string>
<string name="level" fuzzy="true">Derece</string>
<string name="level">Derece %d</string>
<string name="images_uploaded">Wêneyên Barkirî</string>
<string name="review_thanks_yes_button_text">Wêneyê din</string>
<string name="review_thanks_no_button_text">Belê, çima na</string>

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Askar Nazyrov
* Baydastann
* Bosogo
* Kotormochu
* Maksat
@ -10,12 +11,21 @@
<string name="commons_facebook">Викиказынанын Facebook баракчасы</string>
<string name="commons_logo">Викиказынанын логотиби</string>
<string name="commons_website">Викиказынанын сайты</string>
<string name="submit">Жөнөтүү</string>
<string name="add_another_description">Башка сүрөттөмө кошуу</string>
<string name="add_new_contribution">Жаңы салым кошуу</string>
<string name="add_contribution_from_camera">Камерадан салым кошуу</string>
<string name="add_contribution_from_photos">Фотографиялардан салым кошуу</string>
<string name="add_contribution_from_contributions_gallery">Мурунку салымдар галереясынан салым кошуу</string>
<string name="show_captions">Коштомо жазуу</string>
<string name="row_item_language_description">Тилдин мүнөздөмөлөрү</string>
<string name="row_item_caption">Коштомо жазуу</string>
<string name="show_captions_description">Сыпаттама</string>
<string name="nearby_row_image">Сүрөт</string>
<string name="nearby_all">Баары</string>
<string name="nearby_filter_search">Кызыктуу жерди издөө</string>
<string name="nearby_filter_state">Жердин абалы</string>
<string name="appwidget_img">Күндүн сүрөтү</string>
<plurals name="uploads_pending_notification_indicator" fuzzy="true">
<item quantity="one">1 файл жүктөлүүдө</item>
<item quantity="other">%1$d файл жүктөлүүдө</item>
@ -25,6 +35,7 @@
<item quantity="one">1 жүктөө</item>
<item quantity="other">%1$d жүктөө</item>
</plurals>
<string name="starting_uploads">Жүктөө башталууда</string>
<plurals name="starting_multiple_uploads" fuzzy="true">
<item quantity="one">1 жүктөө башталды</item>
<item quantity="other">%1$d жүктөө башталды</item>
@ -34,29 +45,40 @@
<item quantity="other">%d жүктөө</item>
</plurals>
<string name="share_license_summary" fuzzy="true">Бул сүрөт %1$s лицензияланат</string>
<string name="navigation_item_explore">Изилдөө</string>
<string name="preference_category_appearance">Көрүнүш</string>
<string name="preference_category_general">Жалпы</string>
<string name="preference_category_feedback">Кайтарым байланыш</string>
<string name="preference_category_privacy">Купуялык</string>
<string name="app_name">Викиказына</string>
<string name="menu_settings">Параметрлер</string>
<string name="intent_share_upload_label">Викиказынага жүктөө</string>
<string name="upload_in_progress">Жүктөлүүдө</string>
<string name="username">Колдонуучунун аты</string>
<string name="password">Сырсөз</string>
<string name="login_credential">Commons Beta аккаунтуңузга кириңиз</string>
<string name="login">Кирүү</string>
<string name="forgot_password">Сырсөздү унуттуңузбу?</string>
<string name="signup">Катталуу</string>
<string name="logging_in_title">Кирүү</string>
<string name="logging_in_message">Сураныч, күтө туруңуз…</string>
<string name="updating_caption_title">Коштомо жазуулар жана сыпаттамалар жаңыртылууда</string>
<string name="updating_caption_message">Күтө туруңуз…</string>
<string name="login_success" fuzzy="true">Сиз ийгиликтүү кирдиңиз</string>
<string name="login_failed" fuzzy="true">Системага кирүүдө катачылык бар!</string>
<string name="authentication_failed" fuzzy="true">Таану катачылыгы!</string>
<string name="login_success">Ийгиликтүү кирдиңиз!</string>
<string name="login_failed">Системага кирүүдө катачылык бар!</string>
<string name="upload_failed">Файл табылган жок. Башка файлды издеп көрүңүз.</string>
<string name="authentication_failed">Аутентификация ишке ашкан жок. Кайра кириңиз.</string>
<string name="uploading_started">Жүктөө башталды!</string>
<string name="upload_completed_notification_title">%1$s жүктөлдү !</string>
<string name="upload_completed_notification_text">Жүктөлгөн файлды көрүү үчүн басыңыз</string>
<string name="upload_progress_notification_title_start" fuzzy="true">Жүктөө %1$s башталды</string>
<string name="upload_progress_notification_title_start">Файл жүктөлүүдө: %s</string>
<string name="upload_progress_notification_title_in_progress">%1$s жүктөлүүдө</string>
<string name="upload_progress_notification_title_finishing">Жүктөө соңуна жетти %1$s</string>
<string name="upload_failed_notification_title" fuzzy="true">Жүктөө %1$s иш жүзүнө ашкан жок</string>
<string name="upload_failed_notification_title">Жүктөө %1$s иш жүзүнө ашкан жок</string>
<string name="upload_paused_notification_title">%1$s жүктөө токтотулду</string>
<string name="upload_failed_notification_subtitle">Көрүү үчүн басыңыз</string>
<string name="title_activity_contributions" fuzzy="true">Менин жүктөөлөрүм</string>
<string name="upload_paused_notification_subtitle">Көрүү үчүн басыңыз</string>
<string name="title_activity_contributions">Соңку жүктөөлөрүм</string>
<string name="contribution_state_queued">Кезек</string>
<string name="contribution_state_failed">Жүктөө каталары</string>
<string name="contribution_state_in_progress">%1$d%% соңуна чыкты</string>
@ -65,18 +87,24 @@
<string name="menu_from_camera">Сүрөткө тартуу</string>
<string name="menu_nearby">Жакынкы</string>
<string name="provider_contributions">Жүктөөлөрүм</string>
<string name="menu_copy_link">Шилтемени көчүрүү</string>
<string name="menu_share">Бөлүшүү</string>
<string name="share_title_hint" fuzzy="true">Аталышы</string>
<string name="share_title_hint">Коштомо жазуу (талап кылынат)</string>
<string name="add_caption_toast">Бул файлга коштомо жазуу бериңиз</string>
<string name="share_description_hint">Сыпаттама</string>
<string name="login_failed_network" fuzzy="true">Кирүүгө болбой жатат - тармакта үзгүлтүк бар</string>
<string name="login_failed_throttled" fuzzy="true">Өтө көп натыйжасыз иш аракет. Суранабыз, бир нече мүнөттөн кийин кайталаңыз</string>
<string name="share_caption_hint">Коштомо жазуу</string>
<string name="login_failed_network">Кирүүгө болбой жатат - тармакта үзгүлтүк бар</string>
<string name="login_failed_throttled">Өтө көп натыйжасыз аракет. Бир нече мүнөттөн кийин кайта кирип көрүңүз.</string>
<string name="login_failed_blocked">Кечириңиз, бул кодонуучу Уикиказынада блокко алынган.</string>
<string name="login_failed_generic" fuzzy="true">Системага кирүүдө катачылык бар!</string>
<string name="login_failed_2fa_needed">Эки фактордук аутентификация кодун теришиңиз керек.</string>
<string name="login_failed_email_auth_needed">Ырастоочу код электрондук почтаңызга жөнөтүлдү. Аккаунтка кирүү үчүн аны териңиз.</string>
<string name="login_failed_generic">Системага кирүүдө катачылык бар!</string>
<string name="share_upload_button">Жүктөө</string>
<string name="multiple_share_base_title">Файлардын бул тайпасынын аталышын жазыңыз</string>
<string name="provider_modifications">Өзгөрүүлөр</string>
<string name="menu_upload_single">Жүктөө</string>
<string name="categories_search_text_hint">Түрмөктөрдү издөө</string>
<string name="depicts_search_text_hint">Файлдагы элементтерди издөө (тоо, Таж-Махал ж.б.)</string>
<string name="menu_save_categories">Сактоо</string>
<string name="refresh_button">Жаңылоо</string>
<string name="display_list_button">Тизме</string>
@ -86,11 +114,12 @@
<string name="categories_activity_title">Категориялар</string>
<string name="title_activity_settings">Параметрлер</string>
<string name="title_activity_signup">Катталуу</string>
<string name="menu_about">Тиркеме жөнүндө</string>
<string name="title_activity_category_details">Категория</string>
<string name="menu_about">Колдонмо тууралуу</string>
<string name="about_license" fuzzy="true">баштапкы коду ачык тиркемелер, &lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\"&gt;Apache License v2&lt;/a&gt; лицензиясынын негизинде чыгарылган</string>
<string name="about_improve" fuzzy="true">&lt;a href=\"https://github.com/commons-app/apps-android-commons\"&gt;GitHub&lt;/a&gt; шилтемесине баштапкы код. &lt;a href=\" https://github.com/commons-app/apps-android-commons/issues\"&gt;Github&lt;/a&gt; шилтемесиндеги катачылык.</string>
<string name="about_privacy_policy">Купуялык саясаты</string>
<string name="title_activity_about">Тиркеме жөнүндө</string>
<string name="title_activity_about">Колдонмо тууралуу</string>
<string name="menu_feedback">Шарттуу жооп жөнөтүү (Email)</string>
<string name="provider_categories">Жакында колдонулган түрмөктөр</string>
<string name="waiting_first_sync">Алгачкы мезгилдештирүүнү күтүү…</string>
@ -99,6 +128,7 @@
<string name="menu_cancel_upload">Жокко чыгаруу</string>
<string name="menu_download">Жүктөп алуу</string>
<string name="preference_license" fuzzy="true">Лицензия</string>
<string name="preference_theme">Тема</string>
<string name="license_name_cc_by_sa" fuzzy="true">CC Attribution-ShareAlike 3.0</string>
<string name="license_name_cc_by" fuzzy="true">CC Attribution 3.0</string>
<string name="license_name_cc0">CC0</string>
@ -116,23 +146,54 @@
<string name="detail_description_empty">Сыпаттама жок</string>
<string name="menu_refresh">Жаңылоо</string>
<string name="ok">Макул</string>
<string name="upload">Жүктөө</string>
<string name="yes">Ооба</string>
<string name="no">Жок</string>
<string name="media_detail_caption">Коштомо жазуу</string>
<string name="media_detail_title">Аталыш</string>
<string name="media_detail_description">Сыпаттама</string>
<string name="media_detail_discussion">Талкуу</string>
<string name="media_detail_author">Автор</string>
<string name="media_detail_uploaded_date">Жүктөлгөн датасы</string>
<string name="media_detail_license">Лицензия</string>
<string name="media_detail_coordinates">Координаттар</string>
<string name="welcome_image_welcome_wikipedia">Википедияга кош келиңиз</string>
<string name="cancel">Жокко чыгаруу</string>
<string name="navigation_drawer_open">Ачуу</string>
<string name="navigation_drawer_close">Жабуу</string>
<string name="navigation_item_home">Башкы бет</string>
<string name="navigation_item_upload">Жүктөө</string>
<string name="navigation_item_nearby">Жакынкы</string>
<string name="navigation_item_about">Тууралуу</string>
<string name="navigation_item_settings">Параметрлер</string>
<string name="navigation_item_feedback">Кайтарым байланыш</string>
<string name="navigation_item_feedback_github">GitHub аркылуу кайтарым байланыш</string>
<string name="navigation_item_logout">Чыгуу</string>
<string name="navigation_item_info">Нускама</string>
<string name="navigation_item_notification">Кабарламалар</string>
<string name="navigation_item_review">Ырастоо</string>
<string name="no_description_found">сыпаттама табылган жок</string>
<string name="nearby_info_menu_commons_article">Файлдын Викиказынадагы барагы</string>
<string name="nearby_info_menu_wikidata_article">Викимаалыматтын элементи</string>
<string name="nearby_info_menu_wikipedia_article">Википедия макаласы</string>
<string name="null_url">Ката! URL табылган жок</string>
<string name="nominate_deletion">Өчүрүүгө сунуштоо</string>
<string name="nominated_for_deletion">Бул файлды өчүрүү сунушталган.</string>
<string name="nominated_see_more">Толук маалымат алуу үчүн бул баракты караңыз</string>
<string name="skip_login">Аттоо</string>
<string name="navigation_item_login">Кирүү</string>
<string name="skip_login_title">Аккаунтка кирүүнү чындап эле өткөрүп жибергиңиз келеби?</string>
<string name="skip_login_message">Кийин файлдарды жүктөө үчүн аккаунтка кирген болгонуңуз керек болот.</string>
<string name="login_alert_message">Бул функцияны колдонуу үчүн аккаунтка кириңиз</string>
<string name="nearby_wikidata">Викимаалымат</string>
<string name="nearby_wikipedia">Википедия</string>
<string name="about_faq">КБС</string>
<string name="about_translate">Которуу</string>
<string name="about_translate_title">Тилдер</string>
<string name="about_translate_cancel">Жокко чыгаруу</string>
<string name="search_tab_title_media">Медиа</string>
<string name="search_tab_title_categories">Категориялар</string>
<string name="explore_tab_title_mobile">Уюлдук телефон аркылуу жүктөлгөн</string>
<string name="explore_tab_title_map">Карта</string>
<string name="back_button_warning">Жүктөөнү жокко чыгаруу</string>
<string name="back_button_warning_desc">Артка баскычын колдонуу менен бул жүктөө жокко чыгарылат жана сиз ийгиликти жоготосуз</string>

View file

@ -70,7 +70,7 @@
<string name="authentication_failed">D\'Authentifizéierung huet net funktionéiert. Loggt Iech wgl. nach eng Kéier an.</string>
<string name="uploading_started">D\'Eroplueden huet ugefaang!</string>
<string name="upload_completed_notification_title">%1$s eropgelueden!</string>
<string name="upload_completed_notification_text">Dréckt fir de Fichier ze gesinn deen Dir eropgelueden hutt</string>
<string name="upload_completed_notification_text">Tippt fir de Fichier ze gesinn, deen Dir eropgelueden hutt</string>
<string name="upload_progress_notification_title_start">Fichier eroplueden: %s</string>
<string name="upload_progress_notification_title_in_progress">%1$s gëtt eropgelueden</string>
<string name="upload_progress_notification_title_finishing">Eropluede vu(n) %1$s ofschléissen</string>
@ -99,6 +99,7 @@
<string name="login_failed_throttled">Ze dacks ouni Succès probéiert. Probéiert wgl. an e puer Minutten nach eng Kéier.</string>
<string name="login_failed_blocked">Pardon, dëse Benotzer ass op Commons gespaart</string>
<string name="login_failed_2fa_needed">Dir musst de Code vun Ärer Zwee-Facteur-Authentifizéierung uginn.</string>
<string name="login_failed_email_auth_needed">Dir hutt ee Login-Verifikatiounscode per E-Mail geschéckt kritt. Gitt wgl. de Code an, fir Iech anzeloggen.</string>
<string name="login_failed_generic">Aloggen huet net funktionéiert</string>
<string name="share_upload_button">Eroplueden</string>
<string name="multiple_share_base_title">Gitt dëser Biller een Numm</string>
@ -192,6 +193,7 @@
<string name="become_a_tester_title">Beta-Tester ginn</string>
<string name="become_a_tester_description">Schreift Iech op GooglePlay a fir eise Beta-Kanal a kritt fréi Zougang zu neie Funktiounen a Verbesserunge vu Feeler</string>
<string name="_2fa_code">2FA-Code</string>
<string name="email_auth_code">E-Mail-Verifikatiounscode</string>
<string name="logout_verification">Wëllt dir Iech wierklech ausloggen?</string>
<string name="no_subcategory_found">Keng Ënnerkategorie fonnt</string>
<string name="welcome_image_mount_zao">Bierg Zao</string>
@ -274,6 +276,7 @@
<string name="menu_search_button">Sichen</string>
<string name="search_commons">Op Commons sichen</string>
<string name="title_activity_search">Sichen</string>
<string name="search_recent_header">Rezent gesicht:</string>
<string name="search_tab_title_media">Medien</string>
<string name="search_tab_title_categories">Kategorien</string>
<string name="search_tab_title_depictions">Elementer</string>

View file

@ -113,6 +113,7 @@
<string name="login_failed_throttled">Направени се премногу неуспешни обиди. Обидете се пак за некоја минута.</string>
<string name="login_failed_blocked">За жал, корисникот е блокиран на Ризницата</string>
<string name="login_failed_2fa_needed">Мора да го укажете вашиот код за двочинителска заверка.</string>
<string name="login_failed_email_auth_needed">На вашата е-поштенска адреса ви испративме потврден код за најава. Внесете го кодот за да се најавите.</string>
<string name="login_failed_generic">Најавата не успеа</string>
<string name="share_upload_button">Подигни</string>
<string name="multiple_share_base_title">Дајте му име на овој комплет</string>
@ -218,6 +219,7 @@
<string name="become_a_tester_title">Станете бета-испробувач</string>
<string name="become_a_tester_description">Пријавете се на нашиот бета-канал на Google Play и добивајте ран пристап до нови можности и исправки на грешки</string>
<string name="_2fa_code">З-код</string>
<string name="email_auth_code">Испрати го потврдниот код на е-пошта</string>
<string name="logout_verification">Дали навистина сакате да се одјавите?</string>
<string name="mediaimage_failed">Сликата не успеа</string>
<string name="no_subcategory_found">Не пронајдов поткатегории</string>
@ -820,4 +822,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Честитаме. Сите слики од овој албум се подигнати или обележани за неподигање.</string>
<string name="show_in_explore">Прикажи во „Истражи“</string>
<string name="show_in_nearby">Прикажи во „Во близина“</string>
<string name="image_tag_line_created_and_uploaded_by">Создал: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Создал %1$s, а подигнал %2$s</string>
</resources>

View file

@ -138,7 +138,7 @@
<string name="statistics_thanks">Mercejaments recebuts</string>
<string name="title_app_shortcut_setting">Paramètres</string>
<string name="theme_default_name" fuzzy="true">Per defaut</string>
<string name="theme_dark_name">Fosc</string>
<string name="theme_dark_name">Escur</string>
<string name="theme_light_name">Clar</string>
<string name="send_thanks_to_author">Mercejar l\'utilizator</string>
</resources>

View file

@ -22,7 +22,7 @@
<string name="nearby_row_image">ਤਸਵੀਰ</string>
<string name="nearby_all">ਸਾਰੇ</string>
<string name="appwidget_img">ਦਿਨ ਦੀ ਤਸਵੀਰ</string>
<plurals name="uploads_pending_notification_indicator" fuzzy="true">
<plurals name="uploads_pending_notification_indicator">
<item quantity="one"> ਫ਼ਾਈਲ ਚੜ੍ਹਾਈ ਜਾ ਰਹੀ ਹੈ</item>
<item quantity="other">%1$d ਫ਼ਾਈਲਾਂ ਚੜ੍ਹਾਈਆਂ ਜਾ ਰਹੀਆਂ ਹਨ</item>
</plurals>
@ -45,7 +45,7 @@
<string name="preference_category_general">ਆਮ</string>
<string name="preference_category_feedback">ਸੁਝਾਅ</string>
<string name="preference_category_privacy">ਪਰਦੇਦਾਰੀ</string>
<string name="app_name" fuzzy="true">ਵਿਕੀਮੀਡੀਆ ਕਾਮਨਜ਼</string>
<string name="app_name">ਵਿਕੀਮੀਡੀਆ ਸ਼ਾਮਲਾਟ</string>
<string name="menu_settings">ਪਸੰਦਾਂ</string>
<string name="upload_in_progress">ਚੜ੍ਹਾਉਣਾ ਜਾਰੀ ਐ</string>
<string name="username">ਵਰਤੋਂਕਾਰ ਨਾਂ</string>
@ -180,8 +180,11 @@
<string name="media_detail_coordinates_empty">ਕੋਈ ਉਪਲਬਧ ਨਹੀਂ</string>
<string name="_2fa_code">2FA ਕੋਡ</string>
<string name="logout_verification">ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="welcome_image_llamas">ਲਾਮਾ</string>
<string name="welcome_image_rainbow_bridge">ਸਤਰੰਗੀ ਪੁਲ</string>
<string name="welcome_image_welcome_wikipedia">ਵਿਕੀਪੀਡੀਆ \'ਤੇ ਜੀ ਆਇਆਂ ਨੂੰ</string>
<string name="welcome_image_welcome_copyright">ਜੀ ਆਇਆਂ ਨੂੰ ਕਾਪੀਰਾਈਟ</string>
<string name="welcome_image_sydney_opera_house">ਸਿਡਨੀ ਓਪੇਰਾ ਹਾਊਸ</string>
<string name="cancel">ਰੱਦ ਕਰੋ</string>
<string name="navigation_drawer_open">ਖੋਲ੍ਹੋ</string>
<string name="navigation_drawer_close">ਬੰਦ ਕਰੋ</string>
@ -191,10 +194,13 @@
<string name="navigation_item_about">ਬਾਰੇ</string>
<string name="navigation_item_settings">ਤਰਜੀਹਾਂ</string>
<string name="navigation_item_feedback">ਸੁਝਾਅ</string>
<string name="navigation_item_feedback_github">ਗਿੱਟਹਬ (GitHub) ਰਾਹੀਂ ਸੁਝਾਅ</string>
<string name="navigation_item_logout">ਬਾਹਰ ਆਉ</string>
<string name="navigation_item_info">ਸਿਖਲਾਈ</string>
<string name="navigation_item_notification">ਸੂਚਨਾਵਾਂ</string>
<string name="navigation_item_review">ਪਰਖੋ</string>
<string name="no_description_found">ਕੋਈ ਵੇਰਵਾ ਨਹੀਂ ਮਿਲਿਆ</string>
<string name="nearby_info_menu_wikidata_article">ਵਿਕੀਡਾਟਾ ਵਸਤਾਂ</string>
<string name="nearby_info_menu_wikipedia_article">ਵਿਕੀਪੀਡੀਆ ਲੇਖ</string>
<string name="upload_problem_image_dark">ਤਸਵੀਰ ਬਹੁਤ ਗੂੜ੍ਹੀ ਹੈ।</string>
<string name="upload_problem_image_blurry">ਤਸਵੀਰ ਧੁੰਦਲੀ ਹੈ।</string>
@ -203,35 +209,76 @@
<string name="navigation_item_login">ਦਾਖ਼ਲ ਹੋਵੋ</string>
<string name="nearby_wikidata">ਵਿਕੀਡੇਟਾ</string>
<string name="nearby_wikipedia">ਵਿਕੀਪੀਡੀਆ</string>
<string name="about_rate_us">ਸਾਨੂੰ ਦਰਜਾ ਦਿਓ</string>
<string name="about_faq">ਅਕਸਰ ਪੁੱਛੇ ਜਾਂਦੇ ਸੁਆਲ</string>
<string name="user_guide">ਵਰਤੋਂਕਾਰ ਦਸਤਿਆਂ</string>
<string name="welcome_skip_button">ਸਿਖਲਾਈ ਛੱਡੋ</string>
<string name="about_translate">ਤਰਜਮਾ ਕਰੋ</string>
<string name="about_translate_title">ਬੋਲੀਆਂ</string>
<string name="about_translate_proceed">ਅੱਗੇ ਵਧੋ</string>
<string name="about_translate_cancel">ਰੱਦ ਕਰੋ</string>
<string name="retry">ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰੋ</string>
<string name="showcase_view_needs_photo">ਇਸ ਜਗ੍ਹਾ ਨੂੰ ਇੱਕ ਤਸਵੀਰ ਦੀ ਲੋੜ ਏ।</string>
<string name="showcase_view_has_photo">ਇਸ ਜਗ੍ਹਾ \'ਤੇ ਪਹਿਲਾਂ ਹੀ ਇੱਕ ਤਸਵੀਰ ਏ।</string>
<string name="showcase_view_no_longer_exists">ਇਹ ਜਗ੍ਹਾ ਹੁਣ ਮੌਜੂਦ ਨਹੀਂ ਏ।</string>
<string name="no_images_found">ਕੋਈ ਤਸਵੀਰ ਨਹੀਂ ਲੱਭੀ!</string>
<string name="error_loading_images">ਤਸਵੀਰ ਚੜਾਉਨ ਵੇਲੇ ਗਲਤੀ ਆਈ ਏ।</string>
<string name="image_uploaded_by">%1$s: ਵੱਲੋਂ ਚੜ੍ਹਾਈ ਗਈ</string>
<string name="block_notification_title">ਰੋਕ ਲਾਈ ਗਈ</string>
<string name="app_widget_heading">ਦਿਨ ਦੀ ਤਸਵੀਰ</string>
<string name="menu_search_button">ਲੱਭੋ</string>
<string name="title_activity_search">ਲੱਭੋ</string>
<string name="search_recent_header">ਹਾਲੀਆ ਖੋਜਾਂ:</string>
<string name="provider_searches">ਹਾਲ ਦੀਆਂ ਪੁੱਛਗਿੱਛ ਖੋਜਾਂ</string>
<string name="provider_recent_languages">ਹਾਲ ਹੀ ਵਿੱਚ ਬੋਲੀਆਂ ਬਾਰੇ ਪੁੱਛਗਿੱਛ</string>
<string name="search_tab_title_categories">ਸ਼੍ਰੇਣੀਆਂ</string>
<string name="search_tab_title_depictions">ਵਸਤਾਂ</string>
<string name="explore_tab_title_map">ਨਕਸ਼ਾ</string>
<string name="question">ਸਵਾਲ</string>
<string name="result">ਨਤੀਜਾ</string>
<string name="user_not_logged_in">ਤੁਹਾਡੇ ਦਾਖਲੇ ਦੀ ਮਿਆਦ ਪੁੱਗ ਗਈ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਮੁੜ ਦਾਖਲ ਹੋਵੋ।</string>
<string name="continue_message">ਜਾਰੀ ਰੱਖੋ</string>
<string name="correct">ਸਹੀ ਜਵਾਬ</string>
<string name="wrong">ਗਲਤ ਜਵਾਬ</string>
<string name="share_app_title">ਐਪ ਸਾਂਝਾ ਕਰੋ</string>
<string name="rotate">ਘੁੰਮਾਓ</string>
<string name="error_fetching_nearby_places">ਨੇੜਲੀਆਂ ਥਾਵਾਂ ਲੋਡ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕੀਆਂ</string>
<string name="no_pictures_in_this_area">ਇਸ ਖੇਤਰ ਵਿੱਚ ਕੋਈ ਤਸਵੀਰਾਂ ਨਹੀਂ ਹਨ।</string>
<string name="no_nearby_places_around">ਆਲੇ-ਦੁਆਲੇ ਕੋਈ ਨੇੜਲੀ ਥਾਂ ਨਹੀਂ ਏ।</string>
<string name="error_fetching_nearby_monuments">ਨੇਡ਼ਲੇ ਸਮਾਰਕਾਂ ਨੂੰ ਲਿਆਉਣ ਵਿੱਚ ਗਲਤੀ।</string>
<string name="no_recent_searches">ਕੋਈ ਤਾਜ਼ਾ ਖੋਜ ਨਹੀਂ</string>
<string name="delete_recent_searches_dialog">ਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ ਉੱਤੇ ਆਪਣੇ ਖੋਜ ਇਤਿਹਾਸ ਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="delete_search_dialog">ਕੀ ਤੁਸੀਂ ਇਸ ਖੋਜ ਨੂੰ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="search_history_deleted">ਖੋਜ ਇਤਿਹਾਸ ਮਿਟਾਇਆ ਗਿਆ</string>
<string name="nominate_delete">ਮਿਟਾਉਣ ਲਈ ਨਾਮਜ਼ਦ ਕਰੋ</string>
<string name="delete">ਮਿਟਾਓ</string>
<string name="Achievements">ਪ੍ਰਾਪਤੀਆਂ</string>
<string name="Profile">ਪ੍ਰੋਫਾਈਲ</string>
<string name="statistics">ਅੰਕੜੇ</string>
<string name="statistics_thanks">ਧੰਨਵਾਦ ਪ੍ਰਾਪਤ ਹੋਏ</string>
<string name="statistics_featured">ਵਿਸ਼ੇਸ਼ ਤਸਵੀਰ</string>
<string name="statistics_wikidata_edits">\"ਨੇੜਲੀਆਂ ਥਾਵਾਂ\" ਰਾਹੀਂ ਤਸਵੀਰਾਂ</string>
<string name="level">ਪੱਧਰ %d</string>
<string name="images_uploaded">ਤਸਵੀਰਾਂ ਚੜ੍ਹਾਇਆਂ ਗਈਆਂ</string>
<string name="image_reverts">ਤਸਵੀਰਾਂ ਵਾਪਸ ਨਹੀਂ ਕੀਤੀ ਗਈਆਂ</string>
<string name="images_used_by_wiki">ਵਰਤੀ ਗਈਆਂ ਤਸਵੀਰਾਂ</string>
<string name="achievements_share_message">ਆਪਣੀਆਂ ਪ੍ਰਾਪਤੀਆਂ ਨੂੰ ਆਪਣੇ ਦੋਸਤਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰੋ!</string>
<string name="achievements_revert_limit_message">ਘੱਟੋ-ਘੱਟ ਲੋੜੀਂਦਾ:</string>
<string name="error_occurred">ਗਲਤੀ ਆਈ!</string>
<string name="contributions_fragment">ਯੋਗਦਾਨ</string>
<string name="nearby_fragment">ਨੇੜੇ-ਤੇੜੇ</string>
<string name="notifications">ਸੂਚਨਾਵਾਂ</string>
<string name="read_notifications">ਸੂਚਨਾਵਾਂ (ਪੜ੍ਹਿਆਂ)</string>
<string name="list_sheet">ਸੂਚੀ</string>
<string name="next">ਅੱਗੇ</string>
<string name="previous">ਪਿਛਲਾ</string>
<string name="title_page_bookmarks_pictures">ਤਸਵੀਰਾਂ</string>
<string name="title_page_bookmarks_locations">ਟਿਕਾਣਾ</string>
<string name="title_page_bookmarks_categories">ਸ਼੍ਰੇਣੀਆਂ</string>
<string name="search_this_area">ਇਸ ਖੇਤਰ ਵਿੱਚ ਖੋਜ ਕਰੋ</string>
<string name="nearby_card_permission_title">ਇਜਾਜ਼ਤ ਦੀ ਬੇਨਤੀ</string>
<string name="never_ask_again">ਇਹ ਮੁੜ ਕਦੇ ਨਾ ਪੁੱਛੋ</string>
<string name="display_location_permission_title">ਟਿਕਾਣੇਂ ਦੀ ਆਗਿਆ ਮੰਗੋ</string>
<string name="ends_on">ਨੂੰ ਮਿਆਦ ਪੁਗਦੀ</string>
<string name="display_campaigns">ਮੁਹਿੰਮਾਂ ਵੇਖਾਓ</string>
<string name="option_allow">ਇਜਾਜ਼ਤ ਦਿਓ</string>

View file

@ -111,6 +111,7 @@
<string name="login_failed_throttled">Tròpi tentativ falì. Për piasì, ch\'a preuva torna da-sì chèiche minute.</string>
<string name="login_failed_blocked">An dëspias, s\'utent-sì a l\'é stàit blocà ansima a Commons</string>
<string name="login_failed_2fa_needed">A dev fornì sò còdes d\'autentificassion a doi fator.</string>
<string name="login_failed_email_auth_needed">Un còdes ëd verìfica ëd conession a l\'é stàit mandà a soa adrëssa ëd pòsta eletrònica. Për piasì, ch\'a anserissa col còdes për intré ant ël sistema.</string>
<string name="login_failed_generic">Falì a rintré ant ël sistema</string>
<string name="share_upload_button">Carié</string>
<string name="multiple_share_base_title">Deje un nòm a s\'ansem</string>
@ -216,6 +217,7 @@
<string name="become_a_tester_title">Dventé në sperimentador Beta</string>
<string name="become_a_tester_description">Anscriv-se a nòstr canal beta su Google Play a oten-e n\'acess antissipà a le neuve fonsionalità e coression ëd givo</string>
<string name="_2fa_code">Còdes 2FA</string>
<string name="email_auth_code">Mandé un còdes ëd verifica</string>
<string name="logout_verification">Veul-lo për da bon seurte dal sistema?</string>
<string name="mediaimage_failed">Faliment ëd la plancia dël mojen</string>
<string name="no_subcategory_found">Gnun-e sot-categorìe trovà</string>
@ -816,4 +818,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Congratulassion, tute le fòto ëd s\'àlbom a son ëstàita carià opura marcà coma da nen carié.</string>
<string name="show_in_explore">Smon-e andrinta a Explore</string>
<string name="show_in_nearby">Smon-e andrinta a Nearby</string>
<string name="image_tag_line_created_and_uploaded_by">Creà e carià da: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Creà da %1$s e carià da %2$s</string>
</resources>

View file

@ -20,9 +20,9 @@
<string name="add_contribution_from_camera">د کامرې له لارې ونډه ورزياتول</string>
<string name="add_contribution_from_photos">انځورونو له لارې ونډه ورزياتول</string>
<string name="add_contribution_from_contributions_gallery">د پخوانيو ونډو له انځورتونه د ونډې ورزياتول</string>
<string name="show_captions">نيونګې</string>
<string name="show_captions">نيونگې</string>
<string name="row_item_language_description">ژبې سپيناوی</string>
<string name="row_item_caption">نيونګ</string>
<string name="row_item_caption">نيونگ</string>
<string name="show_captions_description">سپيناوی</string>
<string name="nearby_row_image">انځور</string>
<string name="nearby_all">ټول</string>
@ -47,35 +47,55 @@
<item quantity="one">%d upload</item>
<item quantity="other">%d پورته کول</item>
</plurals>
<string name="share_license_summary" fuzzy="true">دا انځور به د %1$s په منښتليک سمبال وي.</string>
<plurals name="share_license_summary">
<item quantity="one">دا انځور به د منښتليک %1$s لاندې وي</item>
<item quantity="other">دا انځورونه به د %1$s منښتليک لاندې وي</item>
</plurals>
<plurals name="upload_count_title">
<item quantity="one">%1$d راپورته کول</item>
<item quantity="other">%1$d راپورته کېدنې</item>
</plurals>
<plurals name="receiving_shared_content">
<item quantity="one">وېشل شوې منځپانگه ترلاسه کوي.د انځورونو بهير شايد يو څه وخت ونيسي، دا د انځورونو په کچې او ستاسو وسيلې پورې اړه لري</item>
<item quantity="other">وېشل شوې منځپانگه ترلاسه کوي.د انځورونو بهير شايد يو څه وخت ونيسي، دا د انځورونو په کچې او ستاسو وسيلې پورې اړه لري</item>
</plurals>
<string name="navigation_item_explore">سپړنه</string>
<string name="preference_category_appearance">ښکارېدنه</string>
<string name="preference_category_general">ټولګړی</string>
<string name="preference_category_feedback">غبرګون</string>
<string name="preference_category_general">ټولگړی</string>
<string name="preference_category_feedback">غبرگون</string>
<string name="preference_category_privacy">پټنتيا</string>
<string name="app_name">ويکي خونديځ</string>
<string name="menu_settings">امستنې</string>
<string name="app_name">ويکيخونديځ</string>
<string name="menu_settings">اوڼنې</string>
<string name="intent_share_upload_label">خونديځ ته راپورته کول</string>
<string name="upload_in_progress">راپورته کول جريان لري</string>
<string name="username">کارن‌نوم</string>
<string name="password">پټنوم</string>
<string name="login_credential">خپل خونديځ بېټا ګڼون ته ورننوځئ</string>
<string name="login_credential">خپل خونديځ بېټا گڼون ته ورننوځئ</string>
<string name="login">ننوتل</string>
<string name="forgot_password">پټنوم مو هېر شوی؟</string>
<string name="signup">نومليکنه</string>
<string name="logging_in_title">په ننوتلو کې دی</string>
<string name="logging_in_message">لطفاً تم شۍ …</string>
<string name="updating_caption_title">نيونګې او سپيناوي تازه کول</string>
<string name="updating_caption_message">په تمه اوسئ</string>
<string name="login_success">بريالی ننوتون</string>
<string name="login_failed">ناسم ننوتون</string>
<string name="upload_failed">دوتنه و نه موندل شوه. لطفاً د يوې بلې دوتنې د موندلو هڅه وکړئ.</string>
<string name="retry_limit_reached">د بياځلي هڅې وروستۍ اندازه پوره شوه! مهرباني وکړئ، لغوه يې کړئ او بيا د راپورته کولو هڅه وکړئ</string>
<string name="logging_in_message">په تمه اوسئ...</string>
<string name="updating_caption_title">نيونگې او سپيناوي تازه کول</string>
<string name="updating_caption_message">په تمه اوسئ...</string>
<string name="login_success">بريالی ننوتون!</string>
<string name="login_failed">ناسم ننوتون!</string>
<string name="upload_failed">دوتنه و نه موندل شوه. مهرباني وکړئ د يوې بلې دوتنې د موندلو هڅه وکړئ.</string>
<string name="retry_limit_reached">د بياځلي هڅې وروستۍ اندازه پوره شوه! مهرباني وکړئ، ناگاره يې کړئ او بيا د راپورته کولو هڅه وکړئ</string>
<string name="unrestricted_battery_mode">بيټري سمون بندول؟</string>
<string name="suggest_unrestricted_mode">کله چې د بیټرۍ اصلاح بنده وي، له ۳ څخه زیاتو عکسونو اپلوډ کول ډیر باوري کار کوي. مهرباني وکړئ د اسانه اپلوډ تجربې لپاره د کامنز ایپ لپاره د ترتیباتو څخه د بیټرۍ اصلاح بند کړئ. \n\n د بیټرۍ اصلاح بندولو لپاره ممکنه ګامونه:\n\n لومړی ګام: لاندې \'ترتیبات\' تڼۍ باندې کلیک وکړئ.\n\n دوهم ګام: له \'نه غوره شوی\' څخه \'ټول ایپس\' ته واړوئ.\n\n دریم ګام: د \"کامن\" یا \"fr.free.nrw.commons\" لټون وکړئ.\n\n څلورم ګام: دا کلیک کړئ او \'غوره نه کړئ\' غوره کړئ.\n\n پنځم ګام: \'بشپړ شوی\' فشار ورکړئ.</string>
<string name="suggest_unrestricted_mode">کله چې د بيټرۍ سمون بند وي، له ۳ څخه زیاتو انځورونو راپورته کول ډېر باوري کار کوي. مهرباني وکړئ د اسانه راپورته کولو تجربې لپاره د خونديځ کارل د اوڼنو څخه بيټرۍ سمون بند کړئ.\n د بيټرۍ سمون بندولو لپاره شوني گامونه:\n\nلومړی گام: لاندې د \'اوڼنې\' تڼۍ کېکاږئ.\n\nدوهم گام: د \'ناسمون\' پرځای \'ټول کاريالونه\' وټاکئ.\n\nدرېم گام: \"خونديځ\" يا \"fr.free.nrw.commons\" وپلټئ.\nڅلورم گام: پرانيزئ او \'ناسمون\' وټاکئ.\nپينځم گام: \'وشو\'کېکاږئ.</string>
<string name="authentication_failed">کره توب نابريالی شو. مهرباني وکړئ، بياځلي ننوځئ.</string>
<string name="uploading_started">پورته کېدنه پيل شوه!</string>
<string name="uploading_queued">راپورته کول په کتار کې دي(د ټاکلي اړيکې ونگه چارن شوې)</string>
<string name="upload_completed_notification_title">%1$s پورته شوی!</string>
<string name="upload_completed_notification_text">د خپلې راپورکېدنې کتلو لپاره دلته وټاپئ.</string>
<string name="upload_progress_notification_title_start">دوتنه راپورته کېږي: %s</string>
<string name="upload_progress_notification_title_in_progress">د %1$s پورته کول</string>
<string name="upload_progress_notification_title_finishing">%1$s راپورته کېدنه بشپړېږي</string>
<string name="upload_failed_notification_title">%1$s راپورته کېدنه نابريالۍ شوه</string>
<string name="upload_paused_notification_title">د %1$s راپورته کېدنه ځنډول شوې</string>
<string name="upload_failed_notification_subtitle">کتلو لپاره دلته وټاپئ</string>
<string name="upload_paused_notification_subtitle">کتلو لپاره دلته وټاپئ</string>
<string name="title_activity_contributions">زما تازه پورته کېدنې</string>
<string name="contribution_state_queued">لږ</string>
<string name="contribution_state_failed">نابريال شو</string>
@ -85,32 +105,61 @@
<string name="menu_from_camera">انځور اخيستل</string>
<string name="menu_nearby">نژدې</string>
<string name="provider_contributions">زما پورته کېدنې</string>
<string name="menu_copy_link">وېبتړ لمېسل</string>
<string name="menu_link_copied">وېبتړ ټينگدړې ته لمېسل شوی دی</string>
<string name="menu_share">شريکول</string>
<string name="share_title_hint" fuzzy="true">سرليک</string>
<string name="menu_view_file_page">د دوتنې مخ کتل</string>
<string name="share_title_hint">نيونگ (اړين دی)</string>
<string name="add_caption_toast">مهرباني وکړئ، د دې دوتنې لپاره نيونگ ورکړئ</string>
<string name="share_description_hint">څرگندونه</string>
<string name="login_failed_network" fuzzy="true">د ننوتلو توان نلري - د شبکې ناکامي</string>
<string name="share_caption_hint">نيونگ</string>
<string name="login_failed_network">غونډال ته ننوتنه ناشونې ده - د جال پاتې راتلنه</string>
<string name="login_failed_throttled">ډیری ناکامه هڅې. لطفا څو دقیقې وروسته بیا هڅه وکړئ.</string>
<string name="login_failed_blocked">بخښنه غواړو، په دي کارن د کامنز لخوا بنديز ولګول شو</string>
<string name="login_failed_generic" fuzzy="true">غونډال کې ننوتنه نابريالې شوه</string>
<string name="login_failed_2fa_needed">تاسو بايد خپل دوه لامليز تاييد کوډ ورکړئ.</string>
<string name="login_failed_email_auth_needed">ستاسو برېښليک پتې ته د ننوتلو تاييد کوډ لېږل شوی دی. مهرباني وکړئ د ننوتلو لپاره کوډ ورکړئ.</string>
<string name="login_failed_generic">غونډال کې ننوتنه نابريالۍ شوه</string>
<string name="share_upload_button">پورته کول</string>
<string name="multiple_share_base_title">د دې ټولگې نوم</string>
<string name="provider_modifications">بدلونونه</string>
<string name="menu_upload_single">پورته کول</string>
<string name="categories_search_text_hint">وېشنيزې پلټل</string>
<string name="depicts_search_text_hint">هغه توکي وپلټئ چې ستاسو رسنۍ يې انځوروي (غر، تاج مح، او نور.)</string>
<string name="menu_save_categories">خوندي کول</string>
<string name="menu_overflow_desc">څنگزنه خوښنۍ</string>
<string name="refresh_button">بياتازه کول</string>
<string name="display_list_button">لړليک</string>
<string name="contributions_subtitle_zero">(تراوسه هيڅ راپورته کېدنه نشته)</string>
<string name="categories_not_found">%1$s سره ورته هيڅ وېشنيزې ونه موندل شوې</string>
<string name="depictions_not_found">%1$s سره هيڅ ورته ويکي‌اومتوک توکي ونه موندل شوه</string>
<string name="no_child_classes">%1$s هيڅ کوشنۍ ټولگې نه لري</string>
<string name="no_parent_classes">%1$s مور ټولگې نه لري</string>
<string name="categories_skip_explanation">ويکي‌اوتوک خونديځ کې د خپلو انځورونو موندلو لپاره وېشنيزې ورگډې کړئ.\nوېشنيزو ورگډولو لپاره ټاپل پيل کړئ.</string>
<string name="categories_activity_title">وېشنيزې</string>
<string name="title_activity_settings">امستنې</string>
<string name="title_activity_signup">نومليکنه</string>
<string name="title_activity_featured_images">ټاکلی انځور</string>
<string name="title_activity_custom_selector">دوديز ټاکونکی</string>
<string name="title_activity_category_details">وېشنيزه</string>
<string name="title_activity_review">ملگرو بياکتنه</string>
<string name="menu_about">په اړه</string>
<string name="about_privacy_policy" fuzzy="true">&lt;a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\"&gt;د پټنتيا تگلاره&lt;/a&gt;</string>
<string name="title_activity_about">په اړه</string>
<string name="menu_feedback">غبرگون لېږنه (برېښليک له لارې)</string>
<string name="no_email_client">هيڅ برېښليک سرچينه نه ده ځای پرځای شوې</string>
<string name="provider_categories">وروستۍ کارېدلې وېشنيزې</string>
<string name="waiting_first_sync">د لومړۍ همغږۍ په تمه...</string>
<string name="no_uploads_yet">تاسې تر اوسه کوم انځور نه دی پورته کړی.</string>
<string name="menu_retry_upload">بياآزمويل</string>
<string name="menu_cancel_upload">ناگارل</string>
<string name="menu_download">ښکته کول</string>
<string name="preference_license">تلواليز منښتليک</string>
<string name="preference_theme" fuzzy="true">د شپې بڼه</string>
<string name="use_previous">مخکنی سرليک او سپيناو وکاروئ</string>
<string name="preference_theme">شاليد</string>
<string name="license_name_cc_by_sa_four">ځانگړي کونگ-ورته وېشنه ۴.۰</string>
<string name="license_name_cc_by_four">ځانگړي کونگ ۴.۰</string>
<string name="license_name_cc_by_sa">ځانگړي کونگ-ورته وېشنه ۳.۰</string>
<string name="license_name_cc_by">ځانگړي کونگ ۳.۰</string>
<string name="license_name_cc_by_3_0">CC BY 3.0</string>
<string name="welcome_final_button_text">هو</string>
<string name="detail_panel_cats_label">وېشنيزې</string>

View file

@ -419,7 +419,7 @@
<string name="provider_bookmarks">Favoritos</string>
<string name="bookmark_empty">Não adicionou nenhum favorito</string>
<string name="provider_bookmarks_location">Favoritos</string>
<string name="log_collection_started">A recolha de registos foi iniciada. REINICIE a aplicação, execute a operação que pretende registar e prima outra vez \"Enviar ficheiro de registos\"</string>
<string name="log_collection_started">A coleta de registros foi iniciada. REINICIE o aplicativo, execute a operação que pretende registrar e toque em Enviar arquivo de registros novamente</string>
<string name="deletion_reason_uploaded_by_mistake">Eu fiz o carregamento por engano</string>
<string name="deletion_reason_publicly_visible">Eu não sabia que seria publicamente visível</string>
<string name="deletion_reason_bad_for_my_privacy">Eu percebi que é ruim para minha privacidade</string>
@ -696,7 +696,7 @@
<string name="place_state_wlm">WLM</string>
<string name="wlm_upload_info">Essa imagem será enviada ao concurso Wiki Loves Monuments</string>
<string name="display_monuments">Monumentos de exibição</string>
<string name="wlm_month_message">Estamos no mês no Wiki Loves Monuments!</string>
<string name="wlm_month_message">Chegou o mês do Wiki Loves Monuments!</string>
<string name="learn_more">SABER MAIS</string>
<string name="wlm_campaign_title">Wiki Loves Monuments</string>
<string name="wlm_campaign_description">O Wiki Loves Monuments é um concurso internacional organizado pela Wikimedia sobre fotografias de monumentos</string>

View file

@ -170,6 +170,7 @@
<string name="login_failed_throttled">Слишком много неудачных попыток. Пожалуйста, попробуйте ещё раз через несколько минут.</string>
<string name="login_failed_blocked">Извините, но участник с таким именем был заблокирован на Викискладе</string>
<string name="login_failed_2fa_needed">Вы должны ввести код двухфакторной аутентификации.</string>
<string name="login_failed_email_auth_needed">Код подтверждения был отправлен на адрес вашей электронной почты. Пожалуйста, введите его для входа.</string>
<string name="login_failed_generic">Ошибка входа в систему</string>
<string name="share_upload_button">Загрузка</string>
<string name="multiple_share_base_title">Введите название для этой группы файлов</string>
@ -275,6 +276,7 @@
<string name="become_a_tester_title">Стать бета-тестером</string>
<string name="become_a_tester_description">Подпишитесь на наш канал бета-версии на Google Play и получите ранний доступ к новым функциям и исправлениям ошибок</string>
<string name="_2fa_code">Код 2ФА</string>
<string name="email_auth_code">Код подтверждения электронной почты</string>
<string name="logout_verification">Вы действительно хотите выйти?</string>
<string name="mediaimage_failed">Ошибка медиафайла</string>
<string name="no_subcategory_found">Подкатегории не найдены.</string>
@ -882,4 +884,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">Поздравляем, все фотографии в этом альбоме либо загружены, либо помечены как не предназначенные для загрузки.</string>
<string name="show_in_explore">Показать в Explore</string>
<string name="show_in_nearby">Показать в Nearby</string>
<string name="image_tag_line_created_and_uploaded_by">Создано и загружено: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Создано %1$s и загружено %2$s</string>
</resources>

View file

@ -748,4 +748,6 @@
<string name="account_vanish_request_confirm">Нестајање је &lt;b&gt;последња опција&lt;/b&gt; и треба је користити &lt;b&gt;само када желите да заувек престанете са уређивањем&lt;/b&gt;, као и да сакријете што више својих прошлих асоцијација.&lt;br/&gt;&lt;br/&gt;Брисање налога на Викимедијној остави се врши променом назива налога тако да други не могу да препознају Ваше доприносе у процесу који се зове учтиви нестанак. &lt;b&gt;Нестајање не гарантује потпуну анонимност и не уклања доприносе на пројектима&lt;/b&gt;.</string>
<string name="caption">Поднапис</string>
<string name="caption_copied_to_clipboard">Поднапис копиран</string>
<string name="image_tag_line_created_and_uploaded_by">Направио и отпремио: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Направио %1$s а отпремио %2$s</string>
</resources>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* AguzulH
* Brahim-essaidi
* Hakim1bal
-->
@ -79,7 +80,7 @@
<string name="Profile">ⵉⴼⵔⵙ</string>
<string name="statistics">ⵉⵙⵉⴹⵏⵏ</string>
<string name="title_app_shortcut_setting">ⵜⵉⵙⵖⴰⵍ</string>
<string name="leaderboard_column_user">ⴰⵏⵙⵎⵔⵙ</string>
<string name="leaderboard_column_user">ⴰⵏⵙⵎⵔ</string>
<string name="leaderboard_column_count">ⵙⵙⵉⴹⵏ</string>
<string name="leaderboard_yearly">ⴰⵙⴳⵯⵙⴰⵏ</string>
<string name="leaderboard_weekly">ⴰⵏⵎⵍⴰⵙⵙ</string>

View file

@ -136,6 +136,7 @@
<string name="login_failed_throttled">失敗次數過多。請於幾分鐘後重試。</string>
<string name="login_failed_blocked">很抱歉,該使用者已被維基共享資源封禁</string>
<string name="login_failed_2fa_needed">必須提供您的雙重驗證代碼。</string>
<string name="login_failed_email_auth_needed">登入驗證碼已發送到您的電子郵件地址。請提供驗證碼以登入。</string>
<string name="login_failed_generic">登入失敗</string>
<string name="share_upload_button">上傳</string>
<string name="multiple_share_base_title">給這個集合命名</string>
@ -241,6 +242,7 @@
<string name="become_a_tester_title">成為 Beta 測試員</string>
<string name="become_a_tester_description">選擇加入我們在 Google Play 上的測試版頻道並儘早訪問新功能和錯誤修復</string>
<string name="_2fa_code">2FA 代碼</string>
<string name="email_auth_code">電子郵件驗證碼</string>
<string name="logout_verification">您確定要登出嗎?</string>
<string name="mediaimage_failed">媒體圖片失敗</string>
<string name="no_subcategory_found">找不到子分類</string>

View file

@ -25,6 +25,7 @@
* Liuxinyu970226
* Looong
* McDutchie
* Mishidexfc
* NACHOgao3
* Qiyue2001
* Shizhao
@ -168,6 +169,7 @@
<string name="login_failed_throttled">失败次数过多。请在几分钟后重试。</string>
<string name="login_failed_blocked">对不起,该用户已经被共享资源封禁</string>
<string name="login_failed_2fa_needed">您必须提供您的双因素验证代码。</string>
<string name="login_failed_email_auth_needed">登录验证码已发送至您的邮箱,请提供该验证码进行登录。</string>
<string name="login_failed_generic">登录失败</string>
<string name="share_upload_button">上传</string>
<string name="multiple_share_base_title">命名这组图像</string>
@ -273,6 +275,7 @@
<string name="become_a_tester_title">成为测试版的测试者</string>
<string name="become_a_tester_description">加入我们在Google Play上的测试计划更早获取新功能以及错误修复</string>
<string name="_2fa_code">2FA代码</string>
<string name="email_auth_code">电子邮件验证码</string>
<string name="logout_verification">您真的想要退出么?</string>
<string name="mediaimage_failed">媒体图片失败</string>
<string name="no_subcategory_found">找不到子分类</string>
@ -873,4 +876,6 @@
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">恭喜,专辑中的所有图片都已上传或标记为不上传。</string>
<string name="show_in_explore">在探索中显示</string>
<string name="show_in_nearby">显示在附近</string>
<string name="image_tag_line_created_and_uploaded_by">创建并上传者: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">由%1$s创建并由%2$s上传</string>
</resources>

View file

@ -111,6 +111,7 @@
<string name="login_failed_throttled">Too many unsuccessful attempts. Please try again in a few minutes.</string>
<string name="login_failed_blocked">Sorry, this user has been blocked on Commons</string>
<string name="login_failed_2fa_needed">You must provide your two factor authentication code.</string>
<string name="login_failed_email_auth_needed">A login verification code has been sent to your email address. Please provide the code to log in.</string>
<string name="login_failed_generic">Log-in failed</string>
<string name="share_upload_button">Upload</string>
<string name="multiple_share_base_title">Name this set</string>
@ -218,6 +219,7 @@
<string name="become_a_tester_description">Opt-in to our beta channel on Google Play and get early access to new features and bug fixes</string>
<string name="beta_opt_in_link">https://play.google.com/apps/testing/fr.free.nrw.commons</string>
<string name="_2fa_code">2FA Code</string>
<string name="email_auth_code">Email verification code</string>
<string name="logout_verification">Do you really want to logout?</string>
<string name="mediaimage_failed">Media Image Failed</string>
<string name="no_subcategory_found">No subcategories found</string>
@ -871,4 +873,6 @@ Upload your first media by tapping on the add button.</string>
<string name="show_in_explore">Show in Explore</string>
<string name="show_in_nearby">Show in Nearby</string>
<string name="image_tag_line_created_and_uploaded_by">Created and uploaded by: %1$s</string>
<string name="image_tag_line_created_by_and_uploaded_by">Created by %1$s and uploaded by %2$s</string>
</resources>

View file

@ -10,6 +10,8 @@ SELECT
(SAMPLE(?wikipediaArticle) AS ?wikipediaArticle)
(SAMPLE(?commonsArticle) AS ?commonsArticle)
(SAMPLE(?commonsCategory) AS ?commonsCategory)
(SAMPLE(?dateOfOfficialClosure) AS ?dateOfOfficialClosure)
(SAMPLE(?pointInTime) AS ?pointInTime)
WHERE {
SERVICE <https://query.wikidata.org/sparql> {
values ?item {
@ -45,6 +47,8 @@ WHERE {
# Get existence
OPTIONAL {?item wdt:P576 ?destroyed}
OPTIONAL {?item wdt:P582 ?endTime}
OPTIONAL {?item wdt:P3999 ?dateOfOfficialClosure}
OPTIONAL {?item wdt:P585 ?pointInTime}
# Get Commons category
OPTIONAL {?item wdt:P373 ?commonsCategory}

View file

@ -50,6 +50,7 @@ fun media(
licenseUrl: String? = "licenseUrl",
author: String? = "creator",
user: String? = "user",
creatorName: String? = null,
pageId: String = "pageId",
categories: List<String>? = listOf("categories"),
coordinates: LatLng? = LatLng(0.0, 0.0, 0.0f),
@ -67,6 +68,7 @@ fun media(
licenseUrl,
author,
user,
creatorName,
categories,
coordinates,
captions,

View file

@ -8,6 +8,7 @@ import androidx.test.core.app.ApplicationProvider
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.soloader.SoLoader
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.MediaDataExtractor
import fr.free.nrw.commons.R
import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.TestUtility.setFinalStatic
@ -46,6 +47,9 @@ class ContributionViewHolderUnitTests {
@Mock
private lateinit var mediaClient: MediaClient
@Mock
private lateinit var mediaDataExtractor: MediaDataExtractor
@Mock
private lateinit var uri: Uri
@ -66,8 +70,9 @@ class ContributionViewHolderUnitTests {
SoLoader.setInTestMode()
Fresco.initialize(ApplicationProvider.getApplicationContext())
activity = Robolectric.buildActivity(ProfileActivity::class.java).create().get()
compositeDisposable = CompositeDisposable()
parent = LayoutInflater.from(activity).inflate(R.layout.layout_contribution, null)
contributionViewHolder = ContributionViewHolder(parent, callback, mediaClient)
contributionViewHolder = ContributionViewHolder(parent, callback, compositeDisposable, mediaClient, mediaDataExtractor)
bindind = LayoutContributionBinding.bind(parent)

View file

@ -10,6 +10,7 @@ import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import java.lang.IllegalArgumentException
@ -42,23 +43,61 @@ class MediaConverterTest {
@Test
fun testConvertIfThumbUrlBlank() {
Mockito.`when`(imageInfo.getMetadata()).thenReturn(metadata)
Mockito.`when`(imageInfo.getThumbUrl()).thenReturn("")
Mockito.`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
Mockito.`when`(imageInfo.getMetadata()?.licenseUrl()).thenReturn("licenseUrl")
Mockito.`when`(imageInfo.getMetadata()?.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(imageInfo.getMetadata()).thenReturn(metadata)
`when`(imageInfo.getThumbUrl()).thenReturn("")
`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
`when`(metadata.licenseUrl()).thenReturn("licenseUrl")
`when`(metadata.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(metadata.artist()).thenReturn("Foo Bar")
media = mediaConverter.convert(page, entity, imageInfo)
assertEquals(media.thumbUrl, media.imageUrl, "originalUrl")
}
@Test
fun testConvertIfThumbUrlNotBlank() {
Mockito.`when`(imageInfo.getMetadata()).thenReturn(metadata)
Mockito.`when`(imageInfo.getThumbUrl()).thenReturn("thumbUrl")
Mockito.`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
Mockito.`when`(imageInfo.getMetadata()?.licenseUrl()).thenReturn("licenseUrl")
Mockito.`when`(imageInfo.getMetadata()?.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(imageInfo.getMetadata()).thenReturn(metadata)
`when`(imageInfo.getThumbUrl()).thenReturn("thumbUrl")
`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
`when`(metadata.licenseUrl()).thenReturn("licenseUrl")
`when`(metadata.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(metadata.artist()).thenReturn("Foo Bar")
media = mediaConverter.convert(page, entity, imageInfo)
assertEquals(media.thumbUrl, "thumbUrl")
}
@Test
fun `test converting artist value (author) with html links`() {
`when`(imageInfo.getMetadata()).thenReturn(metadata)
`when`(imageInfo.getThumbUrl()).thenReturn("thumbUrl")
`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
`when`(metadata.licenseUrl()).thenReturn("licenseUrl")
`when`(metadata.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(metadata.artist()).thenReturn("<a href=\"//commons.wikimedia.org/wiki/User:Foo_Bar\" title=\"Foo Bar\">Foo Bar</a>")
// Artist values like above is very common, found in file pages created via UploadWizard
media = mediaConverter.convert(page, entity, imageInfo)
assertEquals("Foo Bar", media.author)
}
@Test
fun `test convert artist value (author) in plain text`() {
`when`(imageInfo.getMetadata()).thenReturn(metadata)
`when`(imageInfo.getThumbUrl()).thenReturn("thumbUrl")
`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
`when`(metadata.licenseUrl()).thenReturn("licenseUrl")
`when`(metadata.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(metadata.artist()).thenReturn("Foo Bar")
media = mediaConverter.convert(page, entity, imageInfo)
assertEquals("Foo Bar", media.author)
}
@Test
fun `test convert artist value (author) containing red link`() {
`when`(imageInfo.getMetadata()).thenReturn(metadata)
`when`(imageInfo.getThumbUrl()).thenReturn("thumbUrl")
`when`(imageInfo.getOriginalUrl()).thenReturn("originalUrl")
`when`(metadata.licenseUrl()).thenReturn("licenseUrl")
`when`(metadata.dateTime()).thenReturn("yyyy-MM-dd HH:mm:ss")
`when`(metadata.artist()).thenReturn("<a href=\"/w/index.php?title=User:Foo&action=edit&redlink=1\" class=\"new\" title=\"User:Foo (page does not exist)\">Foo</a>")
media = mediaConverter.convert(page, entity, imageInfo)
assertEquals("Foo", media.author)
}
}

View file

@ -173,33 +173,6 @@ class AchievementsFragmentUnitTests {
method.invoke(fragment, "", "")
}
@Test
@Throws(Exception::class)
fun testHideProgressBar() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method =
AchievementsFragment::class.java.getDeclaredMethod(
"hideProgressBar",
Achievements::class.java,
)
method.isAccessible = true
method.invoke(fragment, achievements)
}
@Test
@Throws(Exception::class)
fun testSetAchievementsUploadCount() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method =
AchievementsFragment::class.java.getDeclaredMethod(
"setAchievementsUploadCount",
Achievements::class.java,
Int::class.java,
)
method.isAccessible = true
method.invoke(fragment, achievements, 0)
}
@Test
@Throws(Exception::class)
fun testCheckAccount() {
@ -212,19 +185,6 @@ class AchievementsFragmentUnitTests {
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testSetUploadCount() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method =
AchievementsFragment::class.java.getDeclaredMethod(
"setUploadCount",
Achievements::class.java,
)
method.isAccessible = true
method.invoke(fragment, achievements)
}
@Test
@Throws(Exception::class)
fun testOnError() {
@ -263,18 +223,6 @@ class AchievementsFragmentUnitTests {
method.invoke(fragment, false)
}
@Test
@Throws(Exception::class)
fun testSetWikidataEditCount() {
Shadows.shadowOf(Looper.getMainLooper()).idle()
val method: Method =
AchievementsFragment::class.java.getDeclaredMethod(
"setWikidataEditCount",
)
method.isAccessible = true
method.invoke(fragment)
}
@Test
@Throws(Exception::class)
fun testSetAchievements() {

View file

@ -262,15 +262,4 @@ class UploadActivityUnitTests {
method.isAccessible = true
method.invoke(activity)
}
@Test
@Throws(Exception::class)
fun testOnBackPressed() {
val method: Method =
UploadActivity::class.java.getDeclaredMethod(
"onBackPressed",
)
method.isAccessible = true
method.invoke(activity)
}
}

View file

@ -0,0 +1,78 @@
package fr.free.nrw.commons.utils
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.Media
import fr.free.nrw.commons.TestCommonsApplication
import fr.free.nrw.commons.media.IdAndLabels
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [21], application = TestCommonsApplication::class, qualifiers="en-rUS")
class MediaAttributionUtilTest {
@Mock
private lateinit var appContext: Context
@Before
fun setup() {
appContext = ApplicationProvider.getApplicationContext()
}
@Test
fun getTagLineWithUploaderOnly() {
val media = mock(Media::class.java)
whenever(media.user).thenReturn("TestUploader")
whenever(media.author).thenReturn(null)
assertEquals("Uploaded by: TestUploader",
MediaAttributionUtil.getTagLine(media, appContext))
}
@Test
fun `get tag line from same author and uploader`() {
val media = mock(Media::class.java)
whenever(media.user).thenReturn("TestUser")
whenever(media.getAttributedAuthor()).thenReturn("TestUser")
assertEquals("Created and uploaded by: TestUser",
MediaAttributionUtil.getTagLine(media, appContext))
}
@Test
fun `get creator name from EN label`() {
assertEquals("FooBar",
MediaAttributionUtil.getCreatorName(listOf(IdAndLabels("Q1", mapOf("en" to "FooBar")))))
}
@Test
fun `get creator name from ES label`() {
assertEquals("FooBar",
MediaAttributionUtil.getCreatorName(listOf(IdAndLabels("Q2", mapOf("es" to "FooBar")))))
}
@Test
fun `get creator name from EN label and ignore ES label`() {
assertEquals("Bar",
MediaAttributionUtil.getCreatorName(listOf(
IdAndLabels("Q3", mapOf("en" to "Bar", "es" to "Foo")))))
}
@Test
fun `get creator name from two creators`() {
val name = MediaAttributionUtil.getCreatorName(listOf(
IdAndLabels("Q1", mapOf("en" to "Foo")),
IdAndLabels("Q1", mapOf("en" to "Bar"))
))
assertNotNull(name)
assertTrue(name!!.contains("Foo"))
assertTrue(name.contains("Bar"))
}
}