Merge branch '2.7.x-release' of https://github.com/commons-app/apps-android-commons into 2.7.x-release

This commit is contained in:
misaochan 2018-03-27 19:19:32 +10:00
commit 9e1c55f2a3
9 changed files with 226 additions and 114 deletions

View file

@ -43,6 +43,7 @@ public class Media implements Parcelable {
protected String license; protected String license;
protected String creator; protected String creator;
protected ArrayList<String> categories; // as loaded at runtime? protected ArrayList<String> categories; // as loaded at runtime?
protected boolean requestedDeletion;
private Map<String, String> descriptions; // multilingual descriptions as loaded private Map<String, String> descriptions; // multilingual descriptions as loaded
private HashMap<String, Object> tags = new HashMap<>(); private HashMap<String, Object> tags = new HashMap<>();
private @Nullable LatLng coordinates; private @Nullable LatLng coordinates;
@ -416,4 +417,12 @@ public class Media implements Parcelable {
parcel.writeStringList(categories); parcel.writeStringList(categories);
parcel.writeMap(descriptions); parcel.writeMap(descriptions);
} }
public void setRequestedDeletion(){
requestedDeletion = true;
}
public boolean getRequestedDeletion(){
return requestedDeletion;
}
} }

View file

@ -35,6 +35,7 @@ import timber.log.Timber;
public class MediaDataExtractor { public class MediaDataExtractor {
private final MediaWikiApi mediaWikiApi; private final MediaWikiApi mediaWikiApi;
private boolean fetched; private boolean fetched;
private boolean deletionStatus;
private ArrayList<String> categories; private ArrayList<String> categories;
private Map<String, String> descriptions; private Map<String, String> descriptions;
private String license; private String license;
@ -59,6 +60,14 @@ public class MediaDataExtractor {
throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again."); throw new IllegalStateException("Tried to call MediaDataExtractor.fetch() again.");
} }
try{
Timber.d("Nominated for deletion: " + mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename));
deletionStatus = mediaWikiApi.pageExists("Commons:Deletion_requests/"+filename);
}
catch (Exception e){
Timber.d(e.getMessage());
}
MediaResult result = mediaWikiApi.fetchMediaByFilename(filename); MediaResult result = mediaWikiApi.fetchMediaByFilename(filename);
// In-page category links are extracted from source, as XML doesn't cover [[links]] // In-page category links are extracted from source, as XML doesn't cover [[links]]
@ -296,6 +305,9 @@ public class MediaDataExtractor {
if (license != null) { if (license != null) {
media.setLicense(license); media.setLicense(license);
} }
if (deletionStatus){
media.setRequestedDeletion();
}
// add author, date, etc fields // add author, date, etc fields
} }

View file

@ -1,10 +1,13 @@
package fr.free.nrw.commons.delete; package fr.free.nrw.commons.delete;
import android.app.AlertDialog; import android.app.NotificationManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.view.Gravity;
import android.widget.Toast;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
@ -18,17 +21,18 @@ import fr.free.nrw.commons.di.ApplicationlessInjection;
import fr.free.nrw.commons.mwapi.MediaWikiApi; import fr.free.nrw.commons.mwapi.MediaWikiApi;
import timber.log.Timber; import timber.log.Timber;
import static android.support.v4.content.ContextCompat.startActivity; import static android.support.v4.app.NotificationCompat.DEFAULT_ALL;
import static android.support.v4.app.NotificationCompat.PRIORITY_HIGH;
public class DeleteTask extends AsyncTask<Void, Void, Integer> { public class DeleteTask extends AsyncTask<Void, Integer, Boolean> {
private static final int SUCCESS = 0;
private static final int FAILED = -1;
private static final int ALREADY_DELETED = -2;
@Inject MediaWikiApi mwApi; @Inject MediaWikiApi mwApi;
@Inject SessionManager sessionManager; @Inject SessionManager sessionManager;
public static final int NOTIFICATION_DELETE = 1;
private NotificationManager notificationManager;
private Builder notificationBuilder;
private Context context; private Context context;
private Media media; private Media media;
private String reason; private String reason;
@ -45,10 +49,19 @@ public class DeleteTask extends AsyncTask<Void, Void, Integer> {
.getInstance(context.getApplicationContext()) .getInstance(context.getApplicationContext())
.getCommonsApplicationComponent() .getCommonsApplicationComponent()
.inject(this); .inject(this);
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationBuilder = new NotificationCompat.Builder(context);
Toast toast = new Toast(context);
toast.setGravity(Gravity.CENTER,0,0);
toast = Toast.makeText(context,"Trying to nominate "+media.getDisplayTitle()+ " for deletion",Toast.LENGTH_SHORT);
toast.show();
} }
@Override @Override
protected Integer doInBackground(Void ...voids) { protected Boolean doInBackground(Void ...voids) {
publishProgress(0);
String editToken; String editToken;
String authCookie; String authCookie;
String summary = "Nominating " + media.getFilename() +" for deletion."; String summary = "Nominating " + media.getFilename() +" for deletion.";
@ -56,27 +69,6 @@ public class DeleteTask extends AsyncTask<Void, Void, Integer> {
authCookie = sessionManager.getAuthCookie(); authCookie = sessionManager.getAuthCookie();
mwApi.setAuthCookie(authCookie); mwApi.setAuthCookie(authCookie);
try{
if (mwApi.pageExists("Commons:Deletion_requests/"+media.getFilename())){
return ALREADY_DELETED;
}
}
catch (Exception e) {
Timber.d(e.getMessage());
return FAILED;
}
try {
editToken = mwApi.getEditToken();
}
catch (Exception e){
Timber.d(e.getMessage());
return FAILED;
}
if (editToken.equals("+\\")) {
return FAILED;
}
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
String fileDeleteString = "{{delete|reason=" + reason + String fileDeleteString = "{{delete|reason=" + reason +
"|subpage=" +media.getFilename() + "|subpage=" +media.getFilename() +
@ -84,91 +76,106 @@ public class DeleteTask extends AsyncTask<Void, Void, Integer> {
"|month=" + calendar.getDisplayName(Calendar.MONTH,Calendar.LONG, Locale.getDefault()) + "|month=" + calendar.getDisplayName(Calendar.MONTH,Calendar.LONG, Locale.getDefault()) +
"|year=" + calendar.get(Calendar.YEAR) + "|year=" + calendar.get(Calendar.YEAR) +
"}}"; "}}";
try{
mwApi.prependEdit(editToken,fileDeleteString+"\n",
media.getFilename(),summary);
}
catch (Exception e) {
Timber.d(e.getMessage());
return FAILED;
}
String subpageString = "=== [[:" + media.getFilename() + "]] ===\n" + String subpageString = "=== [[:" + media.getFilename() + "]] ===\n" +
reason + reason +
" ~~~~"; " ~~~~";
try{
mwApi.edit(editToken,subpageString+"\n",
"Commons:Deletion_requests/"+media.getFilename(),summary);
}
catch (Exception e) {
Timber.d(e.getMessage());
return FAILED;
}
String logPageString = "\n{{Commons:Deletion requests/" + media.getFilename() + String logPageString = "\n{{Commons:Deletion requests/" + media.getFilename() +
"}}\n"; "}}\n";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
String date = sdf.format(calendar.getTime()); String date = sdf.format(calendar.getTime());
try{
mwApi.appendEdit(editToken,logPageString+"\n",
"Commons:Deletion_requests/"+date,summary);
}
catch (Exception e) {
Timber.d(e.getMessage());
return FAILED;
}
String userPageString = "\n{{subst:idw|" + media.getFilename() + String userPageString = "\n{{subst:idw|" + media.getFilename() +
"}} ~~~~"; "}} ~~~~";
try{
try {
editToken = mwApi.getEditToken();
if (editToken.equals("+\\")) {
return false;
}
publishProgress(1);
mwApi.prependEdit(editToken,fileDeleteString+"\n",
media.getFilename(),summary);
publishProgress(2);
mwApi.edit(editToken,subpageString+"\n",
"Commons:Deletion_requests/"+media.getFilename(),summary);
publishProgress(3);
mwApi.appendEdit(editToken,logPageString+"\n",
"Commons:Deletion_requests/"+date,summary);
publishProgress(4);
mwApi.appendEdit(editToken,userPageString+"\n", mwApi.appendEdit(editToken,userPageString+"\n",
"User_Talk:"+sessionManager.getCurrentAccount().name,summary); "User_Talk:"+sessionManager.getCurrentAccount().name,summary);
publishProgress(5);
} }
catch (Exception e) { catch (Exception e) {
Timber.d(e.getMessage()); Timber.d(e.getMessage());
return FAILED; return false;
} }
return SUCCESS; return true;
} }
@Override @Override
protected void onPostExecute(Integer result) { protected void onProgressUpdate (Integer... values){
super.onProgressUpdate(values);
String message = ""; String message = "";
String title = ""; switch (values[0]){
switch (result){ case 0:
case SUCCESS: message = "Getting token";
title = "Success";
message = "Successfully nominated " + media.getDisplayTitle() + " deletion.\n" +
"Check the webpage for more details";
break; break;
case FAILED: case 1:
title = "Failed"; message = "Adding delete message to file";
message = "Could not request deletion. Something went wrong.";
break; break;
case ALREADY_DELETED: case 2:
title = "Already Nominated"; message = "Creating Delete requests sub-page";
message = media.getDisplayTitle() + " has already been nominated for deletion.\n" + break;
"Check the webpage for more details"; case 3:
message = "Adding file to Delete requests log";
break;
case 4:
message = "Notifying User on Talk page";
break;
case 5:
message = "Done";
break; break;
} }
AlertDialog alert;
AlertDialog.Builder builder = new AlertDialog.Builder(context); notificationBuilder.setContentTitle("Nominating "+media.getDisplayTitle()+" for deletion")
builder.setTitle(title); .setStyle(new NotificationCompat.BigTextStyle()
builder.setMessage(message); .bigText(message))
builder.setCancelable(true); .setSmallIcon(R.drawable.ic_launcher)
builder.setPositiveButton( .setProgress(5, values[0], false)
R.string.ok, .setOngoing(true);
new DialogInterface.OnClickListener() { notificationManager.notify(NOTIFICATION_DELETE, notificationBuilder.build());
public void onClick(DialogInterface dialog, int id) {} }
});
builder.setNeutralButton(R.string.view_browser, @Override
new DialogInterface.OnClickListener() { protected void onPostExecute(Boolean result) {
public void onClick(DialogInterface dialog, int id) { String message = "";
Intent browserIntent = new Intent(Intent.ACTION_VIEW, media.getFilePageTitle().getMobileUri()); String title = "Nominating for Deletion";
startActivity(context,browserIntent,null);
} if (result){
}); title += ": Success";
alert = builder.create(); message = "Successfully nominated " + media.getDisplayTitle() + " deletion.";
alert.show(); }
else {
title += ": Failed";
message = "Could not request deletion.";
}
notificationBuilder.setDefaults(DEFAULT_ALL)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(message))
.setSmallIcon(R.drawable.ic_launcher)
.setProgress(0,0,false)
.setOngoing(false)
.setPriority(PRIORITY_HIGH);
notificationManager.notify(NOTIFICATION_DELETE, notificationBuilder.build());
} }
} }

View file

@ -15,7 +15,6 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -42,6 +41,7 @@ import fr.free.nrw.commons.R;
import fr.free.nrw.commons.delete.DeleteTask; import fr.free.nrw.commons.delete.DeleteTask;
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment; import fr.free.nrw.commons.di.CommonsDaggerSupportFragment;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.mwapi.MediaWikiApi;
import fr.free.nrw.commons.ui.widget.CompatTextView; import fr.free.nrw.commons.ui.widget.CompatTextView;
import timber.log.Timber; import timber.log.Timber;
@ -69,6 +69,9 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
@Inject @Inject
Provider<MediaDataExtractor> mediaDataExtractorProvider; Provider<MediaDataExtractor> mediaDataExtractorProvider;
@Inject
MediaWikiApi mwApi;
private MediaWikiImageView image; private MediaWikiImageView image;
private MediaDetailSpacer spacer; private MediaDetailSpacer spacer;
@ -79,6 +82,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
private TextView license; private TextView license;
private TextView coordinates; private TextView coordinates;
private TextView uploadedDate; private TextView uploadedDate;
private TextView seeMore;
private LinearLayout nominatedforDeletion;
private LinearLayout categoryContainer; private LinearLayout categoryContainer;
private Button delete; private Button delete;
private ScrollView scrollView; private ScrollView scrollView;
@ -133,6 +138,8 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
license = (TextView) view.findViewById(R.id.mediaDetailLicense); license = (TextView) view.findViewById(R.id.mediaDetailLicense);
coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates); coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates);
uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate); uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate);
seeMore = (TextView) view.findViewById(R.id.seeMore);
nominatedforDeletion = (LinearLayout) view.findViewById(R.id.nominatedDeletionBanner);
delete = (Button) view.findViewById(R.id.nominateDeletion); delete = (Button) view.findViewById(R.id.nominateDeletion);
categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer); categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer);
@ -231,7 +238,6 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
if (success) { if (success) {
extractor.fill(media); extractor.fill(media);
setTextFields(media); setTextFields(media);
setOnClickListeners(media); setOnClickListeners(media);
} else { } else {
@ -284,21 +290,23 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
} }
rebuildCatList(); rebuildCatList();
delete.setVisibility(View.VISIBLE); checkDeletion(media);
} }
private void setOnClickListeners(final Media media) { private void setOnClickListeners(final Media media) {
if (licenseLink(media) != null) { if (licenseLink(media) != null) {
license.setOnClickListener(v -> openWebBrowser(licenseLink(media))); license.setOnClickListener(v -> openWebBrowser(licenseLink(media)));
} else { } else {
Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT); Toast toast = Toast.makeText(getContext(), getString(R.string.null_url), Toast.LENGTH_SHORT);
toast.show(); toast.show();
} }
if (media.getCoordinates() != null) { if (media.getCoordinates() != null) {
coordinates.setOnClickListener(v -> openMap(media.getCoordinates())); coordinates.setOnClickListener(v -> openMap(media.getCoordinates()));
} }
if (delete.getVisibility()==View.VISIBLE){ if (delete.getVisibility() == View.VISIBLE) {
delete.setOnClickListener(v -> { delete.setOnClickListener(v -> {
delete.setEnabled(false);
delete.setTextColor(getResources().getColor(R.color.deleteButtonLight));
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setMessage("Why should this file be deleted?"); alert.setMessage("Why should this file be deleted?");
final EditText input = new EditText(getActivity()); final EditText input = new EditText(getActivity());
@ -343,6 +351,11 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); d.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}); });
} }
if (nominatedforDeletion.getVisibility() == View.VISIBLE){
seeMore.setOnClickListener(v -> {
openWebBrowser(media.getFilePageTitle().getMobileUri().toString());
});
}
} }
private void rebuildCatList() { private void rebuildCatList() {
@ -366,7 +379,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
viewIntent.setAction(Intent.ACTION_VIEW); viewIntent.setAction(Intent.ACTION_VIEW);
viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri()); viewIntent.setData(new PageTitle(selectedCategoryTitle).getCanonicalUri());
//check if web browser available //check if web browser available
if(viewIntent.resolveActivity(getActivity().getPackageManager()) != null){ if (viewIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(viewIntent); startActivity(viewIntent);
} else { } else {
Toast toast = Toast.makeText(getContext(), getString(R.string.no_web_browser), LENGTH_SHORT); Toast toast = Toast.makeText(getContext(), getString(R.string.no_web_browser), LENGTH_SHORT);
@ -434,6 +447,16 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
return media.getCoordinates().getPrettyCoordinateString(); return media.getCoordinates().getPrettyCoordinateString();
} }
private void checkDeletion(Media media){
if (media.getRequestedDeletion()){
delete.setVisibility(View.GONE);
nominatedforDeletion.setVisibility(View.VISIBLE);
}
else{
delete.setVisibility(View.VISIBLE);
nominatedforDeletion.setVisibility(View.GONE);
}
}
private @Nullable private @Nullable
String licenseLink(Media media) { String licenseLink(Media media) {

View file

@ -394,11 +394,9 @@ public class NearbyMapFragment extends DaggerFragment {
} }
}); });
// Remove texts if it doesnt fit // Remove button text if they exceed 1 line or if internal layout has not been built
if (wikipediaButtonText.getLineCount() > 1 // Only need to check for directions button because it is the longest
|| wikidataButtonText.getLineCount() > 1 if (directionsButtonText.getLineCount() > 1 || directionsButtonText.getLineCount() == 0) {
|| commonsButtonText.getLineCount() > 1
|| directionsButtonText.getLineCount() > 1) {
wikipediaButtonText.setVisibility(View.GONE); wikipediaButtonText.setVisibility(View.GONE);
wikidataButtonText.setVisibility(View.GONE); wikidataButtonText.setVisibility(View.GONE);
commonsButtonText.setVisibility(View.GONE); commonsButtonText.setVisibility(View.GONE);
@ -583,7 +581,7 @@ public class NearbyMapFragment extends DaggerFragment {
/* /*
* Add amnchors back before making them visible again. * Add anchors back before making them visible again.
* */ * */
private void addAnchorToBigFABs(FloatingActionButton floatingActionButton, int anchorID) { private void addAnchorToBigFABs(FloatingActionButton floatingActionButton, int anchorID) {
CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams
@ -594,7 +592,7 @@ public class NearbyMapFragment extends DaggerFragment {
} }
/* /*
* Add amnchors back before making them visible again. Big and small fabs have different anchor * Add anchors back before making them visible again. Big and small fabs have different anchor
* gravities, therefore the are two methods. * gravities, therefore the are two methods.
* */ * */
private void addAnchorToSmallFABs(FloatingActionButton floatingActionButton, int anchorID) { private void addAnchorToSmallFABs(FloatingActionButton floatingActionButton, int anchorID) {
@ -651,9 +649,6 @@ public class NearbyMapFragment extends DaggerFragment {
DirectUpload directUpload = new DirectUpload(this, controller); DirectUpload directUpload = new DirectUpload(this, controller);
storeSharedPrefs(); storeSharedPrefs();
directUpload.initiateGalleryUpload(); directUpload.initiateGalleryUpload();
//TODO: App crashes after image upload completes
//TODO: Handle onRequestPermissionsResult
} }
}); });
} }

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<selector
android:layout_height="match_parent"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true" >
<shape
android:shape="rectangle">
<solid
android:color="@color/deleteButton"/>
<corners
android:radius="3dp" />
<stroke
android:width="5px"
android:color="@color/deleteRed" />
</shape>
</item>
<item
android:state_enabled="false" >
<shape
android:shape="rectangle">
<solid
android:color="@color/deleteButtonDark"/>
<corners
android:radius="3dp" />
</shape>
</item>
</selector>

View file

@ -251,10 +251,38 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/small_gap" /> android:layout_height="@dimen/small_gap" />
<LinearLayout
android:id="@+id/nominatedDeletionBanner"
android:background="@color/deleteRed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/standard_gap"
android:visibility="gone">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/nominated_for_deletion"
android:textColor="@color/primaryTextColor"
android:textSize="@dimen/normal_text"
android:textStyle="bold"/>
<TextView
android:id="@+id/seeMore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/nominated_see_more"
android:paddingTop="@dimen/standard_gap"
android:textColor="@color/primaryTextColor"
android:textSize="@dimen/normal_text"
android:textStyle="bold"/>
</LinearLayout>
<Button <Button
android:id="@+id/nominateDeletion" android:id="@+id/nominateDeletion"
style="?android:attr/buttonBarButtonStyle" android:background="@drawable/bg_delete_button"
android:textColor="@color/deleteTextColor" android:textColor="@color/primaryTextColor"
android:layout_margin="@dimen/standard_gap" android:layout_margin="@dimen/standard_gap"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -15,7 +15,10 @@
<color name="primaryTextColor">#ffffff</color> <color name="primaryTextColor">#ffffff</color>
<color name="secondaryTextColor">#000000</color> <color name="secondaryTextColor">#000000</color>
<color name="deleteTextColor">#d50000</color> <color name="deleteRed">#90960a0a</color>
<color name="deleteButton">#44000000</color>
<color name="deleteButtonDark">#88000000</color>
<color name="deleteButtonLight">#44ffffff</color>
<!-- Some colours are same for dark/light themes. They are written two times in case <!-- Some colours are same for dark/light themes. They are written two times in case
we want to change light ones later. we want to change light ones later.

View file

@ -233,6 +233,8 @@
<string name="no_web_browser">No web browser found to open URL</string> <string name="no_web_browser">No web browser found to open URL</string>
<string name="null_url">Error! URL not found</string> <string name="null_url">Error! URL not found</string>
<string name="nominate_deletion">Nominate for Deletion</string> <string name="nominate_deletion">Nominate for Deletion</string>
<string name="nominated_for_deletion">This image has been nominated for deletion.</string>
<string name="nominated_see_more"><u>See webpage for details</u></string>
<string name="view_browser">View in Browser</string> <string name="view_browser">View in Browser</string>
<string name="nearby_location_has_not_changed">Location has not changed.</string> <string name="nearby_location_has_not_changed">Location has not changed.</string>
@ -250,8 +252,9 @@
<string name="nearby_wikidata">WIKIDATA</string> <string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string> <string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string> <string name="nearby_commons">COMMONS</string>
<string name="about_rate_us"><u>Rate Us</u></string>
<string name="about_faq">Frequently Asked Questions</string> <string name="about_rate_us"><u>Rate us</u></string>
<string name="about_faq">FAQ</string>
<string name="welcome_skip_button">Skip Tutorial</string> <string name="welcome_skip_button">Skip Tutorial</string>
<string name="no_internet">Internet unavailable</string> <string name="no_internet">Internet unavailable</string>
@ -261,7 +264,7 @@
<string name="about_translate"><u>Translate</u></string> <string name="about_translate"><u>Translate</u></string>
<string name="about_translate_title">Languages</string> <string name="about_translate_title">Languages</string>
<string name="about_translate_message">Select the langauge you want translations for ?</string> <string name="about_translate_message">Select the language that you would like to submit translations for</string>
<string name="about_translate_proceed">Proceed</string> <string name="about_translate_proceed">Proceed</string>
<string name="about_translate_cancel">Cancel</string> <string name="about_translate_cancel">Cancel</string>