Merge remote-tracking branch 'origin/master' into structured-data

# Conflicts:
#	app/src/main/java/fr/free/nrw/commons/di/CommonsApplicationModule.java
#	app/src/main/java/fr/free/nrw/commons/repository/UploadRemoteDataSource.java
#	app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.java
#	app/src/main/java/fr/free/nrw/commons/upload/UploadModel.java
#	app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailFragment.java
#	app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.java
#	app/src/test/kotlin/fr/free/nrw/commons/upload/FileProcessorTest.kt
#	app/src/test/kotlin/fr/free/nrw/commons/upload/UploadMediaPresenterTest.kt
This commit is contained in:
Sean Mac Gillicuddy 2020-03-20 14:40:13 +00:00
commit 1404bb0da6
69 changed files with 584 additions and 971 deletions

View file

@ -2,6 +2,7 @@ package fr.free.nrw.commons.di;
import android.app.Activity;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.view.inputmethod.InputMethodManager;
import androidx.collection.LruCache;
@ -241,4 +242,9 @@ public class CommonsApplicationModule {
public ContributionDao providesContributionsDao(AppDatabase appDatabase) {
return appDatabase.contributionDao();
}
@Provides
public ContentResolver providesContentResolver(Context context){
return context.getContentResolver();
}
}

View file

@ -186,7 +186,7 @@ public class NotificationActivity extends NavigationBaseActivity {
// Handle item selection
switch (item.getItemId()) {
case R.id.archived:
if (item.getTitle().equals(getString(R.string.menu_option_archived))) {
if (item.getTitle().equals(getString(R.string.menu_option_read))) {
NotificationActivity.startYourself(NotificationActivity.this, "read");
}else if (item.getTitle().equals(getString(R.string.menu_option_unread))) {
onBackPressed();
@ -252,7 +252,7 @@ public class NotificationActivity extends NavigationBaseActivity {
private void setPageTitle() {
if (getSupportActionBar() != null) {
if (getIntent().getStringExtra("title").equals("read")) {
getSupportActionBar().setTitle(R.string.archived_notifications);
getSupportActionBar().setTitle(R.string.read_notifications);
} else {
getSupportActionBar().setTitle(R.string.notifications);
}
@ -261,7 +261,7 @@ public class NotificationActivity extends NavigationBaseActivity {
private void setEmptyView() {
if (getIntent().getStringExtra("title").equals("read")) {
noNotificationText.setText(R.string.no_archived_notification);
noNotificationText.setText(R.string.no_read_notification);
}else {
noNotificationText.setText(R.string.no_notification);
}
@ -272,7 +272,7 @@ public class NotificationActivity extends NavigationBaseActivity {
notificationMenuItem.setTitle(R.string.menu_option_unread);
}else {
notificationMenuItem.setTitle(R.string.menu_option_archived);
notificationMenuItem.setTitle(R.string.menu_option_read);
}
}

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.repository;
import fr.free.nrw.commons.upload.ImageCoordinates;
import java.io.IOException;
import java.util.Comparator;
import java.util.List;
@ -240,4 +241,7 @@ public class UploadRemoteDataSource {
return depictModel.depictionsEntityIdList();
}
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
uploadModel.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex);
}
}

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.repository;
import fr.free.nrw.commons.upload.ImageCoordinates;
import java.util.Comparator;
import java.util.List;
@ -307,4 +308,7 @@ public class UploadRepository {
return remoteDataSource.getNearbyPlaces(decLatitude, decLongitude);
}
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
remoteDataSource.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex);
}
}

View file

@ -1,245 +0,0 @@
package fr.free.nrw.commons.upload;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.exifinterface.media.ExifInterface;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.caching.CacheController;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.mwapi.CategoryApi;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.SimilarImageDialogFragment.Callback;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;
/**
* Processing of the image filePath that is about to be uploaded via ShareActivity is done here
*/
@Singleton
public class FileProcessor implements Callback {
@Inject
CacheController cacheController;
@Inject
GpsCategoryModel gpsCategoryModel;
@Inject
CategoryApi apiCall;
@Inject
@Named("default_preferences")
JsonKvStore defaultKvStore;
private String filePath;
private ContentResolver contentResolver;
private GPSExtractor imageObj;
private String decimalCoords;
private ExifInterface exifInterface;
private boolean haveCheckedForOtherImages = false;
private GPSExtractor tempImageObj;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
@Inject
public FileProcessor() {
}
public void cleanup() {
compositeDisposable.clear();
}
void initFileDetails(@NonNull String filePath, ContentResolver contentResolver) {
this.filePath = filePath;
this.contentResolver = contentResolver;
try {
exifInterface = new ExifInterface(filePath);
} catch (IOException e) {
Timber.e(e);
}
}
/**
* Processes filePath coordinates, either from EXIF data or user location
*/
GPSExtractor processFileCoordinates(SimilarImageInterface similarImageInterface, Context context) {
// Redact EXIF data as indicated in preferences.
redactExifTags(exifInterface, getExifTagsToRedact(context));
Timber.d("Calling GPSExtractor");
imageObj = new GPSExtractor(exifInterface);
decimalCoords = imageObj.getCoords();
if (decimalCoords == null || !imageObj.imageCoordsExists) {
//Find other photos taken around the same time which has gps coordinates
if (!haveCheckedForOtherImages)
findOtherImages(similarImageInterface);// Do not do repeat the process
} else {
useImageCoords();
}
return imageObj;
}
/**
* Gets EXIF Tags from preferences to be redacted.
*
* @param context application context
* @return tags to be redacted
*/
private Set<String> getExifTagsToRedact(Context context) {
Type setType = new TypeToken<Set<String>>() {}.getType();
Set<String> prefManageEXIFTags = defaultKvStore.getStringSet(Prefs.MANAGED_EXIF_TAGS);
Set<String> redactTags = new HashSet<>(Arrays.asList(
context.getResources().getStringArray(R.array.pref_exifTag_values)));
Timber.d(redactTags.toString());
if (prefManageEXIFTags != null) redactTags.removeAll(prefManageEXIFTags);
return redactTags;
}
/**
* Redacts EXIF metadata as indicated in preferences.
*
* @param exifInterface ExifInterface object
* @param redactTags tags to be redacted
*/
public static void redactExifTags(ExifInterface exifInterface, Set<String> redactTags) {
if(redactTags.isEmpty()) return;
Disposable disposable = Observable.fromIterable(redactTags)
.flatMap(tag -> Observable.fromArray(FileMetadataUtils.getTagsFromPref(tag)))
.forEach(tag -> {
Timber.d("Checking for tag: %s", tag);
String oldValue = exifInterface.getAttribute(tag);
if (oldValue != null && !oldValue.isEmpty()) {
Timber.d("Exif tag %s with value %s redacted.", tag, oldValue);
exifInterface.setAttribute(tag, null);
}
});
CompositeDisposable disposables = new CompositeDisposable();
disposables.add(disposable);
disposables.clear();
try {
exifInterface.saveAttributes();
} catch (IOException e) {
Timber.w("EXIF redaction failed: %s", e.toString());
}
}
/**
* Find other images around the same location that were taken within the last 20 sec
* @param similarImageInterface
*/
private void findOtherImages(SimilarImageInterface similarImageInterface) {
Timber.d("filePath" + filePath);
long timeOfCreation = new File(filePath).lastModified();//Time when the original image was created
File folder = new File(filePath.substring(0, filePath.lastIndexOf('/')));
File[] files = folder.listFiles();
Timber.d("folderTime Number:" + files.length);
for (File file : files) {
if (file.lastModified() - timeOfCreation <= (120 * 1000) && file.lastModified() - timeOfCreation >= -(120 * 1000)) {
//Make sure the photos were taken within 20seconds
Timber.d("fild date:" + file.lastModified() + " time of creation" + timeOfCreation);
tempImageObj = null;//Temporary GPSExtractor to extract coords from these photos
try {
tempImageObj = new GPSExtractor(contentResolver.openInputStream(Uri.fromFile(file)));
} catch (Exception e) {
e.printStackTrace();
}
if (tempImageObj != null) {
tempImageObj = new GPSExtractor(file.getAbsolutePath());
}
if (tempImageObj != null) {
Timber.d("not null fild EXIF" + tempImageObj.imageCoordsExists + " coords" + tempImageObj.getCoords());
if (tempImageObj.getCoords() != null && tempImageObj.imageCoordsExists) {
// Current image has gps coordinates and it's not current gps locaiton
Timber.d("This filePath has image coords:" + file.getAbsolutePath());
similarImageInterface.showSimilarImageFragment(filePath, file.getAbsolutePath());
break;
}
}
}
}
haveCheckedForOtherImages = true; //Finished checking for other images
}
/**
* Initiates retrieval of image coordinates or user coordinates, and caching of coordinates.
* Then initiates the calls to MediaWiki API through an instance of CategoryApi.
*/
@SuppressLint("CheckResult")
private void useImageCoords() {
if (decimalCoords != null) {
Timber.d("Decimal coords of image: %s", decimalCoords);
Timber.d("is EXIF data present:" + imageObj.imageCoordsExists + " from findOther image");
// Only set cache for this point if image has coords
if (imageObj.imageCoordsExists) {
double decLongitude = imageObj.getDecLongitude();
double decLatitude = imageObj.getDecLatitude();
cacheController.setQtPoint(decLongitude, decLatitude);
}
List<String> displayCatList = cacheController.findCategory();
boolean catListEmpty = displayCatList.isEmpty();
// If no categories found in cache, call MediaWiki API to match image coords with nearby Commons categories
if (catListEmpty) {
compositeDisposable.add(apiCall.request(decimalCoords)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(
gpsCategoryModel::setCategoryList,
throwable -> {
Timber.e(throwable);
gpsCategoryModel.clear();
}
));
Timber.d("displayCatList size 0, calling MWAPI %s", displayCatList);
} else {
Timber.d("Cache found, setting categoryList in model to %s", displayCatList);
gpsCategoryModel.setCategoryList(displayCatList);
}
} else {
Timber.d("EXIF: no coords");
}
}
@Override
public void onPositiveResponse() {
imageObj = tempImageObj;
decimalCoords = imageObj.getCoords();// Not necessary to use gps as image already ha EXIF data
Timber.d("EXIF from tempImageObj");
useImageCoords();
}
@Override
public void onNegativeResponse() {
Timber.d("EXIF from imageObj");
useImageCoords();
}
}

View file

@ -0,0 +1,191 @@
package fr.free.nrw.commons.upload
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import androidx.exifinterface.media.ExifInterface
import fr.free.nrw.commons.R
import fr.free.nrw.commons.caching.CacheController
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.mwapi.CategoryApi
import fr.free.nrw.commons.settings.Prefs
import io.reactivex.Observable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.io.File
import java.io.IOException
import javax.inject.Inject
import javax.inject.Named
/**
* Processing of the image filePath that is about to be uploaded via ShareActivity is done here
*/
class FileProcessor @Inject constructor(
private val context: Context,
private val contentResolver: ContentResolver,
private val cacheController: CacheController,
private val gpsCategoryModel: GpsCategoryModel,
@param:Named("default_preferences") private val defaultKvStore: JsonKvStore,
private val apiCall: CategoryApi
) {
private val compositeDisposable = CompositeDisposable()
fun cleanup() {
compositeDisposable.clear()
}
/**
* Processes filePath coordinates, either from EXIF data or user location
*/
fun processFileCoordinates(similarImageInterface: SimilarImageInterface, filePath: String?)
: ImageCoordinates {
val exifInterface: ExifInterface? = try {
ExifInterface(filePath!!)
} catch (e: IOException) {
Timber.e(e)
null
}
// Redact EXIF data as indicated in preferences.
redactExifTags(exifInterface, getExifTagsToRedact())
Timber.d("Calling GPSExtractor")
val originalImageCoordinates = ImageCoordinates(exifInterface)
if (originalImageCoordinates.decimalCoords == null) {
//Find other photos taken around the same time which has gps coordinates
findOtherImages(
File(filePath),
similarImageInterface
)
} else {
useImageCoords(originalImageCoordinates)
}
return originalImageCoordinates
}
/**
* Gets EXIF Tags from preferences to be redacted.
*
* @return tags to be redacted
*/
private fun getExifTagsToRedact(): Set<String> {
val prefManageEXIFTags =
defaultKvStore.getStringSet(Prefs.MANAGED_EXIF_TAGS) ?: emptySet()
val redactTags: Set<String> =
context.resources.getStringArray(R.array.pref_exifTag_values).toSet()
return redactTags - prefManageEXIFTags
}
/**
* Redacts EXIF metadata as indicated in preferences.
*
* @param exifInterface ExifInterface object
* @param redactTags tags to be redacted
*/
private fun redactExifTags(exifInterface: ExifInterface?, redactTags: Set<String>) {
compositeDisposable.add(
Observable.fromIterable(redactTags)
.flatMap { Observable.fromArray(*FileMetadataUtils.getTagsFromPref(it)) }
.subscribe(
{ redactTag(exifInterface, it) },
{ Timber.d(it) },
{ save(exifInterface) }
)
)
}
private fun save(exifInterface: ExifInterface?) {
try {
exifInterface?.saveAttributes()
} catch (e: IOException) {
Timber.w("EXIF redaction failed: %s", e.toString())
}
}
private fun redactTag(exifInterface: ExifInterface?, tag: String) {
Timber.d("Checking for tag: %s", tag)
exifInterface?.getAttribute(tag)
?.takeIf { it.isNotEmpty() }
?.let {
exifInterface.setAttribute(tag, null).also {
Timber.d("Exif tag $tag with value $it redacted.")
}
}
}
/**
* Find other images around the same location that were taken within the last 20 sec
*
* @param originalImageCoordinates
* @param fileBeingProcessed
* @param similarImageInterface
*/
private fun findOtherImages(
fileBeingProcessed: File,
similarImageInterface: SimilarImageInterface
) {
val oneHundredAndTwentySeconds = 120 * 1000L
//Time when the original image was created
val timeOfCreation = fileBeingProcessed.lastModified()
LongRange
val timeOfCreationRange =
timeOfCreation - oneHundredAndTwentySeconds..timeOfCreation + oneHundredAndTwentySeconds
fileBeingProcessed.parentFile
.listFiles()
.asSequence()
.filter { it.lastModified() in timeOfCreationRange }
.map { Pair(it, readImageCoordinates(it)) }
.firstOrNull { it.second?.decimalCoords != null }
?.let { fileCoordinatesPair ->
similarImageInterface.showSimilarImageFragment(
fileBeingProcessed.path,
fileCoordinatesPair.first.absolutePath,
fileCoordinatesPair.second
)
}
}
private fun readImageCoordinates(file: File) =
try {
ImageCoordinates(contentResolver.openInputStream(Uri.fromFile(file)))
} catch (e: IOException) {
Timber.e(e)
try {
ImageCoordinates(file.absolutePath)
} catch (ex: IOException) {
Timber.e(ex)
null
}
}
/**
* Initiates retrieval of image coordinates or user coordinates, and caching of coordinates. Then
* initiates the calls to MediaWiki API through an instance of CategoryApi.
*
* @param imageCoordinates
*/
fun useImageCoords(imageCoordinates: ImageCoordinates) {
requireNotNull(imageCoordinates.decimalCoords)
cacheController.setQtPoint(imageCoordinates.decLongitude, imageCoordinates.decLatitude)
val displayCatList = cacheController.findCategory()
// If no categories found in cache, call MediaWiki API to match image coords with nearby Commons categories
if (displayCatList.isEmpty()) {
compositeDisposable.add(
apiCall.request(imageCoordinates.decimalCoords)
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(
{ gpsCategoryModel.categoryList = it },
{
Timber.e(it)
gpsCategoryModel.clear()
}
)
)
Timber.d("displayCatList size 0, calling MWAPI %s", displayCatList)
} else {
Timber.d("Cache found, setting categoryList in model to %s", displayCatList)
gpsCategoryModel.categoryList = displayCatList
}
}
}

View file

@ -68,9 +68,9 @@ public class FileUtils {
try {
ExifInterface exifInterface = new ExifInterface(filePath);
GPSExtractor imageObj = new GPSExtractor(exifInterface);
if (imageObj.imageCoordsExists) { // If image has geolocation information in its EXIF
return imageObj.getCoords();
ImageCoordinates imageObj = new ImageCoordinates(exifInterface);
if (imageObj.getDecimalCoords() != null) { // If image has geolocation information in its EXIF
return imageObj.getDecimalCoords();
} else {
return "";
}

View file

@ -1,152 +0,0 @@
package fr.free.nrw.commons.upload;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.exifinterface.media.ExifInterface;
import java.io.IOException;
import java.io.InputStream;
import timber.log.Timber;
/**
* Extracts geolocation to be passed to API for category suggestions. If a picture with geolocation
* is uploaded, extract latitude and longitude from EXIF data of image.
*/
public class GPSExtractor {
static final GPSExtractor DUMMY= new GPSExtractor();
private double decLatitude;
private double decLongitude;
public boolean imageCoordsExists;
private String latitude;
private String longitude;
private String latitudeRef;
private String longitudeRef;
private String decimalCoords;
/**
* Dummy constructor.
*/
private GPSExtractor(){
}
/**
* Construct from a stream.
*/
GPSExtractor(@NonNull InputStream stream) throws IOException {
ExifInterface exif = new ExifInterface(stream);
processCoords(exif);
}
/**
* Construct from the file path of the image.
* @param path file path of the image
*
*/
GPSExtractor(@NonNull String path) {
try {
ExifInterface exif = new ExifInterface(path);
processCoords(exif);
} catch (IOException | IllegalArgumentException e) {
Timber.w(e);
}
}
/**
* Construct from the file path of the image.
* @param exif exif interface of the image
*
*/
GPSExtractor(@NonNull ExifInterface exif){
processCoords(exif);
}
private void processCoords(ExifInterface exif){
//If image has no EXIF data and user has enabled GPS setting, get user's location
//Always return null as a temporary fix for #1599
if (exif != null && exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) != null) {
//If image has EXIF data, extract image coords
imageCoordsExists = true;
Timber.d("EXIF data has location info");
latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
latitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
longitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
}
}
/**
* Extracts geolocation (either of image from EXIF data, or of user)
* @return coordinates as string (needs to be passed as a String in API query)
*/
@Nullable
String getCoords() {
if(decimalCoords!=null){
return decimalCoords;
}else if (latitude!=null && latitudeRef!=null && longitude!=null && longitudeRef!=null) {
Timber.d("Latitude: %s %s", latitude, latitudeRef);
Timber.d("Longitude: %s %s", longitude, longitudeRef);
decimalCoords = getDecimalCoords(latitude, latitudeRef, longitude, longitudeRef);
return decimalCoords;
} else {
return null;
}
}
public double getDecLatitude() {
return decLatitude;
}
public double getDecLongitude() {
return decLongitude;
}
/**
* Converts format of geolocation into decimal coordinates as required by MediaWiki API
* @return the coordinates in decimals
*/
private String getDecimalCoords(String latitude, String latitude_ref, String longitude, String longitude_ref) {
if (latitude_ref.equals("N")) {
decLatitude = convertToDegree(latitude);
} else {
decLatitude = 0 - convertToDegree(latitude);
}
if (longitude_ref.equals("E")) {
decLongitude = convertToDegree(longitude);
} else {
decLongitude = 0 - convertToDegree(longitude);
}
String decimalCoords = decLatitude + "|" + decLongitude;
Timber.d("Latitude and Longitude are %s", decimalCoords);
return decimalCoords;
}
private double convertToDegree(String stringDMS) {
double result;
String[] DMS = stringDMS.split(",", 3);
String[] stringD = DMS[0].split("/", 2);
double d0 = Double.parseDouble(stringD[0]);
double d1 = Double.parseDouble(stringD[1]);
double degrees = d0/d1;
String[] stringM = DMS[1].split("/", 2);
double m0 = Double.parseDouble(stringM[0]);
double m1 = Double.parseDouble(stringM[1]);
double minutes = m0/m1;
String[] stringS = DMS[2].split("/", 2);
double s0 = Double.parseDouble(stringS[0]);
double s1 = Double.parseDouble(stringS[1]);
double seconds = s0/s1;
result = degrees + (minutes/60) + (seconds/3600);
return result;
}
}

View file

@ -0,0 +1,74 @@
package fr.free.nrw.commons.upload
import androidx.exifinterface.media.ExifInterface
import timber.log.Timber
import java.io.IOException
import java.io.InputStream
/**
* Extracts geolocation to be passed to API for category suggestions. If a picture with geolocation
* is uploaded, extract latitude and longitude from EXIF data of image.
*/
class ImageCoordinates internal constructor(exif: ExifInterface?) {
var decLatitude = 0.0
var decLongitude = 0.0
var imageCoordsExists = false
/**
* @return string of `"[decLatitude]|[decLongitude]"` or null if coordinates do not exist
*/
var decimalCoords: String? = null
/**
* Construct from a stream.
*/
internal constructor(stream: InputStream) : this(ExifInterface(stream))
/**
* Construct from the file path of the image.
* @param path file path of the image
*/
@Throws(IOException::class)
internal constructor(path: String) : this(ExifInterface(path))
init {
//If image has no EXIF data and user has enabled GPS setting, get user's location
//Always return null as a temporary fix for #1599
if (exif != null) {
val latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE)
val latitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF)
val longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE)
val longitudeRef = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF)
if (latitude != null && longitude != null && latitudeRef != null && longitudeRef != null) {
//If image has EXIF data, extract image coords
imageCoordsExists = true
Timber.d("EXIF data has location info")
decLatitude =
if (ExifInterface.LATITUDE_NORTH == latitudeRef) convertToDegree(latitude)
else 0 - convertToDegree(latitude)
decLongitude =
if (ExifInterface.LONGITUDE_EAST == longitudeRef) convertToDegree(longitude)
else 0 - convertToDegree(longitude)
decimalCoords = "$decLatitude|$decLongitude"
}
}
}
/**
* Convert a string to an accurate Degree
*
* @param degreeMinuteSecondString - template string "a/b,c/d,e/f" where the letters represent numbers
* @return the degree accurate to the second
*/
private fun convertToDegree(degreeMinuteSecondString: String) =
degreeMinuteSecondString.split(",").let {
val degrees = evaluateExpression(it[0])
val minutes = evaluateExpression(it[1])
val seconds = evaluateExpression(it[2])
degrees + minutes / 60 + seconds / 3600
}
private fun evaluateExpression(dm: String) =
dm.split("/").let { it[0].toDouble() / it[1].toDouble() }
}

View file

@ -9,20 +9,16 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.Button;
import androidx.annotation.Nullable;
import androidx.fragment.app.DialogFragment;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView;
import java.io.File;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.view.SimpleDraweeView;
import fr.free.nrw.commons.R;
import java.io.File;
/**
* Created by harisanker on 14/2/18.

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.upload;
public interface SimilarImageInterface {
void showSimilarImageFragment(String originalFilePath, String possibleFilePath);
void showSimilarImageFragment(String originalFilePath, String possibleFilePath,
ImageCoordinates similarImageCoordinates);
}

View file

@ -24,7 +24,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
@ -33,21 +32,12 @@ import timber.log.Timber;
@Singleton
public class UploadModel {
private static UploadItem DUMMY = new UploadItem(
Uri.EMPTY, Uri.EMPTY,
"",
"",
GPSExtractor.DUMMY,
null,
-1L, "") {
};
private final JsonKvStore store;
private final List<String> licenses;
private final Context context;
private String license;
private final Map<String, String> licensesByName;
private List<UploadItem> items = new ArrayList<>();
private int currentStepIndex = 0;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private SessionManager sessionManager;
@ -96,19 +86,6 @@ public class UploadModel {
this.selectedCategories = selectedCategories;
}
/**
* pre process a list of items
*/
@SuppressLint("CheckResult")
Observable<UploadItem> preProcessImages(List<UploadableFile> uploadableFiles,
Place place,
String source,
SimilarImageInterface similarImageInterface) {
return Observable.fromIterable(uploadableFiles)
.map(uploadableFile -> getUploadItem(uploadableFile, place, source,
similarImageInterface));
}
/**
* pre process a one item at a time
*/
@ -127,8 +104,6 @@ public class UploadModel {
Place place,
String source,
SimilarImageInterface similarImageInterface) {
fileProcessor.initFileDetails(Objects.requireNonNull(uploadableFile.getFilePath()),
context.getContentResolver());
UploadableFile.DateTimeWithSource dateTimeWithSource = uploadableFile
.getFileCreatedDate(context);
long fileCreatedDate = -1;
@ -138,11 +113,11 @@ public class UploadModel {
createdTimestampSource = dateTimeWithSource.getSource();
}
Timber.d("File created date is %d", fileCreatedDate);
GPSExtractor gpsExtractor = fileProcessor
.processFileCoordinates(similarImageInterface, context);
ImageCoordinates imageCoordinates = fileProcessor
.processFileCoordinates(similarImageInterface, uploadableFile.getFilePath());
UploadItem uploadItem = new UploadItem(uploadableFile.getContentUri(),
Uri.parse(uploadableFile.getFilePath()),
uploadableFile.getMimeType(context), source, gpsExtractor, place, fileCreatedDate,
uploadableFile.getMimeType(context), source, imageCoordinates, place, fileCreatedDate,
createdTimestampSource);
if (place != null) {
uploadItem.title.setTitleText(place.name);
@ -162,14 +137,6 @@ public class UploadModel {
return uploadItem;
}
int getCurrentStep() {
return currentStepIndex + 1;
}
int getStepCount() {
return items.size() + 2;
}
public int getCount() {
return items.size();
}
@ -198,7 +165,7 @@ public class UploadModel {
item.getFileName(), item.uploadMediaDetails.size()!=0? UploadMediaDetail.formatCaptions(item.uploadMediaDetails):new HashMap<>(),
UploadMediaDetail.formatList(item.uploadMediaDetails), -1,
null, null, sessionManager.getAuthorName(),
CommonsApplication.DEFAULT_EDIT_SUMMARY, selectedDepictions, item.gpsCoords.getCoords());
CommonsApplication.DEFAULT_EDIT_SUMMARY, selectedDepictions, item.gpsCoords.getDecimalCoords());
if (item.place != null) {
contribution.setWikiDataEntityId(item.place.getWikiDataEntityId());
// If item already has an image, we need to know it. We don't want to override existing image later
@ -258,6 +225,11 @@ public class UploadModel {
this.selectedDepictions = (ArrayList<String>) selectedDepictions;
}
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
fileProcessor.useImageCoords(imageCoordinates);
items.get(uploadItemIndex).setGpsCoords(imageCoordinates);
}
@SuppressWarnings("WeakerAccess")
public static class UploadItem {
@ -265,22 +237,22 @@ public class UploadModel {
private final Uri mediaUri;
private final String mimeType;
private final String source;
private final GPSExtractor gpsCoords;
private ImageCoordinates gpsCoords;
public void setGpsCoords(ImageCoordinates gpsCoords) {
this.gpsCoords = gpsCoords;
}
private boolean selected = false;
private boolean first = false;
private Title title;
private List<UploadMediaDetail> uploadMediaDetails;
private Place place;
private boolean visited;
private boolean error;
private long createdTimestamp;
private String createdTimestampSource;
private BehaviorSubject<Integer> imageQuality;
@SuppressLint("CheckResult")
UploadItem(Uri originalContentUri,
Uri mediaUri, String mimeType, String source, GPSExtractor gpsCoords,
Uri mediaUri, String mimeType, String source, ImageCoordinates gpsCoords,
Place place,
long createdTimestamp,
String createdTimestampSource) {
@ -302,38 +274,18 @@ public class UploadModel {
return createdTimestampSource;
}
public String getMimeType() {
return mimeType;
}
public String getSource() {
return source;
}
public GPSExtractor getGpsCoords() {
public ImageCoordinates getGpsCoords() {
return gpsCoords;
}
public boolean isSelected() {
return selected;
}
public boolean isFirst() {
return first;
}
public List<UploadMediaDetail> getUploadMediaDetails() {
return uploadMediaDetails;
}
public boolean isVisited() {
return visited;
}
public boolean isError() {
return error;
}
public long getCreatedTimestamp() {
return createdTimestamp;
}
@ -354,10 +306,6 @@ public class UploadModel {
this.imageQuality.onNext(imageQuality);
}
public String getFileExt() {
return MimeTypeMapWrapper.getExtensionFromMimeType(mimeType);
}
public Place getPlace() {
return place;
}
@ -384,10 +332,9 @@ public class UploadModel {
}
//Travis is complaining :P
@Override
public int hashCode() {
return super.hashCode();
return mediaUri.hashCode();
}
/**

View file

@ -1,5 +1,7 @@
package fr.free.nrw.commons.upload.mediaDetails;
import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
@ -12,30 +14,17 @@ import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatImageButton;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.github.chrisbanes.photoview.PhotoView;
import com.jakewharton.rxbinding2.widget.RxTextView;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import com.github.chrisbanes.photoview.PhotoView;
import com.jakewharton.rxbinding2.widget.RxTextView;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.filepicker.UploadableFile;
@ -47,6 +36,7 @@ import fr.free.nrw.commons.upload.Description;
//import fr.free.nrw.commons.upload.DescriptionsAdapter;
import fr.free.nrw.commons.upload.UploadMediaDetail;
import fr.free.nrw.commons.upload.UploadMediaDetailAdapter;
import fr.free.nrw.commons.upload.ImageCoordinates;
import fr.free.nrw.commons.upload.SimilarImageDialogFragment;
import fr.free.nrw.commons.upload.Title;
import fr.free.nrw.commons.upload.UploadBaseFragment;
@ -56,10 +46,15 @@ import fr.free.nrw.commons.utils.DialogUtil;
import fr.free.nrw.commons.utils.ImageUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.disposables.Disposable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import timber.log.Timber;
import static fr.free.nrw.commons.utils.ImageUtils.getErrorMessageForResult;
public class UploadMediaDetailFragment extends UploadBaseFragment implements
UploadMediaDetailsContract.View, UploadMediaDetailAdapter.EventListener {
@ -234,14 +229,6 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
rvDescriptions.setAdapter(uploadMediaDetailAdapter);
}
/**
* returns the default locale value of the user's device
* @return
*/
private String getUserDefaultLocale() {
return getContext().getResources().getConfiguration().locale.getLanguage();
}
/**
* show dialog with info
* @param titleStringID
@ -270,12 +257,14 @@ public class UploadMediaDetailFragment extends UploadBaseFragment implements
}
@Override
public void showSimilarImageFragment(String originalFilePath, String possibleFilePath) {
public void showSimilarImageFragment(String originalFilePath, String possibleFilePath,
ImageCoordinates similarImageCoordinates) {
SimilarImageDialogFragment newFragment = new SimilarImageDialogFragment();
newFragment.setCallback(new SimilarImageDialogFragment.Callback() {
@Override
public void onPositiveResponse() {
Timber.d("positive response from similar image fragment");
presenter.useSimilarPictureCoordinates(similarImageCoordinates, callback.getIndexInViewFlipper(UploadMediaDetailFragment.this));
}
@Override

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.upload.mediaDetails;
import fr.free.nrw.commons.upload.ImageCoordinates;
import java.util.List;
import fr.free.nrw.commons.BasePresenter;
@ -48,6 +49,9 @@ public interface UploadMediaDetailsContract {
void setUploadItem(int index, UploadItem uploadItem);
void fetchPreviousTitleAndDescription(int indexInViewFlipper);
void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex);
}
}

View file

@ -1,15 +1,17 @@
package fr.free.nrw.commons.upload.mediaDetails;
import java.lang.reflect.Proxy;
import javax.inject.Inject;
import javax.inject.Named;
import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD;
import static fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD;
import static fr.free.nrw.commons.utils.ImageUtils.EMPTY_CAPTION;
import static fr.free.nrw.commons.utils.ImageUtils.FILE_NAME_EXISTS;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_KEEP;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.filepicker.UploadableFile;
import fr.free.nrw.commons.nearby.Place;
import fr.free.nrw.commons.repository.UploadRepository;
import fr.free.nrw.commons.upload.GPSExtractor;
import fr.free.nrw.commons.upload.ImageCoordinates;
import fr.free.nrw.commons.upload.SimilarImageInterface;
import fr.free.nrw.commons.upload.UploadModel.UploadItem;
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailsContract.UserActionListener;
@ -18,15 +20,11 @@ import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import java.lang.reflect.Proxy;
import javax.inject.Inject;
import javax.inject.Named;
import timber.log.Timber;
import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD;
import static fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD;
import static fr.free.nrw.commons.utils.ImageUtils.EMPTY_CAPTION;
import static fr.free.nrw.commons.utils.ImageUtils.FILE_NAME_EXISTS;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_KEEP;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
public class UploadMediaPresenter implements UserActionListener, SimilarImageInterface {
private static final UploadMediaDetailsContract.View DUMMY = (UploadMediaDetailsContract.View) Proxy
@ -81,10 +79,10 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
.subscribe(uploadItem ->
{
view.onImageProcessed(uploadItem, place);
GPSExtractor gpsCoords = uploadItem.getGpsCoords();
view.showMapWithImageCoordinates(gpsCoords != null && gpsCoords.imageCoordsExists);
ImageCoordinates gpsCoords = uploadItem.getGpsCoords();
view.showMapWithImageCoordinates(gpsCoords != null && gpsCoords.getImageCoordsExists());
view.showProgress(false);
if (gpsCoords != null && gpsCoords.imageCoordsExists) {
if (gpsCoords != null && gpsCoords.getImageCoordsExists()) {
checkNearbyPlaces(uploadItem);
}
},
@ -159,6 +157,11 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
}
}
@Override
public void useSimilarPictureCoordinates(ImageCoordinates imageCoordinates, int uploadItemIndex) {
repository.useSimilarPictureCoordinates(imageCoordinates, uploadItemIndex);
}
/**
* handles image quality verifications
*
@ -200,12 +203,15 @@ public class UploadMediaPresenter implements UserActionListener, SimilarImageInt
/**
* notifies the user that a similar image exists
*
* @param originalFilePath
* @param possibleFilePath
* @param similarImageCoordinates
*/
@Override
public void showSimilarImageFragment(String originalFilePath, String possibleFilePath) {
view.showSimilarImageFragment(originalFilePath, possibleFilePath);
public void showSimilarImageFragment(String originalFilePath, String possibleFilePath,
ImageCoordinates similarImageCoordinates) {
view.showSimilarImageFragment(originalFilePath, possibleFilePath,
similarImageCoordinates
);
}
}

View file

@ -6,5 +6,5 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:icon="@drawable/ic_more_vert_white_24dp"
android:title="@string/menu_option_archived" />
android:title="@string/menu_option_read" />
</menu>

View file

@ -372,7 +372,7 @@
<string name="contributions_fragment">bydraes</string>
<string name="nearby_fragment">Naby</string>
<string name="notifications">Kennisgewings</string>
<string name="archived_notifications">Kennisgewings (geargiveer)</string>
<string name="read_notifications">Kennisgewings (geargiveer)</string>
<string name="display_nearby_notification">Vertoon kennisgewing in die buurt</string>
<string name="display_nearby_notification_summary">Tik hier om die naaste plek te sien waar u foto\'s benodig</string>
<string name="no_close_nearby">Geen nabygeleë plekke gevind nie</string>

View file

@ -390,7 +390,7 @@
<string name="contributions_fragment">مساهمات</string>
<string name="nearby_fragment">مجاور</string>
<string name="notifications">الإشعارات</string>
<string name="archived_notifications">الإخطارات (مؤرشفة)</string>
<string name="read_notifications">الإخطارات (مؤرشفة)</string>
<string name="display_nearby_notification">عرض الإخطار القريب</string>
<string name="display_nearby_notification_summary">انقر هنا لرؤية أقرب مكان يحتاج إلى صور</string>
<string name="no_close_nearby">لم يتم العثور على أماكن قريبة بالقرب منك</string>
@ -504,9 +504,9 @@
<string name="no_image_reverted">لم يتم إرجاع أية صور</string>
<string name="no_image_uploaded">لا توجد صور مرفوعة</string>
<string name="no_notification">ليست لديك إشعارات غير مقروءة</string>
<string name="no_archived_notification">ليست لديك إشعارات مؤرشفة</string>
<string name="no_read_notification">ليست لديك إشعارات مؤرشفة</string>
<string name="share_logs_using">مشاركة السجلات باستخدام</string>
<string name="menu_option_archived">عرض المؤرشفة</string>
<string name="menu_option_read">عرض المؤرشفة</string>
<string name="menu_option_unread">عرض غير المقروءة</string>
<string name="error_occurred_in_picking_images">حدث خطأ أثناء التقاط الصور</string>
<string name="image_chooser_title">اختيار الصور للرفع</string>

View file

@ -379,7 +379,7 @@
<string name="contributions_fragment">Collaboraciones</string>
<string name="nearby_fragment">Cercanu</string>
<string name="notifications">Avisos</string>
<string name="archived_notifications">Avisos (archivaos)</string>
<string name="read_notifications">Avisos (archivaos)</string>
<string name="display_nearby_notification">Amosar notificaciones de cercanía</string>
<string name="display_nearby_notification_summary">Toca equí para ver el llugar más cercanu que precisa semeyes</string>
<string name="no_close_nearby">Nun s\'atoparon llugares cercanos nos alredores</string>
@ -492,9 +492,9 @@
<string name="no_image_reverted">Nun se revertió nenguna imaxe</string>
<string name="no_image_uploaded">Nun se xubió nenguna imaxe</string>
<string name="no_notification">Nun tienes avisos ensin lleer</string>
<string name="no_archived_notification">Nun tienes avisos archivaos</string>
<string name="no_read_notification">Nun tienes avisos archivaos</string>
<string name="share_logs_using">Compartir rexistros usando</string>
<string name="menu_option_archived">Ver los archivaos</string>
<string name="menu_option_read">Ver los archivaos</string>
<string name="menu_option_unread">Ver los nun lleíos</string>
<string name="error_occurred_in_picking_images">Asocedió un error al escoyer les imaxes</string>
<string name="image_chooser_title">Escueyi les imaxes pa xubir</string>

View file

@ -214,7 +214,7 @@
<string name="preference_author_name_toggle">Използване на персонализирано авторско име</string>
<string name="preference_author_name_toggle_summary">При качването използвайте персонализирано авторско име вместо потребителското си име</string>
<string name="preference_author_name">Персонализирано авторско име</string>
<string name="archived_notifications">Известия (архивирани)</string>
<string name="read_notifications">Известия (архивирани)</string>
<string name="list_sheet">Списък</string>
<string name="next">Следваща</string>
<string name="submit">Изпращане</string>
@ -244,9 +244,9 @@
<string name="no_image_reverted">Няма върнати изображения</string>
<string name="no_image_uploaded">Няма качени изображения</string>
<string name="no_notification">Нямате непрочетени известия</string>
<string name="no_archived_notification">Нямате архивирани известия</string>
<string name="no_read_notification">Нямате архивирани известия</string>
<string name="share_logs_using">Споделяне на дневници, използвайки</string>
<string name="menu_option_archived">Преглеждане на архивирани</string>
<string name="menu_option_read">Преглеждане на архивирани</string>
<string name="menu_option_unread">Преглеждане на непрочетени</string>
<string name="error_occurred_in_picking_images">Възникна грешка при избирането на изображенията</string>
<string name="image_chooser_title">Изберете изображения за качване</string>

View file

@ -319,7 +319,7 @@
<string name="error_occurred">Ur fazi zo bet !</string>
<string name="preference_author_name_toggle">Implijit un anv aozer personelaet</string>
<string name="nearby_fragment">Nepell</string>
<string name="archived_notifications">Kemennoù(diellaouet)</string>
<string name="read_notifications">Kemennoù(diellaouet)</string>
<string name="next">War-lerc\'h</string>
<string name="previous">Kent</string>
<string name="submit">Kas</string>

View file

@ -356,7 +356,7 @@
<string name="contributions_fragment">Contribucions</string>
<string name="nearby_fragment">A prop</string>
<string name="notifications">Notificacions</string>
<string name="archived_notifications">Notificacions (arxivades)</string>
<string name="read_notifications">Notificacions (arxivades)</string>
<string name="display_nearby_notification">Mostra notificacions properes</string>
<string name="display_nearby_notification_summary">Feu un toc aquí per a veure el lloc més proper que necessiti fotos</string>
<string name="no_close_nearby">No s\'han trobat llocs propers prop vostre</string>
@ -437,9 +437,9 @@
<string name="no_image_reverted">No s\'ha revertit cap imatge</string>
<string name="no_image_uploaded">No s\'ha carregat cap imatge</string>
<string name="no_notification">No teniu cap notificació sense llegir</string>
<string name="no_archived_notification">No teniu cap notificació arxivada</string>
<string name="no_read_notification">No teniu cap notificació arxivada</string>
<string name="share_logs_using">Comparteix els registres utilitzant</string>
<string name="menu_option_archived">Mostra els arxivats</string>
<string name="menu_option_read">Mostra els arxivats</string>
<string name="menu_option_unread">Mostra aquelles per llegir</string>
<string name="error_occurred_in_picking_images">S\'ha produït un error en escollir les imatges</string>
<string name="image_chooser_title">Trieu les imatges per carregar</string>

View file

@ -395,7 +395,7 @@
<string name="contributions_fragment">Příspěvky</string>
<string name="nearby_fragment">Poblíž</string>
<string name="notifications">Upozornění</string>
<string name="archived_notifications">Upozornění (přečtená)</string>
<string name="read_notifications">Upozornění (přečtená)</string>
<string name="display_nearby_notification">Zobrazit upozornění v okolí</string>
<string name="display_nearby_notification_summary">Klepnutím sem zobrazíte nejbližší místo, které potřebuje obrázky</string>
<string name="no_close_nearby">Nebyla nalezena žádná místa v okolí</string>
@ -508,9 +508,9 @@
<string name="no_image_reverted">Žádné revertované obrázky</string>
<string name="no_image_uploaded">Žádné nahrané obrázky</string>
<string name="no_notification">Nemáte žádná nepřečtená upozornění</string>
<string name="no_archived_notification">Nemáte nepřečtená upozornění</string>
<string name="no_read_notification">Nemáte nepřečtená upozornění</string>
<string name="share_logs_using">Sdílet logy pomocí</string>
<string name="menu_option_archived">Zobrazit přečtené</string>
<string name="menu_option_read">Zobrazit přečtené</string>
<string name="menu_option_unread">Zobrazit nepřečtené</string>
<string name="error_occurred_in_picking_images">Nastala chyba při vybírání obrázků</string>
<string name="image_chooser_title">Vyberte obrázky, které chcete nahrát</string>

View file

@ -366,7 +366,7 @@
<string name="review_thanks_no_button_text">Næste billede</string>
<string name="no_image">Ingen billeder brugt</string>
<string name="share_logs_using">Del logs ved hjælp af</string>
<string name="menu_option_archived">Vis arkiverede</string>
<string name="menu_option_read">Vis arkiverede</string>
<string name="menu_option_unread">Vis ulæste</string>
<string name="error_occurred_in_picking_images">Der opstod en fejl under udvælgelse af billeder</string>
<string name="please_wait">Vent venligst…</string>

View file

@ -388,7 +388,7 @@
<string name="contributions_fragment">Beiträge</string>
<string name="nearby_fragment">In der Nähe</string>
<string name="notifications">Benachrichtigungen</string>
<string name="archived_notifications">Benachrichtigungen (archiviert)</string>
<string name="read_notifications">Benachrichtigungen (archiviert)</string>
<string name="display_nearby_notification">Benachrichtigungen in der Nähe anzeigen</string>
<string name="display_nearby_notification_summary">Hier tippen, um Orte in der Nähe anzusehen, die Bilder benötigen.</string>
<string name="no_close_nearby">Keine Orte in deiner Umgebung gefunden.</string>
@ -501,9 +501,9 @@
<string name="no_image_reverted">Keine Bilder zurückgesetzt</string>
<string name="no_image_uploaded">Keine Bilder hochgeladen</string>
<string name="no_notification">Du hast keine ungelesenen Benachrichtigungen</string>
<string name="no_archived_notification">Du hast keine archivierten Benachrichtigungen</string>
<string name="no_read_notification">Du hast keine archivierten Benachrichtigungen</string>
<string name="share_logs_using">Lognutzung teilen</string>
<string name="menu_option_archived">Archivierte ansehen</string>
<string name="menu_option_read">Archivierte ansehen</string>
<string name="menu_option_unread">Ungelesene ansehen</string>
<string name="error_occurred_in_picking_images">Beim Auswählen der Bilder ist ein Fehler aufgetreten</string>
<string name="image_chooser_title">Hochzuladende Bilder auswählen</string>

View file

@ -232,7 +232,7 @@
<string name="preference_author_name_toggle">Nameyê nuştekariyo xısusiyi bıgurene</string>
<string name="preference_author_name">Nameyê nuştekariyo xısusi</string>
<string name="contributions_fragment">İştıraki</string>
<string name="archived_notifications">Xeberi (arşifkerdeyi)</string>
<string name="read_notifications">Xeberi (arşifkerdeyi)</string>
<string name="list_sheet">Liste</string>
<string name="next">Bahdoyên</string>
<string name="previous">Verên</string>
@ -256,8 +256,8 @@
<string name="nominate_for_deletion_done">Temam</string>
<string name="review_thanks_yes_button_text">Eya, çıra mebo</string>
<string name="no_notification">Beyanatên şımayê nêwendeyi çıniyê</string>
<string name="no_archived_notification">Beyanatên şımayê arçivkerdeyi çıniyê</string>
<string name="menu_option_archived">Arşivkerdeyan bıvêne</string>
<string name="no_read_notification">Beyanatên şımayê arçivkerdeyi çıniyê</string>
<string name="menu_option_read">Arşivkerdeyan bıvêne</string>
<string name="menu_option_unread">Nêwendeyan bıvêne</string>
<string name="please_wait">Kerem kerên, bıpawên...</string>
<string name="skip_image" fuzzy="true">NÊ RESIMİ RAVİYARNE</string>

View file

@ -406,7 +406,7 @@
<string name="no_image">Δεν χρησιμοποιούνται εικόνες</string>
<string name="no_image_uploaded">Δεν έχουν ανεβεί εικόνες</string>
<string name="no_notification">Δεν έχετε αδιάβαστες ενημερώσεις</string>
<string name="no_archived_notification">Δεν έχετε αρχειοθετημένες ενημερώσεις</string>
<string name="no_read_notification">Δεν έχετε αρχειοθετημένες ενημερώσεις</string>
<string name="please_wait">Παρακαλούμε περιμένετε…</string>
<string name="exif_tag_name_author">Δημιουργός</string>
<string name="exif_tag_name_copyright">Πνευματικά δικαιώματα</string>

View file

@ -381,7 +381,7 @@
<string name="contributions_fragment">Kontribuoj</string>
<string name="nearby_fragment">Apude</string>
<string name="notifications">Sciigoj</string>
<string name="archived_notifications">Sciigoj (enarkivigitaj)</string>
<string name="read_notifications">Sciigoj (enarkivigitaj)</string>
<string name="display_nearby_notification">Montri sciigojn pri apudaĵoj</string>
<string name="display_nearby_notification_summary">Tuŝetu ĉi tie por vidi apudan lokon kiu bezonas bildojn</string>
<string name="no_close_nearby">Neniu proksima loko trovita ĉe vi.</string>
@ -494,9 +494,9 @@
<string name="no_image_reverted">Neniu bildo estis malfarita</string>
<string name="no_image_uploaded">Neniu alŝutita bildo</string>
<string name="no_notification">Vi ne havas nelegitajn sciigojn</string>
<string name="no_archived_notification">Vi ne havas enarkivigitajn sciigojn</string>
<string name="no_read_notification">Vi ne havas enarkivigitajn sciigojn</string>
<string name="share_logs_using">Konigi protokolojn per</string>
<string name="menu_option_archived">Vidi enarkivigitojn</string>
<string name="menu_option_read">Vidi enarkivigitojn</string>
<string name="menu_option_unread">Vidi nelegitojn</string>
<string name="error_occurred_in_picking_images">Eraro okazis dum elektado de bildoj</string>
<string name="image_chooser_title">Elekti alŝutotajn bildojn</string>

View file

@ -404,7 +404,7 @@
<string name="contributions_fragment">Contribuciones</string>
<string name="nearby_fragment">Cercanos</string>
<string name="notifications">Notificaciones</string>
<string name="archived_notifications">Notificaciones (archivadas)</string>
<string name="read_notifications">Notificaciones (archivadas)</string>
<string name="display_nearby_notification">Mostrar notificaciones de cercanía</string>
<string name="display_nearby_notification_summary">Toca aquí para ver el lugar más cercano que necesita fotos</string>
<string name="no_close_nearby">No se encontraron lugares cercanos cerca de ti</string>
@ -517,9 +517,9 @@
<string name="no_image_reverted">Ninguna imagen revertida</string>
<string name="no_image_uploaded">Ninguna imagen subida</string>
<string name="no_notification">No tienes notificaciones sin leer</string>
<string name="no_archived_notification">No tienes notificaciones archivadas</string>
<string name="no_read_notification">No tienes notificaciones archivadas</string>
<string name="share_logs_using">Compartir registros usando</string>
<string name="menu_option_archived">Ver archivados</string>
<string name="menu_option_read">Ver archivados</string>
<string name="menu_option_unread">Ver no leidas</string>
<string name="error_occurred_in_picking_images">Ocurrió un error mientras se elegían imagenes</string>
<string name="image_chooser_title">Elige imágenes para cargar</string>

View file

@ -376,7 +376,7 @@
<string name="contributions_fragment">مشارکت‌ها</string>
<string name="nearby_fragment">در نزدیکی</string>
<string name="notifications">آگاه‌سازی‌ها</string>
<string name="archived_notifications">اعلان‌ها (بایگانی‌شده)</string>
<string name="read_notifications">اعلان‌ها (بایگانی‌شده)</string>
<string name="display_nearby_notification">نمایش اعلان اطراف</string>
<string name="no_close_nearby">هیچ‌ مکان نزدیکی به شما یافته نشد</string>
<string name="list_sheet">فهرست</string>
@ -453,8 +453,8 @@
<string name="no_image_reverted">تصویر برگردانده نشد</string>
<string name="no_image_uploaded">هیچ تصویری بارگذاری نشد</string>
<string name="no_notification">شما هیچ اعلان خوانده‌نشده‌ای ندارید</string>
<string name="no_archived_notification">شما هیچ پیغام بایگانی شده‌ای ندارید</string>
<string name="menu_option_archived">نمایش بایگانی‌شده</string>
<string name="no_read_notification">شما هیچ پیغام بایگانی شده‌ای ندارید</string>
<string name="menu_option_read">نمایش بایگانی‌شده</string>
<string name="menu_option_unread">مشاهده خوانده نشده ها</string>
<string name="image_chooser_title">انتخاب تصویر برای بارگذاری</string>
<string name="please_wait">لطفاً صبر کنید...</string>

View file

@ -366,7 +366,7 @@
<string name="contributions_fragment">Muokkaukset</string>
<string name="nearby_fragment">Lähistöllä</string>
<string name="notifications">Ilmoitukset</string>
<string name="archived_notifications">Ilmoitukset (arkistoidut)</string>
<string name="read_notifications">Ilmoitukset (arkistoidut)</string>
<string name="display_nearby_notification">Näytä lähistöllä-ilmoitus</string>
<string name="list_sheet">Lista</string>
<string name="step_count">Vaihe %1$d/%2$d</string>
@ -420,7 +420,7 @@
<string name="review_copyright_no_button_text">Näyttää hyvälle</string>
<string name="review_thanks_yes_button_text">Kyllä, miksi ei</string>
<string name="review_thanks_no_button_text">Seuraava kuva</string>
<string name="menu_option_archived">Näytä arkistoidut</string>
<string name="menu_option_read">Näytä arkistoidut</string>
<string name="menu_option_unread">Näytä lukemattomat</string>
<string name="image_chooser_title">Valitse tallennettavat tiedostot</string>
<string name="please_wait">Odota…</string>

View file

@ -403,7 +403,7 @@
<string name="contributions_fragment">Contributions</string>
<string name="nearby_fragment">Proche</string>
<string name="notifications">Notifications</string>
<string name="archived_notifications">Notifications (archivées)</string>
<string name="read_notifications">Notifications (archivées)</string>
<string name="display_nearby_notification">Afficher la notification de proximité</string>
<string name="display_nearby_notification_summary">Taper ici pour voir lendroit le plus proche qui a besoin dimages</string>
<string name="no_close_nearby">Aucun endroit à proximité trouvé près de chez vous</string>
@ -517,9 +517,9 @@
<string name="no_image_reverted">Aucune image retournée</string>
<string name="no_image_uploaded">Aucune image téléversée</string>
<string name="no_notification">Vous n\'avez aucune notification non lue</string>
<string name="no_archived_notification">Vous navez pas de notification archivée</string>
<string name="no_read_notification">Vous navez pas de notification archivée</string>
<string name="share_logs_using">Partager les journaux en utilisant</string>
<string name="menu_option_archived">Afficher les archivés</string>
<string name="menu_option_read">Afficher les archivés</string>
<string name="menu_option_unread">Afficher les non lus</string>
<string name="error_occurred_in_picking_images">Erreur lors de la sélection des images</string>
<string name="image_chooser_title">Choisir les images à téléverser</string>

View file

@ -385,7 +385,7 @@
<string name="contributions_fragment">Contribucións</string>
<string name="nearby_fragment">Preto</string>
<string name="notifications">Notificacións</string>
<string name="archived_notifications">Notificacións (arquivadas)</string>
<string name="read_notifications">Notificacións (arquivadas)</string>
<string name="display_nearby_notification">Amosar notificacións de proximidade</string>
<string name="display_nearby_notification_summary">Prema aquí para ver o lugar máis preto que necesita fotos</string>
<string name="no_close_nearby">Non se atoparon lugares preto de ti</string>
@ -482,9 +482,9 @@
<string name="no_image_reverted">Ningunha imaxe revertida</string>
<string name="no_image_uploaded">Ningunha imaxe subida</string>
<string name="no_notification">Non ten ningunha notificación sen ler</string>
<string name="no_archived_notification">Non ten notificacións arquivadas</string>
<string name="no_read_notification">Non ten notificacións arquivadas</string>
<string name="share_logs_using">Compartir os rexistros usando</string>
<string name="menu_option_archived">Ver arquivadas</string>
<string name="menu_option_read">Ver arquivadas</string>
<string name="menu_option_unread">Ver as non lidas</string>
<string name="error_occurred_in_picking_images">Houbo un erro ó escoller as imaxes</string>
<string name="image_chooser_title">Escoller imaxes a subir</string>

View file

@ -351,7 +351,7 @@
<string name="contributions_fragment">योगदान</string>
<string name="nearby_fragment">निकट</string>
<string name="notifications">सूचनायें</string>
<string name="archived_notifications">सूचनाएँ (पुरालेखित)</string>
<string name="read_notifications">सूचनाएँ (पुरालेखित)</string>
<string name="list_sheet">सूची</string>
<string name="storage_permission">स्टोरेज अनुमति</string>
<string name="next">अगला</string>
@ -395,7 +395,7 @@
<string name="no_image_reverted">कोई चित्र वापस नहीं लाया</string>
<string name="no_image_uploaded">कोई चित्र अपलोड नहीं किया</string>
<string name="no_notification" fuzzy="true">आपके पास कोई अपठित सूचना नहीं है</string>
<string name="no_archived_notification" fuzzy="true">आपकी कोई सूचना पुरालेखित नहीं है</string>
<string name="menu_option_archived">पुरालेखित देखें</string>
<string name="no_read_notification" fuzzy="true">आपकी कोई सूचना पुरालेखित नहीं है</string>
<string name="menu_option_read">पुरालेखित देखें</string>
<string name="menu_option_unread">अपठित देखें</string>
</resources>

View file

@ -385,7 +385,7 @@
<string name="contributions_fragment">Közreműködések</string>
<string name="nearby_fragment">Közelben</string>
<string name="notifications">Értesítések</string>
<string name="archived_notifications">Archivált értesítések</string>
<string name="read_notifications">Archivált értesítések</string>
<string name="display_nearby_notification">Közeli értesítések megjelenítése</string>
<string name="no_close_nearby">Nem található közeli hely</string>
<string name="list_sheet">Lista</string>
@ -494,8 +494,8 @@
<string name="no_image_reverted">Nincs visszavont kép</string>
<string name="no_image_uploaded">Nincs feltöltött kép</string>
<string name="no_notification">Nincs olvasatlan üzenet</string>
<string name="no_archived_notification">Nincs archivált üzenet</string>
<string name="menu_option_archived">Archiváltak megtekintése</string>
<string name="no_read_notification">Nincs archivált üzenet</string>
<string name="menu_option_read">Archiváltak megtekintése</string>
<string name="menu_option_unread">Olvasatlanok megtekintése</string>
<string name="error_occurred_in_picking_images">Hiba történt a képek betöltése során</string>
<string name="image_chooser_title">Feltöltendő képek kiválasztása</string>

View file

@ -377,7 +377,7 @@
<string name="contributions_fragment">Kontribusi</string>
<string name="nearby_fragment">Sekitar</string>
<string name="notifications">Pemberitahuan</string>
<string name="archived_notifications">Pemberitahuan (diarsipkan)</string>
<string name="read_notifications">Pemberitahuan (diarsipkan)</string>
<string name="display_nearby_notification">Tampilkan pemberitahuan sekitar</string>
<string name="display_nearby_notification_summary">Tekan di sini untuk melihat tempat terdekat yang membutuhkan gambar</string>
<string name="no_close_nearby">Tidak ada tempat sekitaran yang ditemukan di dekat Anda</string>
@ -430,7 +430,7 @@
<string name="never_ask_again">Jangan pernah menanyakan ini lagi</string>
<string name="display_location_permission_title">Tampilkan izin lokasi</string>
<string name="display_campaigns">Sinahang penyobyahan</string>
<string name="menu_option_archived">Lihat arsip</string>
<string name="menu_option_read">Lihat arsip</string>
<string name="menu_option_unread">Lihat yang belum terbaca</string>
<string name="error_occurred_in_picking_images">Terjadi kesalahan ketika memilih gambar</string>
<string name="image_chooser_title">Pilih Gambar untuk diunggah</string>

View file

@ -372,7 +372,7 @@
<string name="contributions_fragment">Framlög</string>
<string name="nearby_fragment">Nálægt</string>
<string name="notifications">Tilkynningar</string>
<string name="archived_notifications">Tilkynningar (í geymslu)</string>
<string name="read_notifications">Tilkynningar (í geymslu)</string>
<string name="display_nearby_notification">Birta tilkynningu um nágrenni</string>
<string name="display_nearby_notification_summary">Ýttu hér til að sjá nálægasta staðinn sem þarfnast mynda</string>
<string name="no_close_nearby">Engir staðir fundust í nágrenninu</string>
@ -448,7 +448,7 @@
<string name="no_image_reverted">Engar myndir endurstilltar</string>
<string name="no_image_uploaded">Engar myndir sendar inn</string>
<string name="no_notification">Þú ert ekki með neinar ólesnar tilkynningar</string>
<string name="menu_option_archived">Skoða í geymslu</string>
<string name="menu_option_read">Skoða í geymslu</string>
<string name="menu_option_unread">Skoða ólesið</string>
<string name="error_occurred_in_picking_images">Villa kom upp við að velja myndir</string>
<string name="image_chooser_title">Veldu myndir til að senda inn</string>

View file

@ -384,7 +384,7 @@
<string name="contributions_fragment">Contributi</string>
<string name="nearby_fragment">Nelle vicinanze</string>
<string name="notifications">Notifiche</string>
<string name="archived_notifications">Notifiche (archiviate)</string>
<string name="read_notifications">Notifiche (archiviate)</string>
<string name="display_nearby_notification">Mostra notifica nelle vicinanze</string>
<string name="display_nearby_notification_summary">Tocca qui per vedere il luogo più vicino che ha bisogno di immagini</string>
<string name="no_close_nearby">Nessun posto nelle vicinanze trovato vicino a te</string>
@ -464,9 +464,9 @@
<string name="no_image_reverted">Nessuna immagine ripristinata</string>
<string name="no_image_uploaded">Nessuna immagine caricata</string>
<string name="no_notification">Non hai alcuna notifica non letta</string>
<string name="no_archived_notification">Non hai notifiche archiviate</string>
<string name="no_read_notification">Non hai notifiche archiviate</string>
<string name="share_logs_using">Condividi i registri usando</string>
<string name="menu_option_archived">Vedi archiviate</string>
<string name="menu_option_read">Vedi archiviate</string>
<string name="menu_option_unread">Vedi non lette</string>
<string name="error_occurred_in_picking_images">Si è verificato un errore durante la selezione delle immagini</string>
<string name="image_chooser_title">Scegli le immagini da caricare</string>

View file

@ -393,7 +393,7 @@
<string name="contributions_fragment">תרומות</string>
<string name="nearby_fragment">בסביבה</string>
<string name="notifications">התראות</string>
<string name="archived_notifications">התראות (בארכיון)</string>
<string name="read_notifications">התראות (בארכיון)</string>
<string name="display_nearby_notification">הצגת התראות סמוכות</string>
<string name="display_nearby_notification_summary">יש לגעת כאן כדי לצפות במקום הקרוב ביותר שדורש תמונות</string>
<string name="no_close_nearby">לא נמצאו מקומות בסביבתך</string>
@ -507,9 +507,9 @@
<string name="no_image_reverted">לא שוחזרו תמונות</string>
<string name="no_image_uploaded">לא הועלו תמונות</string>
<string name="no_notification">אין לך התראות שלא נקראו</string>
<string name="no_archived_notification">אין לך התראות בארכיון</string>
<string name="no_read_notification">אין לך התראות בארכיון</string>
<string name="share_logs_using">שיתוף יומנים בעזרת</string>
<string name="menu_option_archived">הצגת ארכיון</string>
<string name="menu_option_read">הצגת ארכיון</string>
<string name="menu_option_unread">הצגת התראות שלא נקראו</string>
<string name="error_occurred_in_picking_images">אירעה שגיאה בעת בחירת תמונות</string>
<string name="image_chooser_title">נא לבחור תמונות להעלאה</string>

View file

@ -389,7 +389,7 @@
<string name="contributions_fragment">投稿記録</string>
<string name="nearby_fragment">付近</string>
<string name="notifications">お知らせ</string>
<string name="archived_notifications">お知らせ(過去ログ)</string>
<string name="read_notifications">お知らせ(過去ログ)</string>
<string name="display_nearby_notification">近くの場所のお知らせを表示する</string>
<string name="display_nearby_notification_summary">ここをタップして、近くで画像を募集中の場所を表示</string>
<string name="no_close_nearby">現在地の近くに該当する場所が見つかりません</string>
@ -501,9 +501,9 @@
<string name="no_image_reverted">却下された画像はありません</string>
<string name="no_image_uploaded">投稿した画像はありません</string>
<string name="no_notification">未読のお知らせはありません</string>
<string name="no_archived_notification">過去ログ化したお知らせはありません</string>
<string name="no_read_notification">過去ログ化したお知らせはありません</string>
<string name="share_logs_using">ログの共有に使うアプリ</string>
<string name="menu_option_archived">アーカイブ済みを表示</string>
<string name="menu_option_read">アーカイブ済みを表示</string>
<string name="menu_option_unread">未読を見る</string>
<string name="error_occurred_in_picking_images">画像の選択中にエラーが発生しました</string>
<string name="image_chooser_title">アップロードする画像を選ぶ</string>

View file

@ -306,7 +306,7 @@
<string name="contributions_fragment">წვლილი</string>
<string name="nearby_fragment">ახლოს</string>
<string name="notifications">შეტყობინებები</string>
<string name="archived_notifications">შეტყობინებები (არქივი)</string>
<string name="read_notifications">შეტყობინებები (არქივი)</string>
<string name="list_sheet">სია</string>
<string name="storage_permission">მეხსიერების ნებართვა</string>
<string name="step_count">ნაბიჯი %1$d %2$d-დან</string>

View file

@ -374,7 +374,7 @@
<string name="contributions_fragment">기여</string>
<string name="nearby_fragment">근처</string>
<string name="notifications">알림</string>
<string name="archived_notifications">알림 (보관됨)</string>
<string name="read_notifications">알림 (보관됨)</string>
<string name="display_nearby_notification">주변 알림 표시</string>
<string name="display_nearby_notification_summary">사진이 필요한 주변 장소를 보려면 여기를 탭하세요</string>
<string name="no_close_nearby">당신에게 가까운 주변 장소를 찾지 못했습니다</string>
@ -446,8 +446,8 @@
<string name="skip_image_explanation">이 버튼을 클릭하면 위키미디어 공용으로부터 최근 업로드된 다른 이미지를 제공합니다</string>
<string name="review_image_explanation">이미지를 검토하고 위키미디어 공용의 품질을 개선할 수 있습니다.\n 4가지 검토 변수가 있습니다:\n - 이 이미지가 범위 내에 있는가? \n - 이 이미지가 저작권 규정을 준수하고 있는가? \n - 이 이미지가 올바르게 분류되어 있는가? \n - 모든 것이 문제 없다면 기여자에게 감사를 표할 수도 있습니다.</string>
<string name="no_notification">읽지 않은 알림이 없습니다</string>
<string name="no_archived_notification">보관된 알림이 없습니다</string>
<string name="menu_option_archived">보관한 항목 보기</string>
<string name="no_read_notification">보관된 알림이 없습니다</string>
<string name="menu_option_read">보관한 항목 보기</string>
<string name="menu_option_unread">읽지 않은 항목 보기</string>
<string name="error_occurred_in_picking_images">이미지 선택 도중 오류가 발생했습니다</string>
<string name="image_chooser_title">업로드할 이미지 선택</string>

View file

@ -337,7 +337,7 @@
<string name="review_thanks_no_button_text">Nächst BILD</string>
<string name="no_image">Keng Biller benotzt</string>
<string name="no_image_uploaded">Keng Biller eropgelueden</string>
<string name="no_archived_notification">Dir hutt keng archivéier Notifikatiounen</string>
<string name="no_read_notification">Dir hutt keng archivéier Notifikatiounen</string>
<string name="error_occurred_in_picking_images">Feeler beim Eraussiche vun de Biller</string>
<string name="image_chooser_title">Sicht Biller eraus fir eropzelueden</string>
<string name="please_wait">Waart wgl. ...</string>

View file

@ -188,7 +188,7 @@
<string name="send_thank_send">Sūta pateicību</string>
<string name="send_thank_notification_title">Sūta pateicību</string>
<string name="review_thanks_no_button_text">Nākamais attēls</string>
<string name="menu_option_archived">Skatīt arhivētos</string>
<string name="menu_option_read">Skatīt arhivētos</string>
<string name="menu_option_unread">Skatīt nelasītos</string>
<string name="please_wait">Lūdzu, uzgaidiet...</string>
<string name="skip_image">Izlaist šo attēlu</string>

View file

@ -380,7 +380,7 @@
<string name="contributions_fragment">Придонеси</string>
<string name="nearby_fragment">Во близина</string>
<string name="notifications">Известувања</string>
<string name="archived_notifications">Известувања (архивирани)</string>
<string name="read_notifications">Известувања (архивирани)</string>
<string name="display_nearby_notification">Известувај ме за места во близина</string>
<string name="display_nearby_notification_summary">Допрете тука за да го видите најблиското место без слика</string>
<string name="no_close_nearby">Не најдов места во ваша близина</string>
@ -494,9 +494,9 @@
<string name="no_image_reverted">Нема вратени слики</string>
<string name="no_image_uploaded">Нема подигнати слики</string>
<string name="no_notification">Немате непрочитани известувања</string>
<string name="no_archived_notification">Немате архивирани известувања</string>
<string name="no_read_notification">Немате архивирани известувања</string>
<string name="share_logs_using">Споделувај дневници користејќи</string>
<string name="menu_option_archived">Погл. архивирани</string>
<string name="menu_option_read">Погл. архивирани</string>
<string name="menu_option_unread">Погл. непрочитани</string>
<string name="error_occurred_in_picking_images">Се јави грешка при избирањето на сликите</string>
<string name="image_chooser_title">Изберете слики за подигање</string>

View file

@ -287,7 +287,7 @@
<string name="contributions_fragment">ဆောင်ရွက်ချက်များ</string>
<string name="nearby_fragment">အနီးအနား</string>
<string name="notifications">အသိပေးချက်များ</string>
<string name="archived_notifications">အသိပေးချက်များ (မော်ကွန်းတင်ပြီး)</string>
<string name="read_notifications">အသိပေးချက်များ (မော်ကွန်းတင်ပြီး)</string>
<string name="display_nearby_notification">အနီးအနားအသိပေးချက်ကို ပြသရန်</string>
<string name="list_sheet">စာရင်း</string>
<string name="storage_permission">သိုလှောင်ခန်း ခွင်ပြုချက်</string>
@ -348,7 +348,7 @@
<string name="review_copyright_no_button_text">အဆင်ပြေပုံပေါက်ပါသည်</string>
<string name="review_thanks_no_button_text">နောက်ရုပ်ပုံ</string>
<string name="no_notification">မဖတ်ရသေးသော အသိပေးချက်များ မရှိပါ</string>
<string name="no_archived_notification">မော်ကွန်းတင်ပြီးသော အသိပေးချက်များ မရှိပါ</string>
<string name="no_read_notification">မော်ကွန်းတင်ပြီးသော အသိပေးချက်များ မရှိပါ</string>
<string name="please_wait">ကျေးဇူးပြု၍ ခဏစောင့်ပါ...</string>
<string name="previous_image_title_description">ယခင် ခေါင်းစဉ်/ဖော်ပြချက် မိတ္တူကူးရန်</string>
<string name="welcome_dont_upload_content_description">နမူနာရုပ်ပုံများ အက်ပလုပ်တင်ရန် မဟုတ်ပါ</string>

View file

@ -387,7 +387,7 @@
<string name="contributions_fragment">Bidrag</string>
<string name="nearby_fragment">I nærheten</string>
<string name="notifications">Varsler</string>
<string name="archived_notifications">Varsler (arkivert)</string>
<string name="read_notifications">Varsler (arkivert)</string>
<string name="display_nearby_notification">Vis varsel for steder i nærheten</string>
<string name="display_nearby_notification_summary">Trykk her for å se det nærmeste stedet som trenger bilder</string>
<string name="no_close_nearby">Ingen steder funnet i nærheten av deg</string>
@ -500,9 +500,9 @@
<string name="no_image_reverted">Ingen bilder tilbakestilt</string>
<string name="no_image_uploaded">Ingen bilder lastet opp</string>
<string name="no_notification">Du har uleste varsler</string>
<string name="no_archived_notification">Du har ingen arkiverte varsler</string>
<string name="no_read_notification">Du har ingen arkiverte varsler</string>
<string name="share_logs_using">Del logger ved hjelp av</string>
<string name="menu_option_archived">Vis arkiverte</string>
<string name="menu_option_read">Vis arkiverte</string>
<string name="menu_option_unread">Vis uleste</string>
<string name="error_occurred_in_picking_images">Feil under utvalg av bilder</string>
<string name="image_chooser_title">Velg bilder å laste opp</string>

View file

@ -254,7 +254,7 @@
<string name="contributions_fragment">योगदानहरू</string>
<string name="nearby_fragment">नजिकैको</string>
<string name="notifications">सूचनाहरू</string>
<string name="archived_notifications">सूचनाहरू (अभिलेख)</string>
<string name="read_notifications">सूचनाहरू (अभिलेख)</string>
<string name="list_sheet">सूची</string>
<string name="storage_permission">भण्डारण अनुमति</string>
<string name="next">अर्को</string>

View file

@ -288,7 +288,7 @@
<string name="contributions_fragment">Bijdragen</string>
<string name="nearby_fragment">Dichtbij</string>
<string name="notifications">Meldingen</string>
<string name="archived_notifications">Meldingen (in het archief)</string>
<string name="read_notifications">Meldingen (in het archief)</string>
<string name="display_nearby_notification">Meldingen dichtbij weergeven</string>
<string name="list_sheet">Lijst</string>
<string name="storage_permission">Toestemming om op te slaan</string>
@ -305,9 +305,9 @@
<string name="display_location_permission_title">Machtiging voor locatie weergeven</string>
<string name="display_location_permission_explanation">Naar machtiging voor locatie vragen als dat nodig is voor de functie meldingskaart dichtbij weergeven.</string>
<string name="no_image_uploaded">Geen afbeeldingen geüpload</string>
<string name="no_archived_notification" fuzzy="true">U hebt geen gearchiveerde melding</string>
<string name="no_read_notification" fuzzy="true">U hebt geen gearchiveerde melding</string>
<string name="share_logs_using">Logboeken delen via</string>
<string name="menu_option_archived">Gearchiveerd bekijken</string>
<string name="menu_option_read">Gearchiveerd bekijken</string>
<string name="menu_option_unread">Ongelezen bekijken</string>
<string name="image_chooser_title">Kies de afbeeldingen die u wilt plaatsen</string>
<string name="please_wait">Een ogenblik geduld…</string>

View file

@ -378,7 +378,7 @@
<string name="contributions_fragment">Contribussion</string>
<string name="nearby_fragment">Davzin</string>
<string name="notifications">Notìfiche</string>
<string name="archived_notifications">Notìfiche (archivià)</string>
<string name="read_notifications">Notìfiche (archivià)</string>
<string name="display_nearby_notification">Smon-e la notìfica ëd prossimità</string>
<string name="display_nearby_notification_summary">Sgnaché sì për vëdde ël pòst pi davzin ch\'a l\'ha damanca ëd plance</string>
<string name="no_close_nearby">Gnun pòst trovà davzin a chiel</string>
@ -492,9 +492,9 @@
<string name="no_image_reverted">Gnun-e plance anvertìe</string>
<string name="no_image_uploaded">Gnun-e plance carià</string>
<string name="no_notification">A l\'ha gnun-e notìfiche nen lesùe</string>
<string name="no_archived_notification">A l\'ha gnun-e notìfiche archivià</string>
<string name="no_read_notification">A l\'ha gnun-e notìfiche archivià</string>
<string name="share_logs_using">Partagé j\'argistr dovrand</string>
<string name="menu_option_archived">Vëdde l\'archivi</string>
<string name="menu_option_read">Vëdde l\'archivi</string>
<string name="menu_option_unread">Vëdde lòn ch\'a l\'é ancor nen ëstàit lesù</string>
<string name="error_occurred_in_picking_images">A-i é staje n\'eror an selessionand le plance</string>
<string name="image_chooser_title">Serne le plance da carié</string>

View file

@ -392,7 +392,7 @@
<string name="contributions_fragment">Contribuições</string>
<string name="nearby_fragment">Próximo</string>
<string name="notifications">Notificações</string>
<string name="archived_notifications">Notificações (arquivadas)</string>
<string name="read_notifications">Notificações (arquivadas)</string>
<string name="display_nearby_notification">Exibir notificação próxima</string>
<string name="display_nearby_notification_summary">Toque aqui para ver o local mais próximo que precisa de fotos</string>
<string name="no_close_nearby">Nenhum lugar próximo encontrado perto de você</string>
@ -506,9 +506,9 @@
<string name="no_image_reverted">Nenhuma imagem revertida</string>
<string name="no_image_uploaded">Nenhuma imagem enviada</string>
<string name="no_notification">Não tem nenhuma notificação por ler</string>
<string name="no_archived_notification">Não tem nenhuma notificação arquivada</string>
<string name="no_read_notification">Não tem nenhuma notificação arquivada</string>
<string name="share_logs_using">Compartilhar registros usando</string>
<string name="menu_option_archived">Ver arquivadas</string>
<string name="menu_option_read">Ver arquivadas</string>
<string name="menu_option_unread">Ver não lidas</string>
<string name="error_occurred_in_picking_images">Ocorreu um erro ao escolher imagens</string>
<string name="image_chooser_title">Escolha imagens para fazer o carregamento</string>

View file

@ -392,7 +392,7 @@
<string name="contributions_fragment">Contribuições</string>
<string name="nearby_fragment">Aqui perto</string>
<string name="notifications">Notificações</string>
<string name="archived_notifications">Notificações (arquivadas)</string>
<string name="read_notifications">Notificações (arquivadas)</string>
<string name="display_nearby_notification">Apresentar notificação de proximidade</string>
<string name="display_nearby_notification_summary">Toque aqui para ver o local mais próximo que precisa de fotos</string>
<string name="no_close_nearby">Não foi encontrado nenhum local próximo</string>
@ -505,9 +505,9 @@
<string name="no_image_reverted">Não foi revertida nenhuma imagem</string>
<string name="no_image_uploaded">Não foi carregada nenhuma imagem</string>
<string name="no_notification">Não tem nenhuma notificação por ler</string>
<string name="no_archived_notification">Não tem nenhuma notificação arquivada</string>
<string name="no_read_notification">Não tem nenhuma notificação arquivada</string>
<string name="share_logs_using">Partilhar os registos usando</string>
<string name="menu_option_archived">Ver arquivadas</string>
<string name="menu_option_read">Ver arquivadas</string>
<string name="menu_option_unread">Ver não lidas</string>
<string name="error_occurred_in_picking_images">Ocorreu um erro ao escolher imagens</string>
<string name="image_chooser_title">Escolher imagens a carregar</string>

View file

@ -378,7 +378,7 @@
<string name="contributions_fragment">Contribuții</string>
<string name="nearby_fragment">În apropiere</string>
<string name="notifications">Notificări</string>
<string name="archived_notifications">Notificări (arhivate)</string>
<string name="read_notifications">Notificări (arhivate)</string>
<string name="display_nearby_notification">Afișați notificarea din apropiere</string>
<string name="display_nearby_notification_summary">Apăsați aici pentru a vedea cel mai apropiat loc care are nevoie de imagini</string>
<string name="no_close_nearby">Nu există locuri apropiate găsite în apropierea dvs.</string>

View file

@ -400,7 +400,7 @@
<string name="contributions_fragment">Вклад</string>
<string name="nearby_fragment">Поблизости</string>
<string name="notifications">Уведомления</string>
<string name="archived_notifications">Уведомления (архивированные)</string>
<string name="read_notifications">Уведомления (архивированные)</string>
<string name="display_nearby_notification">Уведомлять меня о местах поблизости</string>
<string name="display_nearby_notification_summary">Нажмите здесь, чтобы увидеть ближайшее место без изображений</string>
<string name="no_close_nearby">Не найдено мест поблизости</string>
@ -515,9 +515,9 @@
<string name="no_image_reverted">Нет откаченых изображений</string>
<string name="no_image_uploaded">Нет загруженных изображений</string>
<string name="no_notification">У вас нет непрочитанных уведомлений</string>
<string name="no_archived_notification">Нет архивированных уведомлений</string>
<string name="no_read_notification">Нет архивированных уведомлений</string>
<string name="share_logs_using">Поделиться лог-файлами</string>
<string name="menu_option_archived">См. архивированные</string>
<string name="menu_option_read">См. архивированные</string>
<string name="menu_option_unread">См. непрочитанные</string>
<string name="error_occurred_in_picking_images">Произошла ошибка при загрузке изображений</string>
<string name="image_chooser_title">Выберите изображения для загрузки</string>

View file

@ -381,7 +381,7 @@
<string name="contributions_fragment">Príspevky</string>
<string name="nearby_fragment">V okolí</string>
<string name="notifications">Upozornenia</string>
<string name="archived_notifications">Upozornenia (prečítané)</string>
<string name="read_notifications">Upozornenia (prečítané)</string>
<string name="display_nearby_notification">Zobraziť notifikáciu o miestach v okolí</string>
<string name="display_nearby_notification_summary">Kliknutím sem sa zobrazí najbližšie miesto, ktoré potrebuje obrázky</string>
<string name="no_close_nearby">Vo vašej blízkosti neboli nájdené žiadne miesta</string>
@ -495,9 +495,9 @@
<string name="no_image_reverted">Žiadne revertované obrázky</string>
<string name="no_image_uploaded">Žiadne nahrané obrázky</string>
<string name="no_notification">Nemáte žiadne neprečítané upozornenia</string>
<string name="no_archived_notification">Nemáte žiadne prečítané upozornenia</string>
<string name="no_read_notification">Nemáte žiadne prečítané upozornenia</string>
<string name="share_logs_using">Zdieľať log pomocou</string>
<string name="menu_option_archived">Zobraziť prečítané</string>
<string name="menu_option_read">Zobraziť prečítané</string>
<string name="menu_option_unread">Zobraziť neprečítané</string>
<string name="error_occurred_in_picking_images">Nastala chyba pri vyberaní obrázkov</string>
<string name="image_chooser_title">Vyberte obrázky, ktoré chcete nahrať</string>

View file

@ -379,7 +379,7 @@
<string name="contributions_fragment">Доприноси</string>
<string name="nearby_fragment">У близини</string>
<string name="notifications">Обавештења</string>
<string name="archived_notifications">Обавештења (архивирана)</string>
<string name="read_notifications">Обавештења (архивирана)</string>
<string name="display_nearby_notification">Прикажи обавештење у близини</string>
<string name="display_nearby_notification_summary">Притисните овде да бисте видели најближе место којем треба слика</string>
<string name="no_close_nearby">Нису пронађена места у близини близу вас</string>
@ -475,9 +475,9 @@
<string name="no_image_reverted">Нема враћених слика</string>
<string name="no_image_uploaded">Нема отпремљених слика</string>
<string name="no_notification">Немате непрочитаних обавештења.</string>
<string name="no_archived_notification">Немате архивираних обавештења</string>
<string name="no_read_notification">Немате архивираних обавештења</string>
<string name="share_logs_using">Подели дневнике користећи</string>
<string name="menu_option_archived">Прикажи архивирано</string>
<string name="menu_option_read">Прикажи архивирано</string>
<string name="menu_option_unread">Прикажи непрочитано</string>
<string name="error_occurred_in_picking_images">Дошло је до грешке при избору слика</string>
<string name="image_chooser_title">Одабир слика за отпремање</string>

View file

@ -369,7 +369,7 @@
<string name="contributions_fragment">Kontribusi</string>
<string name="nearby_fragment">Sabudeureun</string>
<string name="notifications">Iber</string>
<string name="archived_notifications">Iber (arsip)</string>
<string name="read_notifications">Iber (arsip)</string>
<string name="display_nearby_notification">Témbongkeun iber sabudeureun</string>
<string name="no_close_nearby">Taya tempat sabudeureun nu kairong jang anjeun</string>
<string name="list_sheet">Daptar</string>
@ -445,9 +445,9 @@
<string name="no_image_reverted">Taya gambar nu dibalikkeun</string>
<string name="no_image_uploaded">Taya gambar diunjal</string>
<string name="no_notification">Anjeun teu boga iber nu can dibaca</string>
<string name="no_archived_notification">Anjeun teu boga iber arsip</string>
<string name="no_read_notification">Anjeun teu boga iber arsip</string>
<string name="share_logs_using">Bagikeun log pamakéan</string>
<string name="menu_option_archived">Tempo arsip</string>
<string name="menu_option_read">Tempo arsip</string>
<string name="menu_option_unread">Tempo nu can dibaca</string>
<string name="error_occurred_in_picking_images">Éror pas keur nyomot gambar</string>
<string name="image_chooser_title">Pilih Gambar unjalkeuneun</string>

View file

@ -384,7 +384,7 @@
<string name="contributions_fragment">Bidrag</string>
<string name="nearby_fragment">I närheten</string>
<string name="notifications">Aviseringar</string>
<string name="archived_notifications">Aviseringar (arkiverade)</string>
<string name="read_notifications">Aviseringar (arkiverade)</string>
<string name="display_nearby_notification">Visa avisering för i närheten</string>
<string name="display_nearby_notification_summary">Tryck här för att se den närmaste platsen som behöver bilder</string>
<string name="no_close_nearby">Inga platser i närheten hittades som är nära dig</string>
@ -498,9 +498,9 @@
<string name="no_image_reverted">Inga bilder återställdes</string>
<string name="no_image_uploaded">Inga bilder laddades upp</string>
<string name="no_notification">Du har inga olästa aviseringar</string>
<string name="no_archived_notification">Du har inga arkiverade aviseringar</string>
<string name="no_read_notification">Du har inga arkiverade aviseringar</string>
<string name="share_logs_using">Dela loggar med</string>
<string name="menu_option_archived">Visa arkiverade</string>
<string name="menu_option_read">Visa arkiverade</string>
<string name="menu_option_unread">Visa olästa</string>
<string name="error_occurred_in_picking_images">Fel uppstod när bilder valdes ut</string>
<string name="image_chooser_title">Välj bilder att ladda upp</string>

View file

@ -365,7 +365,7 @@
<string name="contributions_fragment">ಕಾಣಿಕೆಲು</string>
<string name="nearby_fragment">ಕೈತಲ್‍ದ</string>
<string name="notifications">ಅಧಿಸೂಚನೆಲು</string>
<string name="archived_notifications" fuzzy="true">ಅಧಿಸೂಚನೆಲು(ಅನುರಕ್ಷಿತ)</string>
<string name="read_notifications" fuzzy="true">ಅಧಿಸೂಚನೆಲು(ಅನುರಕ್ಷಿತ)</string>
<string name="display_nearby_notification">ಕೈತಲ್ದ ಅಧಿಸೂಚನೆ ತೋಜಾಲೆ</string>
<string name="display_nearby_notification_summary">ಚಿತ್ರ ಬೋಡಾಯಿನ ಕೈತಲ್ದ ಜಾಗ ತೂವರೆ ಮುಲ್ಪ ತಟ್ಟ್\'ಲೆ</string>
<string name="no_close_nearby">ಇರೆನ ಮುಟ್ಟೊಡು ಕೈತಲ್ದ ಜಾಗೊಲು ತಿಕ್ಕುಜಾ.</string>
@ -395,8 +395,8 @@
<string name="deletion_reason_uploaded_by_mistake">ಯಾನ್ ಅವೆನ್ ತತ್ತ್\'ದ್ ಮಿತೇರಾಯೆ.</string>
<string name="deletion_reason_publicly_visible">ಅವು ಸಾರ್ವತ್ರಿಕವಾದ್ ತೋಜುಂಡು ಇಂದ್ ಎಂಕ್ ಗೊತ್ತಿತ್ತಿಜಿ.</string>
<string name="deletion_reason_bad_for_my_privacy">ಅವು ಎನ್ನ ಖಾಸಗಿತೆನೊಕು ಹಾಳ್ಂದ್ ಎಂಕ್ ತೆರಿಂಡ್.</string>
<string name="no_archived_notification" fuzzy="true">ಇರೆಗ್ ಅನುರಕ್ಷಿತ ಅಧಿಸೂಚನೆ ಇಜ್ಜಿ</string>
<string name="menu_option_archived">ಅನುರಕ್ಷಿತ ತೂಲೆ</string>
<string name="no_read_notification" fuzzy="true">ಇರೆಗ್ ಅನುರಕ್ಷಿತ ಅಧಿಸೂಚನೆ ಇಜ್ಜಿ</string>
<string name="menu_option_read">ಅನುರಕ್ಷಿತ ತೂಲೆ</string>
<string name="menu_option_unread">ಓದಂದಿನ ತೂಲೆ</string>
<string name="error_occurred_in_picking_images">ಆಕೃತಿಲೆನ್ ಪೆಜ್ಜಿನಗ ದೋಷ ಆಂಡ್</string>
<string name="image_chooser_title">ಮಿತರಾರೆ ಆಕೃತಿಲೆನ್ ಆಯುಲೆ</string>

View file

@ -377,7 +377,7 @@
<string name="contributions_fragment">తోడ్పాటు</string>
<string name="nearby_fragment">చుట్టుపక్కల</string>
<string name="notifications">గమనింపులు</string>
<string name="archived_notifications">గమనింపులు (ఆర్కైవు చేసినవి)</string>
<string name="read_notifications">గమనింపులు (ఆర్కైవు చేసినవి)</string>
<string name="display_nearby_notification">చుట్టుపక్కల గమనింపును చూపించు</string>
<string name="display_nearby_notification_summary">బొమ్మలు అవసరమైన చుట్టుపక్కల స్థలాన్ని చూసేందుకు ఇక్కడ నొక్కండి</string>
<string name="no_close_nearby">మీ చుట్టుపక్కల స్థలాలేమీ కనబడలేదు</string>
@ -490,9 +490,9 @@
<string name="no_image_reverted">బొమ్మలు వేటినీ వెనక్కి తిరక్కొట్టలేదు</string>
<string name="no_image_uploaded">బొమ్మలేమీ ఎక్కించలేదు</string>
<string name="no_notification">మీకు చదవని గమనింపులేమీ లేవు</string>
<string name="no_archived_notification">మీకు ఆర్కైవు చేసిన గమనింపులేమీ లేవు</string>
<string name="no_read_notification">మీకు ఆర్కైవు చేసిన గమనింపులేమీ లేవు</string>
<string name="share_logs_using">దీన్ని వాడి లాగ్‌లను పంచుకోండి</string>
<string name="menu_option_archived">ఆర్కైవులను చూడండి</string>
<string name="menu_option_read">ఆర్కైవులను చూడండి</string>
<string name="menu_option_unread">చదవని వాటిని చూడండి</string>
<string name="error_occurred_in_picking_images">బొమ్మలను ఎంచుకునేటపుడు లోపం దొర్లింది</string>
<string name="image_chooser_title">ఎక్కించేందుకు బొమ్మలను ఎంచుకోండి</string>

View file

@ -396,7 +396,7 @@
<string name="contributions_fragment">Katkılar</string>
<string name="nearby_fragment">Yakınındakiler</string>
<string name="notifications">Bildirimler</string>
<string name="archived_notifications">Bildirimler (arşivlenmiş)</string>
<string name="read_notifications">Bildirimler (arşivlenmiş)</string>
<string name="display_nearby_notification">Yakındaki bildirimi görüntüle</string>
<string name="display_nearby_notification_summary">Resimlere en yakın yeri görmek için buraya dokunun</string>
<string name="no_close_nearby">Size yakın bir yer bulunamadı</string>
@ -510,9 +510,9 @@
<string name="no_image_reverted">Resim döndürülmedi</string>
<string name="no_image_uploaded">Resim yüklenmedi</string>
<string name="no_notification">Okunmamış bildirimleriniz yok</string>
<string name="no_archived_notification">Arşivlenmiş bildiriminiz yok</string>
<string name="no_read_notification">Arşivlenmiş bildiriminiz yok</string>
<string name="share_logs_using">Kullanarak günlükleri paylaş</string>
<string name="menu_option_archived">Arşivlenmişleri görüntüle</string>
<string name="menu_option_read">Arşivlenmişleri görüntüle</string>
<string name="menu_option_unread">Okunmamışları görüntüle</string>
<string name="error_occurred_in_picking_images">Resimler toplanırken hata oluştu</string>
<string name="image_chooser_title">Yüklenecek Görüntüleri Seçin</string>

View file

@ -397,7 +397,7 @@
<string name="contributions_fragment">Внесок</string>
<string name="nearby_fragment">Поблизу</string>
<string name="notifications">Сповіщення</string>
<string name="archived_notifications">Сповіщення (архівовані)</string>
<string name="read_notifications">Сповіщення (архівовані)</string>
<string name="display_nearby_notification">Повідомляти мене про місця поблизу</string>
<string name="display_nearby_notification_summary">Торкніться тут, щоб побачити найближчі місця, які ще не мають зображень</string>
<string name="no_close_nearby">Не знайдено місць поблизу Вас</string>
@ -513,9 +513,9 @@
<string name="no_image_reverted">Відхилених зображень немає</string>
<string name="no_image_uploaded">Завантажених зображень немає</string>
<string name="no_notification">У вас немає непрочитаних сповіщень</string>
<string name="no_archived_notification">Немає архівованих сповіщень</string>
<string name="no_read_notification">Немає архівованих сповіщень</string>
<string name="share_logs_using">Поширення журналів</string>
<string name="menu_option_archived">Перегляд архівованих</string>
<string name="menu_option_read">Перегляд архівованих</string>
<string name="menu_option_unread">Перегляд непрочитаних</string>
<string name="error_occurred_in_picking_images">Сталася помилка при завантаженні зображень</string>
<string name="image_chooser_title">Оберіть зображення для завантаження</string>

View file

@ -389,7 +389,7 @@
<string name="contributions_fragment">貢獻</string>
<string name="nearby_fragment">附近</string>
<string name="notifications">通知</string>
<string name="archived_notifications">通知(已存檔)</string>
<string name="read_notifications">通知(已存檔)</string>
<string name="display_nearby_notification">顯示附近地點通知</string>
<string name="display_nearby_notification_summary">在此輕觸來查看缺少圖片的最近地點</string>
<string name="no_close_nearby">查無靠近您的附近地點</string>
@ -503,9 +503,9 @@
<string name="no_image_reverted">沒有圖片被還原回復</string>
<string name="no_image_uploaded">沒有圖片被上傳</string>
<string name="no_notification">您有尚未讀取的通知</string>
<string name="no_archived_notification">您沒有已存檔通知</string>
<string name="no_read_notification">您沒有已存檔通知</string>
<string name="share_logs_using">分享日誌使用</string>
<string name="menu_option_archived">檢視已存檔</string>
<string name="menu_option_read">檢視已存檔</string>
<string name="menu_option_unread">檢視未讀</string>
<string name="error_occurred_in_picking_images">當挑選圖片時發生錯誤</string>
<string name="image_chooser_title">選擇要上傳的圖片</string>

View file

@ -400,7 +400,7 @@
<string name="contributions_fragment">贡献</string>
<string name="nearby_fragment">附近</string>
<string name="notifications">通知</string>
<string name="archived_notifications">通知(已存档)</string>
<string name="read_notifications">通知(已存档)</string>
<string name="display_nearby_notification">显示附近通知</string>
<string name="display_nearby_notification_summary">点击此处查看最近需要图片的地方</string>
<string name="no_close_nearby">附近找不到靠近您的地方</string>
@ -513,9 +513,9 @@
<string name="no_image_reverted">没有被撤回的图片</string>
<string name="no_image_uploaded">还没有上传图片</string>
<string name="no_notification">您没有任何未读通知</string>
<string name="no_archived_notification">您没有已存档的通知</string>
<string name="no_read_notification">您没有已存档的通知</string>
<string name="share_logs_using">分享日志于</string>
<string name="menu_option_archived">查看已存档</string>
<string name="menu_option_read">查看已存档</string>
<string name="menu_option_unread">查看未读</string>
<string name="error_occurred_in_picking_images">选择图片时出错</string>
<string name="image_chooser_title">选择要上传的图片</string>

View file

@ -36,14 +36,14 @@
</array>
<array name="pref_theme_entries">
<item>@string/theme_default_name</item>
<item>@string/theme_dark_name</item>
<item>@string/theme_light_name</item>
<item>@string/theme_dark_name</item>
<item>@string/theme_default_name</item>
</array>
<string-array name="pref_theme_entries_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
</resources>

View file

@ -407,7 +407,7 @@
<string name="contributions_fragment">Contributions</string>
<string name="nearby_fragment">Nearby</string>
<string name="notifications">Notifications</string>
<string name="archived_notifications">Notifications (archived)</string>
<string name="read_notifications">Notifications (read)</string>
<string name="display_nearby_notification">Display nearby notification</string>
<string name="display_nearby_notification_summary">Tap here to see the nearest place that needs pictures</string>
<string name="no_close_nearby">No nearby places found close to you</string>
@ -538,9 +538,9 @@ Upload your first media by tapping on the add button.</string>
<string name="no_image_uploaded">No images uploaded</string>
<string name="no_notification">You have no unread notifications</string>
<string name="no_archived_notification">You have no archived notifications</string>
<string name="no_read_notification">You have no read notifications</string>
<string name="share_logs_using">Share logs using</string>
<string name="menu_option_archived">View archived</string>
<string name="menu_option_read">View read</string>
<string name="menu_option_unread">View unread</string>
<string name="error_occurred_in_picking_images">Error occurred while picking images</string>
@ -619,7 +619,7 @@ Upload your first media by tapping on the add button.</string>
<string name="wallpaper_set_unsuccessfully">Something went wrong. Could not set the wallpaper</string>
<string name="setting_wallpaper_dialog_title">Set as Wallpaper</string>
<string name="setting_wallpaper_dialog_message">Setting Wallpaper. Please wait…</string>
<string name="theme_default_name">Default</string>
<string name="theme_default_name">Follow system</string>
<string name="theme_dark_name">Dark</string>
<string name="theme_light_name">Light</string>

View file

@ -1,85 +0,0 @@
package fr.free.nrw.commons.upload
import android.content.SharedPreferences
import fr.free.nrw.commons.caching.CacheController
import fr.free.nrw.commons.mwapi.CategoryApi
import org.junit.Before
import org.junit.Test
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import javax.inject.Inject
import javax.inject.Named
class FileProcessorTest {
@Mock
internal var cacheController: CacheController? = null
@Mock
internal var gpsCategoryModel: GpsCategoryModel? = null
@Mock
internal var apiCall: CategoryApi? = null
@Mock
@field:[Inject Named("default_preferences")]
internal var prefs: SharedPreferences? = null
@InjectMocks
var fileProcessor: FileProcessor? = null
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
}
@Test
fun processFileCoordinates() {
}
/**
* Test method to verify redaction Exif metadata
*/
@Test
fun redactExifTags() {
/*
val filePathRef: String? = "src/test/data/exif_redact_sample.jpg"
val filePathTmp: String? = "" + System.getProperty("java.io.tmpdir") + "exif_redact_sample_tmp.jpg"
val inStream = FileInputStream(filePathRef)
val outStream = FileOutputStream(filePathTmp)
val inChannel = inStream.getChannel()
val outChannel = outStream.getChannel()
inChannel.transferTo(0, inChannel.size(), outChannel)
inStream.close()
outStream.close()
val redactTags = mutableSetOf("Author", "Copyright", "Location", "Camera Model",
"Lens Model", "Serial Numbers", "Software")
val exifInterface : ExifInterface? = ExifInterface(filePathTmp.toString())
var nonEmptyTag = false
for (redactTag in redactTags) {
for (tag in FileMetadataUtils.getTagsFromPref(redactTag)) {
val tagValue = exifInterface?.getAttribute(tag)
if(tagValue != null) {
nonEmptyTag = true
break
}
}
if (nonEmptyTag) break
}
// all tags are empty, can't test redaction
assert(nonEmptyTag)
FileProcessor.redactExifTags(exifInterface, redactTags)
for (redactTag in redactTags) {
for (tag in FileMetadataUtils.getTagsFromPref(redactTag)) {
val oldValue = exifInterface?.getAttribute(tag)
assert(oldValue == null)
}
}
*/
}
}

View file

@ -1,6 +1,8 @@
package fr.free.nrw.commons.upload
import androidx.recyclerview.widget.RecyclerView
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import fr.free.nrw.commons.filepicker.UploadableFile
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.repository.UploadRepository
@ -16,9 +18,8 @@ import org.mockito.*
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.verify
import java.util.ArrayList
import java.util.*
/**
@ -26,37 +27,32 @@ import java.util.ArrayList
*/
class UploadMediaPresenterTest {
@Mock
internal var repository: UploadRepository? = null
@Mock
internal var view: UploadMediaDetailsContract.View? = null
private var uploadMediaPresenter: UploadMediaPresenter? = null
internal lateinit var repository: UploadRepository
@Mock
private var uploadableFile: UploadableFile? = null
internal lateinit var view: UploadMediaDetailsContract.View
private lateinit var uploadMediaPresenter: UploadMediaPresenter
@Mock
private var place: Place? = null
private lateinit var uploadableFile: UploadableFile
@Mock
private var uploadItem: UploadModel.UploadItem? = null
private lateinit var place: Place
@Mock
private var title: Title? = null
private lateinit var uploadItem: UploadModel.UploadItem
@Mock
private var uploadMediaDetails: List<UploadMediaDetail>? = null
private lateinit var title: Title
@InjectMocks
var uploadMediaDetailAdapter: UploadMediaDetailAdapter? = null
@Mock
private lateinit var uploadMediaDetails: List<UploadMediaDetail>
var recyclerView: RecyclerView? = null
private lateinit var testObservableUploadItem: Observable<UploadModel.UploadItem>
private lateinit var testSingleImageResult: Single<Int>
private var testObservableUploadItem: Observable<UploadModel.UploadItem>? = null
private var testSingleImageResult: Single<Int>? = null
private var testScheduler: TestScheduler? = null
private lateinit var testScheduler: TestScheduler
/**
* initial setup unit test environment
@ -66,12 +62,10 @@ class UploadMediaPresenterTest {
fun setUp() {
MockitoAnnotations.initMocks(this)
testObservableUploadItem = Observable.just(uploadItem)
uploadMediaDetailAdapter = UploadMediaDetailAdapter();
recyclerView?.adapter = uploadMediaDetailAdapter
testSingleImageResult = Single.just(1)
testScheduler = TestScheduler()
uploadMediaPresenter = UploadMediaPresenter(repository, testScheduler, testScheduler)
uploadMediaPresenter?.onAttachView(view)
uploadMediaPresenter.onAttachView(view)
}
/**
@ -79,12 +73,22 @@ class UploadMediaPresenterTest {
*/
@Test
fun receiveImageTest() {
Mockito.`when`(repository?.preProcessImage(ArgumentMatchers.any(UploadableFile::class.java), ArgumentMatchers.any(Place::class.java), ArgumentMatchers.anyString(), ArgumentMatchers.any(UploadMediaPresenter::class.java))).thenReturn(testObservableUploadItem)
uploadMediaPresenter?.receiveImage(uploadableFile, ArgumentMatchers.anyString(), place)
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.onImageProcessed(ArgumentMatchers.any(UploadModel.UploadItem::class.java), ArgumentMatchers.any(Place::class.java))
verify(view)?.showProgress(false)
whenever(
repository.preProcessImage(
ArgumentMatchers.any(UploadableFile::class.java),
ArgumentMatchers.any(Place::class.java),
ArgumentMatchers.anyString(),
ArgumentMatchers.any(UploadMediaPresenter::class.java)
)
).thenReturn(testObservableUploadItem)
uploadMediaPresenter.receiveImage(uploadableFile, ArgumentMatchers.anyString(), place)
verify(view).showProgress(true)
testScheduler.triggerActions()
verify(view).onImageProcessed(
ArgumentMatchers.any(UploadModel.UploadItem::class.java),
ArgumentMatchers.any(Place::class.java)
)
verify(view).showProgress(false)
}
/**
@ -92,12 +96,13 @@ class UploadMediaPresenterTest {
*/
@Test
fun verifyImageQualityTest() {
Mockito.`when`(repository?.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java))).thenReturn(testSingleImageResult)
Mockito.`when`(uploadItem?.imageQuality).thenReturn(ArgumentMatchers.anyInt())
uploadMediaPresenter?.verifyImageQuality(uploadItem)
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.showProgress(false)
whenever(repository.getImageQuality(ArgumentMatchers.any(UploadModel.UploadItem::class.java)))
.thenReturn(testSingleImageResult)
whenever(uploadItem.imageQuality).thenReturn(ArgumentMatchers.anyInt())
uploadMediaPresenter.verifyImageQuality(uploadItem)
verify(view).showProgress(true)
testScheduler.triggerActions()
verify(view).showProgress(false)
}
/**
@ -106,20 +111,20 @@ class UploadMediaPresenterTest {
@Test
fun handleImageResult() {
//Positive case test
uploadMediaPresenter?.handleImageResult(IMAGE_KEEP)
verify(view)?.onImageValidationSuccess()
uploadMediaPresenter.handleImageResult(IMAGE_KEEP)
verify(view).onImageValidationSuccess()
//Duplicate file name
uploadMediaPresenter?.handleImageResult(FILE_NAME_EXISTS)
verify(view)?.showDuplicatePicturePopup()
uploadMediaPresenter.handleImageResult(FILE_NAME_EXISTS)
verify(view).showDuplicatePicturePopup()
//Empty Caption test
uploadMediaPresenter?.handleImageResult(EMPTY_CAPTION)
verify(view)?.showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
uploadMediaPresenter.handleImageResult(EMPTY_CAPTION)
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
//Bad Picture test
//Empty Caption test
uploadMediaPresenter?.handleImageResult(-7)
uploadMediaPresenter.handleImageResult(-7)
verify(view)?.showBadImagePopup(ArgumentMatchers.anyInt())
}
@ -131,14 +136,13 @@ class UploadMediaPresenterTest {
uploadMediaDetail.languageCode = "en"
val uploadMediaDetailList: ArrayList<UploadMediaDetail> = ArrayList()
uploadMediaDetailList.add(uploadMediaDetail)
uploadMediaDetailAdapter?.addDescription(uploadMediaDetail)
uploadItem?.setMediaDetails(uploadMediaDetailAdapter?.getUploadMediaDetails())
Mockito.`when`(repository?.getImageQuality(uploadItem)).then {
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.showProgress(true)
verify(view)?.onImageValidationSuccess()
uploadMediaPresenter?.setUploadItem(0, uploadItem)
uploadItem.setMediaDetails(uploadMediaDetailList)
Mockito.`when`(repository.getImageQuality(uploadItem)).then {
verify(view).showProgress(true)
testScheduler.triggerActions()
verify(view).showProgress(true)
verify(view).onImageValidationSuccess()
uploadMediaPresenter.setUploadItem(0, uploadItem)
}
}
@ -147,17 +151,15 @@ class UploadMediaPresenterTest {
val uploadMediaDetail = UploadMediaDetail()
uploadMediaDetail.captionText = "added caption"
uploadMediaDetail.languageCode = "en"
uploadMediaDetailAdapter?.addDescription(uploadMediaDetail)
uploadMediaDetail.captionText = "added caption"
uploadMediaDetail.languageCode = "eo"
uploadMediaDetailAdapter?.addDescription(uploadMediaDetail)
uploadItem?.setMediaDetails(uploadMediaDetailAdapter?.getUploadMediaDetails())
Mockito.`when`(repository?.getImageQuality(uploadItem)).then {
verify(view)?.showProgress(true)
testScheduler?.triggerActions()
verify(view)?.showProgress(true)
verify(view)?.onImageValidationSuccess()
uploadMediaPresenter?.setUploadItem(0, uploadItem)
uploadItem.setMediaDetails(Collections.singletonList(uploadMediaDetail))
Mockito.`when`(repository.getImageQuality(uploadItem)).then {
verify(view).showProgress(true)
testScheduler.triggerActions()
verify(view).showProgress(true)
verify(view).onImageValidationSuccess()
uploadMediaPresenter.setUploadItem(0, uploadItem)
}
}
@ -165,52 +167,54 @@ class UploadMediaPresenterTest {
* Test fetch previous image title when there was one
*/
@Test
fun fetchPreviousImageAndTitleTestPositive(){
Mockito.`when`(repository?.getPreviousUploadItem(ArgumentMatchers.anyInt())).thenReturn(uploadItem)
Mockito.`when`(uploadItem?.uploadMediaDetails).thenReturn(uploadMediaDetails)
Mockito.`when`(uploadItem?.title).thenReturn(title)
Mockito.`when`(title?.getTitleText()).thenReturn(ArgumentMatchers.anyString())
fun fetchPreviousImageAndTitleTestPositive() {
whenever(repository.getPreviousUploadItem(ArgumentMatchers.anyInt()))
.thenReturn(uploadItem)
whenever(uploadItem.uploadMediaDetails).thenReturn(uploadMediaDetails)
whenever(uploadItem.title).thenReturn(title)
whenever(title.getTitleText()).thenReturn(ArgumentMatchers.anyString())
uploadMediaPresenter?.fetchPreviousTitleAndDescription(0)
verify(view)?.setTitleAndDescription(ArgumentMatchers.anyString(), ArgumentMatchers.any())
uploadMediaPresenter.fetchPreviousTitleAndDescription(0)
verify(view).setTitleAndDescription(ArgumentMatchers.anyString(), ArgumentMatchers.any())
}
/**
* Test fetch previous image title when there was none
*/
@Test
fun fetchPreviousImageAndTitleTestNegative(){
Mockito.`when`(repository?.getPreviousUploadItem(ArgumentMatchers.anyInt())).thenReturn(null)
uploadMediaPresenter?.fetchPreviousTitleAndDescription(0)
verify(view)?.showMessage(ArgumentMatchers.anyInt(),ArgumentMatchers.anyInt())
fun fetchPreviousImageAndTitleTestNegative() {
whenever(repository.getPreviousUploadItem(ArgumentMatchers.anyInt()))
.thenReturn(null)
uploadMediaPresenter.fetchPreviousTitleAndDescription(0)
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
}
/**
* Test bad image invalid location
*/
@Test
fun handleBadImageBaseTestInvalidLocation(){
uploadMediaPresenter?.handleBadImage(8)
verify(repository)?.saveValue(ArgumentMatchers.anyString(),eq(false))
verify(view)?.showBadImagePopup(8)
fun handleBadImageBaseTestInvalidLocation() {
uploadMediaPresenter.handleBadImage(8)
verify(repository).saveValue(ArgumentMatchers.anyString(), eq(false))
verify(view).showBadImagePopup(8)
}
/**
* Test bad image empty title
*/
@Test
fun handleBadImageBaseTestEmptyTitle(){
uploadMediaPresenter?.handleBadImage(-3)
verify(view)?.showMessage(ArgumentMatchers.anyInt(),ArgumentMatchers.anyInt())
fun handleBadImageBaseTestEmptyTitle() {
uploadMediaPresenter.handleBadImage(-3)
verify(view).showMessage(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
}
/**
* Teste show file already exists
*/
@Test
fun handleBadImageBaseTestFileNameExists(){
uploadMediaPresenter?.handleBadImage(-4)
verify(view)?.showDuplicatePicturePopup()
fun handleBadImageBaseTestFileNameExists() {
uploadMediaPresenter.handleBadImage(-4)
verify(view).showDuplicatePicturePopup()
}
@ -218,18 +222,19 @@ class UploadMediaPresenterTest {
* Test show SimilarImageFragment
*/
@Test
fun showSimilarImageFragmentTest(){
uploadMediaPresenter?.showSimilarImageFragment(ArgumentMatchers.anyString(),ArgumentMatchers.anyString())
verify(view)?.showSimilarImageFragment(ArgumentMatchers.anyString(),ArgumentMatchers.anyString())
fun showSimilarImageFragmentTest() {
val similar: ImageCoordinates = mock()
uploadMediaPresenter.showSimilarImageFragment("original", "possible", similar)
verify(view).showSimilarImageFragment("original", "possible", similar)
}
/**
* Test set upload item
*/
@Test
fun setUploadItemTest(){
uploadMediaPresenter?.setUploadItem(0,uploadItem)
verify(repository)?.updateUploadItem(0,uploadItem)
fun setUploadItemTest() {
uploadMediaPresenter.setUploadItem(0, uploadItem)
verify(repository).updateUploadItem(0, uploadItem)
}
}

View file

@ -1,132 +0,0 @@
package fr.free.nrw.commons.upload
import android.app.Application
import android.content.Context
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.filepicker.UploadableFile
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.nearby.Place
import fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK
import io.reactivex.Single
import org.junit.After
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatchers.*
import org.mockito.InjectMocks
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations
import java.io.FileInputStream
import java.io.InputStream
import java.util.*
import javax.inject.Inject
import javax.inject.Named
class UploadModelTest {
@Mock
@field:[Inject Named("licenses")]
internal var licenses: List<String>? = null
@Mock
@field:[Inject Named("default_preferences")]
internal var prefs: JsonKvStore? = null
@Mock
@field:[Inject Named("licenses_by_name")]
internal var licensesByName: Map<String, String>? = null
@Mock
internal var context: Context? = null
@Mock
internal var sessionManage: SessionManager? = null
@Mock
internal var fileUtilsWrapper: FileUtilsWrapper? = null
@Mock
internal var fileProcessor: FileProcessor? = null
@Mock
internal var imageProcessingService: ImageProcessingService? = null
@InjectMocks
var uploadModel: UploadModel? = null
@Before
@Throws(Exception::class)
fun setUp() {
MockitoAnnotations.initMocks(this)
`when`(context!!.applicationContext)
.thenReturn(mock(Application::class.java))
`when`(fileUtilsWrapper!!.getFileExt(anyString()))
.thenReturn("jpg")
`when`(fileUtilsWrapper!!.getSHA1(any(InputStream::class.java)))
.thenReturn("sha")
`when`(fileUtilsWrapper!!.getFileInputStream(anyString()))
.thenReturn(mock(FileInputStream::class.java))
`when`(fileUtilsWrapper!!.getGeolocationOfFile(anyString()))
.thenReturn("")
`when`(imageProcessingService!!.validateImage(any(UploadModel.UploadItem::class.java)))
.thenReturn(Single.just(IMAGE_OK))
}
@After
@Throws(Exception::class)
fun tearDown() {
}
@Test
fun receive() {
val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
preProcessImages.doOnComplete {
assertTrue(uploadModel!!.items.size == 2)
}
}
@Test
fun getCurrentStep() {
uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
assertTrue(uploadModel!!.currentStep == 1)
}
@Test
fun getStepCount() {
val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
preProcessImages.doOnComplete {
assertTrue(uploadModel!!.stepCount == 4)
}
}
@Test
fun getCount() {
val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
preProcessImages.doOnComplete {
assertTrue(uploadModel!!.count == 2)
}
}
@Test
fun getUploads() {
val preProcessImages = uploadModel!!.preProcessImages(getMediaList(), mock(Place::class.java), "external") { _, _ -> }
preProcessImages.doOnComplete {
assertTrue(uploadModel!!.uploads.size == 2)
}
}
private fun getMediaList(): List<UploadableFile> {
val element = getElement()
val element2 = getElement()
var uriList: List<UploadableFile> = mutableListOf(element, element2)
return uriList
}
private fun getElement(): UploadableFile {
val mock = mock(UploadableFile::class.java)
`when`(mock.filePath).thenReturn(UUID.randomUUID().toString() + "/filePath.jpg")
return mock
}
@Test
fun buildContributions() {
}
}