diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt index aeb62b127c..2af9253174 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryClient.kt @@ -92,8 +92,9 @@ class CategoryClient @Inject constructor(private val categoryInterface: Category it.query()?.pages() ?: emptyList() } .map { - it.map { page -> page.title().replace(CATEGORY_PREFIX, "") } + it.filter { + page -> page.categoryInfo() == null || !page.categoryInfo().isHidden + }.map { page -> page.title().replace(CATEGORY_PREFIX, "") } } } - } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java index a9f030dec7..efc77e1dfc 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryInterface.java @@ -32,7 +32,7 @@ Single searchCategories(@Query("gsrsearch") String filter, * @return */ @GET("w/api.php?action=query&format=json&formatversion=2" - + "&generator=allcategories") + + "&generator=allcategories&prop=categoryinfo") Single searchCategoriesForPrefix(@Query("gacprefix") String prefix, @Query("gaclimit") int itemLimit, @Query("gacoffset") int offset); diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ChunkInfo.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ChunkInfo.kt new file mode 100644 index 0000000000..464ea3145e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ChunkInfo.kt @@ -0,0 +1,36 @@ +package fr.free.nrw.commons.contributions + +import android.os.Parcel +import android.os.Parcelable +import fr.free.nrw.commons.upload.UploadResult +import kotlinx.android.parcel.Parcelize + +data class ChunkInfo( + val uploadResult: UploadResult, + val lastChunkIndex: Int +) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readParcelable(UploadResult::class.java.classLoader), + parcel.readInt() + ) { + } + + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeParcelable(uploadResult, flags) + parcel.writeInt(lastChunkIndex) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): ChunkInfo { + return ChunkInfo(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.kt b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.kt index bd6de67989..592ec9126e 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/Contribution.kt @@ -25,6 +25,7 @@ data class Contribution constructor( val decimalCoords: String? = null, var dateCreatedSource: String? = null, var wikidataPlace: WikidataPlace? = null, + var chunkInfo: ChunkInfo? = null, /** * @return array list of entityids for the depictions */ @@ -36,7 +37,8 @@ data class Contribution constructor( var mimeType: String? = null, val localUri: Uri? = null, var dataLength: Long = 0, - var dateCreated: Date? = null + var dateCreated: Date? = null, + var dateModified: Date? = null ) : Parcelable { fun completeWith(media: Media): Contribution { @@ -68,6 +70,7 @@ data class Contribution constructor( const val STATE_FAILED = 1 const val STATE_QUEUED = 2 const val STATE_IN_PROGRESS = 3 + const val STATE_PAUSED = 4 /** * Formatting captions to the Wikibase format for sending labels diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java index a17a6d54dc..fe7ce5b686 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionDao.java @@ -10,6 +10,8 @@ import androidx.room.Update; import io.reactivex.Completable; import io.reactivex.Single; +import java.util.Calendar; +import java.util.Date; import java.util.List; @Dao @@ -23,7 +25,10 @@ public abstract class ContributionDao { public Completable save(final Contribution contribution) { return Completable - .fromAction(() -> saveSynchronous(contribution)); + .fromAction(() -> { + contribution.setDateModified(Calendar.getInstance().getTime()); + saveSynchronous(contribution); + }); } @Transaction @@ -67,6 +72,9 @@ public Completable delete(final Contribution contribution) { public Completable update(final Contribution contribution) { return Completable - .fromAction(() -> updateSynchronous(contribution)); + .fromAction(() -> { + contribution.setDateModified(Calendar.getInstance().getTime()); + updateSynchronous(contribution); + }); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java index f944a3bd83..ae81f8b761 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionViewHolder.java @@ -43,6 +43,8 @@ public class ContributionViewHolder extends RecyclerView.ViewHolder { ImageButton retryButton; @BindView(R.id.cancelButton) ImageButton cancelButton; + @BindView(R.id.pauseResumeButton) + ImageButton pauseResumeButton; private int position; @@ -93,7 +95,11 @@ public void init(final int position, final Contribution contribution) { case Contribution.STATE_IN_PROGRESS: stateView.setVisibility(View.GONE); progressView.setVisibility(View.VISIBLE); - imageOptions.setVisibility(View.GONE); + addToWikipediaButton.setVisibility(View.GONE); + pauseResumeButton.setVisibility(View.VISIBLE); + cancelButton.setVisibility(View.GONE); + retryButton.setVisibility(View.GONE); + imageOptions.setVisibility(View.VISIBLE); final long total = contribution.getDataLength(); final long transferred = contribution.getTransferred(); if (transferred == 0 || transferred >= total) { @@ -102,10 +108,23 @@ public void init(final int position, final Contribution contribution) { progressView.setProgress((int) (((double) transferred / (double) total) * 100)); } break; + case Contribution.STATE_PAUSED: + stateView.setVisibility(View.VISIBLE); + stateView.setText(R.string.paused); + setResume(); + progressView.setVisibility(View.GONE); + cancelButton.setVisibility(View.GONE); + retryButton.setVisibility(View.GONE); + pauseResumeButton.setVisibility(View.VISIBLE); + imageOptions.setVisibility(View.VISIBLE); + break; case Contribution.STATE_FAILED: stateView.setVisibility(View.VISIBLE); stateView.setText(R.string.contribution_state_failed); progressView.setVisibility(View.GONE); + cancelButton.setVisibility(View.VISIBLE); + retryButton.setVisibility(View.VISIBLE); + pauseResumeButton.setVisibility(View.GONE); imageOptions.setVisibility(View.VISIBLE); break; } @@ -187,4 +206,34 @@ public void imageClicked() { public void wikipediaButtonClicked() { callback.addImageToWikipedia(contribution); } + + /** + * Triggers a callback for pause/resume + */ + @OnClick(R.id.pauseResumeButton) + public void onPauseResumeButtonClicked() { + if (pauseResumeButton.getTag().toString().equals("pause")) { + callback.pauseUpload(contribution); + setResume(); + } else { + callback.resumeUpload(contribution); + setPaused(); + } + } + + /** + * Update pause/resume button to show pause state + */ + private void setPaused() { + pauseResumeButton.setImageResource(R.drawable.pause_icon); + pauseResumeButton.setTag(R.string.pause); + } + + /** + * Update pause/resume button to show resume state + */ + private void setResume() { + pauseResumeButton.setImageResource(R.drawable.play_icon); + pauseResumeButton.setTag(R.string.resume); + } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java index 3624cb757a..8a8df60256 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.java @@ -1,6 +1,7 @@ package fr.free.nrw.commons.contributions; import static fr.free.nrw.commons.contributions.Contribution.STATE_FAILED; +import static fr.free.nrw.commons.contributions.Contribution.STATE_PAUSED; import static fr.free.nrw.commons.contributions.MainActivity.CONTRIBUTIONS_TAB_POSITION; import static fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween; @@ -454,7 +455,7 @@ private void fetchCampaigns() { @Override public void retryUpload(Contribution contribution) { if (NetworkUtils.isInternetConnectionEstablished(getContext())) { - if (contribution.getState() == STATE_FAILED && null != uploadService) { + if (contribution.getState() == STATE_FAILED || contribution.getState() == STATE_PAUSED && null != uploadService) { uploadService.queue(contribution); Timber.d("Restarting for %s", contribution.toString()); } else { @@ -466,6 +467,15 @@ public void retryUpload(Contribution contribution) { } + /** + * Pauses the upload + * @param contribution + */ + @Override + public void pauseUpload(Contribution contribution) { + uploadService.pauseUpload(contribution); + } + /** * Replace whatever is in the current contributionsFragmentContainer view with * mediaDetailPagerFragment, and preserve previous state in back stack. Called when user selects a diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java index 0b777043be..b08b355b18 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListAdapter.java @@ -78,5 +78,9 @@ public interface Callback { void openMediaDetail(int contribution); void addImageToWikipedia(Contribution contribution); + + void pauseUpload(Contribution contribution); + + void resumeUpload(Contribution contribution); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java index 65927f490f..5d14cb01ec 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.java @@ -36,6 +36,7 @@ import javax.inject.Inject; import javax.inject.Named; import org.wikipedia.dataclient.WikiSite; +import timber.log.Timber; /** * Created by root on 01.06.2018. @@ -90,6 +91,7 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment impl private final int SPAN_COUNT_PORTRAIT = 1; + @Override public View onCreateView( final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) { @@ -192,6 +194,7 @@ private void animateFAB(final boolean isFabOpen) { /** * Shows welcome message if user has no contributions yet i.e. new user. */ + @Override public void showWelcomeTip(final boolean shouldShow) { noContributionsYet.setVisibility(shouldShow ? VISIBLE : GONE); } @@ -201,10 +204,12 @@ public void showWelcomeTip(final boolean shouldShow) { * * @param shouldShow True when contributions list should be hidden. */ + @Override public void showProgress(final boolean shouldShow) { progressBar.setVisibility(shouldShow ? VISIBLE : GONE); } + @Override public void showNoContributionsUI(final boolean shouldShow) { noContributionsYet.setVisibility(shouldShow ? VISIBLE : GONE); } @@ -263,6 +268,24 @@ public void addImageToWikipedia(Contribution contribution) { }); } + /** + * Pauses the current upload + * @param contribution + */ + @Override + public void pauseUpload(Contribution contribution) { + callback.pauseUpload(contribution); + } + + /** + * Resumes the current upload + * @param contribution + */ + @Override + public void resumeUpload(Contribution contribution) { + callback.retryUpload(contribution); + } + /** * Display confirmation dialog with instructions when the user tries to add image to wikipedia * @@ -311,6 +334,8 @@ public interface Callback { void retryUpload(Contribution contribution); + void pauseUpload(Contribution contribution); + void showDetail(int position); } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java index 5e21940b53..93499e3633 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsLocalDataSource.java @@ -3,6 +3,7 @@ import androidx.paging.DataSource.Factory; import io.reactivex.Completable; import java.util.ArrayList; +import java.util.Date; import java.util.List; import javax.inject.Inject; diff --git a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt index 45ebf86a71..02975f3e17 100644 --- a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt +++ b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt @@ -10,7 +10,7 @@ import fr.free.nrw.commons.contributions.ContributionDao * The database for accessing the respective DAOs * */ -@Database(entities = [Contribution::class], version = 4, exportSchema = false) +@Database(entities = [Contribution::class], version = 5, exportSchema = false) @TypeConverters(Converters::class) abstract class AppDatabase : RoomDatabase() { abstract fun contributionDao(): ContributionDao diff --git a/app/src/main/java/fr/free/nrw/commons/db/Converters.java b/app/src/main/java/fr/free/nrw/commons/db/Converters.java index 6eecebaec6..3156f5e2dc 100644 --- a/app/src/main/java/fr/free/nrw/commons/db/Converters.java +++ b/app/src/main/java/fr/free/nrw/commons/db/Converters.java @@ -5,6 +5,7 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import fr.free.nrw.commons.CommonsApplication; +import fr.free.nrw.commons.contributions.ChunkInfo; import fr.free.nrw.commons.di.ApplicationlessInjection; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.upload.WikidataPlace; @@ -82,6 +83,16 @@ public static WikidataPlace stringToWikidataPlace(String wikidataPlace) { return readObjectFromString(wikidataPlace, WikidataPlace.class); } + @TypeConverter + public static String chunkInfoToString(ChunkInfo chunkInfo) { + return writeObjectToString(chunkInfo); + } + + @TypeConverter + public static ChunkInfo stringToChunkInfo(String chunkInfo) { + return readObjectFromString(chunkInfo, ChunkInfo.class); + } + @TypeConverter public static String depictionListToString(List depictedItems) { return writeObjectToString(depictedItems); diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt index 02b28ff369..0db4134665 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaClient.kt @@ -107,21 +107,6 @@ class MediaClient @Inject constructor( ) } - private fun mediaFromPageAndEntity(pages: List): Single> { - return if (pages.isEmpty()) - Single.just(emptyList()) - else - getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" }) - .map { - pages.zip(it.entities().values) - .mapNotNull { (page, entity) -> - page.imageInfo()?.let { - mediaConverter.convert(page, entity, it) - } - } - } - } - /** * Fetches Media object from the imageInfo API * @@ -141,7 +126,6 @@ class MediaClient @Inject constructor( fun getPictureOfTheDay(): Single { val date = CommonsDateUtil.getIso8601DateFormatShort().format(Date()) return responseMapper(mediaInterface.getMediaWithGenerator("Template:Potd/$date")).map { it.first() } - } fun getPageHtml(title: String?): Single { @@ -156,7 +140,6 @@ class MediaClient @Inject constructor( mediaDetailInterface.getEntity(entityIds.joinToString("|")) } - fun doesPageContainMedia(title: String?): Single { return pageMediaInterface.getMediaList(title) .map { it.items.isNotEmpty() } @@ -175,4 +158,19 @@ class MediaClient @Inject constructor( it.query()?.pages() ?: emptyList() }.flatMap(::mediaFromPageAndEntity) } + + private fun mediaFromPageAndEntity(pages: List): Single> { + return if (pages.isEmpty()) + Single.just(emptyList()) + else + getEntities(pages.map { "$PAGE_ID_PREFIX${it.pageId()}" }) + .map { + pages.zip(it.entities().values) + .mapNotNull { (page, entity) -> + page.imageInfo()?.let { + mediaConverter.convert(page, entity, it) + } + } + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardConstants.java b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardConstants.java index e31062db64..2679b4a2c3 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardConstants.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardConstants.java @@ -6,6 +6,8 @@ public class LeaderboardConstants { public static final int START_OFFSET = 0; + public static final String USER_LINK_PREFIX = "https://commons.wikimedia.org/wiki/User:"; + public final static String LOADING = "Loading"; public final static String LOADED = "Loaded"; diff --git a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java index eb8f4c234c..c56e6923d4 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/profile/leaderboard/LeaderboardListAdapter.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.profile.leaderboard; +import static fr.free.nrw.commons.profile.leaderboard.LeaderboardConstants.USER_LINK_PREFIX; + import android.content.Context; import android.net.Uri; import android.view.LayoutInflater; @@ -11,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.facebook.drawee.view.SimpleDraweeView; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.Utils; public class LeaderboardListAdapter extends PagedListAdapter { @@ -73,5 +76,13 @@ public void onBindViewHolder(@NonNull LeaderboardListAdapter.ListViewHolder hold avatar.setImageURI(Uri.parse(getItem(position).getAvatar())); username.setText(getItem(position).getUsername()); count.setText(getItem(position).getCategoryCount().toString()); + + /* + Open the user profile in a webview when a username is clicked on leaderboard + We are not using the commons url from build config because the leaderboard is only + supported for prod at the moment + */ + holder.itemView.setOnClickListener(view -> Utils.handleWebUrl(holder.getContext(), Uri.parse( + String.format("%s%s", USER_LINK_PREFIX, getItem(position).getUsername())))); } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/CountingRequestBody.kt b/app/src/main/java/fr/free/nrw/commons/upload/CountingRequestBody.kt index 62c3b3d5c3..9c9d706375 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/CountingRequestBody.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/CountingRequestBody.kt @@ -1,5 +1,6 @@ package fr.free.nrw.commons.upload +import fr.free.nrw.commons.contributions.ChunkInfo import okhttp3.MediaType import okhttp3.RequestBody import okio.* diff --git a/app/src/main/java/fr/free/nrw/commons/upload/StashUploadResult.kt b/app/src/main/java/fr/free/nrw/commons/upload/StashUploadResult.kt new file mode 100644 index 0000000000..8d2e4f2d07 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/upload/StashUploadResult.kt @@ -0,0 +1,12 @@ +package fr.free.nrw.commons.upload + +data class StashUploadResult( + val state: StashUploadState, + val fileKey: String? +) + +enum class StashUploadState { + SUCCESS, + PAUSED, + FAILED +} diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadClient.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadClient.java index 37948b9877..de8e942d52 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadClient.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadClient.java @@ -6,12 +6,16 @@ import android.net.Uri; import androidx.annotation.Nullable; import fr.free.nrw.commons.CommonsApplication; +import fr.free.nrw.commons.contributions.ChunkInfo; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.upload.UploadService.NotificationUpdateProgressListener; import io.reactivex.Observable; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.functions.Consumer; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; +import java.util.Date; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import javax.inject.Inject; import javax.inject.Named; @@ -27,10 +31,17 @@ public class UploadClient { private final int CHUNK_SIZE = 256 * 1024; // 256 KB + //This is maximum duration for which a stash is persisted on MediaWiki + // https://www.mediawiki.org/wiki/Manual:$wgUploadStashMaxAge + private final int MAX_CHUNK_AGE = 6 * 3600 * 1000; // 6 hours + private final UploadInterface uploadInterface; private final CsrfTokenClient csrfTokenClient; private final PageContentsCreator pageContentsCreator; private final FileUtilsWrapper fileUtilsWrapper; + private boolean pauseUploads = false; + + private final CompositeDisposable compositeDisposable = new CompositeDisposable(); @Inject public UploadClient(final UploadInterface uploadInterface, @@ -47,32 +58,68 @@ public UploadClient(final UploadInterface uploadInterface, * Upload file to stash in chunks of specified size. Uploading files in chunks will make handling * of large files easier. Also, it will be useful in supporting pause/resume of uploads */ - Observable uploadFileToStash( - final Context context, final String filename, final File file, + Observable uploadFileToStash( + final Context context, final String filename, final Contribution contribution, final NotificationUpdateProgressListener notificationUpdater) throws IOException { + pauseUploads = false; + File file = new File(contribution.getLocalUri().getPath()); final Observable fileChunks = fileUtilsWrapper.getFileChunks(context, file, CHUNK_SIZE); final MediaType mediaType = MediaType .parse(FileUtils.getMimeType(context, Uri.parse(file.getPath()))); - final long[] offset = {0}; - final String[] fileKey = {null}; - final AtomicReference result = new AtomicReference<>(); - fileChunks.blockingForEach(chunkFile -> { + final AtomicInteger index = new AtomicInteger(); + final AtomicReference chunkInfo = new AtomicReference<>(); + if (contribution.getChunkInfo() != null && isStashValid(contribution)) { + chunkInfo.set(contribution.getChunkInfo()); + } + compositeDisposable.add(fileChunks.forEach(chunkFile -> { + if (pauseUploads) { + return; + } + if (chunkInfo.get() != null && index.get() < chunkInfo.get().getLastChunkIndex()) { + index.getAndIncrement(); + return; + } + final int offset = + chunkInfo.get() != null ? chunkInfo.get().getUploadResult().getOffset() : 0; + final String filekey = + chunkInfo.get() != null ? chunkInfo.get().getUploadResult().getFilekey() : null; + final RequestBody requestBody = RequestBody .create(mediaType, chunkFile); final CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody, - notificationUpdater::onProgress, offset[0], file.length()); - uploadChunkToStash(filename, + notificationUpdater::onProgress, offset, + file.length()); + + compositeDisposable.add(uploadChunkToStash(filename, file.length(), - offset[0], - fileKey[0], - countingRequestBody).blockingSubscribe(uploadResult -> { - result.set(uploadResult); - offset[0] = uploadResult.getOffset(); - fileKey[0] = uploadResult.getFilekey(); - }); - }); - return Observable.just(result.get()); + offset, + filekey, + countingRequestBody).subscribe(uploadResult -> { + chunkInfo.set(new ChunkInfo(uploadResult, index.incrementAndGet())); + notificationUpdater.onChunkUploaded(contribution, chunkInfo.get()); + }, throwable -> { + Timber.e(throwable, "Error occurred in uploading chunk"); + })); + })); + if (pauseUploads) { + return Observable.just(new StashUploadResult(StashUploadState.PAUSED, null)); + } else if (chunkInfo.get() != null) { + return Observable.just(new StashUploadResult(StashUploadState.SUCCESS, + chunkInfo.get().getUploadResult().getFilekey())); + } else { + return Observable.just(new StashUploadResult(StashUploadState.FAILED, null)); + } + } + + /** + * Stash is valid for 6 hours. This function checks the validity of stash + * @param contribution + * @return + */ + private boolean isStashValid(Contribution contribution) { + return contribution.getDateModified() + .after(new Date(System.currentTimeMillis() - MAX_CHUNK_AGE)); } /** @@ -106,6 +153,20 @@ Observable uploadChunkToStash(final String filename, } } + /** + * Dispose the active disposable and sets the pause variable + */ + public void pauseUpload() { + pauseUploads = true; + if (!compositeDisposable.isDisposed()) { + compositeDisposable.dispose(); + } + compositeDisposable.clear(); + } + + /** + * Converts string value to request body + */ @Nullable private RequestBody toRequestBody(@Nullable final String value) { return value == null ? null : RequestBody.create(okhttp3.MultipartBody.FORM, value); diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadResult.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadResult.kt index 0f3f6761e3..0a45999d78 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadResult.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadResult.kt @@ -1,18 +1,47 @@ package fr.free.nrw.commons.upload +import android.os.Parcel +import android.os.Parcelable import org.wikipedia.gallery.ImageInfo private const val RESULT_SUCCESS = "Success" + data class UploadResult( val result: String, val filekey: String, val offset: Int, - val filename: String, - val sessionkey: String, - val imageinfo: ImageInfo -) { + val filename: String +) : Parcelable { + constructor(parcel: Parcel) : this( + parcel.readString(), + parcel.readString(), + parcel.readInt(), + parcel.readString() + ) { + } + fun isSuccessful(): Boolean = result == RESULT_SUCCESS fun createCanonicalFileName() = "File:$filename" + override fun writeToParcel(parcel: Parcel, flags: Int) { + parcel.writeString(result) + parcel.writeString(filekey) + parcel.writeInt(offset) + parcel.writeString(filename) + } + + override fun describeContents(): Int { + return 0 + } + + companion object CREATOR : Parcelable.Creator { + override fun createFromParcel(parcel: Parcel): UploadResult { + return UploadResult(parcel) + } + + override fun newArray(size: Int): Array { + return arrayOfNulls(size) + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java index 75be1b3195..be3e1426ad 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadService.java @@ -5,7 +5,6 @@ import android.content.ContentResolver; import android.content.Intent; import android.graphics.BitmapFactory; -import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -16,6 +15,7 @@ import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; import fr.free.nrw.commons.auth.SessionManager; +import fr.free.nrw.commons.contributions.ChunkInfo; import fr.free.nrw.commons.contributions.Contribution; import fr.free.nrw.commons.contributions.ContributionDao; import fr.free.nrw.commons.contributions.MainActivity; @@ -28,8 +28,8 @@ import io.reactivex.disposables.CompositeDisposable; import io.reactivex.processors.PublishProcessor; import io.reactivex.schedulers.Schedulers; -import java.io.File; import java.io.IOException; +import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; @@ -76,6 +76,7 @@ public class UploadService extends CommonsDaggerService { // Seriously, Android? public static final int NOTIFICATION_UPLOAD_IN_PROGRESS = 1; public static final int NOTIFICATION_UPLOAD_FAILED = 3; + public static final int NOTIFICATION_UPLOAD_PAUSED = 4; protected class NotificationUpdateProgressListener { @@ -119,6 +120,24 @@ public void onProgress(long transferred, long total) { .subscribe()); } + public void onChunkUploaded(Contribution contribution, ChunkInfo chunkInfo) { + contribution.setChunkInfo(chunkInfo); + compositeDisposable.add(contributionDao.update(contribution) + .subscribeOn(ioThreadScheduler) + .subscribe()); + } + } + + /** + * Sets contribution state to paused and disposes the active disposable + * @param contribution + */ + public void pauseUpload(Contribution contribution) { + uploadClient.pauseUpload(); + contribution.setState(Contribution.STATE_PAUSED); + compositeDisposable.add(contributionDao.update(contribution) + .subscribeOn(ioThreadScheduler) + .subscribe()); } @Override @@ -208,13 +227,11 @@ private NotificationCompat.Builder getNotificationBuilder(String channelId) { @SuppressLint("CheckResult") private void uploadContribution(Contribution contribution) { - Uri localUri = contribution.getLocalUri(); - if (localUri == null || localUri.getPath() == null) { + if (contribution.getLocalUri() == null || contribution.getLocalUri().getPath() == null) { Timber.d("localUri/path is null"); return; } - String notificationTag = localUri.toString(); - File localFile = new File(localUri.getPath()); + String notificationTag = contribution.getLocalUri().toString(); Timber.d("Before execution!"); final Media media = contribution.getMedia(); @@ -243,7 +260,7 @@ private void uploadContribution(Contribution contribution) { Observable.fromCallable(() -> "Temp_" + contribution.hashCode() + filename) .flatMap(stashFilename -> uploadClient - .uploadFileToStash(getApplicationContext(), stashFilename, localFile, + .uploadFileToStash(getApplicationContext(), stashFilename, contribution, notificationUpdater)) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) @@ -265,7 +282,7 @@ private void uploadContribution(Contribution contribution) { Timber.d("Stash upload response 1 is %s", uploadStash.toString()); - if (uploadStash.isSuccessful()) { + if (uploadStash.getState() == StashUploadState.SUCCESS) { Timber.d("making sure of uniqueness of name: %s", filename); String uniqueFilename = findUniqueFilename(filename); unfinishedUploads.add(uniqueFilename); @@ -273,7 +290,11 @@ private void uploadContribution(Contribution contribution) { getApplicationContext(), contribution, uniqueFilename, - uploadStash.getFilekey()); + uploadStash.getFileKey()); + } else if (uploadStash.getState() == StashUploadState.PAUSED) { + Timber.d("Contribution upload paused"); + showPausedNotification(contribution); + return Observable.never(); } else { Timber.d("Contribution upload failed. Wikidata entity won't be edited"); showFailedNotification(contribution); @@ -308,7 +329,8 @@ private void onSuccessfulUpload(Contribution contribution, UploadResult uploadRe .add(wikidataEditService.addDepictionsAndCaptions(uploadResult, contribution)); WikidataPlace wikidataPlace = contribution.getWikidataPlace(); if (wikidataPlace != null && wikidataPlace.getImageValue() == null) { - wikidataEditService.createClaim(wikidataPlace, uploadResult.getFilename(), contribution.getMedia().getCaptions()); + wikidataEditService.createClaim(wikidataPlace, uploadResult.getFilename(), + contribution.getMedia().getCaptions()); } saveCompletedContribution(contribution, uploadResult); } @@ -317,7 +339,10 @@ private void saveCompletedContribution(Contribution contribution, UploadResult u compositeDisposable.add(mediaClient.getMedia("File:" + uploadResult.getFilename()) .map(contribution::completeWith) .flatMapCompletable( - newContribution -> contributionDao.saveAndDelete(contribution, newContribution)) + newContribution -> { + newContribution.setDateModified(new Date()); + return contributionDao.saveAndDelete(contribution, newContribution); + }) .subscribe()); } @@ -341,6 +366,24 @@ private void showFailedNotification(Contribution contribution) { .subscribe()); } + private void showPausedNotification(Contribution contribution) { + final String displayTitle = contribution.getMedia().getDisplayTitle(); + curNotification.setTicker(getString(R.string.upload_paused_notification_title, displayTitle)) + .setContentTitle(getString(R.string.upload_paused_notification_title, displayTitle)) + .setContentText(getString(R.string.upload_paused_notification_subtitle)) + .setProgress(0, 0, false) + .setOngoing(false); + notificationManager.notify(contribution.getLocalUri().toString(), NOTIFICATION_UPLOAD_PAUSED, + curNotification.build()); + + contribution.setState(Contribution.STATE_PAUSED); + + compositeDisposable.add(contributionDao + .update(contribution) + .subscribeOn(ioThreadScheduler) + .subscribe()); + } + private String findUniqueFilename(String fileName) throws IOException { String sequenceFileName; for (int sequenceNumber = 1; true; sequenceNumber++) { diff --git a/app/src/main/res/drawable-anydpi-v24/pause_icon.xml b/app/src/main/res/drawable-anydpi-v24/pause_icon.xml new file mode 100644 index 0000000000..0e71a17717 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v24/pause_icon.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi-v24/play_icon.xml b/app/src/main/res/drawable-anydpi-v24/play_icon.xml new file mode 100644 index 0000000000..621aaed2e1 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v24/play_icon.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable-hdpi/pause_icon.png b/app/src/main/res/drawable-hdpi/pause_icon.png new file mode 100644 index 0000000000..b94c9d6942 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/pause_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/play_icon.png b/app/src/main/res/drawable-hdpi/play_icon.png new file mode 100644 index 0000000000..33765b635e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/play_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/pause_icon.png b/app/src/main/res/drawable-mdpi/pause_icon.png new file mode 100644 index 0000000000..d473074565 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/pause_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/play_icon.png b/app/src/main/res/drawable-mdpi/play_icon.png new file mode 100644 index 0000000000..2a8eea9d8c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/play_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/pause_icon.png b/app/src/main/res/drawable-xhdpi/pause_icon.png new file mode 100644 index 0000000000..d558326261 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/pause_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/play_icon.png b/app/src/main/res/drawable-xhdpi/play_icon.png new file mode 100644 index 0000000000..da79fd73c5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/play_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/pause_icon.png b/app/src/main/res/drawable-xxhdpi/pause_icon.png new file mode 100644 index 0000000000..4a44b23e0e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/pause_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/play_icon.png b/app/src/main/res/drawable-xxhdpi/play_icon.png new file mode 100644 index 0000000000..5a262bfb0d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/play_icon.png differ diff --git a/app/src/main/res/layout/layout_contribution.xml b/app/src/main/res/layout/layout_contribution.xml index d63bda70a9..07ee2581a0 100644 --- a/app/src/main/res/layout/layout_contribution.xml +++ b/app/src/main/res/layout/layout_contribution.xml @@ -1,130 +1,130 @@ + + + + + + + android:layout_gravity="center|bottom" + android:background="#AA000000" + android:orientation="horizontal"> + + - + + - - + android:textColor="#FFFFFFFF" + android:visibility="gone" /> - - - - - - - - - - - - - - - - - - - - + android:ellipsize="end" + android:maxLines="2" + android:textColor="#FFFFFFFF" /> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 22c84cc4a2..491c59b23b 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -302,7 +302,7 @@ خطأ أثناء تخزين الصور عنوان وصفي فريد للملف، والذي سيكون بمثابة اسم الملف، يمكنك استخدام لغة واضحة مع مسافات، لا تقم بتضمين امتداد الملف يُرجَى وصف الوسائط قدر الإمكان: أين تم التقاطها؟ ما تظهر؟ ما هو السياق؟ يُرجَى وصف الأشياء أو الأشخاص، اكشف المعلومات التي لا يمكن تخمينها بسهولة، على سبيل المثال الوقت في اليوم إذا كان منظرا طبيعيا، إذا أظهرت الوسائط شيئا غير عادي، فيُرجَى توضيح ما يجعله غير عادي. - (يرجى كتابة وصف موجز للصورة (قيد ٢٥٥ حرف + (يرجى كتابة وصف موجز للصورة (قيد ٢٥٥ حرف هذه الصورة مظلمة للغاية، هل أنت متأكد من رغبتك في رفعها؟ ويكيميديا ​​كومنز للصور ذات القيمة الموسوعية فقط. هذه الصورة ضبابية، هل أنت متأكد من رغبتك في رفعها؟ ويكيميديا ​​كومنز للصور ذات القيمة الموسوعية فقط. مشاكل محتملة في هذه الصورة: @@ -366,6 +366,7 @@ إعادة المحاولة فهمت! هذه هي الأماكن القريبة منك التي تحتاج إلى صور لتوضيح مقالات ويكيبيديا الخاصة بها. \n\nيؤدي النقر فوق \"البحث في هذه المنطقة\" إلى إغلاق الخريطة وإطلاق بحث قريب حول هذا الموقع. + هذه الصفحة لم تعد موجودة. يؤدي النقر على هذا الزر إلى جلب قائمة بهذه الأماكن يمكنك رفع صورة لأي مكان من معرضك أو كاميرتك لم يتم العثور على صور! diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index d6554b7090..7c3a41879e 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -259,7 +259,7 @@ Error al poner les fotos na caché Un títulu descriptivu únicu pal ficheru, que sirvirá para da-y nome al mesmu. Puede usase llinguaxe normal con espacios. Nun incluyas la estensión del ficheru Por favor, describi l\'elementu multimedia tantu como sía posible: ¿ónde se tomó?, ¿qué amuesa?, ¿cuál ye\'l contestu? Por favor, describi los oxetos o persones. Revela la información que nun pueda aldovinase de mou cenciellu, por casu el momentu del día si ye un paisaxe. Si\'l mediu amuesa daqué desacostumao, esplica qué lo fai raro. - Escribi una descripción curtia de la imaxe. (Llende de 255 caráuteres) + Escribi una descripción curtia de la imaxe. (Llende de 255 caráuteres) Esta imaxe ye escura enforma, ¿tas seguru de que quies xubila? Wikimedia Commons ye sólo pa imaxes con valor enciclopédicu. Esta imaxe ta borrosa, ¿tas seguru de que quies xubila? Wikimedia Commons ye sólo pa imaxes con valor enciclopédicu. Problemes potenciales con esta imaxe: diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index cb75f6b2dc..9a4a3fbc38 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -10,6 +10,7 @@ * NahidHossain * Rasal Lia * Sankarshan +* Sibabrata Banerjee * Tahmid02016 * Tauhid16 * আফতাবুজ্জামান @@ -66,7 +67,9 @@ %1$s আপলোড হচ্ছে %1$s আপলোড শেষ হয়েছে %1$s আপলোড ব্যর্থ + %1$s আপলোড বিরত রয়েছে দেখার জন্য টোকা দিন + দেখার জন্য টোকা দিন আমার সাম্প্রতিক আপলোড অপেক্ষারত ব্যর্থ @@ -326,4 +329,7 @@ বুকমার্ক থেকে সরানো হয়েছে বুকমার্কে যোগ করা হয়েছে নিশ্চিত করুন + থামান + পুনরায় শুরু করুন + থামানো হয়েছে diff --git a/app/src/main/res/values-bs/error.xml b/app/src/main/res/values-bs/error.xml index 27a611f8b4..8dffeb1563 100644 --- a/app/src/main/res/values-bs/error.xml +++ b/app/src/main/res/values-bs/error.xml @@ -1,6 +1,7 @@ Commons se srušio diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 9f7e7a7f25..cd6c3c4cf0 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -282,6 +282,9 @@ Annullér Prøv igen Forstået! + Dette sted mangler et billede. + Dette sted har allerede et billede. + Dette sted findes ikke længere. Ingen billeder fundet! Der opstod en fejl under indlæsningen af billeder. Lagt op af: %1$s @@ -391,4 +394,7 @@ Instruktioner Bekræft Instruktioner + sæt på pause + genoptag + Sat på pause diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 94f3e1344a..257f8c8924 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -2,6 +2,7 @@ - Շնորհակալութիւն: + Շնորհակալութիւն diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 233ea21572..6313f39430 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -75,7 +75,9 @@ Sto caricando %1$s Terminato il caricamento di %1$s Caricamento di %1$s non riuscito + Caricamento di %1$s in pausa Premi per visualizzare + Premi per visualizzare I miei ultimi caricamenti In coda Non riuscito @@ -320,6 +322,9 @@ Riprova Capito! Questi sono i luoghi vicino a te che necessitano di immagini per illustrare le loro voci di Wikipedia.\n\nCliccando su \"CERCA QUESTA AREA\" si blocca la mappa e si avvia una ricerca nelle vicinanze intorno a quella posizione. + Questo luogo ha molto bisogno di una foto. + Questo luogo già ha una foto. + Questo luogo non esiste più. Toccando questo pulsante viene visualizzato un elenco di questi luoghi Puoi caricare un\'immagine per ogni luogo dalla tua galleria o fotocamera Nessuna immagine trovata! @@ -545,4 +550,7 @@ 6. Modifica il wikitesto per il posizionamento appropriato, se necessario. Per ulteriori informazioni vedi <a href=\"https://it.wikipedia.org/wiki/Aiuto:Markup_immagini\">questa pagina</a>. 7. Pubblica la voce Copia il wikicodice negli appunti + pausa + riprendi + In pausa diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 2a4f7b9b87..74aab81c32 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -287,7 +287,7 @@ שגיאה בעת שמירת תמונות במטמון כותרת מתארת ייחודית לקובץ, שתשמש כשם הקובץ. ניתן להשתמש בשפה טבעית עם רווחים. אין לכלול את סיומת הקובץ נא לתאר את המדיה כמה שיותר: איפה היא נוצרה? מה היא מראה? מה ההקשר? נא לתאר את העצמים או את האנשים. נא לחשוף מידע שאי־אפשר לנחש בקלות, למשל, הזמן ביום אם זאת תמונת נוף. אם המדיה מציגה משהו בלתי־רגיל, נא להסביר מה מיוחד בה. - נא לרשום תיאור קצר של התמונה. (מוגבל ל־255 תווים) + נא לרשום תיאור קצר של התמונה. (מוגבל ל־255 תווים) התמונה הזאת חשוכה מדי, האם ברצונך באמת להעלות אותה? ויקישיתוף מיועד רק לתמונות בעלות ערך אנציקלופדי. התמונה הזאת מטושטשת, האם ברצונך באמת להעלות אותה? ויקישיתוף מיועד רק לתמונות בעלות ערך אנציקלופדי. בעיות פוטנציאליות עם התמונה הזאת: @@ -351,6 +351,9 @@ לנסות שוב הבנתי! אלה המקומות בסביבתך שזקוקים לתמונות כדי להמחיש את הערכים שלהם בוויקיפדיה.\n\nלחיצה על חיפוש באזור הזה נועלת את המפה ומתחילה חיפוש סביב המיקום הזה. + מקום זה צריך תמונה. + למקום הזה יש כבר תמונה. + מקום זה לא קיים יותר. ניתן ללחוץ על כפתור זה כדי להציג רשימה של המקומות האלה באפשרותך להעלות תמונה של כל מקום מהגלריה או מהמצלמה שלך לא נמצאו תמונות! @@ -622,4 +625,10 @@ האם צילמת את שתי התמונות באותו המקום? האם ברצונך להשתמש בקו הרוחב וקו האורך של התמונה משמאל? לטעון עוד לא נמצאו מקומות, נא לנסות לשנות את החיפוש. + הוספת תמונה לוויקיפדיה + הוראות + אישור + הוראות + העתקת קוד־ויקי ללוח + השהיה diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 56c0b40c8b..c605f81d0c 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -3,6 +3,7 @@ * Abijeet Patro * Aefgh39622 * Afaz +* Bonfire12 * Dude1717 * Hinaloe * Kkairri @@ -12,6 +13,7 @@ * Shirayuki * Suyama * Takot +* Tmv * Whym * Yusuke1109 * Yuukin0248 @@ -73,7 +75,9 @@ %1$s をアップロード中 %1$s のアップロードを完了中 %1$s のアップロードに失敗しました + %1$sのアップロードに失敗しました 閲覧するにはタップしてください + タップでビュー 自分の最近のアップロードファイル 順番待ち中 失敗しました @@ -573,4 +577,7 @@ 位置を有効にしますか? 付近が正確に機能するには、位置を有効にしてください これら2点の撮影場所は同じですか? 右側の画像に緯度経度情報を添付しますか? + 一時停止 + 継続 + 一時停止 diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 37901f6c66..563d004951 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -5,6 +5,7 @@ * Codenstory * Dlsrks1021 * Doyoon1995 +* Ellif * Freebiekr * Garam * Jerrykim306 @@ -74,6 +75,7 @@ %1$s 파일 올리기를 끝내는 중 %1$s 파일 올리기 실패 보려면 탭하세요 + 보려면 탭하세요 내 최근 업로드 대기 중 실패 @@ -269,7 +271,7 @@ 그림 캐시 처리 오류 이 파일을 설명할 수 있는 제목으로, 파일 이름으로 사용됩니다. 띄어쓰기를 포함한 일반적인 단어를 사용할 수 있습니다. 파일 확장자는 포함하지 마세요 미디어에 대해 가능한 많이 설명하십시오: 어디서 촬영한 것인가? 무엇을 보여주는가? 무슨 문맥을 가지는가? 물건이나 사람에 대해 설명하십시오. 풍경에서 시간을 알려주는 것처럼 쉽게 추측할 수 없는 정보를 제공합니다. 미디어가 평범하지 않다면 무엇이 이를 평범하지 않게 만들었는지 설명하십시오. - 그림 설명을 작성해 주세요. (255자 제한) + 그림 설명을 작성해 주세요. (255자 제한) 이 사진은 너무 어둡습니다. 정말 업로드하시겠습니까? 위키미디어 공용은 백과사전적인 가치가 있는 사진을 위한 공간입니다. 이 사진은 흐릿합니다. 정말 업로드하시겠습니까? 위키미디어 공용은 백과사전적인 가치가 있는 사진을 위한 공간입니다. 이 그림에 잠재적인 문제가 있습니다: @@ -331,6 +333,9 @@ 다시 시도 알겠습니다! 이들은 위키백과 글에 사진을 넣을 필요가 있는 당신 주위의 장소들입니다 + 이 장소에는 사진이 필요합니다. + 이 장소의 사진이 이미 있습니다. + 이 장소는 더 이상 있지 않습니다. 이 버튼을 탭하면 이 장소들의 목록을 가져옵니다 갤러리나 카메라 어느 곳이든 사진을 올릴 수 있습니다 그림이 없습니다! @@ -454,7 +459,7 @@ 위치 권한 없이 사진이 필요한 주변 장소를 표시할 수 없습니다 다시는 묻지 않음 위치 권한 표시 - 무언가가 잘못되어, 저희는 당신의 업적을 가져올 수 없었습니다. + 무언가가 잘못되어, 저희는 당신의 업적을 가져올 수 없었습니다 캠페인 표시 진행되고 있는 캠페인 보기 이 기능에는 네트워크 연결이 필요합니다. 연결 설정을 확인해 주십시오. @@ -510,7 +515,7 @@ 기본 설명 언어 성공 실패 - 삭제를 요청할 수 없음. + 삭제를 요청하지 못했습니다. 셀카 흐림 기타 @@ -530,11 +535,11 @@ 사진 필요 장소 유형: 다리, 박물관, 호텔 등. - 로그인에 문제가 생겼습니다, 비밀번호를 재설정 해야합니다!! + 로그인에 문제가 생겼습니다, 비밀번호를 재설정해야 합니다!! 미디어 자식 클래스 부모 클래스 - 가까운 장소 발견 + 주변 장소 발견 찾아보기 북마크 설정 @@ -545,7 +550,7 @@ 배경화면을 설정 중입니다. 기다려 주십시오... 어두움 밝음 - 위치 설정을 열지 못함. 위치를 수동으로 켜세요 + 위치 설정을 열지 못했습니다. 위치를 수동으로 켜주세요 위치를 켭니까? 더 불러오기 발견된 장소가 없습니다. 검색 기준을 바꾸어 보십시오. @@ -554,9 +559,12 @@ 지침 확인 지침 - 1.다음 위키텍스트를 사용하세요: + 1. 다음 위키텍스트를 사용하세요: 2. 확인을 클릭하면 위키백과 문서가 열립니다 5. 위키텍스트를 적절한 위치에 붙여 넣으세요. 7. 문서 게시 클립보드에 위키코드 복사 + 일시 정지 + 계속하기 + 일시 중단됨 diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml index 2d75ff75c3..b416d1a08c 100644 --- a/app/src/main/res/values-lb/strings.xml +++ b/app/src/main/res/values-lb/strings.xml @@ -260,6 +260,9 @@ Ofbriechen Nach eng Kéier probéieren Verstanen! + Dës Plaz brauch eng Foto. + Dës Plaz brauch eng Foto. + Dës Plaz gëtt et net méi. Keng Biller fonnt! Feeler beim Eropluede vu Biller. Eropgeluede vum: %1$s @@ -373,4 +376,7 @@ Confirméieren Instruktiounen 7.Den Artikel publizéieren + ënnerbriechen + virufueren + Ënnerbrach diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index cdbc8390c3..3e24279eb1 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -65,7 +65,9 @@ Подигање на „%1$s“ Завршувам со подигање на „%1$s“ Подигањето на „%1$s“ не успеа + Подигањето на %1$s е запрено Допрете за да погледате + Допрете за да погледате Мои скорешни подигања Чека ред Не успеа @@ -93,7 +95,7 @@ Преиначувања Подигни Пребарај категории - Пребарајте ги предметите прикажани на сликата или снимката (планина, Лесновски манастир и тн.) + Пребарајте ги предметите прикажани на сликата или снимката (планина, Лесновски манастир итн.) Зачувај Превчитај Список @@ -170,7 +172,7 @@ Споделете ги Вашите слики. Да ги оживееме статиите на Википедија! Сликите на Википедија доаѓаат од Ризницата. Со Вашите слики помагате во образованието на луѓето ширум светот. - Избегнуавјте материјали што сте ги нашле на семрежјето, како и слики од плакати, корици од книги и тн. + Избегнуавјте материјали што сте ги нашле на семрежјето, како и слики од плакати, корици од книги итн. Објаснивме добро? Да! Повеќе информации @@ -261,7 +263,7 @@ Грешка при меѓускладирање на сликите Краток и единствен наслов на податотеката, кој ќе служи како нејзин назив. Можете да користите прост јазик со меѓупростор, но не пишувајте ја податотечната наставка Објаснете ја податотеката што подобро можете: Каде е направена? Што е прикажано на неа? Кој е контекстот? Опишете ги предметите, објектите и личностите. Дајте сознанија што не можат лесно да се погодат, како на пр. време од денот ако се работи за природен предел. Ако на неа е претставено нешто необично, објаснете зошто прикажаното е необично. - Ставете краток опис на сликата. (највеќе 255 знаци) + Ставете краток опис на сликата. (највеќе 255 знаци) Сликата ви е претемна. Дали сигурно сакате да ја подигнете? Ризницата е посветена само на слики со енциклопедиска вредност. Сликата ви е матна. Дали сигурно сакате да ја подигнете? Ризницата е посветена само на слики со енциклопедиска вредност. Потенцијални проблеми со сликава: @@ -325,6 +327,9 @@ Пробај пак Јасно! Ова се места во ваша близинана кои им требаат слики за илустрирање на нивните статии на Википедија.\n\nСо стискање на „ПРЕБАРАЈ НА ОВА ПОДРАЧЈЕ“ ќе направите задршка на картата и ќе ви се даде пребарување на нешта во таа околина. + На местово му треба слика. + Местово веќе има слика. + Местово повеќе не постои. Ако допрете на копчево ќе добиете список на тие места Можете да подигнете слика за било кое од местата од вашата галерија или камера Не пронајдов ниедна слика! @@ -571,7 +576,7 @@ Постои Му треба слика Вид на место: - Мост, музеј, хотел и тн. + Мост, музеј, хотел итн. Нешто не е во ред со најавата. Ќе мора да ставите нова лозинка !! СЛИКИ/СНИМКИ ЗАВИСНИ КЛАСИ @@ -610,4 +615,7 @@ 6. По потреба, уредете го викитекстот за да ја ставите сликата во прикладна положба во одност на текстот. Повеќе информации за тоа ќе видите <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">тука</a>. 7. Објавете ја статијата Прекопирајте го викикодот во меѓускладот + запри + продолжи + Запрено diff --git a/app/src/main/res/values-my/strings.xml b/app/src/main/res/values-my/strings.xml index 747e9af3b9..34e0f0d8d8 100644 --- a/app/src/main/res/values-my/strings.xml +++ b/app/src/main/res/values-my/strings.xml @@ -2,6 +2,7 @@ @@ -49,6 +50,8 @@ %1$s ဖိုင်တင်နေသည် ဖိုင်တင်ခြင်း ပြီးဆုံးမှု %1$s ဖိုင်တင်ခြင်း %1$s မအောင်မြင်ပါ + ဖိုင်တင်ခြင်း %1$s မအောင်မြင်ပါ + ကြည့်ရန်နှိပ်ပါ မကြာသေးခင်က မိမိတင်ထားသည်များ မအောင်မြင်ပါ %1$d%% ပြီးဆုံး @@ -374,4 +377,7 @@ အသိပေးချက်ကို ဖတ်ပြီးကြောင်းမှတ်သားပြီးပြီ အမှားအယွင်းအချို့ရှိခဲ့သည် အနီးအနားနေရာ တွေ့ရှိသည် + ခေတ္တရပ် + ခေတ္တရပ်နားရာမှ ပြန်လုပ်ရန် + ခေတ္တရပ်ပြီး diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 2739e5a8e1..f906710ce0 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -3,6 +3,7 @@ * A67-A67 * Abijeet Patro * Bouman4 +* Dutchy45 * Elroy * Festina90 * Klaas van Buiten @@ -67,6 +68,7 @@ Bezig met het uploaden van %1$s Het uploaden van %1$s is afgerond Het uploaden van %1$s is mislukt + Het uploaden van %1$s is gepauzeerd Wijs aan om te bekijken Mijn recente uploads In wachtrij @@ -325,4 +327,7 @@ Instructies Bevestigen Instructies + pauzeren + hervatten + Gepauzeerd diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index 5f6a85cec7..ce44f99915 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -39,7 +39,9 @@ %1$s ߟߊ߬ߦߟߍ߬ߟߌ ߦߋ߫ ߛߋ߲߬ߠߊ߫ %1$s ߟߊ߬ߦߟߍ߬ߟߌ ߞߎ߲߬ߘߏ߲߬ߠߌ߲ ߦߴߌ ߘߐ߫ %1$s ߟߊ߬ߦߟߍ߬ߟߌ ߓߘߊ߫ ߗߌߙߏ߲߫ + %1$s ߟߊߦߟߍ߬ߟߌ ߓߘߊ߫ ߟߊߟߐ߬ ߊ߬ ߛߐ߲߬ߞߌ߲߫ ߞߵߊ߬ ߦߋ߫ + ߊ߬ ߛߐ߲߬ߞߌ߲߫ ߞߵߊ߬ ߦߋ߫ ߒ ߠߊ߫ ߟߊ߬ߦߟߍ߬ߣߍ߲߬ ߞߐ߯ߟߕߊ ߟߎ߬ ߊ߬ ߓߘߊ߫ ߗߌߙߏ߲߫ %1$d%% ߓߘߊ߫ ߘߝߊ߫ @@ -72,6 +74,11 @@ GPS ߟߊߞߎߣߎ߲߫ ߟߊ߬ߦߟߍ߬ߣߍ߲߬ ߕߴߦߋ߲߬ ߡߎߣߎ߲߬ ߞߎߡߘߊ߫ %1$s ߡߊ߫ ߛߐ߬ߘߐ߲߬. + ߥߞߌߘߕߊ ߞߣߐߘߐ߫ ߛߌ߫ ߕߍ߫ ߦߋ߲߬ %1$s ߘߌ߫ + ߘߋߣߍ߲߫ ߛߊ߯ߘߊ߫ ߕߍ߫ %1$s ߓߟߏ߫ + ߡߏߦߌߓߊ߯ ߛߊ߯ߘߊ߫ ߛߌ߫ ߕߍ߫ %1$s ߓߟߏ߫. + ߖߌ߬ߦߊ߬ߓߍ߫ ߦߌ߬ߘߊ߬ߕߊ߫ ߕߍ߫ ߦߋ߲߬ + ߦߌߟߡߊ ߘߏ߫ ߝߙߊ߬ ߞߵߌ ߟߊ߫ ߖߌ߬ߦߊ߬ߓߍ ߞߎ߲߬ߠߞߊ߬ߕߊ߫ ߘߌ߫ ߥߞߌߡߋߘߌߦߊ߫ ߞߐߡߐ߲ ߞߊ߲߬.\nߛߐ߲߬ߞߌ߲߬ߠߌ߲ ߘߊߡߌ߬ߣߊ߬ ߞߊ߬ ߦߌߟߡߊ ߟߎ߫ ߝߙߊ߬. ߦߌߟߡߊ ߟߎ߬ ߟߊ߬ߓߍ߲߬ߢߐ߲߰ߡߦߊ߬ߘߊ ߖߊ߬ߕߋ߬ߘߊ ߟߊߞߊ߬ @@ -107,7 +114,7 @@ ߞߎ߲߬ߕߐ߮:ߛߌߘߑߣߋ߫ ߘߐ߬ߓߛߏ߬ߟߌ߬ ߟߎ ߌ ߦߴߊ߬ ߖߌ߰ ߟߊ߫ ߞߴߌ ߓߘߴߊ߬ ߛߐ߬ߘߐ߲߬؟ ߐ߲߬ߐ߲߬ߐ߲߫߹ - <u>ߞߟߊ߬ߟߐ߲߬ߠߌ߲߬ ߜߘߍ߫ ߟߎ߫</u> + ߞߎ߲߬ߠߊ߬ߝߎ߬ߟߋ߲߬ ߜߘߍ ߟߎ߬ ߦߌߟߡߊ ߟߎ߬ ߟߊ߬ߢߎ߲߬ߠߌ߲ ߦߵߌ ߘߐ߫... ߊ߬ ߡߊ߫ ߓߊߕߐ߬ߡߐ߲߬ @@ -146,6 +153,7 @@ ߞߐߡߐ߲ ߛߌ߲ߞߐ߲ ߞߐߡߐ߲ ߞߍߦߙߐ ߞߐߡߐ߲ ߝߋߛߑߓߎߞ ߞߐߜߍ + ߝߊ߲߬ߝߘߊ ߞߘߐߟߊ ߖߌ߬ߦߊ߬ߓߍ ߖߌ߬ߦߊ߬ߓߍ߫ ߡߊ߫ ߛߐ߬ߘߐ߲߬ ߦߌߟߡߊߙߋ߲߫ ߕߴߦߋ߲߬ ߖߌ߬ߦߊ߬ߓߍ ߟߊߦߟߍ߬ @@ -211,6 +219,11 @@ ߊ߬ ߘߐߛߊ߬ ߊ߬ ߡߊߝߍߣߍ߲߫ ߕߎ߲߯ ߊ߬ ߟߊߛߐ߬ߘߐ߲߬߹ + ߦߙߐ ߡߊ߬ߞߏ ߦߋ߫ ߖߌ߬ߦߊ߬ߓߍ ߟߊ߫ + ߖߌ߬ߦߊ߬ߓߍ ߘߏ߫ ߦߋ߫ ߦߙߐ ߣߌ߲߬ ߘߐ߫ ߞߘߐ߬ߡߊ߲߫ + ߦߙߐ ߣߌ߲߬ ߕߍߣߊ߬ ߡߍ߲߫ ߠߊ߫ ߓߍߓߊ߯ߦߊ ߘߐ߫ ߏ߬ ߞߐ߫. + ߞߎ߬ߘߎ ߣߌ߲߬ ߛߐ߲߬ߞߌ߲ ߘߌ߫ ߦߙߐ ߢߌ߲߬ ߠߎ߬ ߛߙߍߘߍ ߟߊߛߊ߬ߦߌ߫ ߟߊ߫. + ߌ ߘߌ߫ ߛߋ߫ ߦߙߐ ߓߍ߯ ߖߌ߬ߦߊ߬ߓߍ ߟߊߦߟߍ߬ ߟߊ߫ ߞߊ߬ ߓߐ߫ ߌ ߟߊ߫ ߖߌ߬ߦߊ߬ߝߍ ߘߐ߫ ߥߟߊ߫ ߞߍߟߊ߲ ߠߊ߫ ߖߌ߬ߦߊ߬ߓߍ߫ ߡߊ߫ ߛߐ߬ߘߐ߲߬ ߝߎ߬ߕߎ߲߬ߕߌ ߓߌ߬ߟߊ߬ߣߍ߲߫ ߊ߬ ߘߐ߫ ߞߵߌ ߕߏ߫ ߖߌ߬ߦߊ߬ߓߍ ߟߊߦߍ߬ߟߍ ߞߊ߲߬. ߖߌ߬ߦߊ߬ߓߍ ߟߊ߬ߦߟߍ߬ߣߍ߲߬ ߦߋ߫: %1$s ߟߋ߬ ߓߟߏ߫ @@ -257,6 +270,8 @@ ߊ߬ ߞߘߊߡߊ߫ ߞߐߕߐ߮ ߣߌ߲߬ ߕߐ߮ ߦߋ߫ ߦߋ߲߬ %1$s ߞߘߐ߬ߡߊ߲߫. ߌ ߦߴߊ߬ ߝߍ߬ ߞߵߊ߬ ߘߊߓߊ߲߫ ߓߊ߬؟ ߖߌ߬ߦߊ߬ߓߍ ߟߎ߬ + ߒ ߣߵߊ߬ ߟߊߦߟߍ߬ ߟߊ߫ ߢߌ߬ߣߊ߬ ߓߟߏ ߟߋ߬ ߡߊ߬ + ߒ ߕߎ߲߬ ߡߴߊ߬ ߟߐ߲߫ ߞߴߊ߬ ߘߌ߫ ߞߍ߫ ߟߊ߬ߥߊ߲߬ߞߊ߬ߟߌ߬ ߦߋߕߊ߫ ߘߌ߫ ߞߌߢߍ߲߫ ߝߊ߲߭ ߓߍ߯ ߊߡߋߙߌߞߌ߬ ߋߙߐߔߎ߬ @@ -299,6 +314,9 @@ ߖߌ߬ߦߊ߬ߓߍ ߣߊ߬ߕߐ ߖߌ߬ߦߊ߬ߓߍ߬ ߡߊ߫ ߟߊߓߊ߯ߙߊ߫ ߖߌ߬ߦߊ߬ߓߍ߫ ߡߊ߫ ߟߊߦߟߍ߬ + ߘߐ߬ߞߊ߬ߙߊ߲߬ߣߍ߲ ߠߎ߬ ߦߋ߫ + ߘߐ߬ߞߊ߬ߙߊ߲߬ߓߊߟߌ ߟߎ߬ ߦߋ߫ + ߝߎ߬ߕߎ߲߬ߕߌ ߓߌ߬ߟߊ߬ߣߍ߲߫ ߊ߬ ߘߐ߫ ߞߵߌ ߕߏ߫ ߖߌ߬ߦߊ߬ߓߍ ߓߊߕߐ߬ߡߐ߲ ߞߊ߲߬. ߖߌ߬ߦߊ߬ߓߍ߫ ߟߊߦߟߍ߬ߕߊ ߘߏ߫ ߛߎߥߊ߲ߘߌ߫ ߡߊ߬ߞߐ߬ߣߐ߲߬ߠߌ߲ ߞߍ߫ ߖߊ߰ߣߌ߲߬... ߖߌ߬ߦߊ߬ߓߍ ߣߌ߲߬ ߠߊߜߊ߲߫ @@ -306,10 +324,12 @@ ߓߊߦߟߍߡߊ߲ ߤߊߞߍ ߘߌ߲߬ߞߌߙߊ ߖߌ߬ߦߊ߬ߕߊ߬ߟߊ߲ ߛߎ߮ߦߊ + ߟߥߊ߬ߟߌ߬ߟߊ߲ ߠߊߖߍ߲ߛߍ߲ ߢߌ߲߬ ߠߎ߫ ߞߊ߲߬... ߖߌ߬ߦߊ߬ߓߍ ߞߌ߬ߓߊ߬ߙߏ߬ߦߊ ߦߌߟߡߊߙߋ߲߫ ߕߴߦߋ߲߬ ߘߊ߲߬ߠߊ߬ߕߍ߰ߟߌ ߡߊ߫ ߛߐ߬ߘߐ߲߬ ߟߊ߬ߦߟߍ߬ߟߌ ߘߊߓߌ߬ߟߊ߬ + ߓߟߏߡߟߊ߫ ߛߌ߫ ߕߍ߫ ߖߌ߬ߦߊ߬ߓߍ ߣߊ߬ߕߐ ߞߎ߲߬ߕߐ߮ ߟߊ߫ ߥߟߴߊ߬ ߞߊ߲߬ߛߓߍߟߌ ߡߎ߲߬ߠߊ߫ %1$s ߖߏ߬ߛߌ߬ߕߐ߫؟ %1$s ߟߊߦߟߍ߬ߣߍ߲߬ ߦߋ߫: %2$s ߟߋ߬ ߓߟߏ߫ ߞߊ߲߬ߛߓߍߟߌ ߞߍ߫ ߞߊ߲ ߓߊߖߎߡߊ @@ -319,6 +339,7 @@ %1$s ߕߐ߯ߦߊߟߌ ߦߴߌ ߘߐ߫ ߖߏ߬ߛߌ߬ߟߌ ߞߊ߲ߡߊ߬ ߊ߬ ߓߘߊ߫ ߗߌߙߏ߲߫ ߌ ߕߍ߫ ߛߋ߫ ߖߏ߰ߛߌ߬ߟߌ ߡߊߢߌߣߌ߲߫ ߠߊ߫ + ߛߍߟߑߝߌ ߘߏ߫ ߢߟߊߝߎ߬ߟߎ߲߬ߜߊ߬ߣߍ߲ ߘߏ߫ ߜߘߍ߫ ߖߌ߬ߦߊ߬ߓߍ ߜߍ߬ߙߍ߲߬ߘߍ߬ߣߍ߲ @@ -329,7 +350,17 @@ ߌ ߡߊ߫ ߓߟߏߓߌߟߊߢߐ߲߯ߞߊ߲ ߛߌ߫ ߞߍ߫ ߡߎߣߎ߲߬ ߖߊ߬ߕߋ߬ߘߊ ߓߘߊ߫ ߛߌ߲ߘߌ߫߹ ߝߎ߬ߕߎ߲߬ߕߌ ߘߏ߫ ߕߘߍ߬ ߦߋ߫ ߦߋ߲߬߹ + ߊ߬ ߦߋ߫ ߦߋ߲߬ + ߡߊ߬ߞߏ ߦߋ߫ ߖߌ߬ߦߊ߬ߓߍ ߟߊ߫ + ߦߙߐ ߛߎ߯ߦߊ: + ߛߍ߲߸ ߗߍߓߏ߲߸ ߖߌ߬ߦߊ߬ߓߏ߲ ߊ߬ ߣߌ߫. + ߞߏ ߘߏ߫ ߓߍ߲߬ ߣߍ߲߬ ߕߍ߫ ߜߊ߲߬ߞߎ߲߬ߠߌ߲ ߘߐ߫߸ ߌ ߦߴߌ ߟߊ߫ ߕߊ߬ߡߌ߲߬ߞߊ߲ ߡߊߝߊ߲߬ߟߋ߲߬߹߹ + ߘߋ߲ ߠߎ߬ ߟߊ߫ ߛߊ߯ߘߊ ߟߎ߫ + ߡߏߦߌߓߊ߮ ߟߎ߬ ߟߊ߫ ߛߊ߯ߘߊ ߟߎ߫ + ߛߌ߰ߢߐ߲߰ ߦߙߐ ߦߴߊ߬ ߘߐ߫ + ߦߙߐ %1$s ߖߌ߬ߦߊ߬ߓߍ ߟߋ߬ ߦߋ߫ ߣߌ߲߬ ߘߌ߫ ߓߊ߬؟ ߘߌ߬ߓߌ + ߦߋߟߋ߲ ߘߏߜߘߍ߫ ߟߎ߫ ߟߊߢߎ߲߫ ߖߌ߬ߦߊ߬ߓߍ ߝߙߊ߬ ߥߞߌߔߋߘߌߦߊ ߞߊ߲߬ ߌ ߦߴߊ߬ ߝߍ߬ ߞߊ߬ ߖߌ߬ߦߊ߬ߓߍ ߣߌ߲߬ ߓߌ߬ߟߊ߬ %1$ ߞߊ߲ ߥߞߌߔߋߘߌߦߊ ߞߎߡߘߊ ߟߊ߫ ߓߊ߬؟ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index b1aff476b4..3c974eb5b7 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -15,6 +15,7 @@ * Rezonansowy * Rzuwig * Sp5uhe +* Strebski * Ty221 * Vesihiisi * WaldiSt @@ -58,6 +59,12 @@ %1$d Przesłanych Przesłania + + Odbieranie udostępnianych treści. Przetwarzanie obrazu może zająć trochę czasu, w zależności od jego rozmiaru i urządzenia + Odbieranie udostępnionej treści. Przetwarzanie obrazów może zająć trochę czasu, w zależności od ich rozmiaru i urządzenia + Odbieranie udostępnionej treści. Przetwarzanie obrazów może zająć trochę czasu, w zależności od ich rozmiaru i urządzenia + + Odkrywaj Odkrywaj Wygląd @@ -71,7 +78,7 @@ Prześlij do Commons Nazwa użytkownika Hasło - Zaloguj sie do Commons Beta + Zaloguj się na konto Commons Beta Zaloguj się Nie pamiętasz hasła? Zarejestruj się @@ -88,7 +95,9 @@ Wysyłanie %1$s Zakończono wysyłanie pliku %1$s Wysyłanie %1$s nieudane + Zatrzymano przesyłanie %1$ plików Dotknij, aby zobaczyć + Dotknij, aby zobaczyć Niedawno przesłane W kolejce Porażka @@ -198,7 +207,7 @@ Tak! Więcej informacji Kategorie - Ładowanie… + Wczytywanie… Nic nie zaznaczono Brak podpisu Bez opisu @@ -284,7 +293,7 @@ Błąd podczas buforowania zdjęć Podaj krótką, opisową i unikalną nazwę, która będzie służyła jako nazwa pliku. Możesz używać prostego języka i spacji. Nie dodawaj rozszerzenia pliku. Opisz jak najwięcej mediów: Gdzie zostało zrobione? Co to pokazuje? Jaki jest kontekst? Proszę opisać przedmioty lub osoby. Ujawnij informacje, których nie można łatwo odgadnąć, na przykład porę dnia, jeśli jest to krajobraz. Jeśli media pokazują coś niezwykłego, wyjaśnij, co sprawia, że ​​jest to niezwykłe. - Proszę napisać krótki opis obrazu. (Limit do 255 znaków) + Proszę napisać krótki opis obrazu. (Limit do 255 znaków) To zdjęcie jest zbyt ciemne, czy na pewno chcesz je załadować? Wikimedia Commons jest tylko dla zdjęć o wartości encyklopedycznej. To zdjęcie jest rozmazane, czy na pewno chcesz je załadować? Wikimedia Commons jest tylko dla zdjęć o wartości encyklopedycznej. Potencjalne problemy z tym obrazem: @@ -348,10 +357,13 @@ Ponów próbę Wszystko jasne! Kliknięcie „WYSZUKAJ TEN OBSZAR” blokuje mapę i rozpoczyna pobliskie wyszukiwanie w tej lokalizacji. + To miejsce wymaga zdjęcia. + To miejsce już posiada zdjęcie. + To miejsce już nie istnieje. Stuknięcie tego przycisku powoduje wyświetlenie listy tych miejsc Możesz przesłać zdjęcie do dowolnego miejsca ze swojej galerii lub aparatu Nie znaleziono grafik! - Wystąpił błąd podczas ładowania grafik. + Wystąpił błąd podczas wczytywania grafik. Przesłano przez %1$s Zablokowany(-a) Zostałeś zablokowany(-a) w Commons @@ -363,9 +375,9 @@ Szukaj Ostatnie wyszukiwania: Ostatnio wyszukiwane zapytania - Wystąpił błąd podczas ładowania kategorii. + Wystąpił błąd podczas wczytywania kategorii. Wystąpił błąd podczas ładowania obrazów. - Wystąpił błąd podczas ładowania podkategorii. + Wystąpił błąd podczas wczytywania podkategorii. Multimedia Kategorie Elementy @@ -431,6 +443,7 @@ Powiadomienia (przeczytaj) Wyświetl powiadomienie w pobliżu Stuknij tutaj, aby zobaczyć najbliższe miejsce, które wymaga zdjęć + Nie odnaleziono pobliskich Tobie miejsc Lista Uprawnienie do przechowywania Potrzebujemy Twojej zgody na dostęp do zewnętrznej pamięci urządzenia w celu przesyłania obrazów. @@ -468,6 +481,7 @@ Nie wybrano kategorii Obrazy bez kategorii rzadko nadają się do użycia. Czy na pewno chcesz kontynuować bez wybierania kategorii? Nie wybrano żadnych obrazów + Obrazy ze wskazanymi przedstawieniami są łatwiejsze do znalezienia i częściej używane. Czy na pewno chcesz kontynuować bez wybierania przedstawień? (Dla wszystkich obrazów w zestawie) Przeszukaj ten obszar Prośba o pozwolenie @@ -479,6 +493,7 @@ Coś poszło nie tak, nie mogliśmy pobrać twoich osiągnięć Zrobiłeś tak wiele wkładu, że nasz system obliczania osiągnięć nie może sobie poradzić. To jest najwyższym osiągnięciem. Kończy się na: + Wyświetl kampanie Zobacz trwające kampanie Kampanie już nie będą widoczne. Jednak w razie potrzeby możesz ponownie włączyć to powiadomienie w ustawieniach. Ta funkcja wymaga połączenia sieciowego, sprawdź ustawienia połączenia. @@ -512,6 +527,7 @@ Czy chciałbyś podziękować autorowi? Kliknij NIE, aby nominować ten obraz do usunięcia, jeśli nie jest w ogóle przydatny. Logo, zrzuty ekranu, plakaty filmowe często stanowią naruszenie praw autorskich.\nKliknij NIE, aby nominować ten obraz do usunięcia + %1$s będzie wdzięczny za Twoje docenienie Och, to nie jest nawet skategoryzowane! Ten obraz należy do kategorii %1$s Jest poza zakresem, ponieważ jest @@ -593,6 +609,8 @@ Most, muzeum, hotel itp. Coś poszło nie tak podczas logowania, musisz zresetować hasło! MEDIA + KLASY POTOMNE + KLASY NADRZĘDNE Znaleziono miejsce w pobliżu Czy jest to zdjęcie miejsca %1$s? Odkryj @@ -611,7 +629,7 @@ Włączyć lokalizację? Lokalizacja W pobliżu wymaga włączonej lokalizacji, aby działać poprawnie Czy zrobiłeś te dwa zdjęcia w tym samym miejscu? Czy chcesz użyć szerokości/długości geograficznej obrazu po prawej stronie? - Załaduj więcej + Wczytaj więcej Nie znaleziono miejsc, spróbuj zmienić kryteria wyszukiwania. Dodaj obraz do Wikipedii Czy chcesz dodać to zdjęcie do artykułu w Wikipedii w języku %1$s? @@ -627,4 +645,7 @@ 6. Edytuj wikitekst w celu odpowiedniego pozycjonowania, jeśli to konieczne. Aby uzyskać więcej informacji, zobacz <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">here</a>. 7. Opublikuj artykuł Skopiuj wikicode do schowka + zatrzymaj + wznów + Zatrzymano diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index 86b1c12d24..f62cf282ac 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -63,7 +63,9 @@ %1$s carià Fin dël cariament %1$s Cariament falì a %1$s + Cariament %1$s an pàusa Sgnaché për ësmon-e + Sgnaché për vëdde Ij mè cariament recent An coa Falì @@ -259,7 +261,7 @@ Eror antramentre ch\'as butavo le plance an memòria local Un tìtol dëscritiv ùnich për l\'archivi, che a servirà com nòm d\'archivi. A peul dovré un lengagi sempi con djë spassi. Ch\'a ancluda pa l\'estension dl\'archivi Për piasì, ch\'a descriva ël mojen mej ch\'a peul: Andoa a l\'é stàit fàit? Për piasì, ch\'a descriva j\'oget o le përson-e. Ch\'a arvela j\'anformassion ch\'a l\'é nen belfé andviné, për esempi l\'ora dël dì, s\'a l\'é un panorama. Si ël mojen a smon cheicòs ëd foravìa, për piasì ch\'a spiega lòn ch\'a lo rend foravìa. - Për piasì, ch\'a scriva na curta descrission ëd la plancia (limità a 255 caràter). + Për piasì, ch\'a scriva na curta descrission ëd la plancia (limità a 255 caràter). Sa plancia a l\'é tròp sombra, e-lo sigur ëd vorèj cariela? Wikipedia Commons a l\'é mach për plance con un valor enciclopédich. Sa plancia a l\'é tërbola, e-lo sigur ëd vorèj cariela? Wikipedia Comun a l\'é mach për plance con un valor enciclopédich. Problema potensiaj con costa plancia: @@ -323,6 +325,9 @@ Prové torna Fàit! A-i é dij pòst davzin a chiel ch\'a l\'han da manca ëd plance për ilustré ij sò artìcoj su Wikipedia.\n\nSgnaché su \'SËRCHÉ AN COSTA ZÒNA\' a blòca la carta e a fa parte n\'arserca ëd prossimità davzin a cola posission. + Ës pòst-sì a l\'ha damanca ëd na fòto. + Ës pòst-sì a l\'ha già na fòto. + Ës pòst a esist pi. Sgnacand su \'s boton a comparirà na lista ëd si pòst A peul carié na fòto da \'n pòst qualsëssìa ëd soa galarìa o màchina fòto Gnun-e plance trovà! @@ -608,4 +613,7 @@ 6. Modifiché ël wikitest për posissionelo bin, si necessari. Për pi d\'anformassion, vëdde <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">here</a>. 7. Publiché l\'artìcol Copié ël còdes wiki an sla taulëtta + pàusa + ancaminé torna + An pàura diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3360a40ac0..6816cac3cd 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -77,7 +77,9 @@ %1$s enviando! Terminando o envio de %1$s Envio de %1$s falhou + Envio de %1$s em pausa Toque para ver + Toque para ver Meus envios recentes Na fila Falhou @@ -273,7 +275,7 @@ Erro durante o cache de imagens Um título descritivo exclusivo para o arquivo, que servirá como um nome de arquivo. Você pode usar linguagem simples com espaços. Não inclua a extensão do arquivo Por favor, descreva a mídia tanto quanto possível: onde foi tomada? O que isso mostra? Qual é o contexto? Descreva os objetos ou pessoas. Revelar informações que não podem ser facilmente adivinhadas, por exemplo, a hora do dia, se for uma paisagem. Se a mídia mostrar algo incomum, explique o que torna incomum. - Por favor, escreva uma breve descrição da imagem. (Limite a 255 caracteres) + Por favor, escreva uma breve descrição da imagem. (Limite a 255 caracteres) Esta foto está muito escura, você tem certeza de que deseja enviá-la? O Wikimedia Commons é apenas para imagens com valor enciclopédico. Esta foto está embaçada, tem certeza de que deseja enviá-la? O Wikimedia Commons é apenas para imagens com valor enciclopédico. Problemas potenciais com esta imagem: @@ -337,6 +339,9 @@ Tentar novamente Entendido! Estes são os lugares perto de si que precisam de fotografias para ilustrar os respetivos artigos na Wikipédia.\n\nClicar em \'Pesquisar nesta área\' bloqueia a localização do mapa e inicia uma pesquisa de lugares na área circundante. + Este lugar precisa de uma foto. + Este lugar já tem uma foto. + Este lugar não existe mais. Tocar neste botão fará surgir uma lista destes lugares Pode carregar uma fotografia para qualquer dos lugares, da sua galeria ou câmara Não foi encontrada nenhuma imagem! @@ -622,4 +627,7 @@ 6. Editar o wikitexto para o posicionamento apropriado, se necessário. Para mais informações, veja <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">aqui</a>. 7. Publique o artigo Copiar wikicode para a área de transferência + pausar + continuar + Pausado diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 1d33bbf100..f9396e7f36 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -77,7 +77,9 @@ A carregar %1$s A terminar o carregamento de %1$s O carregamento de %1$s falhou + Carregamento de %1$s em pausa Tocar para ver + Tocar para ver Carregamentos recentes Em espera Falhado @@ -90,7 +92,9 @@ Partilhar Ver no navegador Legenda (obrigatória) + Forneça uma legenda para este ficheiro, por favor Descrição + Legenda (limite de 255 caracteres) Não é possível iniciar uma sessão - falha de rede Não é possível iniciar uma sessão - verifique o seu nome de utilizador e a palavra-passe, por favor Demasiadas tentativas mal sucedidas. Por favor, tente novamente dentro de minutos. @@ -103,6 +107,7 @@ Modificações Carregar Pesquisar categorias + Procurar elementos que o seu conteúdo multimédia retrata (montanha, o Taj Mahal, etc.) Gravar Atualizar Lista @@ -110,6 +115,10 @@ Ativar GPS Ainda não foram enviados ficheiros Não foi encontrada nenhuma categoria que corresponda a %1$s + Não foi encontrado nenhum elemento Wikidata que corresponda a %1$s + %1$s não tem nenhuma classe descendente + %1$s não tem nenhuma classe progenitora + Não há nenhuma imagem para a representação Adicione categorias para tornar as suas imagens mais fáceis de encontrar na wiki Wikimedia Commons.\nComece a escrever para adicionar categorias. Categorias Configurações @@ -126,6 +135,7 @@ Enviar comentários (por correio eletrónico) Não foi instalado nenhum cliente de correio eletrónico Categorias usadas recentemente + Representações usadas recentemente A aguardar pela primeira sincronização… Não carregou ainda nenhuma foto. Tentar novamente @@ -136,7 +146,7 @@ Usar título e descrição anteriores Obter automaticamente a localização atual Se a imagem não estiver georreferenciada, obtém a localização atual e georreferencia a imagem com ela. Aviso: isto revela a sua localização corrente. - Modo noturno + Tema Atribuição-CompartilhaIgual 4.0 Atribuição 4.0 Atribuição–CompartilhaIgual 3.0 @@ -182,7 +192,8 @@ A carregar… Nenhuma selecionada Sem legenda - Sem descrição + Não há nenhuma representação + Não há nenhuma descrição Não há nenhuma discussão Licença desconhecida Atualizar @@ -195,11 +206,14 @@ Locais Próximos Não foi encontrado nenhum local próximo Aviso - Este ficheiro já existe na wiki Commons. Tem a certeza de que deseja continuar? + Foi encontrada uma imagem duplicada + Este ficheiro já foi destruído na wiki Commons. Tem a certeza de que deseja continuar? + Carregar Sim Não Legenda Título + Representações Descrição Discussão Autor @@ -261,6 +275,7 @@ Erro ao colocar imagens na cache Um título descritivo exclusivo para o ficheiro, que servirá como um nome de ficheiro. Pode utilizar uma linguagem simples com espaços. Não inclua a extensão do ficheiro Descreva o elemento multimédia da melhor forma possível, por favor. Onde foi tirado? O que é mostrado? Qual é o contexto? Descreva os objetos ou pessoas. Indique as informações que não podem ser facilmente adivinhadas; por exemplo, a hora do dia, se for uma paisagem. Se o ficheiro mostra algo incomum, explique o que é incomum. + Escreva uma breve descrição da imagem, por favor (limite de 255 caracteres). Esta imagem está demasiado escura; tem a certeza de que deseja carregá-la? A wiki Wikimedia Commons só aceita as imagens de valor enciclopédico. Esta imagem está desfocada; tem a certeza de que deseja carregá-la? A wiki Wikimedia Commons serve apenas para imagens de valor enciclopédico. Possíveis problemas com esta imagem: @@ -270,6 +285,7 @@ Esta fotografia foi tirada num local diferente. Carregue só fotografias tiradas por si, por favor. Não carregue fotografias que encontrou na conta do Facebook de outra pessoa. Quer, mesmo assim, carregar esta fotografia? + Problemas encontrados na imagem Carregue só fotografias tiradas por si, por favor. Não carregue fotografias que tenha descarregado da Internet. Permitir Utilizar armazenamento externo @@ -323,6 +339,9 @@ Tentar novamente Entendido! Estes são os locais próximos de si que precisam de fotografias para ilustrar os respetivos artigos na Wikipédia.\n\nClicar em \'Pesquisar nesta área\' bloqueia a localização do mapa e inicia uma pesquisa de locais na área circundante. + Este local precisa de uma foto. + Este local já tem uma foto. + Este local já não existe. Tocar neste botão fará surgir uma lista destes locais Pode carregar uma fotografia de qualquer local, vinda da sua galeria ou câmara Não foi encontrada nenhuma imagem! @@ -339,6 +358,7 @@ Pesquisas recentes: Consultas pesquisadas recentemente Ocorreu um erro ao carregar categorias. + Ocorreu um erro ao carregar representações. Ocorreu um erro ao carregar subcategorias. Multimédia Categorias @@ -402,7 +422,7 @@ Contribuições Aqui perto Notificações - Notificações (arquivadas) + Notificações (lidas) Apresentar notificação de proximidade Toque aqui para ver o local mais próximo que precisa de fotos Não foi encontrado nenhum local próximo @@ -442,6 +462,8 @@ Pacífico Não foi selecionada nenhuma categoria As imagens sem categorias só raramente são utilizáveis. Tem a certeza de que deseja continuar sem selecionar categorias? + Não foram selecionadas representações + As imagens com representações são encontradas mais facilmente e mais propensas a serem usadas. Tem a certeza de que deseja continuar sem selecionar representações? (Para todas as imagens do conjunto) Pesquisar nesta área Pedido de permissões @@ -451,6 +473,7 @@ Apresentar permissões de localização Pedir permissões de localização quando for necessário para a funcionalidade do cartão de notificação de proximidade. Algo correu mal, não conseguimos obter as suas realizações + As suas contribuições foram tantas que o nosso sistema de cálculo de realizações não consegue processá-las. Essa é a realização máxima. Termina em: Apresentar campanhas Ver as campanhas em andamento @@ -505,9 +528,9 @@ Não foi revertida nenhuma imagem Não foi carregada nenhuma imagem Não tem nenhuma notificação por ler - Não tem nenhuma notificação arquivada + Não tem nenhuma notificação lida Partilhar os registos usando - Ver arquivadas + Ver lidas Ver não lidas Ocorreu um erro ao escolher imagens Escolher imagens a carregar @@ -515,6 +538,7 @@ As fotografias destacadas são imagens de fotógrafos e ilustradores altamente qualificados, que a comunidade da wiki Wikimedia Commons escolheu como as de melhor qualidade do \'\'site\'\'. As imagens carregadas via \"Locais próximos\" são as imagens que são carregadas descobrindo locais do mapa. Esta funcionalidade permite que os editores enviem uma notificação de agradecimento aos utilizadores que fizerem edições úteis - usando uma pequena hiperligação de agradecimento na página do historial ou na de diferenças. + Copiar legendas e descrição anteriores Clique para reutilizar o título e a descrição que inseriu na sua fotografia anterior e adequá-los à atual Exemplos de imagens que podem ser carregadas na wiki Commons Exemplos de imagens que não devem ser carregadas @@ -533,6 +557,7 @@ Partilhar aplicação por... Informação da imagem Não foi encontrada nenhuma categoria + Não foi encontrada nenhuma representação Carregamento cancelado Não há dados para o título ou descrição da imagem anterior Porque deve %1$s ser eliminado? @@ -566,11 +591,43 @@ Ponte, museu, hotel, etc. Ocorreu algo de errado com a sessão, tem de redefinir a sua palavra-passe! MULTIMÉDIA + CLASSES DESCENDENTES + CLASSES PROGENITORAS Foi encontrado um local próximo Isto é uma foto do local %1$s? + Explorar + Marcadores + Definições Removido dos marcadores Adicionado aos marcadores Ocorreu um problema. Não foi possível definir a imagem de fundo Definir como imagem de fundo A definir a imagem de fundo. Aguarde, por favor... + Seguir sistema + Escuro + Claro + Não foi possível abrir as definições de localização. Ative a localização manualmente, por favor + Para obter os melhores resultados, escolha o modo Alta Precisão. + Ativar a localização? + A funcionalidade de proximidade precisa que a localização esteja ativada para funcionar corretamente + Tirou estas duas fotos no mesmo lugar? Quer usar a latitude/longitude da fotografia da direita? + Carregar mais + Não foi encontrado nenhum local; tente alterar os seus critérios de pesquisa. + Adicionar imagem à Wikipédia + Deseja adicionar esta fotografia ao artigo da Wikipédia em %1$s? + Instruções + Tenha o cuidado de seguir as diretrizes de edição! + Confirmar + Instruções + 1. Usar o seguinte texto wiki: + 2. Clicar em \"Confirmar\" abrirá o artigo da Wikipédia + 3. Encontrar uma secção apropriada no artigo para a sua imagem + 4. Clicar o ícone \"Editar\" (que parece um lápis) dessa secção. + 5. Inserir o texto wiki no local apropriado. + 6. Editar o texto wiki para colocar no posicionamento apropriado, se necessário. Para mais informações, ver <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">aqui</a>. + 7. Publicar o artigo + Copiar código wiki para a área de transferência + pausar + continuar + Em pausa diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 0af6aab153..cc78e91b5f 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -270,7 +270,7 @@ Eroare la cache imaginilor Un titlu descriptiv unic pentru fișier, care va servi ca nume de fișier. Puteți utiliza un limbaj simplu cu spații. Nu includeți extensia de fișier Vă rugăm să descrieți media cât mai mult posibil: Unde a fost făcut? Ce arată? Care este contextul? Descrieți obiectele sau persoanele. Dezvăluiți informații care nu pot fi ușor ghicite, cum ar fi timpul zilei dacă este un peisaj. În cazul în care materialul transmis arată ceva neobișnuit, vă rugăm să explicați ceea ce o face neobișnuită. - Vă rugăm să scrieți o scurtă descriere a imaginii. (Limită la 255 de caractere) + Vă rugăm să scrieți o scurtă descriere a imaginii. (Limită la 255 de caractere) Această imagine este prea întunecată, sunteți sigur că doriți să o încărcați? Wikimedia Commons este numai pentru imagini cu valoare enciclopedică. Această imagine este neclară, sunteți sigur că doriți să o încărcați? Wikimedia Commons este numai pentru imagini cu valoare enciclopedică. Probleme potențiale cu această imagine: diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 144e0b2d1b..c79372028e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -12,6 +12,7 @@ * Iluvatar * Kaganer * MaxBioHazard +* Monirec * Movses * Nitch * Okras @@ -207,6 +208,7 @@ Категории Загрузка… Ничего не выбрано + Без подписи Нет описания Обсуждений нет Неизвестная лицензия @@ -287,7 +289,7 @@ Ошибка при кэшировании картинок Уникальное описание, которое будет сохранено как имя файла. Вы можете использовать естественный язык, разделяя слова пробелами. Пожалуйста, не указывайте расширение файла. Пожалуйста, подробно опишите загружаемый файл: где он был снят? что на нём изображено? каков его контекст? Пожалуйста опишите изображённых персон или объекты. Добавьте информацию, о которой нельзя легко догадаться, например, время суток, когда снимался файл. Если снято что-то необычное, постарайтесь пояснить, что именно в этом необычного. - Пожалуйста, напишите краткое описание изображения (не более 255 символов). + Пожалуйста, напишите краткое описание изображения (не более 255 символов). Это изображение слишком тёмное. Вы уверены, что хотите его загрузить? Викисклад подходит только для изображений, имеющих энциклопедическую ценность. Это изображение размыто. Вы уверены, что хотите его загрузить? Викисклад подходит только для изображений, имеющих энциклопедическую ценность. Потенциальные проблемы с этим изображением: @@ -430,7 +432,7 @@ Вклад Поблизости Уведомления - Уведомления (архивированные) + Уведомления (читать) Уведомлять меня о местах поблизости Нажмите здесь, чтобы увидеть ближайшее место без изображений Не найдено мест поблизости @@ -620,6 +622,8 @@ Мест не найдено, попытайтесь изменить критерии поиска. Добавить изображение в Википедию Инструкции + Соблюдайте правила редактирования! Подтвердить Инструкции + Скопировать вики-код в буфер обмена diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 7be29c36f0..5ccd78e4bb 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -5,11 +5,14 @@ * Luky001 * Patriccck * Sudo77(new) +* TomášPolonec --> - + nahráva sa %1$d súbor - nahrávajú sa %1$d súbory + nahrávajú sa %1$d súbory + nahráva sa %1$d súborov + nahráva sa %1$d súborov \@string/contributions_subtitle_zero @@ -103,6 +106,9 @@ Žiadne nahrané súbory Žiadne kategórie nezodpovedajú „%1$s“ Neboli nájdené žiadne položky Wikiúdajov zhodujúce sa s %1$s + %1$s nemá žiadne dcérske triedy + %1$s nemá žiadne rodičovské triedy + Žiaden obrázok na zobrazenie Pridajte kategórie, aby bolo vaše obrázky možné na Wikimedia Commons nájsť.\nPre pridanie kategórií začnite písať. Kategórie Nastavenia @@ -119,6 +125,7 @@ Odoslať spätnú väzbu (emailom) Nemáte nainštalovaného žiadneho e-mailového klienta Nedávno použité kategórie + Nedávno použité zobrazenia Čaká sa na prvú synchronizáciu… Ešte ste nenahrali žiadne fotografie. Znova @@ -175,6 +182,7 @@ Načítava sa… Nič nebolo vybrané Žiadny titulok + Žiadne zobrazenie Bez popisu Žiadna diskusia Neznáma licencia @@ -193,7 +201,9 @@ Nahrať Áno Nie + Titulok Názov + Zobrazenia Popis Diskusia Autor @@ -255,6 +265,7 @@ Chyba pri ukladaní obrázkov Jedinečný popis súboru, ktorý bude slúžiť ako názov súboru. Môžete použiť bežný jazyk s medzerami. Nezadávajte príponu súboru. Opíšte obrázok čo najviac, ako je to len možné: Kde bol zhotovený? Čo znázorňuje? Aký je kontext obrázku? Popíšte, prosím, predmety alebo osoby na obrázku a nezabudnite na informácie, ktoré nie je možné ľahko odhadnúť zo samotného obrázku, ako je napríklad denná doba, pokiaľ ide o krajinu. Ak je na obrázku niečo neobvyklé, popíšte, čo ho robí neobvyklým. + Prosím napíšte krátky popis obrázku (maximálne 255 znakov). Tento obrázok je príliš tmavý. Ste si istí, že ho chcete nahrať? Wikimedia Commons slúži len na obrázky s encyklopedickou hodnotou. Tento obrázok je rozmazaný. Ste si istí, že ho chcete nahrať? Wikimedia Commons slúži len na obrázky s encyklopedickou hodnotou. Potenciálne problémy s týmto obrázkom: @@ -317,6 +328,9 @@ Obnoviť Rozumiem Toto sú miesta v blízkosti vašej súčasnej polohy, ktoré potrebujú fotografie na ilustráciu príslušných článkov na Wikipédii.\n\nKliknutím na PREHĽADAŤ TÚTO OBLASŤ sa zamkne mapa a spustí sa prehľadávanie okolia daného miesta. + Toto miesto potrebuje obrázok. + Toto miesto už má obrázok. + Toto miesto už nejestvuje. Ťuknutím na toto tlačidlo otvoríte zoznam týchto miest Môžete nahrať obrázok akéhokoľvek z týchto miest z vašej galérie alebo priamo z fotoaparátu. Neboli nájdené žiadne obrázky! @@ -333,9 +347,11 @@ Nedávne hľadania: Nedávno hľadané dopyty Chyba pri načítaní kategórií. + Chyba pri načítaní zobrazení. Chyba pri načítaní podkategórií. Multimediálne súbory Kategórie + Položky Najlepšie Nahrané mobilom Obrázok bol pridaný do položky %1$s na Wikiúdajoch! @@ -395,7 +411,7 @@ Príspevky V okolí Upozornenia - Upozornenia (prečítané) + Upozornenia (prečítané) Zobraziť notifikáciu o miestach v okolí Kliknutím sem sa zobrazí najbližšie miesto, ktoré potrebuje obrázky Vo vašej blízkosti neboli nájdené žiadne miesta @@ -434,7 +450,8 @@ Ázia Tichomorie Neboli vybrané žiadne kategórie - Obrázky bez kategórií sú používané len zriedka. Naozaj chcete nahrať obrázok bez výberu kategórií? + Obrázky bez kategórií sú zriedka použiteľné. Naozaj chcete nahrať obrázok bez výberu kategórií? + Neboli zvolené žiadne zobrazenia (Pre všetky obrázky v sade) Prehľadať túto oblasť Je požadované oprávnenie @@ -499,9 +516,9 @@ Žiadne revertované obrázky Žiadne nahrané obrázky Nemáte žiadne neprečítané upozornenia - Nemáte žiadne prečítané upozornenia + Nemáte žiadne prečítané upozornenia Zdieľať log pomocou - Zobraziť prečítané + Zobraziť prečítané Zobraziť neprečítané Nastala chyba pri vyberaní obrázkov Vyberte obrázky, ktoré chcete nahrať @@ -509,6 +526,7 @@ Najlepšie obrázky sú fotografie od vysoko skúsených fotografov a ilustrátorov, ktoré vybrala komunita Wikimedie Commons ako jedny z najkvalitnejších na stránke. Obrázky nahrané cez Miesta v okolí sú obrázky, ktoré sú nahrané vďaka objavovaniu miest na mape. Táto funkcia umožňuje poslať poďakovanie za užitočné úpravy používateľom – použitím malého odkazu poďakovať v histórií stránky alebo na stránke rozdielu medzi revíziami. + Kopírovať predchádzajúce titulky a popis Kliknutím znovu použijete názov a popis, ktorý ste zadali pri predchádzajúcom obrázku, a upravíte ho tak, aby vyhovoval vášmu aktuálnemu obrázku Príklady dobrých obrázkov na nahranie na Commons Príklady obrázkov, ktoré by ste nemali nahrávať @@ -572,6 +590,22 @@ Predvolený Tmavý Svetlý + Pre najpresnejšie výsledky zvoľte režim vysokej presnosti. Zapnúť lokáciu? + Načítať ďalšie + Neboli nájdené žiadne miesta, skúste zmeniť vyhľadávacie kritériá. + Pridať obrázok na Wikipédiu + Chcete pridať tento obrázok do článku na %1$s Wikipédii? + Pokyny + Dbajte na to, aby ste sa držali návodov na editovanie! Potvrdiť + Inštrukcie + 1. Použiť nasledovný wikitext: + 2. Po kliknutí na „Potvrdiť“ sa otvorí článok na Wikipédii + 3. Nájdite vhodný odsek v článku pre Váš obrázok + 4. Kliknite na ikonku „Upraviť“ (tú s ceruzkou) pre daný odsek. + 5. Vložte wikitext na vhodné miesto. + 6. Ak načim, upravte wikitext pre vhodné umiestnenie. Pre viac informácií, pozrite <a href=\"https://sk.wikipedia.org/wiki/Pomoc:Obr%C3%A1zok#Vlo%C5%BEenie_obr%C3%A1zku_do_%C4%8Dl%C3%A1nku\">sem</a>. + 7. Uložte článok + Skopírujte wikikód diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 53b1d43907..bc6ee42af8 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -5,6 +5,7 @@ * Ainali * Jopparn * Liuxinyu970226 +* Sabelöga * Skalman * Tor.klingberg * WikiPhoenix @@ -32,12 +33,12 @@ Dessa bilder kommer att licensieras under %1$s - %1$d uppladdning - %1$d uppladdningar + %1$d Uppladdning + %1$d Uppladdningar Hämtar delat innehåll. Det kan ta en stund att behandla bilden beroende på bildens storlek och din enhet - Hämtar delat innehåll. Det kan ta en stund att behandla bilderna beroende på bildens storlek och din enhet + Hämtar delat innehåll. Det kan ta en stund att behandla bilderna beroende på bildernas storlek och din enhet Utforska Utforska @@ -61,7 +62,7 @@ Inloggningen lyckades! Det gick inte att logga in! Filen hittades inte. Försök med en annan fil. - Autentisering misslyckades, var god logga in igen! + Autentisering misslyckades, var god logga in igen Överföring påbörjad! %1$s överförd! Tryck för att visa din uppladdning @@ -69,7 +70,9 @@ %1$s laddas upp Avslutar uppladdning av %1$s Uppladdning av %1$s misslyckades + Uppladdning av %1$s pausades Tryck för att visa + Tryck för att visa Mina senaste uppladdningar Köade Misslyckades @@ -81,7 +84,7 @@ Mina uppladdningar Dela Visa i webbläsaren - Bildtext (nödvändigt) + Bildtext (obligatoriskt) Var god ange en bildtext för denna fil Beskrivning Bildtext (maximalt 255 tecken) @@ -122,7 +125,7 @@ Integritetspolicy Erkännande Om - Skicka feedback (via e-post) + Skicka återkoppling (via e-post) Ingen e-postklient är installerad Nyligen använda kategorier Senast använda skildringar @@ -265,7 +268,7 @@ Fel uppstod när bilder cachelagras En unik beskrivande titel för filen, som kommer att fungera som ett filnamn. Du kan använda klarspråk med mellanslag. Ta inte med filändelsen Beskriv mediafilen så mycket som möjligt. Var togs den? Vad visar den? Vad är sammanhanget? Beskriv föremålen eller personerna. Ge information som inte kan gissas fram, t.ex. tidpunkten om det är ett landskap. Om mediafilen visar någonting ovanligt, förklara vad som gör den ovanlig. - Var god skriv en kort beskrivning av bilden. (Maximalt 255 tecken) + Var god skriv en kort beskrivning av bilden. (Maximalt 255 tecken) Denna bild är för mörk, är du säker på att du vill ladda upp den? Wikimedia Commons är endast till för bilder med encyklopediskt värde. Denna bild är suddig, är du säker på att du vill ladda upp den? Wikimedia Commons är endast till för bilder med encyklopediskt värde. Möjliga problem med denna bild: @@ -294,7 +297,7 @@ Hoppa över Logga in Vill du verkligen hoppa över inloggningen? - Du behöver logga ini för att ladda upp bilder i framtiden. + Du behöver logga in för att ladda upp bilder i framtiden. Logga in för att använda denna funktion Kopiera wikitexten till urklipp Wikitexten kopierades till urklipp @@ -329,6 +332,9 @@ Försök igen Uppfattat! Detta är platserna nära dig som behöver bilder för att illustrera deras Wikipedia-artiklar.\n\nNär du klickar på \"SÖK I DETTA OMRÅDE\" kommer kartan låsas och en sökning startas i närheten runt detta plats. + Den här platsen behöver ett foto. + Den här platsen har redan ett foto. + Den här platsen finns inte längre. Klicka på den här knappen för att få upp en lista med dessa platser Du kan ladda upp en bild från vilken plats som helst från ditt galleri eller kamera Inga bilder hittades! @@ -360,20 +366,20 @@ Är det okej att ladda upp denna bild? Fråga Resultat - Om du fortsätter ladda upp bilder som kommer att raderas kommer ditt konto förmodligen bannlysas. Är du säker på att du vill avsluta frågesporten? - Fler än %1$s av bilderna du har laddat upp har raderats. Om du fortsätter ladda upp bilder som kommer att raderas kommer ditt konto förmodligen bannlysas.\n\nVill du se guiden igen och sedan göra frågesporten för att hjälpa dig förstå vilka bildtyper du bör och inte bör ladda upp? + Om du fortsätter ladda upp bilder som behöver raderas kommer ditt konto förmodligen blockeras. Är du säker på att du vill avsluta frågorna? + Fler än %1$s av bilderna du laddat upp har raderats. Om du fortsätter ladda upp bilder som behöver raderas kommer ditt konto förmodligen blockeras.\n\nVill du se guiden igen och sedan svara på frågor för att hjälpa dig förstå vilka bildtyper du bör och inte bör ladda upp? Bilder på dig själv (selfies) har inte mycket encyklopediskt värde. Ladda inte upp en bild på dig själv såvida du inte har en Wikipedia-artikel om dig. Bilder på monument och utomhuslandskap är okej att ladda upp i de flesta länder. Observera att tillfälliga konstinstallationer är oftast upphovsrättsskyddade och inte okej att ladda upp. Skärmdumpar på webbplatser anses vara deriverade verk och föremål för all upphovsrätt på själva webbplatsen. Dessa kan användas efter tillstånd från författaren. Utan sådant tillstånd anses all konst du skapar baserat på deras verk juridiskt sett vara en olicensierad kopia som ägs av den ursprungliga författaren. Ett av Commons mål är att samla ihop kvalitetsbilder. Därför bör inte suddiga bilder laddas upp. Försök alltid att ta fina bilder med bra ljus. Bilder som skildrar teknologi eller kultur är mycket välkomna på Commons. - VARNING: Fler än %1$s av bilderna du har laddat upp har raderats. Om du fortsätter ladda upp bilder som kommer att raderas kommer ditt konto förmodligen bannlysas. + VARNING: Fler än %1$s av bilderna du har laddat upp har raderats. Om du fortsätter ladda upp bilder som behöver raderas kommer ditt konto förmodligen blockeras. Du svarade rätt på %1$s av svaren. Gratulerar! Välj ett av de två alternativet för att svara på frågan Inloggningssessionen löptes ut, var god logga in igen. Dela din frågesport med dina vänner! Fortsätt - Korrekt svar + Rätt svar Fel svar Är det okej att ladda upp denna skärmdump? Dela app @@ -537,7 +543,7 @@ Upphovsrätt Plats Kameramodell - Linsmodell + Objektiv Serienummer Programvara Ladda upp foton till Wikimedia Commons direkt från din telefon. Ladda ned Commons-appen nu: %1$s @@ -614,4 +620,7 @@ 6. Redigera wikitexten för att placera den mer lämpligt vid behov. För mer information, se <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">här</a>. 7. Publicera artikeln Kopiera wikikod till urklipp + pausa + återuppta + Pausad diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 449dd2f2aa..2a61e36cc9 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -4,6 +4,7 @@ * Aefgh39622 * B20180 * Horus +* Korrawit * Nitisart Jungtrakungrat * Octahedron80 * Patsagorn Y. @@ -41,7 +42,7 @@ ชื่อผู้ใช้ รหัสผ่าน ลงชื่อเข้าระบบบัญชีคอมมอนส์บีตาของคุณ - ลงชื่อเข้า + เข้าสู่ระบบ ลืมรหัสผ่านหรือ? สมัครสมาชิก กำลังเข้าสู่ระบบ diff --git a/app/src/main/res/values-tr/error.xml b/app/src/main/res/values-tr/error.xml index 19e9f72947..2a09a6c363 100644 --- a/app/src/main/res/values-tr/error.xml +++ b/app/src/main/res/values-tr/error.xml @@ -4,10 +4,11 @@ * Emperyan * Hedda * Sayginer +* ToprakM --> Commons çöktü - Hata. Bir şeyler yanlış gitti! + Ups. Bir şeyler yanlış gitti! Ne yaptığınızı bize söyleyin, ardından bizimle e-posta ile durumu paylaşın. Sorunu düzeltmemize yardımcı olacak! Teşekkürler! diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 4071bc780d..5195bfd31f 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -81,7 +81,9 @@ %1$s yükleniyor %1$s yüklemesi bitiriliyor %1$s dosyasının yüklemesi başarısız oldu - Görüntülemek için dokunun + %1$s yükleme duraklatıldı + Görüntülemek için tıklayın + Görüntülemek için tıklayın Son Yüklemelerim Sırada Başarısız @@ -142,17 +144,17 @@ Henüz yüklenmiş hiç fotoğrafınız yok. Tekrar dene İptal - Bu resmi göndererek bunun kendi çalışmam olduğunu, telif hakkıyla korunan materyal veya özçekim (selfie) içermediğini ve başka türlü <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons politikalarına</a> uyduğunu beyan ederim + Bu resmi göndererek bunun kendi çalışmam olduğunu, telif hakkıyla korunan materyal veya özçekim (selfie) içermediğini ve diğer <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons politikalarına</a> uyduğunu beyan ederim. İndir Varsayılan Lisans Önceki başlığı ve açıklamayı kullan Otomatik olarak mevcut konumu al Görüntü coğrafi olarak etiketlenmemişse geçerli konumu alır ve görüntüye coğrafi etiket ekler. Uyarı: Bu, geçerli konumunuzu gösterir. Tema - Attribution-ShareAlike 4.0 - Attribution 4.0 - Attribution-ShareAlike 3.0 - Attribution 3.0 + Atıf-BenzerPaylaşım 4.0 + Atıf 4.0 + Atıf-BenzerPaylaşım 3.0 + Atıf 3.0 CC0 CC BY-SA 3.0 CC BY-SA 3.0 (Avusturya) @@ -277,7 +279,7 @@ Resimleri önbelleğe alırken hata oluştu Dosya adı olarak kullanılacak benzersiz bir açıklayıcı başlık. Sade bir dil kullanabilirsiniz. Dosya uzantısını dahil etmeyin Lütfen medyayı olabildiğince açıklayın: Nerede çekildi? Ne gösteriyor? Bağlam nedir? Lütfen nesneleri veya kişileri tanımlayın. Kolayca tahmin edilemeyen bilgileri, örneğin bir manzara ise günün saatini gösterin. Medya alışılmadık bir şey gösteriyorsa lütfen alışılmadık hâle getiren şeyi açıklayın. - Lütfen resmin kısa bir açıklamasını yazın. (255 karakterle sınırı vardır) + Lütfen resmin kısa bir açıklamasını yazın. (255 karakterle sınırı vardır) Bu resim çok karanlık, yüklemek istediğinizden emin misiniz? Wikimedia Commons yalnızca ansiklopedik değeri olan resimler içindir. Bu resim bulanık, yüklemek istediğinizden emin misiniz? Wikimedia Commons yalnızca ansiklopedik değeri olan resimler içindir. Bu görselle ilgili olası sorunlar: @@ -297,7 +299,7 @@ Uygulama ile ilgili sorunları çözmek için geliştiricilere günlük dosyasını e-posta yoluyla gönderin. Not: Günlükler potansiyel olarak tanımlayıcı bilgiler içerebilir URL\'yi açacak web tarayıcısı bulunamadı Hata! URL bulunamadı - Silinme Adayı + Silinmeye aday göster Bu görüntü silinmek üzere aday gösterildi. Web sayfasının detaylarını gör %1$s, silme için aday gösteriliyor. @@ -341,6 +343,9 @@ Tekrar dene Anladım! Bunlar, Vikipedi maddeleri görselleştirmek için resimlere ihtiyaç duyan size yakın yerler.\n\n\'BU ALANI ARA\'yı tıklamak haritayı açar ve o konumun yakınında bir arama başlatır. + Burada bir fotoğrafa ihtiyacı var. + Burada zaten bir fotoğrafı var. + Burası artık mevcut değil. Bu butona dokunduğunuzda bu yerlerin bir listesi görüntülenir Galerinizden veya kameranızdan herhangi bir yer için resim yükleyebilirsiniz Resim bulunamadı! @@ -396,7 +401,7 @@ Arama geçmişinizi silmek istediğinizden emin misiniz? Bu aramayı silmek istiyor musunuz? Arama geçmişi silindi - Silinmesi İçin Aday Göster + Silinmeye Aday Göster Sil Başarılar İstatistikler @@ -489,11 +494,11 @@ %1$s için istenen kategori kontrolü %1$s için kategori kontrolü istenemedi %1$s için kategori kontrolü isteniyor - Dosyaya silme mesajı ekleme + Dosyaya silme mesajı ekleniyor Yapıldı - Mesaj sayfasında kullanıcıya haber verme - Silme isteklerine dosya ekleneme - İstekleri sil alt sayfası oluşturma + Mesaj sayfasında kullanıcıya haber veriliyor + Dosya, silme istekleri kayıtlarına ekleniyor + Silme istekleri alt sayfası oluşturuluyor Emin değil Teşekkür Gönderme: Başarılı %1$s sayesinde başarıyla gönderildi @@ -626,4 +631,7 @@ 6. Gerekirse vikimetini uygun konumlandırma için düzenleyin. Daha fazla bilgi için <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image\">buraya</a> bakın. 7. Maddeyi yayınlayın Vikikodu panoya kopyala + duraklat + devam et + Durduruldu diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 5638c22732..07f029c455 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -87,7 +87,9 @@ %1$s завантажується Завершення завантаження %1$s Не вдалося завантажити %1$s + Завантаження %1$s призупинене Торкніться, щоб переглянути + Торкніться, щоб переглянути Мої останні завантаження У черзі Не вдалося @@ -283,7 +285,7 @@ Помилка кешування зображень Унікальна описова назва файлу. Ви можете використовувати простий текст з пробілами. Не вказуйте розширення файлу Будь ласка, докладно опишіть файл: де його було зроблено? що на ньому зображено? який контекст? Будь ласка, опишіть об\'єкти чи осіб. Додайте інформацію, яку не можна легко здогадатися, наприклад, пору доби для фотографії пейзажу. Якщо зображено щось незвичайне, спробуйте пояснити, що робить його незвичайним. - Будь ласка, створіть короткий опис цього зображення (не більше 255 символів). + Будь ласка, створіть короткий опис цього зображення (не більше 255 символів). Це зображення надто темне; Ви впевнені, що хочете його завантажити? Вікісховище призначене для зображень, що мають енциклопедичне значення. Це зображення розмите; Ви впевнені, що хочете його завантажити? Вікісховище призначене для зображень, що мають енциклопедичне значення. Потенційні проблеми з цим зображенням: @@ -347,6 +349,9 @@ Повторити Зрозуміло Це місця поблизу, про які є статті Вікіпедії, але які потребують ілюстрацій.\n\nПісля натискання кнопки \"Шукати в цій зоні\" карта фіксується та відбувається пошук поблизу вказаного місця. + Цьому місцю бракує фото. + Це місце уже має фото. + Це місце більше не існує. Натискання цієї кнопки згенерує список таких місць Ви можете завантажити зображення для любого з цих місць, зробивши знімок камерою або вибравши зображення з галереї Зображень не знайдено! @@ -616,5 +621,23 @@ Увімкнути визначення місця розташування? «Поблизу» потребує увімкненого визначення місця розташування, щоб працювати належним чином Ви зробили ці два знімки в одному й тому ж місці? Хочете використати широту/довготу зображення справа? + Завантажити більше Місць не знайдено, спробуйте змінити критерії пошуку. + Додати зображення у Вікіпедію + Ви хочете додати це зображення у статтю Вікіпедії мовою %1$s? + Інструкції + Дотримуйтеся правил редагування! + Підтвердити + Інструкції + 1. Використовуйте такий вікітекст: + 2. Натискання на «Підтвердити» відкриє статтю Вікіпедії + 3. Знайдіть розділ статті, до якого пасуватиме ваше зображення + 4. Натисніть на іконку «Редагувати» (у вигляді олівця) біля цього розділу. + 5. Вставте вікітекст у підхожому місці. + 6. Відредагуйте вікітекст за потреби, вказавши потрібне розміщення. Детальнішу інформацію знайдете <a href=\"https://uk.wikipedia.org/wiki/Довідка:Розширений_синтаксис_зображень\">тут</a>. + 7. Опублікуйте статтю + Скопіювати вікікод у буфер обміну + пауза + продовжити + Призупинено diff --git a/app/src/main/res/values-vec/strings.xml b/app/src/main/res/values-vec/strings.xml index 7bd70b190d..86673517e4 100644 --- a/app/src/main/res/values-vec/strings.xml +++ b/app/src/main/res/values-vec/strings.xml @@ -231,7 +231,7 @@ Informasion Inpostasion Feedback - Va fora + Deslòghite Tutorial Notifega In evidensa diff --git a/app/src/main/res/values-xmf/strings.xml b/app/src/main/res/values-xmf/strings.xml index 880d0aaae0..ad24b62152 100644 --- a/app/src/main/res/values-xmf/strings.xml +++ b/app/src/main/res/values-xmf/strings.xml @@ -55,6 +55,7 @@ ეხარგუაშ თება %1$ %1$ ეხარგუაქ ვემიხუჯინუ ოძირაფალო ქეგუწკანტეთ + ოძირაფალო ქეგუწკანტეთ ჩქიმი ბოლო ეხარგუეფი რადი ვემიხუჯინუ diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 3fadb61a8c..6c829458b0 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -76,7 +76,9 @@ 正在上傳%1$s 即將完成上傳%1$s 上傳%1$s失敗 + 已暫停上傳%1$s 輕觸檢視 + 輕觸檢視 我最近的上傳 已佇列 失敗 @@ -272,7 +274,7 @@ 在快取圖片時發生錯誤 用於本檔案的唯一描述性標題。您可以使用帶有空格的簡明語言,另外請不要包含副檔名。 請盡可能描述媒體內容:拍攝於何處?是顯示什麼事物?有什麼脈絡?請描述對象或人物。透露出一些較不易猜測的訊息,例如是風景的話,可以是一天裡的時間。如果媒體顯示出一些不正常的事物,請說明出造成不正常原因。 - 請寫入圖片的簡要描述(不能超過 255 個字元) + 請寫入圖片的簡要描述(不能超過 255 個字元) 此圖片太暗,您確定您要上傳它嗎?維基共享資源僅適用對於百科全書有價值的圖片。 此圖片太模糊,您確定您要上傳它嗎?維基共享資源僅適用對於百科全書有價值的圖片。 此圖片有以下潛在問題: @@ -336,6 +338,9 @@ 重試 了解! 這些是在您的周遭,並且需要圖片來圖解、描述它們本身的維基百科條目之地點。\n\n請點擊「搜尋此區域」來查看地圖,然後在位置啟動周遭搜尋。 + 此地點需要照片。 + 此地點已有照片。 + 此地點已不存在。 輕觸此按鈕來帶出這些地點的清單 您可從您的圖庫或相機,來上傳任何地點的圖片 找不到圖片! @@ -543,8 +548,8 @@ 作者 版權 位置 - 相機模型 - 透鏡模型 + 相機型號 + 透鏡型號 序號 軟體 從您的手機上直接更新照片到維基共享資源,請現在下載共享資源應用程式:%1$s @@ -621,4 +626,7 @@ 6. 若有需要,可編輯維基語法來調整到適當的定位。更多相關資訊請查看<a href=\"https://zh.wikipedia.org/wiki/Help:%E5%9B%BE%E5%83%8F\">此頁面</a>。 7. 發布條目 複製維基代碼到剪貼簿 + 暫停 + 繼續 + 已暫停 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 0613283d37..cf2adb15c3 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -14,6 +14,7 @@ * Looong * Qiyue2001 * Shizhao +* Shuiwater * SomeyaMako * VulpesVulpes825 * Wxyveronica @@ -87,7 +88,9 @@ %1$s正在上传 正在完成上传%1$s 上传%1$s失败 + 上传%1$s已暂停 点击查看 + 点击查看 我的最近上传 已入队列 失败 @@ -132,8 +135,8 @@ 关于 维基共享资源应用是由维基媒体社区的受助者和志愿者创建和维护的开源应用。维基媒体基金会不参与该应用程序的创立,开发或维护。 创建新的<a href=\"%1$s\">GitHub问题</a>以发送错误报告和建议。 - <u>隐私政策</u> - <u>信用</u> + 隐私政策 + 制作人员 关于 发送反馈(通过电子邮件) 未安装电子邮件客户端 @@ -148,7 +151,7 @@ 使用之前的标题及描述 自动获取当前位置 如果图片没有地理标记,以及地理标签图片的话,就取得当前位置。警告:这将暴露您的当前位置。 - 夜间模式 + 主题 署名-ShareAlike4.0 署名4.0 署名-ShareAlike3.0 @@ -189,10 +192,11 @@ 请避免上传您在互联网找到的有版权的素材以及海报的图像、图书封面等。 您明白了吗? 是! - <u>更多信息</u> + 更多信息 分类 正在载入… 未选择 + 无字幕 没有说明 没有讨论 未知许可协议 @@ -293,7 +297,7 @@ 错误!找不到URL 提交删除 此图片已被提交删除。 - <u>查看网页获取详情</u> + 查看网页获取详情 提名%1$s删除。 提名删除:%1$s 在浏览器中预览 @@ -335,6 +339,9 @@ 重试 明白了! 这些是您附近需要图片以阐明维基百科条目的地方。\n点击“检索这个区域”来锁定地图并启动定位功能来检索附近位置。 + 这个地点需要一张照片。 + 这个地点已经有一张图片了。 + 这个地点不再存在。 点按此按钮会出现这些地点的列表 您可以从您的图库或照相机中上传任意地点的图片 找不到图片! @@ -590,4 +597,7 @@ 确认 说明 复制维基代码到剪贴板 + 暂停 + 继续 + 已暂停 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2cfeec0728..f73c0f73ba 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -60,7 +60,9 @@ %1$s uploading Finishing uploading %1$s Uploading %1$s failed + Uploading %1$s paused Tap to view + Tap to view My Recent Uploads Queued Failed @@ -261,7 +263,7 @@ Error while caching pictures A unique descriptive title for the file, which will serve as a filename. You may use plain language with spaces. Do not include the file extension Please describe the media as much as possible: Where was it taken? What does it show? What is the context? Please describe the objects or persons. Reveal information that can not be easily guessed, for instance the time of day if it is a landscape. If the media shows something unusual, please explain what makes it unusual. - Please write a brief description of the image. (Limit to 255 characters) + Please write a brief description of the image. The first caption would be used as the Title for the image. This picture is too dark, are you sure you want to upload it? Wikimedia Commons is only for pictures with encyclopedic value. This picture is blurry, are you sure you want to upload it? Wikimedia Commons is only for pictures with encyclopedic value. @@ -649,6 +651,9 @@ Upload your first media by tapping on the add button. 6. Edit the wikitext for appropriate positioning, if necessary. For more information, see <a href="https://en.wikipedia.org/wiki/Wikipedia:Manual_of_Style/Images#How_to_place_an_image">here</a>. 7. Publish the article Copy wikicode to clipboard + pause + resume + Paused Achievements Leaderboard Rank: diff --git a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt index 8c39e6e9d3..d6b09a11b4 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/media/MediaClientTest.kt @@ -2,268 +2,234 @@ package fr.free.nrw.commons.media import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.whenever +import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.Media import fr.free.nrw.commons.explore.media.MediaConverter -import fr.free.nrw.commons.media.model.PageMediaListItem import fr.free.nrw.commons.media.model.PageMediaListResponse -import fr.free.nrw.commons.utils.CommonsDateUtil import io.reactivex.Single -import junit.framework.Assert.* +import media import org.junit.Before import org.junit.Test -import org.mockito.* -import org.mockito.Mockito.* -import org.wikipedia.dataclient.mwapi.ImageDetails +import org.mockito.ArgumentMatchers +import org.mockito.Mock +import org.mockito.MockitoAnnotations import org.wikipedia.dataclient.mwapi.MwQueryPage import org.wikipedia.dataclient.mwapi.MwQueryResponse import org.wikipedia.dataclient.mwapi.MwQueryResult import org.wikipedia.gallery.ImageInfo import org.wikipedia.wikidata.Entities -import java.util.* class MediaClientTest { @Mock - internal var mediaInterface: MediaInterface? = null + internal lateinit var mediaInterface: MediaInterface + @Mock - internal var mediaConverter: MediaConverter? = null + internal lateinit var mediaConverter: MediaConverter + @Mock - internal var mediaDetailInterface: MediaDetailInterface? = null + internal lateinit var mediaDetailInterface: MediaDetailInterface @Mock - internal var pageMediaInterface: PageMediaInterface? = null + internal lateinit var pageMediaInterface: PageMediaInterface + val continuationMap = mapOf("continuation" to "continuation") - @InjectMocks - var mediaClient: MediaClient? = null + private lateinit var mediaClient: MediaClient @Before @Throws(Exception::class) fun setUp() { MockitoAnnotations.initMocks(this) + mediaClient = + MediaClient(mediaInterface, pageMediaInterface, mediaDetailInterface, mediaConverter) } @Test - fun checkPageExistsUsingTitle() { - val mwQueryPage = mock(MwQueryPage::class.java) - `when`(mwQueryPage.pageId()).thenReturn(10) - val mwQueryResult = mock(MwQueryResult::class.java) - `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) - `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) - val mockResponse = mock(MwQueryResponse::class.java) - `when`(mockResponse.query()).thenReturn(mwQueryResult) - - `when`(mediaInterface!!.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - - val checkPageExistsUsingTitle = - mediaClient!!.checkPageExistsUsingTitle("File:Test.jpg").blockingGet() - assertTrue(checkPageExistsUsingTitle) + fun `getMediaById maps response of interface`() { + val (mwQueryResponse, media) = expectSuccessfulMapping() + whenever(mediaInterface.getMediaById("id")).thenReturn(Single.just(mwQueryResponse)) + mediaClient.getMediaById("id").test().assertValue(media) } @Test - fun checkPageNotExistsUsingTitle() { - val mwQueryPage = mock(MwQueryPage::class.java) - `when`(mwQueryPage.pageId()).thenReturn(0) - val mwQueryResult = mock(MwQueryResult::class.java) - `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) - `when`(mwQueryResult.pages()).thenReturn(listOf()) - val mockResponse = mock(MwQueryResponse::class.java) - `when`(mockResponse.query()).thenReturn(mwQueryResult) - - `when`(mediaInterface!!.checkPageExistsUsingTitle(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - - val checkPageExistsUsingTitle = - mediaClient!!.checkPageExistsUsingTitle("File:Test.jpg").blockingGet() - assertFalse(checkPageExistsUsingTitle) + fun `checkPageExistsUsingTitle returns true for greater than 0 id`() { + val mwQueryResponse = expectResponseWithPageId(1) + whenever(mediaInterface.checkPageExistsUsingTitle("")) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.checkPageExistsUsingTitle("").test().assertValue(true) } @Test - fun checkFileExistsUsingSha() { - val mwQueryPage = mock(MwQueryPage::class.java) - val mwQueryResult = mock(MwQueryResult::class.java) - `when`(mwQueryResult.allImages()).thenReturn(listOf(mock(ImageDetails::class.java))) - `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) - `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) - val mockResponse = mock(MwQueryResponse::class.java) - `when`(mockResponse.query()).thenReturn(mwQueryResult) - - `when`(mediaInterface!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - - val checkFileExistsUsingSha = mediaClient!!.checkFileExistsUsingSha("abcde").blockingGet() - assertTrue(checkFileExistsUsingSha) + fun `checkPageExistsUsingTitle returns false for 0 id`() { + val mwQueryResponse = expectResponseWithPageId(0) + whenever(mediaInterface.checkPageExistsUsingTitle("")) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.checkPageExistsUsingTitle("").test().assertValue(false) } @Test - fun checkFileNotExistsUsingSha() { - val mwQueryPage = mock(MwQueryPage::class.java) - val mwQueryResult = mock(MwQueryResult::class.java) - `when`(mwQueryResult.allImages()).thenReturn(listOf()) - `when`(mwQueryResult.firstPage()).thenReturn(mwQueryPage) - `when`(mwQueryResult.pages()).thenReturn(listOf(mwQueryPage)) - val mockResponse = mock(MwQueryResponse::class.java) - `when`(mockResponse.query()).thenReturn(mwQueryResult) - - `when`(mediaInterface!!.checkFileExistsUsingSha(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - - val checkFileExistsUsingSha = mediaClient!!.checkFileExistsUsingSha("abcde").blockingGet() - assertFalse(checkFileExistsUsingSha) + fun `checkFileExistsUsingSha returns false with no Images`() { + val mwQueryResponse = mockQuery { + whenever(allImages()).thenReturn(listOf()) + } + whenever(mediaInterface.checkFileExistsUsingSha("")) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.checkFileExistsUsingSha("").test().assertValue(false) } @Test - fun getMedia() { - val (mockResponse, media: Media) = expectGetEntitiesAndMediaConversion() - - `when`(mediaInterface!!.getMedia(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - - mediaClient!!.getMedia("abcde").test().assertValue(media) + fun `checkFileExistsUsingSha returns true with Images`() { + val mwQueryResponse = mockQuery { + whenever(allImages()).thenReturn(listOf(mock())) + } + whenever(mediaInterface.checkFileExistsUsingSha("")) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.checkFileExistsUsingSha("").test().assertValue(true) } @Test - fun getMediaNull() { - val imageInfo = ImageInfo() - - val mwQueryPage = mock(MwQueryPage::class.java) - `when`(mwQueryPage.title()).thenReturn("Test") - `when`(mwQueryPage.imageInfo()).thenReturn(imageInfo) - - val mwQueryResult = mock(MwQueryResult::class.java) - `when`(mwQueryResult.firstPage()).thenReturn(null) - val mockResponse = mock(MwQueryResponse::class.java) - `when`(mockResponse.query()).thenReturn(mwQueryResult) - - `when`(mediaInterface!!.getMedia(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) - mediaClient!!.getMedia("abcde").test().assertErrorMessage("List is empty.") + fun `getMediaListFromCategory is continuable and returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping(continuationMap) + whenever(mediaInterface.getMediaListFromCategory("", 10, emptyMap())) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.getMediaListFromCategory("").test().assertValues(listOf(media)) + + whenever(mediaInterface.getMediaListFromCategory("", 10, continuationMap)) + .thenReturn(Single.error(Exception())) + mediaClient.getMediaListFromCategory("").test().assertError { true } + + mediaClient.resetCategoryContinuation("") + val (resetMwQueryResponse, resetMedia)=expectSuccessfulMapping() + whenever(mediaInterface.getMediaListFromCategory("", 10, emptyMap())) + .thenReturn(Single.just(resetMwQueryResponse)) + mediaClient.getMediaListFromCategory("").test().assertValues(listOf(resetMedia)) } @Test - fun getPictureOfTheDay() { - val template = "Template:Potd/" + CommonsDateUtil.getIso8601DateFormatShort().format(Date()) - - val (mockResponse, media: Media) = expectGetEntitiesAndMediaConversion() - `when`(mediaInterface!!.getMediaWithGenerator(template)) - .thenReturn(Single.just(mockResponse)) - mediaClient!!.getPictureOfTheDay().test().assertValue(media) + fun `getMediaListForUser is continuable and returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping(null) + whenever(mediaInterface.getMediaListForUser("", 10, emptyMap())) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.getMediaListForUser("").test().assertValues(listOf(media)) + mediaClient.getMediaListForUser("").test().assertValue(emptyList()) } - private fun expectGetEntitiesAndMediaConversion(): Pair { - val mockResponse = mock(MwQueryResponse::class.java) - val queryResult: MwQueryResult = mock() - whenever(mockResponse.query()).thenReturn(queryResult) - val queryPage: MwQueryPage = mock() - whenever(queryResult.pages()).thenReturn(listOf(queryPage)) - whenever(queryPage.pageId()).thenReturn(0) - val entities: Entities = mock() - whenever(mediaDetailInterface!!.getEntity("M0")).thenReturn(Single.just(entities)) - val entity: Entities.Entity = mock() - whenever(entities.entities()).thenReturn(mapOf("id" to entity)) - val media: Media = mock() - val imageInfo = mock() - whenever(queryPage.imageInfo()).thenReturn(imageInfo) - whenever(mediaConverter!!.convert(queryPage, entity, imageInfo)).thenReturn(media) - return Pair(mockResponse, media) + @Test + fun `getMediaListFromSearch returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping() + whenever(mediaInterface.getMediaListFromSearch("", 0, 1)) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.getMediaListFromSearch("", 0, 1) + .test() + .assertValues(listOf(media)) } - @Captor - private val continuationCaptor: ArgumentCaptor>? = null - @Test - fun getMediaListFromCategoryTwice() { - val mockContinuation = mapOf(Pair("gcmcontinue", "test")) - - val (mockResponse, media: Media) = expectGetEntitiesAndMediaConversion() - `when`(mockResponse.continuation()).thenReturn(mockContinuation) - - `when`( - mediaInterface!!.getMediaListFromCategory( - ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), - continuationCaptor!!.capture() - ) - ) - .thenReturn(Single.just(mockResponse)) - - val media1 = mediaClient!!.getMediaListFromCategory("abcde").blockingGet().get(0) - val media2 = mediaClient!!.getMediaListFromCategory("abcde").blockingGet().get(0) - - assertEquals(continuationCaptor.allValues[0], emptyMap()) - assertEquals(continuationCaptor.allValues[1], mockContinuation) - - assertEquals(media1, media) - assertEquals(media2, media) + fun `fetchImagesForDepictedItem returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping() + whenever(mediaInterface.fetchImagesForDepictedItem("haswbstatement:${BuildConfig.DEPICTS_PROPERTY}=", "0", "1")) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.fetchImagesForDepictedItem("", 0, 1) + .test() + .assertValues(listOf(media)) } @Test - fun getMediaListForUser() { - val mockContinuation = mapOf("gcmcontinue" to "test") - - val (mockResponse, media: Media) = expectGetEntitiesAndMediaConversion() - whenever(mockResponse.continuation()).thenReturn(mockContinuation) - - whenever( - mediaInterface!!.getMediaListForUser( - ArgumentMatchers.anyString(), ArgumentMatchers.anyInt(), - continuationCaptor!!.capture() - ) - ) - .thenReturn(Single.just(mockResponse)) - val media1 = mediaClient!!.getMediaListForUser("Test").blockingGet().get(0) - val media2 = mediaClient!!.getMediaListForUser("Test").blockingGet().get(0) - - verify(mediaInterface, times(2))?.getMediaListForUser( - ArgumentMatchers.anyString(), - ArgumentMatchers.anyInt(), ArgumentMatchers.anyMap() - ) + fun `getMedia returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping() + whenever(mediaInterface.getMedia("")).thenReturn(Single.just(mwQueryResponse)) + mediaClient.getMedia("").test().assertValues(media) } @Test - fun getPageHtmlTest() { - val mwParseResult = mock(MwParseResult::class.java) - - `when`(mwParseResult.text()).thenReturn("Test") - - val mockResponse = MwParseResponse() - mockResponse.setParse(mwParseResult) - - `when`(mediaInterface!!.getPageHtml(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) + fun `getPictureOfTheDay returns mapped response`() { + val (mwQueryResponse, media) = expectSuccessfulMapping() + whenever(mediaInterface.getMediaWithGenerator(ArgumentMatchers.startsWith("Template:Potd/"))) + .thenReturn(Single.just(mwQueryResponse)) + mediaClient.getPictureOfTheDay().test().assertValues(media) + } - assertEquals("Test", mediaClient!!.getPageHtml("abcde").blockingGet()) + @Test + fun `getPageHtml with null parse result returns empty`() { + val mwParseResponse = mock() + whenever(mediaInterface.getPageHtml("")).thenReturn(Single.just(mwParseResponse)) + whenever(mwParseResponse.parse()).thenReturn(null) + mediaClient.getPageHtml("").test().assertValues("") } @Test - fun doesPageContainMedia() { - val mock = mock(PageMediaListResponse::class.java) - whenever(mock.items).thenReturn(listOf(mock(PageMediaListItem::class.java))) - `when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mock)) + fun `getPageHtml with parse result returns text`() { + val mwParseResponse = mock() + whenever(mediaInterface.getPageHtml("")).thenReturn(Single.just(mwParseResponse)) + val mwParseResult = mock() + whenever(mwParseResponse.parse()).thenReturn(mwParseResult) + whenever(mwParseResult.text()).thenReturn("text") + mediaClient.getPageHtml("").test().assertValues("text") + } - mediaClient!!.doesPageContainMedia("Test").test().assertValue(true) + @Test + fun `getEntities throws exception for empty ids`() { + mediaClient.getEntities(emptyList()).test().assertErrorMessage("empty list passed for ids") } @Test - fun doesPageContainMediaWithNoMedia() { - val mock = mock(PageMediaListResponse::class.java) - whenever(mock.items).thenReturn(listOf()) - `when`(pageMediaInterface!!.getMediaList(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mock)) + fun `getEntities invokes interface with non empty ids`() { + val entities = mock() + whenever(mediaDetailInterface.getEntity("1|2")).thenReturn(Single.just(entities)) + mediaClient.getEntities(listOf("1","2")).test().assertValue(entities) + } - mediaClient!!.doesPageContainMedia("Test").test().assertValue(false) + @Test + fun `doesPageContainMedia returns false for empty items`() { + val pageMediaListResponse = mock() + whenever(pageMediaInterface.getMediaList("")) + .thenReturn(Single.just(pageMediaListResponse)) + whenever(pageMediaListResponse.items).thenReturn(emptyList()) + mediaClient.doesPageContainMedia("").test().assertValue(false) } @Test - fun getPageHtmlTestNull() { - val mockResponse = MwParseResponse() - mockResponse.setParse(null) + fun `doesPageContainMedia returns true for non empty items`() { + val pageMediaListResponse = mock() + whenever(pageMediaInterface.getMediaList("")) + .thenReturn(Single.just(pageMediaListResponse)) + whenever(pageMediaListResponse.items).thenReturn(listOf(mock())) + mediaClient.doesPageContainMedia("").test().assertValue(true) + } - `when`(mediaInterface!!.getPageHtml(ArgumentMatchers.anyString())) - .thenReturn(Single.just(mockResponse)) + private fun mockQuery(queryReceiver: MwQueryResult.() -> Unit): MwQueryResponse { + val mwQueryResponse = mock() + val mwQueryResult = mock() + whenever(mwQueryResponse.query()).thenReturn(mwQueryResult) + mwQueryResult.queryReceiver() + return mwQueryResponse + } - assertEquals("", mediaClient!!.getPageHtml("abcde").blockingGet()) + private fun expectResponseWithPageId(expectedId: Int): MwQueryResponse { + return mockQuery { + val mwQueryPage = mock() + whenever(firstPage()).thenReturn(mwQueryPage) + whenever(mwQueryPage.pageId()).thenReturn(expectedId) + } + } + + private fun expectSuccessfulMapping(continuationMap: Map? = emptyMap()): Pair { + val media = media() + val mwQueryPage = mock() + val mwQueryResponse = mockQuery { + whenever(pages()).thenReturn(listOf(mwQueryPage, mwQueryPage)) + whenever(mwQueryPage.pageId()).thenReturn(1, 2) + } + whenever(mwQueryResponse.continuation()).thenReturn(continuationMap) + val entities = mock() + whenever(mediaDetailInterface.getEntity("M1|M2")).thenReturn(Single.just(entities)) + val entity = mock() + whenever(entities.entities()).thenReturn(mapOf("a" to entity, "b" to entity)) + val imageInfo = mock() + whenever(mwQueryPage.imageInfo()).thenReturn(imageInfo, null) + whenever(mediaConverter.convert(mwQueryPage, entity, imageInfo)).thenReturn(media) + return Pair(mwQueryResponse, media) } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt new file mode 100644 index 0000000000..27859fa7a4 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/nearby/NearbyParentFragmentPresenterTest.kt @@ -0,0 +1,444 @@ +package fr.free.nrw.commons.nearby + +import com.mapbox.mapboxsdk.annotations.Marker +import com.nhaarman.mockitokotlin2.* +import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao +import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType +import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract +import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations + +/** + * The unit test class for NearbyParentFragmentPresenter + */ +class NearbyParentFragmentPresenterTest { + @Mock + internal lateinit var nearbyParentFragmentView: NearbyParentFragmentContract.View + @Mock + internal lateinit var bookmarkLocationsDao: BookmarkLocationsDao + @Mock + internal lateinit var latestLocation: LatLng + @Mock + internal lateinit var cameraTarget: LatLng + @Mock + internal lateinit var selectedLabels: List