Merge branch 'master' into featuredImages

This commit is contained in:
Vivek Maskara 2018-04-19 23:44:33 +05:30 committed by GitHub
commit b108dff460
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
276 changed files with 4290 additions and 2539 deletions

View file

@ -1,5 +1,15 @@
# Wikimedia Commons for Android # Wikimedia Commons for Android
## v2.7.0
- New Nearby Places UI with direct uploads (and associated category suggestions)
- Added two-factor authentication login
- Added Notifications activity to display user talk messages
- Added real-time location tracking in Nearby
- Added "rate us", "translate", and FB link in About
- Improvements to UI of navigation drawer, tutorial, media details view, login activity and Settings
- Added option to nominate picture for deletion in media details view
- Too many bug and crash fixes to mention!
## v2.6.7 ## v2.6.7
- Added null checks to prevent frequent crashes in ModificationsSyncAdapter - Added null checks to prevent frequent crashes in ModificationsSyncAdapter

View file

@ -1 +1,19 @@
Please see our guidelines in the wiki: https://github.com/commons-app/apps-android-commons/wiki/Volunteers-welcome%21 Thanks for considering to contribute to this project! A few guidelines for
people who want to contribute their code to this software are documented in
[this project's Wiki](https://github.com/commons-app/apps-android-commons/wiki/Contributing-Guidelines).
If you're not sure where to start head on to [this wiki page](https://github.com/commons-app/apps-android-commons/wiki/Volunteers-welcome!).
Here's a gist of the guidelines,
# Make separate commits for logically separate changes
# Describe your changes well in the commit message
The first line of the commit message should be a short description of what has
changed. It is also good to prefix the first line with "area: " where the "area"
is a filename or identifier for the general area of the code being modified.
The body should provide a meaningful commit message.
# Write tests for your code (if possible)
# Make sure the Wiki pages don't become stale by updating them (if needed)

10
CREDITS
View file

@ -30,6 +30,16 @@ their contribution to the product.
* Bruke Mekuria Mulugeta * Bruke Mekuria Mulugeta
* Paul Hawke * Paul Hawke
* Vishan Seru * Vishan Seru
* Abhishek Poonia
* Ayushi Negi
* Harisanker Pradeep
* Hassan Ismaeel
* Jatin Rao
* Meghna Gupta
* S Balakrishnan
* Suchit Kar
* Tanvi Dadu
* Ujjwal Agrawal
3rd party open source libraries used: 3rd party open source libraries used:
* Butterknife * Butterknife

View file

@ -11,18 +11,19 @@ dependencies {
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar'
implementation 'in.yuvi:http.fluent:1.3' implementation 'in.yuvi:http.fluent:1.3'
implementation 'com.android.volley:volley:1.0.0' implementation 'com.android.volley:volley:1.0.0'
implementation 'ch.acra:acra:4.7.0' implementation 'ch.acra:acra:4.9.2'
implementation 'org.mediawiki:api:1.3' implementation 'org.mediawiki:api:1.3'
implementation 'commons-codec:commons-codec:1.10' implementation 'commons-codec:commons-codec:1.10'
implementation 'com.github.pedrovgs:renderers:3.3.3' implementation 'com.github.pedrovgs:renderers:3.3.3'
implementation 'com.google.code.gson:gson:2.8.1' implementation 'com.google.code.gson:gson:2.8.1'
implementation 'com.jakewharton.timber:timber:4.5.1' implementation 'com.jakewharton.timber:timber:4.5.1'
implementation 'info.debatty:java-string-similarity:0.24' implementation 'info.debatty:java-string-similarity:0.24'
implementation 'com.borjabravo:readmoretextview:2.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.4.1@aar'){ implementation ('com.mapbox.mapboxsdk:mapbox-android-sdk:5.4.1@aar'){
transitive=true transitive=true
} }
implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION" implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION"
implementation "com.android.support:appcompat-v7:$SUPPORT_LIB_VERSION" implementation "com.android.support:appcompat-v7:$SUPPORT_LIB_VERSION"
implementation "com.android.support:design:$SUPPORT_LIB_VERSION" implementation "com.android.support:design:$SUPPORT_LIB_VERSION"
@ -41,8 +42,6 @@ dependencies {
// explicitly depend on RxJava's latest version for bug fixes and new features. // explicitly depend on RxJava's latest version for bug fixes and new features.
implementation 'com.android.support:multidex:1.0.3' implementation 'com.android.support:multidex:1.0.3'
testImplementation "org.robolectric:multidex:3.4.2"
implementation 'io.reactivex.rxjava2:rxjava:2.1.2' implementation 'io.reactivex.rxjava2:rxjava:2.1.2'
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0' implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.0.0' implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.0.0'
@ -54,33 +53,25 @@ dependencies {
implementation "com.google.dagger:dagger:$DAGGER_VERSION" implementation "com.google.dagger:dagger:$DAGGER_VERSION"
implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION" implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION" kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION" kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
testImplementation "org.robolectric:multidex:3.4.2"
testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:3.7.1' testImplementation 'org.robolectric:robolectric:3.7.1'
testImplementation 'org.mockito:mockito-all:1.10.19' testImplementation 'com.nhaarman:mockito-kotlin:1.5.0'
testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1' testImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1' androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1'
androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIB_VERSION" androidTestImplementation "com.android.support:support-annotations:$SUPPORT_LIB_VERSION"
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2-alpha1'
debugImplementation "com.squareup.leakcanary:leakcanary-android:$LEAK_CANARY" debugImplementation "com.squareup.leakcanary:leakcanary-android:$LEAK_CANARY"
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY" releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY" testImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$LEAK_CANARY"
implementation "com.google.dagger:dagger:$DAGGER_VERSION"
implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION"
kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION"
implementation 'com.borjabravo:readmoretextview:2.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
} }
android { android {
@ -91,8 +82,8 @@ android {
defaultConfig { defaultConfig {
applicationId 'fr.free.nrw.commons' applicationId 'fr.free.nrw.commons'
versionCode 82 versionCode 83
versionName '2.6.7' versionName '2.7.0'
setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName())
minSdkVersion project.minSdkVersion minSdkVersion project.minSdkVersion
@ -137,6 +128,7 @@ android {
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"" buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\"" buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\""
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\"" buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\""
buildConfigField "String", "COMMONS_URL", "\"https://commons.wikimedia.org\""
buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.org/wiki/\"" buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.org/wiki/\""
buildConfigField "String", "EVENTLOG_URL", "\"https://www.wikimedia.org/beacon/event\"" buildConfigField "String", "EVENTLOG_URL", "\"https://www.wikimedia.org/beacon/event\""
buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\"" buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\""
@ -152,6 +144,7 @@ android {
buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"" buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\""
buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\"" buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\""
buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\"" buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\""
buildConfigField "String", "COMMONS_URL", "\"https://commons.wikimedia.beta.wmflabs.org\""
buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\"" buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\""
buildConfigField "String", "EVENTLOG_URL", "\"https://commons.wikimedia.beta.wmflabs.org/beacon/event\"" buildConfigField "String", "EVENTLOG_URL", "\"https://commons.wikimedia.beta.wmflabs.org/beacon/event\""
buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\"" buildConfigField "String", "EVENTLOG_WIKI", "\"commonswiki\""

View file

@ -6,11 +6,15 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.UnderlineSpan; import android.text.style.UnderlineSpan;
import android.util.Log; import android.util.Log;
import android.support.customtabs.CustomTabsIntent; import android.support.customtabs.CustomTabsIntent;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.LinearLayout; import android.widget.LinearLayout;
@ -62,6 +66,18 @@ public class AboutActivity extends NavigationBaseActivity {
content.setSpan(new UnderlineSpan(), 0, content.length(), 0); content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
faqText.setText(content); faqText.setText(content);
versionText.setText(BuildConfig.VERSION_NAME); versionText.setText(BuildConfig.VERSION_NAME);
TextView rate_us = findViewById(R.id.about_rate_us);
TextView privacy_policy = findViewById(R.id.about_privacy_policy);
TextView translate = findViewById(R.id.about_translate);
TextView credits = findViewById(R.id.about_credits);
TextView faq = findViewById(R.id.about_faq);
rate_us.setText(Html.fromHtml(getString(R.string.about_rate_us)));
privacy_policy.setText(Html.fromHtml(getString(R.string.about_privacy_policy)));
translate.setText(Html.fromHtml(getString(R.string.about_translate)));
credits.setText(Html.fromHtml(getString(R.string.about_credits)));
faq.setText(Html.fromHtml(getString(R.string.about_faq)));
initDrawer(); initDrawer();
} }
@ -108,6 +124,28 @@ public class AboutActivity extends NavigationBaseActivity {
Utils.handleWebUrl(this,Uri.parse("https://github.com/commons-app/apps-android-commons/wiki/Frequently-Asked-Questions\\")); Utils.handleWebUrl(this,Uri.parse("https://github.com/commons-app/apps-android-commons/wiki/Frequently-Asked-Questions\\"));
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_about, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.share_app_icon:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "http://play.google.com/store/apps/details?id=fr.free.nrw.commons");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share app via..."));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@OnClick(R.id.about_translate) @OnClick(R.id.about_translate)
public void launchTranslate(View view) { public void launchTranslate(View view) {
final ArrayAdapter<String> languageAdapter = new ArrayAdapter<String>(AboutActivity.this, final ArrayAdapter<String> languageAdapter = new ArrayAdapter<String>(AboutActivity.this,

View file

@ -54,9 +54,11 @@ public class CommonsApplication extends MultiDexApplication {
public static final String FEEDBACK_EMAIL = "commons-app-android@googlegroups.com"; public static final String FEEDBACK_EMAIL = "commons-app-android@googlegroups.com";
public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback";
public static final String LOGS_PRIVATE_EMAIL = "commons-app-android-private@googlegroups.com"; public static final String LOGS_PRIVATE_EMAIL = "commons-app-android-private@googlegroups.com";
public static final String FEEDBACK_EMAIL_SUBJECT = "Commons Android App (%s) Feedback"; public static final String LOGS_PRIVATE_EMAIL_SUBJECT = "Commons Android App (%s) Logs";
private RefWatcher refWatcher; private RefWatcher refWatcher;

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

@ -177,7 +177,7 @@ public class Utils {
} }
} }
public static void handleWebUrl(Context context,Uri url){ public static void handleWebUrl(Context context, Uri url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, url); Intent browserIntent = new Intent(Intent.ACTION_VIEW, url);
if (browserIntent.resolveActivity(context.getPackageManager()) == null) { if (browserIntent.resolveActivity(context.getPackageManager()) == null) {
Toast toast = Toast.makeText(context, context.getString(R.string.no_web_browser), LENGTH_SHORT); Toast toast = Toast.makeText(context, context.getString(R.string.no_web_browser), LENGTH_SHORT);

View file

@ -280,8 +280,11 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment {
private Observable<CategoryItem> directCategories() { private Observable<CategoryItem> directCategories() {
String directCategory = directPrefs.getString("Category", ""); String directCategory = directPrefs.getString("Category", "");
// Strip newlines to prevent blank categories, and to tidy existing categories
directCategory = directCategory.replace("\n", "");
List<String> categoryList = new ArrayList<>(); List<String> categoryList = new ArrayList<>();
Timber.d("Direct category found: " + directCategory); Timber.d("Direct category found: " + "'" + directCategory + "'");
if (!directCategory.equals("")) { if (!directCategory.equals("")) {
hasDirectCategories = true; hasDirectCategories = true;

View file

@ -105,6 +105,7 @@ public class CategoryDao {
return items; return items;
} }
@NonNull
Category fromCursor(Cursor cursor) { Category fromCursor(Cursor cursor) {
// Hardcoding column positions! // Hardcoding column positions!
return new Category( return new Category(

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;
@ -71,6 +71,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;
@ -82,6 +85,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 LinearLayout authorLayout; private LinearLayout authorLayout;
private Button delete; private Button delete;
@ -142,6 +147,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);
authorLayout = (LinearLayout) view.findViewById(R.id.authorLinearLayout); authorLayout = (LinearLayout) view.findViewById(R.id.authorLinearLayout);
@ -247,7 +254,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 {
@ -300,21 +306,24 @@ 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) {
enableDeleteButton(true);
delete.setOnClickListener(v -> { delete.setOnClickListener(v -> {
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());
@ -325,6 +334,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment {
String reason = input.getText().toString(); String reason = input.getText().toString();
DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason); DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason);
deleteTask.execute(); deleteTask.execute();
enableDeleteButton(false);
} }
}); });
alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@ -359,6 +369,20 @@ 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 enableDeleteButton(boolean visibility) {
delete.setEnabled(visibility);
if(visibility) {
delete.setTextColor(getResources().getColor(R.color.primaryTextColor));
} else {
delete.setTextColor(getResources().getColor(R.color.deleteButtonLight));
}
} }
private void rebuildCatList() { private void rebuildCatList() {
@ -382,7 +406,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);
@ -450,6 +474,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

@ -23,7 +23,6 @@ import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils; import org.apache.http.util.EntityUtils;
import org.mediawiki.api.ApiResult; import org.mediawiki.api.ApiResult;
import org.mediawiki.api.MWApi; import org.mediawiki.api.MWApi;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import java.io.IOException; import java.io.IOException;
@ -41,16 +40,12 @@ import java.util.concurrent.Callable;
import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.PageTitle; import fr.free.nrw.commons.PageTitle;
import fr.free.nrw.commons.notification.Notification; import fr.free.nrw.commons.notification.Notification;
import fr.free.nrw.commons.notification.NotificationUtils;
import in.yuvi.http.fluent.Http; import in.yuvi.http.fluent.Http;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.Single; import io.reactivex.Single;
import timber.log.Timber; import timber.log.Timber;
import static fr.free.nrw.commons.notification.NotificationType.UNKNOWN;
import static fr.free.nrw.commons.notification.NotificationUtils.getNotificationFromApiResult;
import static fr.free.nrw.commons.notification.NotificationUtils.getNotificationType;
import static fr.free.nrw.commons.notification.NotificationUtils.isCommonsNotification;
/** /**
* @author Addshore * @author Addshore
*/ */
@ -434,33 +429,25 @@ public class ApacheHttpClientMediaWikiApi implements MediaWikiApi {
.param("notprop", "list") .param("notprop", "list")
.param("format", "xml") .param("format", "xml")
.param("meta", "notifications") .param("meta", "notifications")
.param("notfilter", "!read") // .param("meta", "notifications")
.param("notformat", "model")
.get() .get()
.getNode("/api/query/notifications/list"); .getNode("/api/query/notifications/list");
} catch (IOException e) { } catch (IOException e) {
Timber.e("Failed to obtain searchCategories", e); Timber.e("Failed to obtain searchCategories", e);
} }
if (notificationNode == null) { if (notificationNode == null
|| notificationNode.getDocument() == null
|| notificationNode.getDocument().getChildNodes() == null
|| notificationNode.getDocument().getChildNodes().getLength() == 0) {
return new ArrayList<>(); return new ArrayList<>();
} }
List<Notification> notifications = new ArrayList<>();
NodeList childNodes = notificationNode.getDocument().getChildNodes(); NodeList childNodes = notificationNode.getDocument().getChildNodes();
return NotificationUtils.getNotificationsFromList(context, childNodes);
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (isCommonsNotification(node)
&& !getNotificationType(node).equals(UNKNOWN)) {
notifications.add(getNotificationFromApiResult(context, node));
}
}
return notifications;
} }
@Override @Override
public boolean existingFile(String fileSha1) throws IOException { public boolean existingFile(String fileSha1) throws IOException {
return api.action("query") return api.action("query")

View file

@ -8,6 +8,7 @@ import android.support.v7.app.AlertDialog;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import timber.log.Timber;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
@ -23,46 +24,25 @@ class DirectUpload {
this.controller = controller; this.controller = controller;
} }
void initiateCameraUpload() { // These permission requests will be handled by the Fragments.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // Do not use requestCode 1 as it will conflict with NearbyActivity's requestCodes
if (ContextCompat.checkSelfPermission(fragment.getActivity(), WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.getActivity().shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.write_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> {
fragment.getActivity().requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 3);
dialog.dismiss();
})
.setNegativeButton("Cancel", null)
.create()
.show();
} else {
fragment.getActivity().requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 3);
}
} else {
controller.startCameraCapture();
}
} else {
controller.startCameraCapture();
}
}
void initiateGalleryUpload() { void initiateGalleryUpload() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(fragment.getActivity(), READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(fragment.getActivity(), READ_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.getActivity().shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) { if (fragment.shouldShowRequestPermissionRationale(READ_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity()) new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.read_storage_permission_rationale)) .setMessage(fragment.getActivity().getString(R.string.read_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> { .setPositiveButton("OK", (dialog, which) -> {
fragment.getActivity().requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 1); Timber.d("Requesting permissions for read external storage");
fragment.requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, 4);
dialog.dismiss(); dialog.dismiss();
}) })
.setNegativeButton("Cancel", null) .setNegativeButton("Cancel", null)
.create() .create()
.show(); .show();
} else { } else {
fragment.getActivity().requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, fragment.requestPermissions(new String[]{READ_EXTERNAL_STORAGE},
1); 4);
} }
} else { } else {
controller.startGalleryPick(); controller.startGalleryPick();
@ -72,4 +52,28 @@ class DirectUpload {
controller.startGalleryPick(); controller.startGalleryPick();
} }
} }
void initiateCameraUpload() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(fragment.getActivity(), WRITE_EXTERNAL_STORAGE) != PERMISSION_GRANTED) {
if (fragment.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(fragment.getActivity())
.setMessage(fragment.getActivity().getString(R.string.write_storage_permission_rationale))
.setPositiveButton("OK", (dialog, which) -> {
fragment.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 5);
dialog.dismiss();
})
.setNegativeButton("Cancel", null)
.create()
.show();
} else {
fragment.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE}, 5);
}
} else {
controller.startCameraCapture();
}
} else {
controller.startCameraCapture();
}
}
} }

View file

@ -1,13 +1,15 @@
package fr.free.nrw.commons.nearby; package fr.free.nrw.commons.nearby;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.BottomSheetBehavior;
import android.support.v4.app.FragmentTransaction; import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.Menu; import android.view.Menu;
@ -16,7 +18,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -27,20 +28,18 @@ import javax.inject.Inject;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LatLng;
import fr.free.nrw.commons.location.LocationServiceManager; import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.location.LocationUpdateListener; import fr.free.nrw.commons.location.LocationUpdateListener;
import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.UriSerializer; import fr.free.nrw.commons.utils.UriSerializer;
import fr.free.nrw.commons.utils.ViewUtil; import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
@ -63,17 +62,20 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Inject @Inject
NearbyController nearbyController; NearbyController nearbyController;
private LatLng curLatLang; private LatLng curLatLng;
private Bundle bundle; private Bundle bundle;
private Disposable placesDisposable; private Disposable placesDisposable;
private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed
private BottomSheetBehavior bottomSheetBehavior; // Behavior for list bottom sheet private BottomSheetBehavior bottomSheetBehavior; // Behavior for list bottom sheet
private BottomSheetBehavior bottomSheetBehaviorForDetails; // Behavior for details bottom sheet private BottomSheetBehavior bottomSheetBehaviorForDetails; // Behavior for details bottom sheet
private NearbyMapFragment nearbyMapFragment; public NearbyMapFragment nearbyMapFragment;
private NearbyListFragment nearbyListFragment; private NearbyListFragment nearbyListFragment;
private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName(); private static final String TAG_RETAINED_MAP_FRAGMENT = NearbyMapFragment.class.getSimpleName();
private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName(); private static final String TAG_RETAINED_LIST_FRAGMENT = NearbyListFragment.class.getSimpleName();
private final String NETWORK_INTENT_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
private BroadcastReceiver broadcastReceiver;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -128,11 +130,17 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection // Handle item selection
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_display_list: case R.id.action_display_list:
bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN); if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_COLLAPSED || bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_HIDDEN){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}else if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED){
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
return true; return true;
default: default:
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -157,6 +165,11 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
showLocationPermissionDeniedErrorDialog(); showLocationPermissionDeniedErrorDialog();
} }
} }
break;
default:
// This is needed to allow the request codes from the Fragments to be routed appropriately
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
} }
} }
@ -254,8 +267,6 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); super.onStop();
locationManager.removeLocationListener(this);
locationManager.unregisterLocationManager();
} }
@Override @Override
@ -271,6 +282,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
super.onResume(); super.onResume();
lockNearbyView = false; lockNearbyView = false;
checkGps(); checkGps();
addNetworkBroadcastReceiver();
} }
@Override @Override
@ -283,9 +295,33 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
// to the retained fragment object to perform its own cleanup. // to the retained fragment object to perform its own cleanup.
removeMapFragment(); removeMapFragment();
removeListFragment(); removeListFragment();
} }
unregisterReceiver(broadcastReceiver);
broadcastReceiver = null;
locationManager.removeLocationListener(this);
locationManager.unregisterLocationManager();
} }
private void addNetworkBroadcastReceiver() {
IntentFilter intentFilter = new IntentFilter(NETWORK_INTENT_ACTION);
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (NetworkUtils.isInternetConnectionEstablished(NearbyActivity.this)) {
refreshView(LocationServiceManager
.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED);
} else {
ViewUtil.showLongToast(NearbyActivity.this, getString(R.string.no_internet));
}
}
};
this.registerReceiver(broadcastReceiver, intentFilter);
}
/** /**
@ -297,15 +333,21 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (lockNearbyView) { if (lockNearbyView) {
return; return;
} }
if (!NetworkUtils.isInternetConnectionEstablished(this)) {
hideProgressBar();
return;
}
locationManager.registerLocationManager(); locationManager.registerLocationManager();
LatLng lastLocation = locationManager.getLastLocation(); LatLng lastLocation = locationManager.getLastLocation();
if (curLatLang != null && curLatLang.equals(lastLocation)) { //refresh view only if location has changed if (curLatLng != null && curLatLng.equals(lastLocation)) { //refresh view only if location has changed
return; return;
} }
curLatLang = lastLocation; curLatLng = lastLocation;
if (curLatLang == null) { if (curLatLng == null) {
Timber.d("Skipping update of nearby places as location is unavailable"); Timber.d("Skipping update of nearby places as location is unavailable");
return; return;
} }
@ -314,7 +356,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) { .equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) {
progressBar.setVisibility(View.VISIBLE); progressBar.setVisibility(View.VISIBLE);
placesDisposable = Observable.fromCallable(() -> nearbyController placesDisposable = Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLang)) .loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces); .subscribe(this::populatePlaces);
@ -323,7 +365,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriSerializer()) .registerTypeAdapter(Uri.class, new UriSerializer())
.create(); .create();
String gsonCurLatLng = gson.toJson(curLatLang); String gsonCurLatLng = gson.toJson(curLatLng);
bundle.putString("CurLatLng", gsonCurLatLng); bundle.putString("CurLatLng", gsonCurLatLng);
updateMapFragment(true); updateMapFragment(true);
} }
@ -336,7 +378,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
.registerTypeAdapter(Uri.class, new UriSerializer()) .registerTypeAdapter(Uri.class, new UriSerializer())
.create(); .create();
String gsonPlaceList = gson.toJson(placeList); String gsonPlaceList = gson.toJson(placeList);
String gsonCurLatLng = gson.toJson(curLatLang); String gsonCurLatLng = gson.toJson(curLatLng);
String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates); String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates);
if (placeList.size() == 0) { if (placeList.size() == 0) {
@ -388,6 +430,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (nearbyMapFragment != null) { if (nearbyMapFragment != null) {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager(); android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().remove(nearbyMapFragment).commit(); fm.beginTransaction().remove(nearbyMapFragment).commit();
nearbyMapFragment = null;
} }
} }
@ -399,6 +442,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
if (nearbyListFragment != null) { if (nearbyListFragment != null) {
android.support.v4.app.FragmentManager fm = getSupportFragmentManager(); android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().remove(nearbyListFragment).commit(); fm.beginTransaction().remove(nearbyListFragment).commit();
nearbyListFragment = null;
} }
} }
@ -413,34 +457,34 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
NearbyMapFragment nearbyMapFragment = getMapFragment(); NearbyMapFragment nearbyMapFragment = getMapFragment();
if (nearbyMapFragment != null && curLatLang != null) { if (nearbyMapFragment != null && curLatLng != null) {
hideProgressBar(); // In case it is visible (this happens, not an impossible case) hideProgressBar(); // In case it is visible (this happens, not an impossible case)
/* /*
* If we are close to nearby places boundaries, we need a significant update to * If we are close to nearby places boundaries, we need a significant update to
* get new nearby places. Check order is south, north, west, east * get new nearby places. Check order is south, north, west, east
* */ * */
if (nearbyMapFragment.boundaryCoordinates != null if (nearbyMapFragment.boundaryCoordinates != null
&& (curLatLang.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude() && (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude()
|| curLatLang.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude() || curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude()
|| curLatLang.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude() || curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude()
|| curLatLang.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) { || curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) {
// populate places // populate places
placesDisposable = Observable.fromCallable(() -> nearbyController placesDisposable = Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLang)) .loadAttractionsFromLocation(curLatLng))
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(this::populatePlaces); .subscribe(this::populatePlaces);
nearbyMapFragment.setArguments(bundle); nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSignificantly(); nearbyMapFragment.updateMapSignificantly();
updateListFragment(); updateListFragment();
return; return;
} }
if (isSlightUpdate) { if (isSlightUpdate) {
nearbyMapFragment.setArguments(bundle); nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSlightly(); nearbyMapFragment.updateMapSlightly();
} else { } else {
nearbyMapFragment.setArguments(bundle); nearbyMapFragment.setBundleForUpdtes(bundle);
nearbyMapFragment.updateMapSignificantly(); nearbyMapFragment.updateMapSignificantly();
updateListFragment(); updateListFragment();
} }
@ -454,7 +498,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp
} }
private void updateListFragment() { private void updateListFragment() {
nearbyListFragment.setArguments(bundle); nearbyListFragment.setBundleForUpdates(bundle);
nearbyListFragment.updateNearbyListSignificantly(); nearbyListFragment.updateNearbyListSignificantly();
} }

View file

@ -54,41 +54,47 @@ public class NearbyController {
} }
List<Place> places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage()); List<Place> places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage());
LatLng[] boundaryCoordinates = {places.get(0).location, // south if (places.size() > 0) {
places.get(0).location, // north LatLng[] boundaryCoordinates = {places.get(0).location, // south
places.get(0).location, // west places.get(0).location, // north
places.get(0).location};// east, init with a random location places.get(0).location, // west
places.get(0).location};// east, init with a random location
if (curLatLng != null) {
Timber.d("Sorting places by distance..."); if (curLatLng != null) {
final Map<Place, Double> distances = new HashMap<>(); Timber.d("Sorting places by distance...");
for (Place place: places) { final Map<Place, Double> distances = new HashMap<>();
distances.put(place, computeDistanceBetween(place.location, curLatLng)); for (Place place : places) {
// Find boundaries with basic find max approach distances.put(place, computeDistanceBetween(place.location, curLatLng));
if (place.location.getLatitude() < boundaryCoordinates[0].getLatitude()) { // Find boundaries with basic find max approach
boundaryCoordinates[0] = place.location; if (place.location.getLatitude() < boundaryCoordinates[0].getLatitude()) {
} boundaryCoordinates[0] = place.location;
if (place.location.getLatitude() > boundaryCoordinates[1].getLatitude()) {
boundaryCoordinates[1] = place.location;
}
if (place.location.getLongitude() < boundaryCoordinates[2].getLongitude()) {
boundaryCoordinates[2] = place.location;
}
if (place.location.getLongitude() > boundaryCoordinates[3].getLongitude()) {
boundaryCoordinates[3] = place.location;
}
}
Collections.sort(places,
(lhs, rhs) -> {
double lhsDistance = distances.get(lhs);
double rhsDistance = distances.get(rhs);
return (int) (lhsDistance - rhsDistance);
} }
); if (place.location.getLatitude() > boundaryCoordinates[1].getLatitude()) {
boundaryCoordinates[1] = place.location;
}
if (place.location.getLongitude() < boundaryCoordinates[2].getLongitude()) {
boundaryCoordinates[2] = place.location;
}
if (place.location.getLongitude() > boundaryCoordinates[3].getLongitude()) {
boundaryCoordinates[3] = place.location;
}
}
Collections.sort(places,
(lhs, rhs) -> {
double lhsDistance = distances.get(lhs);
double rhsDistance = distances.get(rhs);
return (int) (lhsDistance - rhsDistance);
}
);
}
nearbyPlacesInfo.placeList = places;
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
return nearbyPlacesInfo;
}
else {
return null;
} }
nearbyPlacesInfo.placeList = places;
nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates;
return nearbyPlacesInfo;
} }
/** /**

View file

@ -33,6 +33,8 @@ import static android.app.Activity.RESULT_OK;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class NearbyListFragment extends DaggerFragment { public class NearbyListFragment extends DaggerFragment {
private Bundle bundleForUpdates; // Carry information from activity about changed nearby places and current location
private static final Type LIST_TYPE = new TypeToken<List<Place>>() { private static final Type LIST_TYPE = new TypeToken<List<Place>>() {
}.getType(); }.getType();
private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() { private static final Type CUR_LAT_LNG_TYPE = new TypeToken<LatLng>() {
@ -80,8 +82,7 @@ public class NearbyListFragment extends DaggerFragment {
} }
public void updateNearbyListSignificantly() { public void updateNearbyListSignificantly() {
Bundle bundle = this.getArguments(); adapterFactory.updateAdapterData(getPlaceListFromBundle(bundleForUpdates),
adapterFactory.updateAdapterData(getPlaceListFromBundle(bundle),
(RVRendererAdapter<Place>) recyclerView.getAdapter()); (RVRendererAdapter<Place>) recyclerView.getAdapter());
} }
@ -106,8 +107,8 @@ public class NearbyListFragment extends DaggerFragment {
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults); Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
switch (requestCode) { switch (requestCode) {
// 1 = "Read external storage" allowed when gallery selected // 4 = "Read external storage" allowed when gallery selected
case 1: { case 4: {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Timber.d("Call controller.startGalleryPick()"); Timber.d("Call controller.startGalleryPick()");
controller.startGalleryPick(); controller.startGalleryPick();
@ -115,8 +116,8 @@ public class NearbyListFragment extends DaggerFragment {
} }
break; break;
// 3 = "Write external storage" allowed when camera selected // 5 = "Write external storage" allowed when camera selected
case 3: { case 5: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Timber.d("Call controller.startCameraCapture()"); Timber.d("Call controller.startCameraCapture()");
controller.startCameraCapture(); controller.startCameraCapture();
@ -140,4 +141,8 @@ public class NearbyListFragment extends DaggerFragment {
} }
} }
public void setBundleForUpdates(Bundle bundleForUpdates) {
this.bundleForUpdates = bundleForUpdates;
}
} }

View file

@ -53,8 +53,10 @@ import javax.inject.Named;
import dagger.android.support.DaggerFragment; import dagger.android.support.DaggerFragment;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.utils.UriDeserializer; import fr.free.nrw.commons.utils.UriDeserializer;
import fr.free.nrw.commons.utils.ViewUtil;
import timber.log.Timber; import timber.log.Timber;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@ -97,6 +99,7 @@ public class NearbyMapFragment extends DaggerFragment {
private Animation fab_open; private Animation fab_open;
private Animation rotate_forward; private Animation rotate_forward;
private ContributionController controller; private ContributionController controller;
private DirectUpload directUpload;
private Place place; private Place place;
private Marker selected; private Marker selected;
@ -105,7 +108,10 @@ public class NearbyMapFragment extends DaggerFragment {
private PolygonOptions currentLocationPolygonOptions; private PolygonOptions currentLocationPolygonOptions;
private boolean isBottomListSheetExpanded; private boolean isBottomListSheetExpanded;
private final double CAMERA_TARGET_SHIFT_FACTOR = 0.06; private final double CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT = 0.06;
private final double CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE = 0.04;
private Bundle bundleForUpdtes;// Carry information from activity about changed nearby places and current location
@Inject @Inject
@Named("prefs") @Named("prefs")
@ -120,6 +126,10 @@ public class NearbyMapFragment extends DaggerFragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
controller = new ContributionController(this);
directUpload = new DirectUpload(this, controller);
Bundle bundle = this.getArguments(); Bundle bundle = this.getArguments();
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer()) .registerTypeAdapter(Uri.class, new UriDeserializer())
@ -184,14 +194,12 @@ public class NearbyMapFragment extends DaggerFragment {
} }
public void updateMapSlightly() { public void updateMapSlightly() {
// Get arguments from bundle for new location
Bundle bundle = this.getArguments();
if (mapboxMap != null) { if (mapboxMap != null) {
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer()) .registerTypeAdapter(Uri.class, new UriDeserializer())
.create(); .create();
if (bundle != null) { if (bundleForUpdtes != null) {
String gsonLatLng = bundle.getString("CurLatLng"); String gsonLatLng = bundleForUpdtes.getString("CurLatLng");
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType(); Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
curLatLng = gson.fromJson(gsonLatLng, curLatLngType); curLatLng = gson.fromJson(gsonLatLng, curLatLngType);
} }
@ -201,17 +209,15 @@ public class NearbyMapFragment extends DaggerFragment {
} }
public void updateMapSignificantly() { public void updateMapSignificantly() {
Bundle bundle = this.getArguments();
if (mapboxMap != null) { if (mapboxMap != null) {
if (bundle != null) { if (bundleForUpdtes != null) {
Gson gson = new GsonBuilder() Gson gson = new GsonBuilder()
.registerTypeAdapter(Uri.class, new UriDeserializer()) .registerTypeAdapter(Uri.class, new UriDeserializer())
.create(); .create();
String gsonPlaceList = bundle.getString("PlaceList"); String gsonPlaceList = bundleForUpdtes.getString("PlaceList");
String gsonLatLng = bundle.getString("CurLatLng"); String gsonLatLng = bundleForUpdtes.getString("CurLatLng");
String gsonBoundaryCoordinates = bundle.getString("BoundaryCoord"); String gsonBoundaryCoordinates = bundleForUpdtes.getString("BoundaryCoord");
Type listType = new TypeToken<List<Place>>() {}.getType(); Type listType = new TypeToken<List<Place>>() {}.getType();
List<Place> placeList = gson.fromJson(gsonPlaceList, listType); List<Place> placeList = gson.fromJson(gsonPlaceList, listType);
Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType(); Type curLatLngType = new TypeToken<fr.free.nrw.commons.location.LatLng>() {}.getType();
@ -253,13 +259,28 @@ public class NearbyMapFragment extends DaggerFragment {
} }
// Make camera to follow user on location change // Make camera to follow user on location change
CameraPosition position = new CameraPosition.Builder() CameraPosition position ;
.target(isBottomListSheetExpanded ? if(ViewUtil.isPortrait(getActivity())){
new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR, position = new CameraPosition.Builder()
curMapBoxLatLng.getLongitude()) .target(isBottomListSheetExpanded ?
: curMapBoxLatLng ) // Sets the new camera position new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
.zoom(mapboxMap.getCameraPosition().zoom) // Same zoom level curMapBoxLatLng.getLongitude())
.build(); : curMapBoxLatLng ) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}else {
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curMapBoxLatLng.getLongitude())
: curMapBoxLatLng ) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}
mapboxMap.animateCamera(CameraUpdateFactory mapboxMap.animateCamera(CameraUpdateFactory
.newCameraPosition(position), 1000); .newCameraPosition(position), 1000);
@ -273,12 +294,21 @@ public class NearbyMapFragment extends DaggerFragment {
if (mapboxMap != null && curLatLng != null) { if (mapboxMap != null && curLatLng != null) {
if (isBottomListSheetExpanded) { if (isBottomListSheetExpanded) {
// Make camera to follow user on location change // Make camera to follow user on location change
position = new CameraPosition.Builder() if(ViewUtil.isPortrait(getActivity())) {
.target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR, position = new CameraPosition.Builder()
curLatLng.getLongitude())) // Sets the new camera target above .target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
// current to make it visible when sheet is expanded curLatLng.getLongitude())) // Sets the new camera target above
.zoom(11) // Same zoom level // current to make it visible when sheet is expanded
.build(); .zoom(11) // Fixed zoom level
.build();
} else {
position = new CameraPosition.Builder()
.target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curLatLng.getLongitude())) // Sets the new camera target above
// current to make it visible when sheet is expanded
.zoom(11) // Fixed zoom level
.build();
}
} else { } else {
// Make camera to follow user on location change // Make camera to follow user on location change
@ -344,10 +374,29 @@ public class NearbyMapFragment extends DaggerFragment {
fabRecenter.setOnClickListener(view -> { fabRecenter.setOnClickListener(view -> {
if (curLatLng != null) { if (curLatLng != null) {
mapView.getMapAsync(mapboxMap -> { mapView.getMapAsync(mapboxMap -> {
CameraPosition position = new CameraPosition.Builder() CameraPosition position;
.target(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude())) // Sets the new camera position
.zoom(11) // Sets the zoom if(ViewUtil.isPortrait(getActivity())){
.build(); // Creates a CameraPosition from the builder position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT,
curLatLng.getLongitude())
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}else {
position = new CameraPosition.Builder()
.target(isBottomListSheetExpanded ?
new LatLng(curLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_LANDSCAPE,
curLatLng.getLongitude())
: new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude(), 0)) // Sets the new camera position
.zoom(isBottomListSheetExpanded ?
11 // zoom level is fixed to 11 when bottom sheet is expanded
:mapboxMap.getCameraPosition().zoom) // Same zoom level
.build();
}
mapboxMap.animateCamera(CameraUpdateFactory mapboxMap.animateCamera(CameraUpdateFactory
.newCameraPosition(position), 1000); .newCameraPosition(position), 1000);
@ -394,11 +443,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);
@ -408,6 +455,8 @@ public class NearbyMapFragment extends DaggerFragment {
private void setupMapView(Bundle savedInstanceState) { private void setupMapView(Bundle savedInstanceState) {
MapboxMapOptions options = new MapboxMapOptions() MapboxMapOptions options = new MapboxMapOptions()
.compassGravity(Gravity.BOTTOM | Gravity.LEFT)
.compassMargins(new int[]{12, 0, 0, 24})
.styleUrl(Style.OUTDOORS) .styleUrl(Style.OUTDOORS)
.logoEnabled(false) .logoEnabled(false)
.attributionEnabled(false) .attributionEnabled(false)
@ -536,7 +585,9 @@ public class NearbyMapFragment extends DaggerFragment {
transparentView.setAlpha(0); transparentView.setAlpha(0);
closeFabs(isFabOpen); closeFabs(isFabOpen);
hideFAB(); hideFAB();
this.getView().requestFocus(); if (this.getView() != null) {
this.getView().requestFocus();
}
break; break;
} }
} }
@ -583,7 +634,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 +645,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) {
@ -615,7 +666,7 @@ public class NearbyMapFragment extends DaggerFragment {
directionsButton.setOnClickListener(view -> { directionsButton.setOnClickListener(view -> {
//Open map app at given position //Open map app at given position
Intent mapIntent = new Intent(Intent.ACTION_VIEW, place.location.getGmmIntentUri()); Intent mapIntent = new Intent(Intent.ACTION_VIEW, this.place.location.getGmmIntentUri());
if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) { if (mapIntent.resolveActivity(getActivity().getPackageManager()) != null) {
startActivity(mapIntent); startActivity(mapIntent);
} }
@ -635,9 +686,6 @@ public class NearbyMapFragment extends DaggerFragment {
fabCamera.setOnClickListener(view -> { fabCamera.setOnClickListener(view -> {
if (fabCamera.isShown()) { if (fabCamera.isShown()) {
Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
controller = new ContributionController(this);
DirectUpload directUpload = new DirectUpload(this, controller);
storeSharedPrefs(); storeSharedPrefs();
directUpload.initiateCameraUpload(); directUpload.initiateCameraUpload();
} }
@ -646,14 +694,8 @@ public class NearbyMapFragment extends DaggerFragment {
fabGallery.setOnClickListener(view -> { fabGallery.setOnClickListener(view -> {
if (fabGallery.isShown()) { if (fabGallery.isShown()) {
Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription());
controller = new ContributionController(this);
DirectUpload directUpload = new DirectUpload(this, controller);
storeSharedPrefs(); storeSharedPrefs();
directUpload.initiateGalleryUpload(); directUpload.initiateGalleryUpload();
//TODO: App crashes after image upload completes
//TODO: Handle onRequestPermissionsResult
} }
}); });
} }
@ -670,9 +712,10 @@ public class NearbyMapFragment extends DaggerFragment {
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults); Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults);
// Do not use requestCode 1 as it will conflict with NearbyActivity's requestCodes
switch (requestCode) { switch (requestCode) {
// 1 = "Read external storage" allowed when gallery selected // 4 = "Read external storage" allowed when gallery selected
case 1: { case 4: {
if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) {
Timber.d("Call controller.startGalleryPick()"); Timber.d("Call controller.startGalleryPick()");
controller.startGalleryPick(); controller.startGalleryPick();
@ -680,8 +723,8 @@ public class NearbyMapFragment extends DaggerFragment {
} }
break; break;
// 3 = "Write external storage" allowed when camera selected // 5 = "Write external storage" allowed when camera selected
case 3: { case 5: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Timber.d("Call controller.startCameraCapture()"); Timber.d("Call controller.startCameraCapture()");
controller.startCameraCapture(); controller.startCameraCapture();
@ -705,8 +748,7 @@ public class NearbyMapFragment extends DaggerFragment {
} }
private void openWebView(Uri link) { private void openWebView(Uri link) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, link); Utils.handleWebUrl(getContext(), link);
startActivity(browserIntent);
} }
private void animateFAB(boolean isFabOpen) { private void animateFAB(boolean isFabOpen) {
@ -729,7 +771,7 @@ public class NearbyMapFragment extends DaggerFragment {
} }
} }
private void closeFabs ( boolean isFabOpen){ private void closeFabs ( boolean isFabOpen){
if (isFabOpen) { if (isFabOpen) {
fabPlus.startAnimation(rotate_backward); fabPlus.startAnimation(rotate_backward);
fabCamera.startAnimation(fab_close); fabCamera.startAnimation(fab_close);
@ -740,6 +782,11 @@ public class NearbyMapFragment extends DaggerFragment {
} }
} }
public void setBundleForUpdtes(Bundle bundleForUpdtes) {
this.bundleForUpdtes = bundleForUpdtes;
}
@Override @Override
public void onStart() { public void onStart() {
if (mapView != null) { if (mapView != null) {
@ -781,6 +828,9 @@ public class NearbyMapFragment extends DaggerFragment {
if (mapView != null) { if (mapView != null) {
mapView.onDestroy(); mapView.onDestroy();
} }
selected = null;
currentLocationMarker = null;
super.onDestroyView(); super.onDestroyView();
} }

View file

@ -27,6 +27,7 @@ import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.contributions.ContributionController;
import fr.free.nrw.commons.di.ApplicationlessInjection; import fr.free.nrw.commons.di.ApplicationlessInjection;
import timber.log.Timber; import timber.log.Timber;
@ -200,8 +201,7 @@ public class PlaceRenderer extends Renderer<Place> {
} }
private void openWebView(Uri link) { private void openWebView(Uri link) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, link); Utils.handleWebUrl(getContext(), link);
view.getContext().startActivity(browserIntent);
} }
private boolean showMenu() { private boolean showMenu() {

View file

@ -10,12 +10,14 @@ public class Notification {
public String date; public String date;
public String description; public String description;
public String link; public String link;
public String iconUrl;
public Notification(NotificationType notificationType, String notificationText, String date, String description, String link) { public Notification(NotificationType notificationType, String notificationText, String date, String description, String link, String iconUrl) {
this.notificationType = notificationType; this.notificationType = notificationType;
this.notificationText = notificationText; this.notificationText = notificationText;
this.date = date; this.date = date;
this.description = description; this.description = description;
this.link = link; this.link = link;
this.iconUrl = iconUrl;
} }
} }

View file

@ -6,13 +6,18 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.widget.Toast; import android.view.View;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import com.pedrogomez.renderers.RVRendererAdapter; import com.pedrogomez.renderers.RVRendererAdapter;
import java.lang.ref.WeakReference;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -20,14 +25,15 @@ import javax.inject.Inject;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import fr.free.nrw.commons.Utils;
import fr.free.nrw.commons.theme.NavigationBaseActivity; import fr.free.nrw.commons.theme.NavigationBaseActivity;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import timber.log.Timber; import timber.log.Timber;
import static android.widget.Toast.LENGTH_SHORT;
/** /**
* Created by root on 18.12.2017. * Created by root on 18.12.2017.
*/ */
@ -36,6 +42,8 @@ public class NotificationActivity extends NavigationBaseActivity {
NotificationAdapterFactory notificationAdapterFactory; NotificationAdapterFactory notificationAdapterFactory;
@BindView(R.id.listView) RecyclerView recyclerView; @BindView(R.id.listView) RecyclerView recyclerView;
@BindView(R.id.progressBar) ProgressBar progressBar;
@BindView(R.id.container) RelativeLayout relativeLayout;
@Inject NotificationController controller; @Inject NotificationController controller;
@ -57,22 +65,44 @@ public class NotificationActivity extends NavigationBaseActivity {
recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setLayoutManager(new LinearLayoutManager(this));
DividerItemDecoration itemDecor = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); DividerItemDecoration itemDecor = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(itemDecor); recyclerView.addItemDecoration(itemDecor);
addNotifications(); refresh();
} }
private void refresh() {
if (!NetworkUtils.isInternetConnectionEstablished(this)) {
progressBar.setVisibility(View.GONE);
Snackbar.make(relativeLayout , R.string.no_internet, Snackbar.LENGTH_INDEFINITE)
.setAction(R.string.retry, view -> {
refresh();
}).show();
}else {
progressBar.setVisibility(View.VISIBLE);
addNotifications();
}
}
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
private void addNotifications() { private void addNotifications() {
Timber.d("Add notifications"); Timber.d("Add notifications");
if(mNotificationWorkerFragment == null){ if(mNotificationWorkerFragment == null){
Observable.fromCallable(() -> controller.getNotifications()) Observable.fromCallable(() -> {
progressBar.setVisibility(View.VISIBLE);
return controller.getNotifications();
})
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(notificationList -> { .subscribe(notificationList -> {
Collections.reverse(notificationList);
Timber.d("Number of notifications is %d", notificationList.size()); Timber.d("Number of notifications is %d", notificationList.size());
initializeAndSetNotificationList(notificationList);
setAdapter(notificationList); setAdapter(notificationList);
}, throwable -> Timber.e(throwable, "Error occurred while loading notifications")); progressBar.setVisibility(View.GONE);
}, throwable -> {
Timber.e(throwable, "Error occurred while loading notifications");
ViewUtil.showSnackbar(relativeLayout, R.string.error_notifications);
progressBar.setVisibility(View.GONE);
});
} else { } else {
setAdapter(mNotificationWorkerFragment.getNotificationList()); setAdapter(mNotificationWorkerFragment.getNotificationList());
} }
@ -82,17 +112,14 @@ public class NotificationActivity extends NavigationBaseActivity {
if (url == null || url.equals("")) { if (url == null || url.equals("")) {
return; return;
} }
Intent browser = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); Utils.handleWebUrl(this, Uri.parse(url));
//check if web browser available
if(browser.resolveActivity(this.getPackageManager()) != null){
startActivity(browser);
} else {
Toast toast = Toast.makeText(this, getString(R.string.no_web_browser), LENGTH_SHORT);
toast.show();
}
} }
private void setAdapter(List<Notification> notificationList) { private void setAdapter(List<Notification> notificationList) {
if(notificationList == null || notificationList.isEmpty()) {
ViewUtil.showSnackbar(relativeLayout, R.string.no_notifications);
return;
}
notificationAdapterFactory = new NotificationAdapterFactory(notification -> { notificationAdapterFactory = new NotificationAdapterFactory(notification -> {
Timber.d("Notification clicked %s", notification.link); Timber.d("Notification clicked %s", notification.link);
handleUrl(notification.link); handleUrl(notification.link);

View file

@ -20,7 +20,6 @@ import fr.free.nrw.commons.R;
public class NotificationRenderer extends Renderer<Notification> { public class NotificationRenderer extends Renderer<Notification> {
@BindView(R.id.title) ReadMoreTextView title; @BindView(R.id.title) ReadMoreTextView title;
@BindView(R.id.description) ReadMoreTextView description;
@BindView(R.id.time) TextView time; @BindView(R.id.time) TextView time;
@BindView(R.id.icon) ImageView icon; @BindView(R.id.icon) ImageView icon;
private NotificationClicked listener; private NotificationClicked listener;
@ -48,13 +47,10 @@ public class NotificationRenderer extends Renderer<Notification> {
@Override @Override
public void render() { public void render() {
Notification notification = getContent(); Notification notification = getContent();
StringBuilder str = new StringBuilder(notification.notificationText); String str = notification.notificationText.trim();
str.append(" " ); str = str.concat(" ");
title.setText(str); title.setText(str);
time.setText(notification.date); time.setText(notification.date);
StringBuilder desc = new StringBuilder(notification.description);
desc.append(" ");
description.setText(desc);
switch (notification.notificationType) { switch (notification.notificationType) {
case THANK_YOU_EDIT: case THANK_YOU_EDIT:
icon.setImageResource(R.drawable.ic_edit_black_24dp); icon.setImageResource(R.drawable.ic_edit_black_24dp);

View file

@ -1,16 +1,24 @@
package fr.free.nrw.commons.notification; package fr.free.nrw.commons.notification;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import fr.free.nrw.commons.BuildConfig; import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.R; import fr.free.nrw.commons.R;
import static fr.free.nrw.commons.notification.NotificationType.THANK_YOU_EDIT;
import static fr.free.nrw.commons.notification.NotificationType.UNKNOWN;
public class NotificationUtils { public class NotificationUtils {
private static final String COMMONS_WIKI = "commonswiki"; private static final String COMMONS_WIKI = "commonswiki";
@ -29,27 +37,124 @@ public class NotificationUtils {
return NotificationType.handledValueOf(type); return NotificationType.handledValueOf(type);
} }
public static List<Notification> getNotificationsFromBundle(Context context, Node document) {
Element bundledNotifications = getBundledNotifications(document);
NodeList childNodes = bundledNotifications.getChildNodes();
List<Notification> notifications = new ArrayList<>();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (isUsefulNotification(node)) {
notifications.add(getNotificationFromApiResult(context, node));
}
}
return notifications;
}
@NonNull
public static List<Notification> getNotificationsFromList(Context context, NodeList childNodes) {
List<Notification> notifications = new ArrayList<>();
for (int i = 0; i < childNodes.getLength(); i++) {
Node node = childNodes.item(i);
if (isUsefulNotification(node)) {
if (isBundledNotification(node)) {
notifications.addAll(getNotificationsFromBundle(context, node));
} else {
notifications.add(getNotificationFromApiResult(context, node));
}
}
}
return notifications;
}
private static boolean isUsefulNotification(Node node) {
return isCommonsNotification(node)
&& !getNotificationType(node).equals(UNKNOWN)
&& !getNotificationType(node).equals(THANK_YOU_EDIT);
}
public static boolean isBundledNotification(Node document) {
Element bundleElement = getBundledNotifications(document);
if (bundleElement == null) {
return false;
}
return bundleElement.getChildNodes().getLength() > 0;
}
private static Element getBundledNotifications(Node document) {
return (Element) getNode(document, "bundledNotifications");
}
public static Notification getNotificationFromApiResult(Context context, Node document) { public static Notification getNotificationFromApiResult(Context context, Node document) {
NotificationType type = getNotificationType(document); NotificationType type = getNotificationType(document);
String notificationText = ""; String notificationText = "";
String link = getNotificationLink(document); String link = getPrimaryLink(document);
String description = getNotificationDescription(document); String description = getNotificationDescription(document);
String iconUrl = getNotificationIconUrl(document);
switch (type) { switch (type) {
case THANK_YOU_EDIT: case THANK_YOU_EDIT:
notificationText = context.getString(R.string.notifications_thank_you_edit); notificationText = context.getString(R.string.notifications_thank_you_edit);
break; break;
case EDIT_USER_TALK: case EDIT_USER_TALK:
notificationText = getUserTalkMessage(context, document); notificationText = getNotificationText(document);
break; break;
case MENTION: case MENTION:
notificationText = getMentionMessage(context, document); notificationText = getMentionMessage(context, document);
description = getMentionDescription(document);
break; break;
case WELCOME: case WELCOME:
notificationText = getWelcomeMessage(context, document); notificationText = getWelcomeMessage(context, document);
break; break;
} }
return new Notification(type, notificationText, getTimestamp(document), description, link); return new Notification(type, notificationText, getTimestamp(document), description, link, iconUrl);
}
private static String getNotificationText(Node document) {
String notificationBody = getNotificationBody(document);
if (notificationBody == null || notificationBody.trim().equals("")) {
return getNotificationHeader(document);
}
return notificationBody;
}
private static String getNotificationHeader(Node document) {
Node body = getNode(getModel(document), "header");
if (body != null) {
String textContent = body.getTextContent();
return textContent.replace("<strong>", "").replace("</strong>", "");
} else {
return "";
}
}
private static String getNotificationBody(Node document) {
Node body = getNode(getModel(document), "body");
if (body != null) {
String textContent = body.getTextContent();
return textContent.replace("<strong>", "").replace("</strong>", "");
} else {
return "";
}
}
private static String getMentionDescription(Node document) {
Node body = getNode(getModel(document), "body");
return body != null ? body.getTextContent() : "";
}
private static String getNotificationIconUrl(Node document) {
String format = "%s%s";
Node iconUrl = getNode(getModel(document), "iconUrl");
if(iconUrl == null) {
return null;
} else {
String url = iconUrl.getTextContent();
return String.format(format, BuildConfig.COMMONS_URL, url);
}
} }
public static String getMentionMessage(Context context, Node document) { public static String getMentionMessage(Context context, Node document) {
@ -57,16 +162,31 @@ public class NotificationUtils {
return String.format(format, getAgent(document), getNotificationDescription(document)); return String.format(format, getAgent(document), getNotificationDescription(document));
} }
@SuppressLint("StringFormatMatches")
public static String getUserTalkMessage(Context context, Node document) { public static String getUserTalkMessage(Context context, Node document) {
String format = context.getString(R.string.notifications_talk_page_message); String format = context.getString(R.string.notifications_talk_page_message);
return String.format(format, getAgent(document)); return String.format(format, getAgent(document));
} }
@SuppressLint("StringFormatInvalid")
public static String getWelcomeMessage(Context context, Node document) { public static String getWelcomeMessage(Context context, Node document) {
String welcomeMessageFormat = context.getString(R.string.notifications_welcome); String welcomeMessageFormat = context.getString(R.string.notifications_welcome);
return String.format(welcomeMessageFormat, getAgent(document)); return String.format(welcomeMessageFormat, getAgent(document));
} }
private static String getPrimaryLink(Node document) {
Node links = getNode(getModel(document), "links");
Element primaryLink = (Element) getNode(links, "primary");
if (primaryLink != null) {
return primaryLink.getAttribute("url");
}
return "";
}
private static Node getModel(Node document) {
return getNode(document, "_.2A.");
}
private static String getAgent(Node document) { private static String getAgent(Node document) {
Element agentElement = (Element) getNode(document, "agent"); Element agentElement = (Element) getNode(document, "agent");
if (agentElement != null) { if (agentElement != null) {
@ -83,16 +203,6 @@ public class NotificationUtils {
return ""; return "";
} }
private static String getNotificationLink(Node document) {
String format = "%s%s";
Element titleElement = (Element) getNode(document, "title");
if (titleElement != null) {
String fullName = titleElement.getAttribute("full");
return String.format(format, BuildConfig.HOME_URL, fullName);
}
return "";
}
private static String getNotificationDescription(Node document) { private static String getNotificationDescription(Node document) {
Element titleElement = (Element) getNode(document, "title"); Element titleElement = (Element) getNode(document, "title");
if (titleElement != null) { if (titleElement != null) {

View file

@ -151,8 +151,9 @@ public class SettingsFragment extends PreferenceFragment {
emailSelectorIntent.setData(Uri.parse("mailto:")); emailSelectorIntent.setData(Uri.parse("mailto:"));
//initialize the emailIntent //initialize the emailIntent
final Intent emailIntent = new Intent(Intent.ACTION_SEND); final Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{CommonsApplication.FEEDBACK_EMAIL}); // Logs must be sent to the PRIVATE email. Please do not modify this without good reason!
emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.FEEDBACK_EMAIL_SUBJECT, BuildConfig.VERSION_NAME)); emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{CommonsApplication.LOGS_PRIVATE_EMAIL});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.LOGS_PRIVATE_EMAIL_SUBJECT, BuildConfig.VERSION_NAME));
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); emailIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
emailIntent.setSelector( emailSelectorIntent ); emailIntent.setSelector( emailSelectorIntent );

View file

@ -1,12 +1,18 @@
package fr.free.nrw.commons.upload; package fr.free.nrw.commons.upload;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapRegionDecoder; import android.graphics.BitmapRegionDecoder;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.ContributionsActivity;
import fr.free.nrw.commons.utils.ImageUtils; import fr.free.nrw.commons.utils.ImageUtils;
import timber.log.Timber; import timber.log.Timber;
@ -21,16 +27,13 @@ import timber.log.Timber;
public class DetectUnwantedPicturesAsync extends AsyncTask<Void, Void, ImageUtils.Result> { public class DetectUnwantedPicturesAsync extends AsyncTask<Void, Void, ImageUtils.Result> {
interface Callback {
void onResult(ImageUtils.Result result);
}
private final Callback callback;
private final String imageMediaFilePath; private final String imageMediaFilePath;
public final WeakReference<Activity> activityWeakReference;
DetectUnwantedPicturesAsync(String imageMediaFilePath, Callback callback) { DetectUnwantedPicturesAsync(WeakReference<Activity> activityWeakReference, String imageMediaFilePath) {
this.callback = callback; //this.callback = callback;
this.imageMediaFilePath = imageMediaFilePath; this.imageMediaFilePath = imageMediaFilePath;
this.activityWeakReference = activityWeakReference;
} }
@Override @Override
@ -53,7 +56,29 @@ public class DetectUnwantedPicturesAsync extends AsyncTask<Void, Void, ImageUtil
@Override @Override
protected void onPostExecute(ImageUtils.Result result) { protected void onPostExecute(ImageUtils.Result result) {
super.onPostExecute(result); super.onPostExecute(result);
//callback to UI so that it can take necessary decision based on the result obtained Activity activity = activityWeakReference.get();
callback.onResult(result);
if (result != ImageUtils.Result.IMAGE_OK) {
//show appropriate error message
String errorMessage = result == ImageUtils.Result.IMAGE_DARK ? activity.getString(R.string.upload_image_too_dark) : activity.getString(R.string.upload_image_blurry);
AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(activity);
errorDialogBuilder.setMessage(errorMessage);
errorDialogBuilder.setTitle(activity.getString(R.string.warning));
errorDialogBuilder.setPositiveButton(activity.getString(R.string.no), (dialogInterface, i) -> {
//user does not wish to upload the picture, take them back to ContributionsActivity
Intent intent = new Intent(activity, ContributionsActivity.class);
dialogInterface.dismiss();
activity.startActivity(intent);
});
errorDialogBuilder.setNegativeButton(activity.getString(R.string.yes), (dialogInterface, i) -> {
//user wishes to go ahead with the upload of this picture, just dismiss this dialog
dialogInterface.dismiss();
});
AlertDialog errorDialog = errorDialogBuilder.create();
if (!activity.isFinishing()) {
errorDialog.show();
}
}
} }
} }

View file

@ -415,31 +415,9 @@ public class ShareActivity
private void performUnwantedPictureDetectionProcess() { private void performUnwantedPictureDetectionProcess() {
String imageMediaFilePath = FileUtils.getPath(this,mediaUri); String imageMediaFilePath = FileUtils.getPath(this,mediaUri);
DetectUnwantedPicturesAsync detectUnwantedPicturesAsync = new DetectUnwantedPicturesAsync(imageMediaFilePath, result -> { DetectUnwantedPicturesAsync detectUnwantedPicturesAsync
= new DetectUnwantedPicturesAsync(new WeakReference<Activity>(this)
if (result != ImageUtils.Result.IMAGE_OK) { , imageMediaFilePath);
//show appropriate error message
String errorMessage = result == ImageUtils.Result.IMAGE_DARK ? getString(R.string.upload_image_too_dark) : getString(R.string.upload_image_blurry);
AlertDialog.Builder errorDialogBuilder = new AlertDialog.Builder(this);
errorDialogBuilder.setMessage(errorMessage);
errorDialogBuilder.setTitle(getString(R.string.warning));
errorDialogBuilder.setPositiveButton(getString(R.string.no), (dialogInterface, i) -> {
//user does not wish to upload the picture, take them back to ContributionsActivity
Intent intent = new Intent(ShareActivity.this, ContributionsActivity.class);
dialogInterface.dismiss();
startActivity(intent);
});
errorDialogBuilder.setNegativeButton(getString(R.string.yes), (dialogInterface, i) -> {
//user wishes to go ahead with the upload of this picture, just dismiss this dialog
dialogInterface.dismiss();
});
AlertDialog errorDialog = errorDialogBuilder.create();
if (!isFinishing()) {
errorDialog.show();
}
}
});
detectUnwantedPicturesAsync.execute(); detectUnwantedPicturesAsync.execute();
} }

View file

@ -14,7 +14,9 @@ import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
@ -225,18 +227,6 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
.commit(); .commit();
} }
@OnTouch(R.id.share_license_summary)
boolean showLicence(View view, MotionEvent motionEvent) {
if (motionEvent.getActionMasked() == ACTION_DOWN) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(licenseUrlFor(license)));
startActivity(intent);
return true;
} else {
return false;
}
}
@OnClick(R.id.titleDescButton) @OnClick(R.id.titleDescButton)
void setTitleDescButton() { void setTitleDescButton() {
@ -294,8 +284,10 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment {
@SuppressLint("StringFormatInvalid") @SuppressLint("StringFormatInvalid")
private void setLicenseSummary(String license) { private void setLicenseSummary(String license) {
licenseSummaryView.setText(getString(R.string.share_license_summary, getString(Utils.licenseNameFor(license)))); String licenseHyperLink = "<a href='" + licenseUrlFor(license)+"'>"+ getString(Utils.licenseNameFor(license)) + "</a><br>";
} licenseSummaryView.setMovementMethod(LinkMovementMethod.getInstance());
licenseSummaryView.setText(Html.fromHtml(getString(R.string.share_license_summary, licenseHyperLink)));
}
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {

View file

@ -0,0 +1,18 @@
package fr.free.nrw.commons.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class NetworkUtils {
public static boolean isInternetConnectionEstablished(Context context) {
ConnectivityManager cm =
(ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null &&
activeNetwork.isConnectedOrConnecting();
}
}

View file

@ -1,7 +1,11 @@
package fr.free.nrw.commons.utils; package fr.free.nrw.commons.utils;
import android.app.Activity;
import android.content.Context;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.view.Display;
import android.view.View; import android.view.View;
import android.widget.Toast;
public class ViewUtil { public class ViewUtil {
@ -9,4 +13,18 @@ public class ViewUtil {
Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show(); Snackbar.make(view, messageResourceId, Snackbar.LENGTH_SHORT).show();
} }
public static void showLongToast(Context context, String text) {
Toast.makeText(context, text,
Toast.LENGTH_LONG).show();
}
public static boolean isPortrait(Context context) {
Display orientation = ((Activity)context).getWindowManager().getDefaultDisplay();
if(orientation.getWidth() < orientation.getHeight()){
return true;
} else {
return false;
}
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

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

@ -0,0 +1,5 @@
<vector android:alpha="0.84" android:height="32dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#ffffffff" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View file

@ -111,7 +111,7 @@
android:layout_marginTop="@dimen/standard_gap" android:layout_marginTop="@dimen/standard_gap"
android:gravity="center" android:gravity="center"
android:textColor="@color/primaryColor" android:textColor="@color/primaryColor"
android:text="@string/about_rate_us" /> />
<TextView <TextView
android:id="@+id/about_privacy_policy" android:id="@+id/about_privacy_policy"
@ -121,7 +121,7 @@
android:layout_marginTop="@dimen/standard_gap" android:layout_marginTop="@dimen/standard_gap"
android:textColor="@color/primaryColor" android:textColor="@color/primaryColor"
android:gravity="center" android:gravity="center"
android:text="@string/about_privacy_policy" /> />
<TextView <TextView
android:id="@+id/about_translate" android:id="@+id/about_translate"
@ -131,7 +131,7 @@
android:textColor="@color/primaryColor" android:textColor="@color/primaryColor"
android:layout_marginTop="@dimen/standard_gap" android:layout_marginTop="@dimen/standard_gap"
android:gravity="center" android:gravity="center"
android:text="@string/about_translate" /> />
<TextView <TextView
android:id="@+id/about_credits" android:id="@+id/about_credits"
@ -141,7 +141,7 @@
android:textColor="@color/primaryColor" android:textColor="@color/primaryColor"
android:layout_marginTop="@dimen/standard_gap" android:layout_marginTop="@dimen/standard_gap"
android:gravity="center" android:gravity="center"
android:text="@string/about_credits" /> />
<TextView <TextView
android:id="@+id/about_faq" android:id="@+id/about_faq"
@ -153,15 +153,6 @@
android:gravity="center" android:gravity="center"
/> />
<TextView
android:id="@+id/about_uploads_to"
style="?android:textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/large_gap"
android:alpha="0.2"
android:gravity="center" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>
</ScrollView> </ScrollView>

View file

@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/coordinator_layout" android:id="@+id/coordinator_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -21,9 +21,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_below="@id/toolbar"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@ -37,33 +38,14 @@
android:id="@+id/container" android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
android:layout_alignBottom="@id/toolbar"
android:layout_alignParentRight="true"
android:layout_marginRight="28dp"
android:layout_marginBottom="-96dp"
android:visibility="invisible"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
app:backgroundTint="@color/button_blue"
android:clickable="true"
app:srcCompat="@drawable/ic_list_white_24dp"
android:scaleType="center"
/>
<View <View
android:id="@+id/transparentView" android:id="@+id/transparentView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_alignParentLeft="true" android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" android:layout_below="@id/toolbar"
android:layout_alignParentTop="true"
android:layout_marginTop="18dp"
android:background="#aa969696" android:background="#aa969696"
android:elevation="6dp"> android:elevation="6dp">

View file

@ -6,6 +6,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<RelativeLayout <RelativeLayout
android:id="@+id/container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -15,6 +16,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/listView" android:id="@+id/listView"
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -14,6 +14,7 @@
android:id="@+id/welcomePagerIndicator" android:id="@+id/welcomePagerIndicator"
android:layout_height="@dimen/half_standard_height" android:layout_height="@dimen/half_standard_height"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_gravity="bottom" /> android:layout_gravity="bottom"
android:padding="5dp" />
</FrameLayout> </FrameLayout>

View file

@ -37,8 +37,11 @@
android:id="@+id/title" android:id="@+id/title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textSize="16sp" /> android:textSize="16sp"
android:layout_marginRight="50dp"
android:maxLines="2"
android:ellipsize="end"
/>
<TextView <TextView
android:id="@+id/category" android:id="@+id/category"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View file

@ -284,10 +284,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

@ -74,6 +74,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/standard_gap" android:layout_marginTop="@dimen/standard_gap"
android:gravity="center" android:gravity="center"
android:clickable="true"
android:textColorLink="@color/button_blue"
android:text="@string/share_license_summary" /> android:text="@string/share_license_summary" />
<fr.free.nrw.commons.ui.widget.HtmlTextView <fr.free.nrw.commons.ui.widget.HtmlTextView

View file

@ -45,27 +45,12 @@
android:layout_toRightOf="@id/icon" android:layout_toRightOf="@id/icon"
android:layout_toStartOf="@id/time" android:layout_toStartOf="@id/time"
android:ellipsize="end" android:ellipsize="end"
app:trimLines="2" app:trimMode="trimModeLength"
app:trimLength="60"
android:layout_alignParentTop="true"
app:colorClickableText="#969494" app:colorClickableText="#969494"
android:textAppearance="@style/TextAppearance.AppCompat.Body2" android:textAppearance="@style/TextAppearance.AppCompat.Body2"
tools:text="@string/placeholder_place_name" tools:text="@string/placeholder_place_name"
android:padding="12dp"
/> />
<com.borjabravo.readmoretextview.ReadMoreTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignEnd="@id/time"
android:layout_alignLeft="@id/title"
android:layout_alignRight="@id/time"
android:layout_alignStart="@id/title"
android:layout_below="@id/title"
android:layout_marginBottom="16dp"
android:ellipsize="end"
app:trimLines="2"
app:colorClickableText="#969494"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
tools:text="@string/placeholder_place_description"
/>
</RelativeLayout> </RelativeLayout>

View file

@ -9,4 +9,5 @@
android:minHeight="?attr/actionBarSize" android:minHeight="?attr/actionBarSize"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="?attr/colorPrimaryDark"> android:background="?attr/colorPrimaryDark">
</android.support.v7.widget.Toolbar> </android.support.v7.widget.Toolbar>

View file

@ -1,47 +1,56 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/drawer_main">
<item
android:id="@+id/action_home"
android:icon="@drawable/ic_home_black_24dp"
android:title="@string/navigation_item_home" />
<item <item
android:id="@+id/action_home" android:id="@+id/action_nearby"
android:icon="@drawable/ic_home_black_24dp" android:icon="@drawable/ic_location_black_24dp"
android:title="@string/navigation_item_home"/> android:title="@string/navigation_item_nearby" />
<item <item
android:id="@+id/action_nearby" android:id="@+id/action_featured_images"
android:icon="@drawable/ic_location_black_24dp" android:icon="@drawable/ic_star_black_24dp"
android:title="@string/navigation_item_nearby"/> android:title="@string/navigation_item_featured_images"/>
<item </group>
android:id="@+id/action_notifications" <group android:id="@+id/drawer_account">
android:icon="@drawable/ic_notifications_black_24dp" <item
android:title="@string/navigation_item_notification"/> android:id="@+id/action_notifications"
android:icon="@drawable/ic_notifications_black_24dp"
android:title="@string/navigation_item_notification" />
<item
android:id="@+id/action_about"
android:icon="@drawable/ic_info_outline_black_24dp"
android:title="@string/navigation_item_about"/>
<item <item
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:icon="@drawable/ic_settings_black_24dp" android:icon="@drawable/ic_settings_black_24dp"
android:title="@string/navigation_item_settings"/> android:title="@string/navigation_item_settings" />
<item </group>
android:id="@+id/action_introduction" <group android:id="@+id/drawer_contact">
android:icon="@drawable/ic_help_black_24dp" <item
android:title="@string/navigation_item_info"/> android:id="@+id/action_about"
android:icon="@drawable/ic_info_outline_black_24dp"
android:title="@string/navigation_item_about" />
<item
android:id="@+id/action_introduction"
android:icon="@drawable/ic_help_black_24dp"
android:title="@string/navigation_item_info" />
<item <item
android:id="@+id/action_feedback" android:id="@+id/action_feedback"
android:icon="@drawable/ic_feedback_black_24dp" android:icon="@drawable/ic_feedback_black_24dp"
android:title="@string/navigation_item_feedback"/> android:title="@string/navigation_item_feedback" />
<item
android:id="@+id/action_logout"
android:icon="@drawable/ic_exit_to_app_black_24dp"
android:title="@string/navigation_item_logout"/>
<item </group>
android:id="@+id/action_featured_images"
android:icon="@drawable/ic_star_black_24dp" <group android:id="@+id/drawer_logout">
android:title="@string/navigation_item_featured_images"/> <item
android:id="@+id/action_logout"
android:icon="@drawable/ic_exit_to_app_black_24dp"
android:title="@string/navigation_item_logout" />
</group>
</menu> </menu>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
>
<item
android:id="@+id/share_app_icon"
android:title="@string/refresh_button"
android:icon="@drawable/ic_share_black_24dp"
android:orderInCategory="1"
app:showAsAction="ifRoom"
/>
</menu>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Андрей
-->
<resources> <resources>
<string name="crash_dialog_title">Аиҧҟьара</string> <string name="crash_dialog_title">Аиҧҟьара</string>
<string name="crash_dialog_ok_toast">Иҭабуп!</string> <string name="crash_dialog_ok_toast">Иҭабуп!</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Envlh
* Андрей
-->
<resources> <resources>
<string name="menu_settings">Архиарақәа</string> <string name="menu_settings">Архиарақәа</string>
<string name="username">Ахархәаҩ ихьӡ</string> <string name="username">Ахархәаҩ ихьӡ</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Naudefj
-->
<resources> <resources>
<string name="crash_dialog_title">Commons het omgeval</string> <string name="crash_dialog_title">Commons het omgeval</string>
<string name="crash_dialog_text">Oeps. Er is iets misgegaan.</string> <string name="crash_dialog_text">Oeps. Er is iets misgegaan.</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Akamycoco
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">kukay</string> <string name="crash_dialog_ok_toast">kukay</string>
</resources> </resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ali1
* Mido
-->
<resources> <resources>
<string name="crash_dialog_title">لقد تعطل كومنز</string> <string name="crash_dialog_title">لقد تعطل كومنز</string>
<string name="crash_dialog_text">عفوا. حدث خطأ!</string> <string name="crash_dialog_text">عفوا. حدث خطأ!</string>

View file

@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ali1
* Antime
* Azouz.anis
* ButterflyOfFire
* Claw eg
* Meno25
* Mido
* Monrokhoury
* Mr. Ibrahem
* OsamaK
* ترجمان05
* محمد أحمد عبد الفتاح
* مشعل الحربي
-->
<resources> <resources>
<string name="preference_category_general">عام</string> <string name="preference_category_general">عام</string>
<string name="app_name">كومنز</string> <string name="app_name">كومنز</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Man2fly2002
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">ܬܘܕܝ ܠܟ!</string> <string name="crash_dialog_ok_toast">ܬܘܕܝ ܠܟ!</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Xuacu
-->
<resources> <resources>
<string name="crash_dialog_title">Commons colgóse</string> <string name="crash_dialog_title">Commons colgóse</string>
<string name="crash_dialog_text">Vaya. ¡Daqué funcionó mal!</string> <string name="crash_dialog_text">Vaya. ¡Daqué funcionó mal!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Xuacu
-->
<resources> <resources>
<string name="preference_category_appearance">Aspeutu</string> <string name="preference_category_appearance">Aspeutu</string>
<string name="preference_category_general">Xeneral</string> <string name="preference_category_general">Xeneral</string>
@ -59,6 +62,7 @@
<string name="categories_search_text_hint">Guetar categoríes</string> <string name="categories_search_text_hint">Guetar categoríes</string>
<string name="menu_save_categories">Guardar</string> <string name="menu_save_categories">Guardar</string>
<string name="refresh_button">Refrescar</string> <string name="refresh_button">Refrescar</string>
<string name="display_list_button">Llista</string>
<string name="gps_disabled">El GPS ta desactiváu nel preséu. ¿Quiés activalu?</string> <string name="gps_disabled">El GPS ta desactiváu nel preséu. ¿Quiés activalu?</string>
<string name="enable_gps">Activar GPS</string> <string name="enable_gps">Activar GPS</string>
<string name="contributions_subtitle_zero">Inda nun hai xubes</string> <string name="contributions_subtitle_zero">Inda nun hai xubes</string>
@ -151,8 +155,8 @@
<string name="detail_description_empty">Ensin descripción</string> <string name="detail_description_empty">Ensin descripción</string>
<string name="detail_license_empty">Llicencia desconocida</string> <string name="detail_license_empty">Llicencia desconocida</string>
<string name="menu_refresh">Refrescar</string> <string name="menu_refresh">Refrescar</string>
<string name="read_storage_permission_rationale">Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string> <string name="read_storage_permission_rationale" fuzzy="true">Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string>
<string name="write_storage_permission_rationale">Permisu riquíu: escritura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string> <string name="write_storage_permission_rationale" fuzzy="true">Permisu riquíu: escritura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él.</string>
<string name="location_permission_rationale">Permisu opcional: llograr l\'allugamientu actual pa suxerir categoríes</string> <string name="location_permission_rationale">Permisu opcional: llograr l\'allugamientu actual pa suxerir categoríes</string>
<string name="ok">Aceutar</string> <string name="ok">Aceutar</string>
<string name="title_activity_nearby">Llugares cercanos</string> <string name="title_activity_nearby">Llugares cercanos</string>
@ -211,6 +215,7 @@
<string name="no_description_found">nun s\'atoparon descripciones</string> <string name="no_description_found">nun s\'atoparon descripciones</string>
<string name="nearby_info_menu_commons_article">Páxina del ficheru en Commons</string> <string name="nearby_info_menu_commons_article">Páxina del ficheru en Commons</string>
<string name="nearby_info_menu_wikidata_article">Elementu de WikiData</string> <string name="nearby_info_menu_wikidata_article">Elementu de WikiData</string>
<string name="nearby_info_menu_wikipedia_article">Artículu de Wikipedia</string>
<string name="error_while_cache">Error al poner les fotos na caché</string> <string name="error_while_cache">Error al poner les fotos na caché</string>
<string name="title_info">Un títulu descriptivu únicu pal ficheru, que sirvirá para da-y nome al ficheru. Se pue usar llinguax normal con espacios. Nun amiestes la estensión del ficheru</string> <string name="title_info">Un títulu descriptivu únicu pal ficheru, que sirvirá para da-y nome al ficheru. Se pue usar llinguax normal con espacios. Nun amiestes la estensión del ficheru</string>
<string name="description_info">Por favor, describi l\'elementu multimedia tantu como sía posible: ¿ónde se tomó?, ¿qué amuesa?, ¿cuál ye\'l contestu? Por favor, describi los oxetos o persones. Revela la información que nun pueda aldovinase de mou cenciellu, por casu el momentu del día si ye un paisaxe. Si\'l mediu amuesa daqué desacostumao, esplica qué lo fai raro.</string> <string name="description_info">Por favor, describi l\'elementu multimedia tantu como sía posible: ¿ónde se tomó?, ¿qué amuesa?, ¿cuál ye\'l contestu? Por favor, describi los oxetos o persones. Revela la información que nun pueda aldovinase de mou cenciellu, por casu el momentu del día si ye un paisaxe. Si\'l mediu amuesa daqué desacostumao, esplica qué lo fai raro.</string>
@ -224,6 +229,9 @@
<string name="send_log_file_description">Unviar ficheru de rexistru a los desendolcadores per corréu electrónicu</string> <string name="send_log_file_description">Unviar ficheru de rexistru a los desendolcadores per corréu electrónicu</string>
<string name="no_web_browser">Nun s\'alcontró un restolador p\'abrir la URL</string> <string name="no_web_browser">Nun s\'alcontró un restolador p\'abrir la URL</string>
<string name="null_url">¡Error! Nun s\'alcontró la URL</string> <string name="null_url">¡Error! Nun s\'alcontró la URL</string>
<string name="nominate_deletion">Marcada pa desaniciar</string>
<string name="nominated_for_deletion">Esta imaxe marcóse pa desaniciar.</string>
<string name="view_browser">Ver nel restolador</string>
<string name="nearby_location_has_not_changed">L\'allugamientu nun camudó.</string> <string name="nearby_location_has_not_changed">L\'allugamientu nun camudó.</string>
<string name="nearby_location_not_available">L\'allugamientu nun ta disponible.</string> <string name="nearby_location_not_available">L\'allugamientu nun ta disponible.</string>
<string name="location_permission_rationale_nearby">Ríquese permisu p\'amosar una llista de llugares cercanos</string> <string name="location_permission_rationale_nearby">Ríquese permisu p\'amosar una llista de llugares cercanos</string>
@ -234,6 +242,21 @@
<string name="notifications_thank_you_edit">Gracies por facer una edición</string> <string name="notifications_thank_you_edit">Gracies por facer una edición</string>
<string name="notifications_mention">%1$s te mentó en %2$s.</string> <string name="notifications_mention">%1$s te mentó en %2$s.</string>
<string name="toggle_view_button">Alternar vista</string> <string name="toggle_view_button">Alternar vista</string>
<string name="about_faq">Entrugues más frecuentes</string> <string name="nearby_directions">CÓMO LLEGAR</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_rate_us">&lt;u&gt;Puntúanos&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;EMF&lt;/u&gt;</string>
<string name="welcome_skip_button">Saltar el tutorial</string> <string name="welcome_skip_button">Saltar el tutorial</string>
<string name="no_internet">Internet nun ta disponible</string>
<string name="internet_established">Internet ta disponible</string>
<string name="error_notifications">Error al llograr les notificaciones</string>
<string name="no_notifications">Nun s\'alcontraron notificaciones</string>
<string name="about_translate">&lt;u&gt;Traducir&lt;/u&gt;</string>
<string name="about_translate_title">Llingües</string>
<string name="about_translate_message">Escueye l\'idioma pal que quies unviar traducciones</string>
<string name="about_translate_proceed">Siguir</string>
<string name="about_translate_cancel">Encaboxar</string>
<string name="retry">Retentar</string>
</resources> </resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Dağlı95
* Khan27
-->
<resources> <resources>
<string name="crash_dialog_title">Nasazlıq</string> <string name="crash_dialog_title">Nasazlıq</string>
<string name="crash_dialog_text">Uups. Nəsə düzgün çalışmır!</string> <string name="crash_dialog_text">Uups. Nəsə düzgün çalışmır!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Mousa
-->
<resources> <resources>
<string name="crash_dialog_title">کامانز ایشدن دوشدو</string> <string name="crash_dialog_title">کامانز ایشدن دوشدو</string>
<string name="crash_dialog_text">اوخ. بیر خطا قاباغا گلدی!</string> <string name="crash_dialog_text">اوخ. بیر خطا قاباغا گلدی!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kareyac
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">Дзякуем!</string> <string name="crash_dialog_ok_toast">Дзякуем!</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Thakurji
-->
<resources> <resources>
<string name="crash_dialog_title">Commons crash hoe gais</string> <string name="crash_dialog_title">Commons crash hoe gais</string>
<string name="crash_dialog_text">Oops, Koi chij wrong hoe gais</string> <string name="crash_dialog_text">Oops, Koi chij wrong hoe gais</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Wikibilim
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">Рақмет!</string> <string name="crash_dialog_ok_toast">Рақмет!</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Servien
-->
<resources> <resources>
<string name="crash_dialog_title">Commons is vasteleupen</string> <string name="crash_dialog_title">Commons is vasteleupen</string>
<string name="crash_dialog_text">Oeps. Der gung iets mis.</string> <string name="crash_dialog_text">Oeps. Der gung iets mis.</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Joetaras
-->
<resources> <resources>
<string name="crash_dialog_title">Commons ha sckattate</string> <string name="crash_dialog_title">Commons ha sckattate</string>
<string name="crash_dialog_text">Mudu. Quacchecose ha sciute male!</string> <string name="crash_dialog_text">Mudu. Quacchecose ha sciute male!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Zoranzoki21
-->
<resources> <resources>
<string name="crash_dialog_title">Ostava se srušila</string> <string name="crash_dialog_title">Ostava se srušila</string>
<string name="crash_dialog_text">Ups! Nešto je pošlo naopako.</string> <string name="crash_dialog_text">Ups! Nešto je pošlo naopako.</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ego and his own
* Milicevic01
* Zoranzoki21
-->
<resources> <resources>
<string name="app_name">Ostava</string> <string name="app_name">Ostava</string>
<string name="menu_settings">Podešavanja</string> <string name="menu_settings">Podešavanja</string>
@ -134,8 +139,8 @@
<string name="detail_description_empty">Nema opisa</string> <string name="detail_description_empty">Nema opisa</string>
<string name="detail_license_empty">Nepoznata licenca</string> <string name="detail_license_empty">Nepoznata licenca</string>
<string name="menu_refresh">Osveži</string> <string name="menu_refresh">Osveži</string>
<string name="read_storage_permission_rationale">Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše.</string> <string name="read_storage_permission_rationale" fuzzy="true">Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše.</string>
<string name="write_storage_permission_rationale">Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga.</string> <string name="write_storage_permission_rationale" fuzzy="true">Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga.</string>
<string name="location_permission_rationale">Opciona dozvola: Preuzmi trenutnu lokaciju za predloge kategorija</string> <string name="location_permission_rationale">Opciona dozvola: Preuzmi trenutnu lokaciju za predloge kategorija</string>
<string name="ok">U redu</string> <string name="ok">U redu</string>
<string name="title_activity_nearby">Mesta u blizini</string> <string name="title_activity_nearby">Mesta u blizini</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ibrahim
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">Ташаккур!</string> <string name="crash_dialog_ok_toast">Ташаккур!</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Рустам Нурыев
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">Рәхмәт!</string> <string name="crash_dialog_ok_toast">Рәхмәт!</string>
</resources> </resources>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Lizalizaufa
* Sagan
* Рустам Нурыев
-->
<resources> <resources>
<string name="preference_category_appearance">Тышҡы күренеш</string> <string name="preference_category_appearance">Тышҡы күренеш</string>
<string name="preference_category_general">Ғәҙәти</string> <string name="preference_category_general">Ғәҙәти</string>
@ -149,8 +154,8 @@
<string name="detail_description_empty">Һүрәтләүе юҡ</string> <string name="detail_description_empty">Һүрәтләүе юҡ</string>
<string name="detail_license_empty">Билдәһеҙ лицензия</string> <string name="detail_license_empty">Билдәһеҙ лицензия</string>
<string name="menu_refresh">Яңыртып алыу</string> <string name="menu_refresh">Яңыртып алыу</string>
<string name="read_storage_permission_rationale">Кәрәкле рөхсәт: тышҡы һаҡлағыстан алып уҡыу. Ҡушымта шунһыҙ эшләмәйәсәк.</string> <string name="read_storage_permission_rationale" fuzzy="true">Кәрәкле рөхсәт: тышҡы һаҡлағыстан алып уҡыу. Ҡушымта шунһыҙ эшләмәйәсәк.</string>
<string name="write_storage_permission_rationale">Кәрәкле рөхсәт: тышҡы һаҡлағысҡа яҙыу. Ҡушымта шунһыҙ эшләмәйәсәк.</string> <string name="write_storage_permission_rationale" fuzzy="true">Кәрәкле рөхсәт: тышҡы һаҡлағысҡа яҙыу. Ҡушымта шунһыҙ эшләмәйәсәк.</string>
<string name="location_permission_rationale">Мотлаҡ булмаған рөхсәт: категория тәҡдиме өсөн ошо урынды алыу</string> <string name="location_permission_rationale">Мотлаҡ булмаған рөхсәт: категория тәҡдиме өсөн ошо урынды алыу</string>
<string name="title_activity_nearby">Яҡындағы урындар</string> <string name="title_activity_nearby">Яҡындағы урындар</string>
<string name="no_nearby">Яҡындағы урындар табылманы</string> <string name="no_nearby">Яҡындағы урындар табылманы</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Geopoet
-->
<resources> <resources>
<string name="crash_dialog_title">Kagrugaringan nagkagarabá</string> <string name="crash_dialog_title">Kagrugaringan nagkagarabá</string>
<string name="crash_dialog_text">Oops. May bagay an napasala!</string> <string name="crash_dialog_text">Oops. May bagay an napasala!</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* DCLXVI
* Vodnokon4e
-->
<resources> <resources>
<string name="crash_dialog_title">Неуспех с Общомедия</string> <string name="crash_dialog_title">Неуспех с Общомедия</string>
<string name="crash_dialog_text">Опа. Нещо се обърка!</string> <string name="crash_dialog_text">Опа. Нещо се обърка!</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* DCLXVI
* MegaAlex
* StanProg
* Vodnokon4e
* АдмиралАнимЕ
-->
<resources> <resources>
<string name="app_name">Общомедия</string> <string name="app_name">Общомедия</string>
<string name="menu_settings">Настройки</string> <string name="menu_settings">Настройки</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aftabuzzaman
* Bellayet
* Sankarshan
-->
<resources> <resources>
<string name="crash_dialog_title">কমন্স ক্র্যাশ করেছে</string> <string name="crash_dialog_title">কমন্স ক্র্যাশ করেছে</string>
<string name="crash_dialog_text">ওহ, কিছু একটা ত্রুটি হয়েছে!</string> <string name="crash_dialog_text">ওহ, কিছু একটা ত্রুটি হয়েছে!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aftabuzzaman
* Bellayet
* Elias Ahmmad
* Leemon2010
* Mohammed Galib Hasan
* Muktogayn
* Rasal Lia
* Sankarshan
* Tauhid16
-->
<resources> <resources>
<string name="preference_category_appearance">অবয়ব</string> <string name="preference_category_appearance">অবয়ব</string>
<string name="preference_category_general">সাধারণ</string> <string name="preference_category_general">সাধারণ</string>
@ -59,6 +70,7 @@
<string name="categories_search_text_hint">বিষয়শ্রেণী অনুসন্ধান</string> <string name="categories_search_text_hint">বিষয়শ্রেণী অনুসন্ধান</string>
<string name="menu_save_categories">সংরক্ষণ</string> <string name="menu_save_categories">সংরক্ষণ</string>
<string name="refresh_button">পুনঃসতেজ</string> <string name="refresh_button">পুনঃসতেজ</string>
<string name="display_list_button">তালিকা</string>
<string name="gps_disabled">GPS আপনার ডিভাইসে অক্ষম করা আছে। আপনি কি এটি সক্ষম করতে চান?</string> <string name="gps_disabled">GPS আপনার ডিভাইসে অক্ষম করা আছে। আপনি কি এটি সক্ষম করতে চান?</string>
<string name="enable_gps">GPS সক্রিয় করুন</string> <string name="enable_gps">GPS সক্রিয় করুন</string>
<string name="contributions_subtitle_zero">এখনো কোন আপলোড নেই</string> <string name="contributions_subtitle_zero">এখনো কোন আপলোড নেই</string>
@ -150,8 +162,8 @@
<string name="detail_description_empty">বিবরণ নেই</string> <string name="detail_description_empty">বিবরণ নেই</string>
<string name="detail_license_empty">অজানা লাইসেন্স</string> <string name="detail_license_empty">অজানা লাইসেন্স</string>
<string name="menu_refresh">পুনঃসতেজ</string> <string name="menu_refresh">পুনঃসতেজ</string>
<string name="read_storage_permission_rationale">প্রয়োজনীয় অনুমতি: বহিঃস্ত সঞ্চয়স্থান পড়া। এটি ছাড়া অ্যাপ কাজ করবে না।</string> <string name="read_storage_permission_rationale" fuzzy="true">প্রয়োজনীয় অনুমতি: বহিঃস্ত সঞ্চয়স্থান পড়া। এটি ছাড়া অ্যাপ কাজ করবে না।</string>
<string name="write_storage_permission_rationale">অনুমতি প্রয়োজন: অালাদাভাবে সংযুক্ত স্টোরেজ লিখুন। এটি ছাড়া অ্যাপটি চলতে পারেনা।</string> <string name="write_storage_permission_rationale" fuzzy="true">অনুমতি প্রয়োজন: অালাদাভাবে সংযুক্ত স্টোরেজ লিখুন। এটি ছাড়া অ্যাপটি চলতে পারেনা।</string>
<string name="location_permission_rationale">ঐচ্ছিক অনুমতি: বিষয়শ্রেণী পরামর্শের জন্য বর্তমান অবস্থান নেয়</string> <string name="location_permission_rationale">ঐচ্ছিক অনুমতি: বিষয়শ্রেণী পরামর্শের জন্য বর্তমান অবস্থান নেয়</string>
<string name="ok">ঠিক আছে</string> <string name="ok">ঠিক আছে</string>
<string name="title_activity_nearby">কাছাকাছি স্থান</string> <string name="title_activity_nearby">কাছাকাছি স্থান</string>
@ -210,6 +222,7 @@
<string name="no_description_found">কোন বিবরণ পাওয়া যায়নি</string> <string name="no_description_found">কোন বিবরণ পাওয়া যায়নি</string>
<string name="nearby_info_menu_commons_article">কমন্সে ফাইলের পাতা</string> <string name="nearby_info_menu_commons_article">কমন্সে ফাইলের পাতা</string>
<string name="nearby_info_menu_wikidata_article">উইকিউপাত্ত পদ</string> <string name="nearby_info_menu_wikidata_article">উইকিউপাত্ত পদ</string>
<string name="nearby_info_menu_wikipedia_article">উইকিপিডিয়া নিবন্ধ</string>
<string name="error_while_cache">ছবি আনার সময় ত্রুটি</string> <string name="error_while_cache">ছবি আনার সময় ত্রুটি</string>
<string name="title_info">ফাইলের একটি স্বতন্ত্র বর্ণনামূলক নাম যা ফাইলের নাম হিসাবে কাজ করবে। অাপনি সাধারণ ভাষা ব্যবহার করতে পারেন শূন্যস্থানসহ। ফাইলের এক্সটেনশন যুক্ত করবেন না।</string> <string name="title_info">ফাইলের একটি স্বতন্ত্র বর্ণনামূলক নাম যা ফাইলের নাম হিসাবে কাজ করবে। অাপনি সাধারণ ভাষা ব্যবহার করতে পারেন শূন্যস্থানসহ। ফাইলের এক্সটেনশন যুক্ত করবেন না।</string>
<string name="description_info">যতটা সম্ভব মিডিয়াটি বর্ণনা করুন: এটি কোথায় ধারণ করা হয়েছিল? এটি কি প্রদর্শন করে? এটির প্রসঙ্গ কি? ধারণকৃত বস্তু অথবা ব্যক্তির বর্ণনা করুন। সহজে অনুমান করা যায়না সেরকম তথ্য উদঘাটন করুন, উদাহরণস্বরূপ, যদি ল্যান্ডস্কেপ হয় তাহলে দিবসকালের সময় দিন।</string> <string name="description_info">যতটা সম্ভব মিডিয়াটি বর্ণনা করুন: এটি কোথায় ধারণ করা হয়েছিল? এটি কি প্রদর্শন করে? এটির প্রসঙ্গ কি? ধারণকৃত বস্তু অথবা ব্যক্তির বর্ণনা করুন। সহজে অনুমান করা যায়না সেরকম তথ্য উদঘাটন করুন, উদাহরণস্বরূপ, যদি ল্যান্ডস্কেপ হয় তাহলে দিবসকালের সময় দিন।</string>
@ -222,6 +235,8 @@
<string name="send_log_file">লগ ফাইল পাঠান</string> <string name="send_log_file">লগ ফাইল পাঠান</string>
<string name="send_log_file_description">ইমেইলের মাধ্যমে উন্নয়নকারীর কাছে লগ ফাইল পাঠান</string> <string name="send_log_file_description">ইমেইলের মাধ্যমে উন্নয়নকারীর কাছে লগ ফাইল পাঠান</string>
<string name="null_url">ত্রুটি! ইউআরএল পাওয়া যায়নি</string> <string name="null_url">ত্রুটি! ইউআরএল পাওয়া যায়নি</string>
<string name="nominate_deletion">অপসারণের জন্য মনোনীত</string>
<string name="view_browser">ব্রাউজারে দেখুন</string>
<string name="nearby_location_has_not_changed">অবস্থান পরিবর্তন হয়নি।</string> <string name="nearby_location_has_not_changed">অবস্থান পরিবর্তন হয়নি।</string>
<string name="nearby_location_not_available">অবস্থান উপলব্ধ নয়।</string> <string name="nearby_location_not_available">অবস্থান উপলব্ধ নয়।</string>
<string name="location_permission_rationale_nearby">কাছাকাছি স্থানসমূহের একটি তালিকা প্রদর্শন করতে অনুমতি প্রয়োজন</string> <string name="location_permission_rationale_nearby">কাছাকাছি স্থানসমূহের একটি তালিকা প্রদর্শন করতে অনুমতি প্রয়োজন</string>
@ -231,6 +246,14 @@
<string name="notifications_talk_page_message">%1$s আপনার আলাপ পাতায় একটি বার্তা দিয়েছেন</string> <string name="notifications_talk_page_message">%1$s আপনার আলাপ পাতায় একটি বার্তা দিয়েছেন</string>
<string name="notifications_thank_you_edit">একটি সম্পাদনা করার জন্য আপনাকে ধন্যবাদ</string> <string name="notifications_thank_you_edit">একটি সম্পাদনা করার জন্য আপনাকে ধন্যবাদ</string>
<string name="notifications_mention">%1$s আপনাকে %2$s-এ উল্লেখ করেছেন।</string> <string name="notifications_mention">%1$s আপনাকে %2$s-এ উল্লেখ করেছেন।</string>
<string name="about_faq">প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ</string> <string name="nearby_directions">দিকনির্দেশ</string>
<string name="nearby_wikidata">উইকিউপাত্ত</string>
<string name="nearby_wikipedia">উইকিপিডিয়া</string>
<string name="nearby_commons">কমন্স</string>
<string name="about_faq" fuzzy="true">প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ</string>
<string name="welcome_skip_button">টিউটোরিয়াল এড়ান</string> <string name="welcome_skip_button">টিউটোরিয়াল এড়ান</string>
<string name="no_internet">ইন্টারনেট অনুপলব্ধ</string>
<string name="internet_established">ইন্টারনেট উপলব্ধ</string>
<string name="no_notifications">কোন বিজ্ঞপ্তি পাওয়া যায়নি</string>
<string name="retry">পুনঃচেষ্টা করুন</string>
</resources> </resources>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Fohanno
* Gwenn-Ael
-->
<resources> <resources>
<string name="crash_dialog_title">Commons zo aet er c\'hleuz</string> <string name="crash_dialog_title">Commons zo aet er c\'hleuz</string>
<string name="crash_dialog_text">Hopala ! Un dra bennak a-dreuz zo bet !</string> <string name="crash_dialog_text">Hopala ! Un dra bennak a-dreuz zo bet !</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Dishual
* Fohanno
* Fulup
* Gwenn-Ael
* Y-M D
-->
<resources> <resources>
<string name="preference_category_appearance">Neuz</string> <string name="preference_category_appearance">Neuz</string>
<string name="preference_category_general">Hollek</string> <string name="preference_category_general">Hollek</string>
@ -146,8 +153,8 @@
<string name="detail_description_empty">Deskrivadur ebet</string> <string name="detail_description_empty">Deskrivadur ebet</string>
<string name="detail_license_empty">Aotre-implijout dizanv</string> <string name="detail_license_empty">Aotre-implijout dizanv</string>
<string name="menu_refresh">Freskaat</string> <string name="menu_refresh">Freskaat</string>
<string name="read_storage_permission_rationale">Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro.</string> <string name="read_storage_permission_rationale" fuzzy="true">Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro.</string>
<string name="write_storage_permission_rationale">Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se.</string> <string name="write_storage_permission_rationale" fuzzy="true">Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se.</string>
<string name="location_permission_rationale">Aotre diret : kaout al lec\'hiadur red evit kinnig rummadoù</string> <string name="location_permission_rationale">Aotre diret : kaout al lec\'hiadur red evit kinnig rummadoù</string>
<string name="ok">Mat eo</string> <string name="ok">Mat eo</string>
<string name="title_activity_nearby">Lec\'hioù nes</string> <string name="title_activity_nearby">Lec\'hioù nes</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Srdjan m
-->
<resources> <resources>
<string name="crash_dialog_title">Commons se srušio</string> <string name="crash_dialog_title">Commons se srušio</string>
<string name="crash_dialog_text">Ups. Nešto je pošlo po zlu!</string> <string name="crash_dialog_text">Ups. Nešto je pošlo po zlu!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* CERminator
* DzWiki
* Srdjan m
-->
<resources> <resources>
<string name="app_name">Commons</string> <string name="app_name">Commons</string>
<string name="menu_settings">Postavke</string> <string name="menu_settings">Postavke</string>
@ -133,7 +138,7 @@
<string name="detail_description_empty">Nema opisa</string> <string name="detail_description_empty">Nema opisa</string>
<string name="detail_license_empty">Nepoznata licenca</string> <string name="detail_license_empty">Nepoznata licenca</string>
<string name="menu_refresh">Osvježi</string> <string name="menu_refresh">Osvježi</string>
<string name="read_storage_permission_rationale">Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog.</string> <string name="read_storage_permission_rationale" fuzzy="true">Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog.</string>
<string name="location_permission_rationale">Neobavezna dozvola: Dobavljanje trenutne lokacije za predlaganje kategorija</string> <string name="location_permission_rationale">Neobavezna dozvola: Dobavljanje trenutne lokacije za predlaganje kategorija</string>
<string name="ok">U redu</string> <string name="ok">U redu</string>
<string name="title_activity_nearby">Mjesta u blizini</string> <string name="title_activity_nearby">Mjesta u blizini</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Toniher
* XVEC
-->
<resources> <resources>
<string name="crash_dialog_title">El Commons s\'ha penjat</string> <string name="crash_dialog_title">El Commons s\'ha penjat</string>
<string name="crash_dialog_text">Uups ! Quelcom ha anat malament !</string> <string name="crash_dialog_text">Uups ! Quelcom ha anat malament !</string>

View file

@ -1,4 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Alvaro Vidal-Abarca
* Fitoschido
* Kippelboy
* MarionaDSR
* Pintor Smeargle
* Pitort
* Toniher
* XVEC
-->
<resources> <resources>
<string name="preference_category_appearance">Aparença</string> <string name="preference_category_appearance">Aparença</string>
<string name="preference_category_location">Ubicació</string> <string name="preference_category_location">Ubicació</string>
@ -181,5 +191,5 @@
<string name="read_article">LLEGIU LARTICLE</string> <string name="read_article">LLEGIU LARTICLE</string>
<string name="notifications_thank_you_edit">Gràcies per fer una modificació</string> <string name="notifications_thank_you_edit">Gràcies per fer una modificació</string>
<string name="notifications_mention" fuzzy="true">%1$s us ha mencionat a %2$s.</string> <string name="notifications_mention" fuzzy="true">%1$s us ha mencionat a %2$s.</string>
<string name="about_faq">Preguntes freqüents</string> <string name="about_faq" fuzzy="true">Preguntes freqüents</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Умар
-->
<resources> <resources>
<string name="crash_dialog_ok_toast">Баркалла!</string> <string name="crash_dialog_ok_toast">Баркалла!</string>
</resources> </resources>

View file

@ -1,6 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Chmee2
* Ilimanaq29
* Patriccck
-->
<resources> <resources>
<string name="crash_dialog_title">Commons spadly</string> <string name="crash_dialog_title">Aplikace Commons spadla</string>
<string name="crash_dialog_text">Něco se pokazilo!</string> <string name="crash_dialog_text">Něco se pokazilo!</string>
<string name="crash_dialog_comment_prompt">Řekněte nám, co jste dělali a dejte nám to vědět e-mailem. Pomůže sjednat nápravu!</string> <string name="crash_dialog_comment_prompt">Řekněte nám, co jste dělali a dejte nám to vědět e-mailem. Pomůže sjednat nápravu!</string>
<string name="crash_dialog_ok_toast">Děkujeme vám!</string> <string name="crash_dialog_ok_toast">Děkujeme vám!</string>

View file

@ -1,4 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Aktron
* Chmee2
* Dvorapa
* Frettie
* Ilimanaq29
* Jkjk
* Leanes
* Matěj Suchánek
* Mormegil
* Patriccck
* Spotter
* Vojtěch Dostál
* Walter Klosse
-->
<resources> <resources>
<string name="preference_category_appearance">Vzhled</string> <string name="preference_category_appearance">Vzhled</string>
<string name="preference_category_general">Obecné</string> <string name="preference_category_general">Obecné</string>
@ -59,6 +74,7 @@
<string name="categories_search_text_hint">Hledání kategorií</string> <string name="categories_search_text_hint">Hledání kategorií</string>
<string name="menu_save_categories">Uložit</string> <string name="menu_save_categories">Uložit</string>
<string name="refresh_button">Obnovit</string> <string name="refresh_button">Obnovit</string>
<string name="display_list_button">Seznam</string>
<string name="gps_disabled">GPS ve vašem zařízení není povoleno. Chtěli byste ho spustit?</string> <string name="gps_disabled">GPS ve vašem zařízení není povoleno. Chtěli byste ho spustit?</string>
<string name="enable_gps">Spustit GPS</string> <string name="enable_gps">Spustit GPS</string>
<string name="contributions_subtitle_zero">Žádné nahrané soubory</string> <string name="contributions_subtitle_zero">Žádné nahrané soubory</string>
@ -151,8 +167,8 @@
<string name="detail_description_empty">Bez popisu</string> <string name="detail_description_empty">Bez popisu</string>
<string name="detail_license_empty">Neznámá licence</string> <string name="detail_license_empty">Neznámá licence</string>
<string name="menu_refresh">Obnovit</string> <string name="menu_refresh">Obnovit</string>
<string name="read_storage_permission_rationale">Požadováno oprávnění ke čtení externího úložiště. Aplikace bez toho nemůže pracovat.</string> <string name="read_storage_permission_rationale">Požadované oprávnění: Čtení externího úložiště. Aplikace bez toho nemůže pracovat.</string>
<string name="write_storage_permission_rationale">Požadováno oprávnění k zápisu do externího úložiště. Aplikace bez toho nemůže pracovat.</string> <string name="write_storage_permission_rationale">Požadované oprávnění: Zapisování do externího úložiště. Aplikace bez toho nemůže pracovat.</string>
<string name="location_permission_rationale">Volitelně: Umožněte aplikaci, aby získávala aktuální polohu a nabízela na jejím základě kategorie</string> <string name="location_permission_rationale">Volitelně: Umožněte aplikaci, aby získávala aktuální polohu a nabízela na jejím základě kategorie</string>
<string name="ok">OK</string> <string name="ok">OK</string>
<string name="title_activity_nearby">Místa v okolí</string> <string name="title_activity_nearby">Místa v okolí</string>
@ -211,6 +227,7 @@
<string name="no_description_found">nebyl nalezen žádný popisek</string> <string name="no_description_found">nebyl nalezen žádný popisek</string>
<string name="nearby_info_menu_commons_article">Stránka souboru na Commons</string> <string name="nearby_info_menu_commons_article">Stránka souboru na Commons</string>
<string name="nearby_info_menu_wikidata_article">Položka Wikidat</string> <string name="nearby_info_menu_wikidata_article">Položka Wikidat</string>
<string name="nearby_info_menu_wikipedia_article">Článek na Wikipedii</string>
<string name="error_while_cache">Chyba při meziukládání obrázků</string> <string name="error_while_cache">Chyba při meziukládání obrázků</string>
<string name="title_info">Unikátní a popisný název pro daný soubor, který bude sloužit jako název souboru. Můžete použít běžný psaný jazyk s mezerami; nezahrnujte koncovku souboru.</string> <string name="title_info">Unikátní a popisný název pro daný soubor, který bude sloužit jako název souboru. Můžete použít běžný psaný jazyk s mezerami; nezahrnujte koncovku souboru.</string>
<string name="description_info">Popište prosím obrázek, jak jen to je možné: Kde byl pořízen? Co znázorňuje? Jaký je kontext obrázku? Popisujte prosím významné předměty nebo osoby na obrázku a nezapomeňte na informace, které není možné snadno odhadnout ze samotného obrázku, jako je například denní doba, pokud jde o krajinu. Pokud je na obrázku něco neobvyklého, popište, co to dělá neobvyklým.</string> <string name="description_info">Popište prosím obrázek, jak jen to je možné: Kde byl pořízen? Co znázorňuje? Jaký je kontext obrázku? Popisujte prosím významné předměty nebo osoby na obrázku a nezapomeňte na informace, které není možné snadno odhadnout ze samotného obrázku, jako je například denní doba, pokud jde o krajinu. Pokud je na obrázku něco neobvyklého, popište, co to dělá neobvyklým.</string>
@ -225,6 +242,8 @@
<string name="no_web_browser">Nebyl nalezen žádný webový prohlížeč k otevření URL</string> <string name="no_web_browser">Nebyl nalezen žádný webový prohlížeč k otevření URL</string>
<string name="null_url">Chyba! URL nenalezeno</string> <string name="null_url">Chyba! URL nenalezeno</string>
<string name="nominate_deletion">Navrhnout na smazání</string> <string name="nominate_deletion">Navrhnout na smazání</string>
<string name="nominated_for_deletion">Tento obrázek byl nominován na smazání.</string>
<string name="nominated_see_more"> .</string>
<string name="view_browser">Zobrazit v prohlížeči</string> <string name="view_browser">Zobrazit v prohlížeči</string>
<string name="nearby_location_has_not_changed">Vaše umístění se nezměnilo.</string> <string name="nearby_location_has_not_changed">Vaše umístění se nezměnilo.</string>
<string name="nearby_location_not_available">Umístění není dostupné.</string> <string name="nearby_location_not_available">Umístění není dostupné.</string>
@ -236,6 +255,21 @@
<string name="notifications_thank_you_edit">Děkujeme za vaši editaci</string> <string name="notifications_thank_you_edit">Děkujeme za vaši editaci</string>
<string name="notifications_mention">%1$s vás zmínil na %2$s.</string> <string name="notifications_mention">%1$s vás zmínil na %2$s.</string>
<string name="toggle_view_button">Přepnout pohled</string> <string name="toggle_view_button">Přepnout pohled</string>
<string name="about_faq">Často kladené dotazy</string> <string name="nearby_directions">POKYNY</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIE</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_rate_us">&lt;u&gt;Ohodnoť nás&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;Často kladené otázky&lt;/u&gt;</string>
<string name="welcome_skip_button">Přeskočit úvod</string> <string name="welcome_skip_button">Přeskočit úvod</string>
<string name="no_internet">Internet je nedostupný</string>
<string name="internet_established">Internet je dostupný</string>
<string name="error_notifications">Při načítání oznámení došlo k chybě</string>
<string name="no_notifications">Nebyly nalezeny žádné oznámení</string>
<string name="about_translate">&lt;u&gt;Přeložit&lt;/u&gt;</string>
<string name="about_translate_title">Jazyky</string>
<string name="about_translate_message">Vyberte jazyk, pro který chcete odeslat překlady</string>
<string name="about_translate_proceed">Pokračovat</string>
<string name="about_translate_cancel">Zrušit</string>
<string name="retry">Zkusit znovu</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kaszeba
-->
<resources> <resources>
<string name="crash_dialog_title">Pókôza sã fela Commons.</string> <string name="crash_dialog_title">Pókôza sã fela Commons.</string>
<string name="crash_dialog_text">Wejle! Cos je lëchò pòszłé!</string> <string name="crash_dialog_text">Wejle! Cos je lëchò pòszłé!</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Kaszeba
-->
<resources> <resources>
<string name="app_name">Commons</string> <string name="app_name">Commons</string>
<string name="menu_settings">Nastôwë</string> <string name="menu_settings">Nastôwë</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Lloffiwr
* Robin Owain
-->
<resources> <resources>
<string name="crash_dialog_title">Aeth rhywbeth o\'i le yn Comin</string> <string name="crash_dialog_title">Aeth rhywbeth o\'i le yn Comin</string>
<string name="crash_dialog_text">Wwwwps. Aeth rhywbeth o\'i le!</string> <string name="crash_dialog_text">Wwwwps. Aeth rhywbeth o\'i le!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Cymrodor
* Lloffiwr
* Robin Owain
-->
<resources> <resources>
<string name="app_name">Comin Wicimedia</string> <string name="app_name">Comin Wicimedia</string>
<string name="menu_settings">Gosodiadau</string> <string name="menu_settings">Gosodiadau</string>

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Christian List
* Jsmakaayb
-->
<resources> <resources>
<string name="crash_dialog_title">Commons gik ned</string> <string name="crash_dialog_title">Commons gik ned</string>
<string name="crash_dialog_text">Ups. Noget gik galt!</string> <string name="crash_dialog_text">Ups. Noget gik galt!</string>

View file

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Christian List
* Envlh
* Joedalton
* Jsmakaayb
* Luckas
* Overlaet
-->
<resources> <resources>
<string name="preference_category_appearance">Udseende</string> <string name="preference_category_appearance">Udseende</string>
<string name="preference_category_general">Generelt</string> <string name="preference_category_general">Generelt</string>
@ -151,8 +159,8 @@
<string name="detail_description_empty">Ingen beskrivelse</string> <string name="detail_description_empty">Ingen beskrivelse</string>
<string name="detail_license_empty">Ukendt licens</string> <string name="detail_license_empty">Ukendt licens</string>
<string name="menu_refresh">Opdater</string> <string name="menu_refresh">Opdater</string>
<string name="read_storage_permission_rationale">Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse.</string> <string name="read_storage_permission_rationale" fuzzy="true">Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse.</string>
<string name="write_storage_permission_rationale">Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion.</string> <string name="write_storage_permission_rationale" fuzzy="true">Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion.</string>
<string name="location_permission_rationale">Valgfri tilladelse: Hent nuværende position for kategoriforslag</string> <string name="location_permission_rationale">Valgfri tilladelse: Hent nuværende position for kategoriforslag</string>
<string name="ok">O.k.</string> <string name="ok">O.k.</string>
<string name="title_activity_nearby">Steder i nærheden</string> <string name="title_activity_nearby">Steder i nærheden</string>
@ -236,6 +244,6 @@
<string name="notifications_thank_you_edit">Tak fordi du lavede en redigering</string> <string name="notifications_thank_you_edit">Tak fordi du lavede en redigering</string>
<string name="notifications_mention">%1$s nævnte dig på %2$s.</string> <string name="notifications_mention">%1$s nævnte dig på %2$s.</string>
<string name="toggle_view_button">Skift visning</string> <string name="toggle_view_button">Skift visning</string>
<string name="about_faq">Ofte stillede spørgsmål</string> <string name="about_faq" fuzzy="true">Ofte stillede spørgsmål</string>
<string name="welcome_skip_button">Udelad øvelse</string> <string name="welcome_skip_button">Udelad øvelse</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Metalhead64
-->
<resources> <resources>
<string name="crash_dialog_title">Commons ist abgestürzt</string> <string name="crash_dialog_title">Commons ist abgestürzt</string>
<string name="crash_dialog_text">Huch! Etwas ist schiefgelaufen.</string> <string name="crash_dialog_text">Huch! Etwas ist schiefgelaufen.</string>

View file

@ -1,4 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Envlh
* Inkowik
* Kghbln
* Metalhead64
* Sujan
-->
<resources> <resources>
<string name="preference_category_appearance">Erscheinung</string> <string name="preference_category_appearance">Erscheinung</string>
<string name="preference_category_general">Allgemein</string> <string name="preference_category_general">Allgemein</string>
@ -152,8 +159,8 @@
<string name="detail_description_empty">Keine Beschreibung</string> <string name="detail_description_empty">Keine Beschreibung</string>
<string name="detail_license_empty">Unbekannte Lizenz</string> <string name="detail_license_empty">Unbekannte Lizenz</string>
<string name="menu_refresh">Aktualisieren</string> <string name="menu_refresh">Aktualisieren</string>
<string name="read_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher lesen. Die App funktioniert ohne diese Berechtigung nicht.</string> <string name="read_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher lesen. Die App kann ohne diese Berechtigung nicht auf deine Galerie zugreifen.</string>
<string name="write_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne dies nicht funktionieren.</string> <string name="write_storage_permission_rationale">Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne diese Berechtigung nicht auf deine Kamera zugreifen.</string>
<string name="location_permission_rationale">Optionale Berechtigung: Ruft den aktuellen Standort für Kategorievorschläge ab</string> <string name="location_permission_rationale">Optionale Berechtigung: Ruft den aktuellen Standort für Kategorievorschläge ab</string>
<string name="ok">Okay</string> <string name="ok">Okay</string>
<string name="title_activity_nearby">Orte in der Nähe</string> <string name="title_activity_nearby">Orte in der Nähe</string>
@ -227,6 +234,8 @@
<string name="no_web_browser">Zum Öffnen der URL wurde kein Webbrowser gefunden</string> <string name="no_web_browser">Zum Öffnen der URL wurde kein Webbrowser gefunden</string>
<string name="null_url">Fehler! URL nicht gefunden</string> <string name="null_url">Fehler! URL nicht gefunden</string>
<string name="nominate_deletion">Zur Löschung vorschlagen</string> <string name="nominate_deletion">Zur Löschung vorschlagen</string>
<string name="nominated_for_deletion">Dieses Bild wurde zur Löschung vorgeschlagen.</string>
<string name="nominated_see_more"/>
<string name="view_browser">Im Browser ansehen</string> <string name="view_browser">Im Browser ansehen</string>
<string name="nearby_location_has_not_changed">Der Standort hat sich nicht geändert.</string> <string name="nearby_location_has_not_changed">Der Standort hat sich nicht geändert.</string>
<string name="nearby_location_not_available">Der Standort ist nicht verfügbar.</string> <string name="nearby_location_not_available">Der Standort ist nicht verfügbar.</string>
@ -242,7 +251,17 @@
<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"/> <string name="about_rate_us">&lt;u&gt;Bewerte uns&lt;/u&gt;</string>
<string name="about_faq">Häufig gestellte Fragen</string> <string name="about_faq">&lt;u&gt;Häufig gestellte Fragen&lt;/u&gt;</string>
<string name="welcome_skip_button">Tutorial überspringen</string> <string name="welcome_skip_button">Tutorial überspringen</string>
<string name="no_internet">Internet nicht verfügbar</string>
<string name="internet_established">Internet verfügbar</string>
<string name="error_notifications">Fehler beim Abruf der Benachrichtigungen</string>
<string name="no_notifications">Keine Benachrichtigungen gefunden</string>
<string name="about_translate">&lt;u&gt;Übersetzen&lt;/u&gt;</string>
<string name="about_translate_title">Sprachen</string>
<string name="about_translate_message">Wähle die Sprache aus, für die du Übersetzungen durchführen möchtest.</string>
<string name="about_translate_proceed">Fortfahren</string>
<string name="about_translate_cancel">Abbrechen</string>
<string name="retry">Erneut versuchen</string>
</resources> </resources>

View file

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 1917 Ekim Devrimi
* Gorizon
* Marmase
* Mirzali
-->
<resources> <resources>
<string name="crash_dialog_title">Commons lığiya</string> <string name="crash_dialog_title">Commons lığiya</string>
<string name="crash_dialog_text">Oops. Thebayo nigurweyino!</string> <string name="crash_dialog_text">Oops. Thebayo nigurweyino!</string>
<string name="crash_dialog_comment_prompt">Şıma se kerd bı, marê vacê. Dıma e-posta ra bırışê marê. Ney timar kerdışi de marê beno desteg!</string> <string name="crash_dialog_comment_prompt">Şıma se kerd bı, marê vacê. Dıma e-posta ra bırışê marê. Ney timar kerdışi de marê beno desteg!</string>
<string name="crash_dialog_ok_toast">Teşekur kena</string> <string name="crash_dialog_ok_toast">Teşekur kenan!</string>
</resources> </resources>

View file

@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 1917 Ekim Devrimi
* Envlh
* Gambollar
* Gorizon
* Gırd
* Marmase
* Mirzali
-->
<resources> <resources>
<string name="app_name">Commons</string> <string name="app_name">Commons</string>
<string name="menu_settings">Eyari</string> <string name="menu_settings">Eyari</string>
@ -26,7 +35,7 @@
</plurals> </plurals>
<string name="title_activity_contributions">Barkerdışê mınê peyêni</string> <string name="title_activity_contributions">Barkerdışê mınê peyêni</string>
<string name="contribution_state_queued">Ratneya</string> <string name="contribution_state_queued">Ratneya</string>
<string name="contribution_state_failed">Nêbı</string> <string name="contribution_state_failed">Ebe ser nêkewt</string>
<string name="contribution_state_in_progress">%1$d%% temamya</string> <string name="contribution_state_in_progress">%1$d%% temamya</string>
<string name="contribution_state_starting">Bar beno</string> <string name="contribution_state_starting">Bar beno</string>
<string name="menu_from_gallery">Galeri ra</string> <string name="menu_from_gallery">Galeri ra</string>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Nirajan pant
-->
<resources> <resources>
<string name="crash_dialog_text">हैत्मरा। केइचीज गलत भयो।</string> <string name="crash_dialog_text">हैत्मरा। केइचीज गलत भयो।</string>
<string name="crash_dialog_ok_toast">धन्यवाद!</string> <string name="crash_dialog_ok_toast">धन्यवाद!</string>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Auslaender
* Evropi
* Geraki
-->
<resources> <resources>
<string name="crash_dialog_title">Τα Commons παρουσίασαν σφάλμα</string> <string name="crash_dialog_title">Τα Commons παρουσίασαν σφάλμα</string>
<string name="crash_dialog_text">Ωχ. Κάτι πήγε στραβά!</string> <string name="crash_dialog_text">Ωχ. Κάτι πήγε στραβά!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Astralnet
* Evropi
* Geraki
* Glavkos
* KATRINE1992
* ManosHacker
* Nikosgranturismogt
* Nikosguard
* Tgkarounos
-->
<resources> <resources>
<string name="preference_category_appearance">Εμφάνιση</string> <string name="preference_category_appearance">Εμφάνιση</string>
<string name="preference_category_general">Γενικά</string> <string name="preference_category_general">Γενικά</string>
@ -152,8 +163,8 @@
<string name="detail_description_empty">Καμία περιγραφή</string> <string name="detail_description_empty">Καμία περιγραφή</string>
<string name="detail_license_empty">Άγνωστη άδεια</string> <string name="detail_license_empty">Άγνωστη άδεια</string>
<string name="menu_refresh">Ανανέωση</string> <string name="menu_refresh">Ανανέωση</string>
<string name="read_storage_permission_rationale">Απαιτούμενη άδεια: Ανάγνωση εξωτερικής αποθήκευσης. Η εφαρμογή δεν μπορεί να λειτουργήσει χωρίς αυτή.</string> <string name="read_storage_permission_rationale">Απαιτούμενη άδεια: Ανάγνωση εξωτερικής αποθήκευσης. Η εφαρμογή δεν μπορεί να έχει πρόσβαση στην συλλογή σας χωρίς αυτή.</string>
<string name="write_storage_permission_rationale">Απαιτούμενη άδεια: Με εξωτερική αποθήκευση.Το πρόγραμμα δεν μπορεί να λειτουργήσει με αυτήν.</string> <string name="write_storage_permission_rationale">Απαιτούμενη άδεια: Με εξωτερική αποθήκευση. Το πρόγραμμα δεν μπορεί να έχει πρόσβαση στην κάμερα σας χωρίς αυτήν.</string>
<string name="location_permission_rationale">Προαιρετική άδεια: Ανάκτηση τρέχουσας θέσης σας για προτάσεις κατηγοριών</string> <string name="location_permission_rationale">Προαιρετική άδεια: Ανάκτηση τρέχουσας θέσης σας για προτάσεις κατηγοριών</string>
<string name="ok">Εντάξει</string> <string name="ok">Εντάξει</string>
<string name="title_activity_nearby">Κοντινοί Τόποι</string> <string name="title_activity_nearby">Κοντινοί Τόποι</string>
@ -227,6 +238,8 @@
<string name="no_web_browser">Δεν βρέθηκε φυλλομετρητής για το άνοιγμα της διευθύνσεως URL</string> <string name="no_web_browser">Δεν βρέθηκε φυλλομετρητής για το άνοιγμα της διευθύνσεως URL</string>
<string name="null_url">Σφάλμα! Η διεύθυνση URL δεν βρέθηκε</string> <string name="null_url">Σφάλμα! Η διεύθυνση URL δεν βρέθηκε</string>
<string name="nominate_deletion">Προτείνετε για διαγραφή</string> <string name="nominate_deletion">Προτείνετε για διαγραφή</string>
<string name="nominated_for_deletion">Αυτή εικόνα έχει προταθεί για διαγραφή.</string>
<string name="nominated_see_more"/>
<string name="view_browser">Προβολή στον περιηγητή</string> <string name="view_browser">Προβολή στον περιηγητή</string>
<string name="nearby_location_has_not_changed">Ο εντοπισμός δεν έχει αλλάξει.</string> <string name="nearby_location_has_not_changed">Ο εντοπισμός δεν έχει αλλάξει.</string>
<string name="nearby_location_not_available">Ο τόπος δεν είναι διαθέσιμος.</string> <string name="nearby_location_not_available">Ο τόπος δεν είναι διαθέσιμος.</string>
@ -242,7 +255,17 @@
<string name="nearby_wikidata">Βικιδεδομένα</string> <string name="nearby_wikidata">Βικιδεδομένα</string>
<string name="nearby_wikipedia">Βικιπαίδεια</string> <string name="nearby_wikipedia">Βικιπαίδεια</string>
<string name="nearby_commons">Κοινά</string> <string name="nearby_commons">Κοινά</string>
<string name="about_rate_us"/> <string name="about_rate_us">&lt;u&gt;Βαθμολογήστε μας&lt;/u&gt;</string>
<string name="about_faq">Συχνές ερωτήσεις</string> <string name="about_faq">&lt;u&gt;Συχνές ερωτήσεις&lt;/u&gt;</string>
<string name="welcome_skip_button">Παράβλεψη εισαγωγής</string> <string name="welcome_skip_button">Παράβλεψη εισαγωγής</string>
<string name="no_internet">Το διαδίκτυο δεν είναι διαθέσιμο</string>
<string name="internet_established">Το διαδίκτυο είναι διαθέσιμο</string>
<string name="error_notifications">Σφάλμα κατά την συγκέντρωση ειδοποιήσεων</string>
<string name="no_notifications">Δεν βρέθηκαν ειδοποιήσεις</string>
<string name="about_translate">&lt;u&gt;Μεταφράστε&lt;/u&gt;</string>
<string name="about_translate_title">Γλώσσες</string>
<string name="about_translate_message">Επιλέξτε την γλώσσα που θα θέλατε να υποβάλετε μεταφράσεις για αυτή</string>
<string name="about_translate_proceed">Συνέχεια</string>
<string name="about_translate_cancel">Ακύρωση</string>
<string name="retry">Ξαναπροσπαθήστε</string>
</resources> </resources>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Fitoschido
* Jduranboger
* Vivaelcelta
-->
<resources> <resources>
<string name="crash_dialog_title">Commons falló</string> <string name="crash_dialog_title">Commons falló</string>
<string name="crash_dialog_text">Vaya. ¡Algo salió mal!</string> <string name="crash_dialog_text">Vaya. ¡Algo salió mal!</string>

View file

@ -1,4 +1,15 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* 2axterix2
* Benfutbol10
* Fitoschido
* Jduranboger
* Luisangelrg
* Macofe
* MarionaDSR
* Miguel2706
* Vivaelcelta
-->
<resources> <resources>
<string name="preference_category_appearance">Apariencia</string> <string name="preference_category_appearance">Apariencia</string>
<string name="preference_category_general">Generales</string> <string name="preference_category_general">Generales</string>
@ -59,6 +70,7 @@
<string name="categories_search_text_hint">Buscar categorías</string> <string name="categories_search_text_hint">Buscar categorías</string>
<string name="menu_save_categories">Guardar</string> <string name="menu_save_categories">Guardar</string>
<string name="refresh_button">Actualizar</string> <string name="refresh_button">Actualizar</string>
<string name="display_list_button">Lista</string>
<string name="gps_disabled">El GPS está desactivado en tu dispositivo. ¿Quieres activarlo?</string> <string name="gps_disabled">El GPS está desactivado en tu dispositivo. ¿Quieres activarlo?</string>
<string name="enable_gps">Activar GPS</string> <string name="enable_gps">Activar GPS</string>
<string name="contributions_subtitle_zero">No hay subidas aún</string> <string name="contributions_subtitle_zero">No hay subidas aún</string>
@ -125,7 +137,7 @@
<string name="tutorial_1_text">Wikimedia Commons aloja la mayoría de las imágenes utilizadas en Wikipedia.</string> <string name="tutorial_1_text">Wikimedia Commons aloja la mayoría de las imágenes utilizadas en Wikipedia.</string>
<string name="tutorial_1_subtext">¡Tus imágenes ayudan a instruir a personas de todo el mundo!</string> <string name="tutorial_1_subtext">¡Tus imágenes ayudan a instruir a personas de todo el mundo!</string>
<string name="tutorial_2_text">Carga únicamente imágenes capturadas o creadas por ti.</string> <string name="tutorial_2_text">Carga únicamente imágenes capturadas o creadas por ti.</string>
<string name="tutorial_2_subtext" fuzzy="true">- Objetos naturales (flores, animales, montañas)\n- Objetos útiles (bicicletas, estaciones de tren)\n- Personas famosas (tu alcalde, algún atleta olímpico que conociste)</string> <string name="tutorial_2_subtext">Objetos naturales (flores, animales, montañas)\n• Objetos útiles (bicicletas, estaciones de tren)\n• Personas famosas (tu alcalde, algún atleta olímpico que conociste)</string>
<string name="tutorial_2_subtext_1">Naturaleza (flores, animales, montañas)</string> <string name="tutorial_2_subtext_1">Naturaleza (flores, animales, montañas)</string>
<string name="tutorial_2_subtext_2">Objetos utilitarios (bicicletas, estaciones de tren)</string> <string name="tutorial_2_subtext_2">Objetos utilitarios (bicicletas, estaciones de tren)</string>
<string name="tutorial_2_subtext_3">Gente famosa (tu regente, algún atleta que hayas conocido…)</string> <string name="tutorial_2_subtext_3">Gente famosa (tu regente, algún atleta que hayas conocido…)</string>
@ -138,6 +150,7 @@
<string name="tutorial_4_subtext">- Título: Casa de la Ópera de Sídney\n- Descripción: Casa de la Ópera de Sídney vista desde el otro lado de la bahía\n- Categorías: Casa de la Ópera de Sídney desde el oeste, Vistas a distancia de la Casa de la Ópera de Sídney</string> <string name="tutorial_4_subtext">- Título: Casa de la Ópera de Sídney\n- Descripción: Casa de la Ópera de Sídney vista desde el otro lado de la bahía\n- Categorías: Casa de la Ópera de Sídney desde el oeste, Vistas a distancia de la Casa de la Ópera de Sídney</string>
<string name="tutorial_4_subtext_1">Título: Ópera de Sídney</string> <string name="tutorial_4_subtext_1">Título: Ópera de Sídney</string>
<string name="tutorial_4_subtext_2">Descripción: La Ópera de Sídney, vista desde el otro lado de la bahía</string> <string name="tutorial_4_subtext_2">Descripción: La Ópera de Sídney, vista desde el otro lado de la bahía</string>
<string name="tutorial_4_subtext_3">Categorías: Ópera de Sídney desde el oeste, Vistas a distancia de la Ópera de Sídney</string>
<string name="welcome_wikipedia_text">Contribuye con tus imágenes.\n¡Ayuda a que los artículos de Wikipedia tengan vida!</string> <string name="welcome_wikipedia_text">Contribuye con tus imágenes.\n¡Ayuda a que los artículos de Wikipedia tengan vida!</string>
<string name="welcome_wikipedia_subtext">Las imágenes en Wikipedia proceden de\nWikimedia Commons.</string> <string name="welcome_wikipedia_subtext">Las imágenes en Wikipedia proceden de\nWikimedia Commons.</string>
<string name="welcome_copyright_text">Tus imágenes ayudan a educar a la gente\nalrededor del mundo.</string> <string name="welcome_copyright_text">Tus imágenes ayudan a educar a la gente\nalrededor del mundo.</string>
@ -150,8 +163,8 @@
<string name="detail_description_empty">Sin descripción</string> <string name="detail_description_empty">Sin descripción</string>
<string name="detail_license_empty">Licencia desconocida</string> <string name="detail_license_empty">Licencia desconocida</string>
<string name="menu_refresh">Actualizar</string> <string name="menu_refresh">Actualizar</string>
<string name="read_storage_permission_rationale">Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede funcionar sin él.</string> <string name="read_storage_permission_rationale">Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede acceder a la galería sin él.</string>
<string name="write_storage_permission_rationale">Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede funcionar sin él.</string> <string name="write_storage_permission_rationale">Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede acceder a la cámara sin él.</string>
<string name="location_permission_rationale">Permiso opcional: obtener la ubicación actual para sugerir categorías</string> <string name="location_permission_rationale">Permiso opcional: obtener la ubicación actual para sugerir categorías</string>
<string name="ok">Aceptar</string> <string name="ok">Aceptar</string>
<string name="title_activity_nearby">Lugares cercanos</string> <string name="title_activity_nearby">Lugares cercanos</string>
@ -210,6 +223,7 @@
<string name="no_description_found">no se encontró ninguna descripción</string> <string name="no_description_found">no se encontró ninguna descripción</string>
<string name="nearby_info_menu_commons_article">Página del archivo en Commons</string> <string name="nearby_info_menu_commons_article">Página del archivo en Commons</string>
<string name="nearby_info_menu_wikidata_article">Elemento de Wikidata</string> <string name="nearby_info_menu_wikidata_article">Elemento de Wikidata</string>
<string name="nearby_info_menu_wikipedia_article">Artículo de Wikipedia</string>
<string name="error_while_cache">Error al almacenar imágenes en la antememoria</string> <string name="error_while_cache">Error al almacenar imágenes en la antememoria</string>
<string name="title_info">Un título único descriptivo para el archivo, que servirá como un nombre de archivo. Puede usar un lenguaje claro con espacios. No incluya la extensión del archivo.</string> <string name="title_info">Un título único descriptivo para el archivo, que servirá como un nombre de archivo. Puede usar un lenguaje claro con espacios. No incluya la extensión del archivo.</string>
<string name="description_info">Por favor, describa el elemento multimedia tanto como sea posible: ¿dónde fue tomado?, ¿qué muestra?, ¿cuál es el contexto? Por favor, describa los objetos o personas. Ofrezca la información que no puede ser inferida tan fácilmente, por ejemplo el momento del día si es un paisaje. Si el medio muestra algo inusual, explique qué lo hace insual.</string> <string name="description_info">Por favor, describa el elemento multimedia tanto como sea posible: ¿dónde fue tomado?, ¿qué muestra?, ¿cuál es el contexto? Por favor, describa los objetos o personas. Ofrezca la información que no puede ser inferida tan fácilmente, por ejemplo el momento del día si es un paisaje. Si el medio muestra algo inusual, explique qué lo hace insual.</string>
@ -224,6 +238,7 @@
<string name="no_web_browser">No se encontró ningún navegador con el que abrir el URL</string> <string name="no_web_browser">No se encontró ningún navegador con el que abrir el URL</string>
<string name="null_url">Error: no se encontró el URL</string> <string name="null_url">Error: no se encontró el URL</string>
<string name="nominate_deletion">Nominar para borrado</string> <string name="nominate_deletion">Nominar para borrado</string>
<string name="nominated_for_deletion">Se ha nominado esta imagen para su borrado.</string>
<string name="view_browser">Ver en navegador</string> <string name="view_browser">Ver en navegador</string>
<string name="nearby_location_has_not_changed">La ubicación no ha cambiado.</string> <string name="nearby_location_has_not_changed">La ubicación no ha cambiado.</string>
<string name="nearby_location_not_available">La ubicación no está disponible.</string> <string name="nearby_location_not_available">La ubicación no está disponible.</string>
@ -234,5 +249,19 @@
<string name="notifications_talk_page_message">%1$s dejó un mensaje en tu página de discusión</string> <string name="notifications_talk_page_message">%1$s dejó un mensaje en tu página de discusión</string>
<string name="notifications_thank_you_edit">Gracias por realizar una edición</string> <string name="notifications_thank_you_edit">Gracias por realizar una edición</string>
<string name="notifications_mention">%1$s te ha mencionado en %2$s.</string> <string name="notifications_mention">%1$s te ha mencionado en %2$s.</string>
<string name="about_faq">Preguntas frecuentes</string> <string name="nearby_directions">CÓMO LLEGAR</string>
<string name="nearby_wikidata">WIKIDATA</string>
<string name="nearby_wikipedia">WIKIPEDIA</string>
<string name="nearby_commons">COMMONS</string>
<string name="about_faq">&lt;u&gt;Preguntas frecuentes&lt;/u&gt;</string>
<string name="welcome_skip_button">Omitir tutorial</string>
<string name="no_internet">Internet no disponible</string>
<string name="internet_established">Internet disponible</string>
<string name="error_notifications">Error al recuperar las notificaciones</string>
<string name="no_notifications">No se encontró ninguna notificación</string>
<string name="about_translate">&lt;u&gt;Traducir&lt;/u&gt;</string>
<string name="about_translate_title">Idiomas</string>
<string name="about_translate_message">Selecciona el idioma en que quieres enviar traducciones</string>
<string name="about_translate_cancel">Cancelar</string>
<string name="retry">Reintentar</string>
</resources> </resources>

View file

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Theklan
-->
<resources> <resources>
<string name="crash_dialog_title">Commons apurtu da</string> <string name="crash_dialog_title">Commons apurtu da</string>
<string name="crash_dialog_text">Uiii. Zerbait gaizki dabil!</string> <string name="crash_dialog_text">Uiii. Zerbait gaizki dabil!</string>

View file

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* An13sa
* Fitoschido
* Mikel Ibaiba
* Sator
* Subi
* Theklan
-->
<resources> <resources>
<string name="app_name">Commons</string> <string name="app_name">Commons</string>
<string name="menu_settings">Hobespenak</string> <string name="menu_settings">Hobespenak</string>

View file

@ -1,4 +1,10 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Ebraminio
* Mjbmr
* Reza1615
* جواد
-->
<resources> <resources>
<string name="crash_dialog_title">ویکی‌انبار متوقف شده‌است</string> <string name="crash_dialog_title">ویکی‌انبار متوقف شده‌است</string>
<string name="crash_dialog_text">اوه. خطایی در کار است!</string> <string name="crash_dialog_text">اوه. خطایی در کار است!</string>

View file

@ -1,11 +1,27 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Arash.pt
* Ebraminio
* Mjbmr
* Omidh
* Ommmmid
* Reza1615
* Yoosef Pooranvary
* جواد
-->
<resources> <resources>
<string name="preference_category_appearance">نمایش صفحه</string>
<string name="preference_category_general">عمومی</string>
<string name="preference_category_feedback">بازخورد</string>
<string name="preference_category_location">مکان</string>
<string name="app_name">ویکی‌انبار</string> <string name="app_name">ویکی‌انبار</string>
<string name="bullet"></string>
<string name="menu_settings">تنظیمات</string> <string name="menu_settings">تنظیمات</string>
<string name="username">نام کاربری</string> <string name="username">نام کاربری</string>
<string name="password">گذرواژه</string> <string name="password">گذرواژه</string>
<string name="login_credential">به حساب کاربری ویکی‌انبار آزمایشی وارد شوید</string> <string name="login_credential">به حساب کاربری ویکی‌انبار آزمایشی وارد شوید</string>
<string name="login">ورود</string> <string name="login">ورود</string>
<string name="forgot_password">رمز خود را فراموش کرده‌اید؟</string>
<string name="signup">ثبت نام</string> <string name="signup">ثبت نام</string>
<string name="logging_in_title">واردشدن</string> <string name="logging_in_title">واردشدن</string>
<string name="logging_in_message">شکیبا باشید...</string> <string name="logging_in_message">شکیبا باشید...</string>
@ -37,6 +53,7 @@
<string name="menu_share">به اشتراک‌گذاشتن</string> <string name="menu_share">به اشتراک‌گذاشتن</string>
<string name="menu_open_in_browser">مشاهده در مرورگر</string> <string name="menu_open_in_browser">مشاهده در مرورگر</string>
<string name="share_title_hint">عنوان</string> <string name="share_title_hint">عنوان</string>
<string name="add_title_toast">لطفاً نامی را برای این پرونده انتخاب کنید</string>
<string name="share_description_hint">توضیحات</string> <string name="share_description_hint">توضیحات</string>
<string name="login_failed_network">قادر به ورود نیست - شکست شبکه‌ای</string> <string name="login_failed_network">قادر به ورود نیست - شکست شبکه‌ای</string>
<string name="login_failed_username">ناتوانی در ورود - لطفاً نام کاربریتان را بررسی کنید</string> <string name="login_failed_username">ناتوانی در ورود - لطفاً نام کاربریتان را بررسی کنید</string>
@ -52,6 +69,7 @@
<string name="categories_search_text_hint">جستجوی رده‌ها</string> <string name="categories_search_text_hint">جستجوی رده‌ها</string>
<string name="menu_save_categories">ذخیره</string> <string name="menu_save_categories">ذخیره</string>
<string name="refresh_button">تازه کردن</string> <string name="refresh_button">تازه کردن</string>
<string name="display_list_button">فهرست</string>
<string name="gps_disabled">مکان‌یاب در دستگاه شما خاموش است. آیا دوست دارید فعال شود؟</string> <string name="gps_disabled">مکان‌یاب در دستگاه شما خاموش است. آیا دوست دارید فعال شود؟</string>
<string name="enable_gps">فعال کردن مکان‌یاب</string> <string name="enable_gps">فعال کردن مکان‌یاب</string>
<string name="contributions_subtitle_zero">هنوز هیچ بارگذاری</string> <string name="contributions_subtitle_zero">هنوز هیچ بارگذاری</string>
@ -72,8 +90,8 @@
<string name="menu_about">درباره</string> <string name="menu_about">درباره</string>
<string name="about_license">اپلیکیشن ویکی‌انبار بنیاد ویکی‌مدیا یک نرم‌افزار آزاد است که توسط کاربران داوطلب و پاداش‌بگیر ایجاد و نگهداری می‌شود. بنیاد ویکی‌مدیا در ایجاد، نگهداری و توسعهٔ آن دخالتی ندارد.</string> <string name="about_license">اپلیکیشن ویکی‌انبار بنیاد ویکی‌مدیا یک نرم‌افزار آزاد است که توسط کاربران داوطلب و پاداش‌بگیر ایجاد و نگهداری می‌شود. بنیاد ویکی‌مدیا در ایجاد، نگهداری و توسعهٔ آن دخالتی ندارد.</string>
<string name="about_improve">ایجاد یک &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;درخواست در گیت‌هاب&lt;/a&gt; برای گزارش باگ و یا پیشنهاد یک خصوصیت جدید.</string> <string name="about_improve">ایجاد یک &lt;a href=\"https://github.com/commons-app/apps-android-commons/issues\"&gt;درخواست در گیت‌هاب&lt;/a&gt; برای گزارش باگ و یا پیشنهاد یک خصوصیت جدید.</string>
<string name="about_privacy_policy" fuzzy="true">&lt;a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\"&gt;سیاست حفظ حریم خصوصی&lt;/a&gt;</string> <string name="about_privacy_policy">&lt;u&gt;سیاست حفظ حریم خصوصی&lt;/u&gt;</string>
<string name="about_credits" fuzzy="true">&lt;a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\"&gt;مجوز&lt;/a&gt;</string> <string name="about_credits">&lt;u&gt;مجوز&lt;/u&gt;</string>
<string name="title_activity_about">درباره</string> <string name="title_activity_about">درباره</string>
<string name="menu_feedback">ارسال بازخورد (از طریق ایمیل)</string> <string name="menu_feedback">ارسال بازخورد (از طریق ایمیل)</string>
<string name="no_email_client">نرم‌افزار ایمیل نصب نیست</string> <string name="no_email_client">نرم‌افزار ایمیل نصب نیست</string>
@ -85,7 +103,7 @@
<string name="share_license_summary">این نگاره تحت مجوز %1$s است</string> <string name="share_license_summary">این نگاره تحت مجوز %1$s است</string>
<string name="media_upload_policy">با بارگذاری این تصویر، تأیید می‌کنم که این اثر کار خودم است و از محتوای دارای حق تکثیر یا سلفی برای ایجاد آن استفاده نکرده‌ام و شرایط ذکر شده در By submitting this picture, I declare that this is my own work, that it does not contain copyrighted material or selfies, and otherwise adheres to &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;سیاست‌های ویکی‌انبار&lt;/a&gt; را رعایت می‌کند.</string> <string name="media_upload_policy">با بارگذاری این تصویر، تأیید می‌کنم که این اثر کار خودم است و از محتوای دارای حق تکثیر یا سلفی برای ایجاد آن استفاده نکرده‌ام و شرایط ذکر شده در By submitting this picture, I declare that this is my own work, that it does not contain copyrighted material or selfies, and otherwise adheres to &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;سیاست‌های ویکی‌انبار&lt;/a&gt; را رعایت می‌کند.</string>
<string name="menu_download">دریافت</string> <string name="menu_download">دریافت</string>
<string name="preference_license" fuzzy="true">مجوز</string> <string name="preference_license">مجوز پیش‌فرض</string>
<string name="use_previous">از عنوان/توضیحات پیشین استفاده کنید</string> <string name="use_previous">از عنوان/توضیحات پیشین استفاده کنید</string>
<string name="allow_gps">دریافت خودکار موقعیت کنونی</string> <string name="allow_gps">دریافت خودکار موقعیت کنونی</string>
<string name="allow_gps_summary">درحال دریافت موقعیت برای پیشنهاد رده در صورتی که برچسب جغرافیایی وجود نداشته باشد.</string> <string name="allow_gps_summary">درحال دریافت موقعیت برای پیشنهاد رده در صورتی که برچسب جغرافیایی وجود نداشته باشد.</string>
@ -114,7 +132,7 @@
<string name="tutorial_1_text">ویکی‌انبار اکثر پرونده‌هایی که در ویکی‌پدیا استفاده می‌شوند را در خود نگه می‌دارد.</string> <string name="tutorial_1_text">ویکی‌انبار اکثر پرونده‌هایی که در ویکی‌پدیا استفاده می‌شوند را در خود نگه می‌دارد.</string>
<string name="tutorial_1_subtext">تصاویر شما به مردم در اقصی نقاط دنیا کمک می‌کند!</string> <string name="tutorial_1_subtext">تصاویر شما به مردم در اقصی نقاط دنیا کمک می‌کند!</string>
<string name="tutorial_2_text">لطفاً تصاویری که توسط خودتان گرفته شده‌اند یا ایجاد شده‌اند را بارگذاری کنید:</string> <string name="tutorial_2_text">لطفاً تصاویری که توسط خودتان گرفته شده‌اند یا ایجاد شده‌اند را بارگذاری کنید:</string>
<string name="tutorial_2_subtext" fuzzy="true">-اجسام طبیعی (گیاه، جانور، کوه)\n-اجسام کاربردی (دوچرخه، ایستگاه قطار)\n-افراد مشهور (شهردار، قهرمانان المپیک)</string> <string name="tutorial_2_subtext">•اجسام طبیعی (گیاه، جانور، کوه)\n•اجسام کاربردی (دوچرخه، ایستگاه قطار)\n•افراد مشهور (شهردار، قهرمانان المپیک)</string>
<string name="tutorial_3_text">لطفاً بارگذاری نکنید:</string> <string name="tutorial_3_text">لطفاً بارگذاری نکنید:</string>
<string name="tutorial_3_subtext">-سلفی خودتان یا تصویر دوستانتان\n-تصاویری که از اینترنت دانلود کردید\n-نماگرفت از دیگر اپلیکیشن‌‌ها</string> <string name="tutorial_3_subtext">-سلفی خودتان یا تصویر دوستانتان\n-تصاویری که از اینترنت دانلود کردید\n-نماگرفت از دیگر اپلیکیشن‌‌ها</string>
<string name="tutorial_4_text">نمونه بارگذاری:</string> <string name="tutorial_4_text">نمونه بارگذاری:</string>
@ -131,8 +149,8 @@
<string name="detail_description_empty">بدون توضیحات</string> <string name="detail_description_empty">بدون توضیحات</string>
<string name="detail_license_empty">مجوز ناشناخته</string> <string name="detail_license_empty">مجوز ناشناخته</string>
<string name="menu_refresh">تازه‌کردن</string> <string name="menu_refresh">تازه‌کردن</string>
<string name="read_storage_permission_rationale">اجازه‌های مورد نیاز: مطالعهٔ حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند.</string> <string name="read_storage_permission_rationale" fuzzy="true">اجازه‌های مورد نیاز: مطالعهٔ حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند.</string>
<string name="write_storage_permission_rationale">اجازه‌های مورد نیاز: نوشتن حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند.</string> <string name="write_storage_permission_rationale" fuzzy="true">اجازه‌های مورد نیاز: نوشتن حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند.</string>
<string name="location_permission_rationale">اجازه‌های اختیاری: دریافت موقعیت برای پیشنهاد رده</string> <string name="location_permission_rationale">اجازه‌های اختیاری: دریافت موقعیت برای پیشنهاد رده</string>
<string name="ok">تأیید</string> <string name="ok">تأیید</string>
<string name="title_activity_nearby">مکان‌‌های اطراف</string> <string name="title_activity_nearby">مکان‌‌های اطراف</string>
@ -202,6 +220,8 @@
<string name="login_to_your_account">ورود به حساب کاربریتان</string> <string name="login_to_your_account">ورود به حساب کاربریتان</string>
<string name="send_log_file">ارسال فایل سیاهه</string> <string name="send_log_file">ارسال فایل سیاهه</string>
<string name="send_log_file_description">ارسال فایل سیاهه به‌وسیلهٔ ایمیل برای توسعه‌دهندگان</string> <string name="send_log_file_description">ارسال فایل سیاهه به‌وسیلهٔ ایمیل برای توسعه‌دهندگان</string>
<string name="nominated_see_more"> .</string>
<string name="view_browser">مشاهده در مرورگر</string>
<string name="nearby_location_has_not_changed">مکان تغییر نکرده‌است.</string> <string name="nearby_location_has_not_changed">مکان تغییر نکرده‌است.</string>
<string name="nearby_location_not_available">مکان موجود نیست.</string> <string name="nearby_location_not_available">مکان موجود نیست.</string>
<string name="location_permission_rationale_nearby">برای نمایش مکان‌ّای اطراف نیاز به اجازه است.</string> <string name="location_permission_rationale_nearby">برای نمایش مکان‌ّای اطراف نیاز به اجازه است.</string>
@ -212,4 +232,18 @@
<string name="notifications_thank_you_edit">برای ویرایش ممنون</string> <string name="notifications_thank_you_edit">برای ویرایش ممنون</string>
<string name="notifications_mention">%1$s در %2$s به شما اشاره کرده‌است.</string> <string name="notifications_mention">%1$s در %2$s به شما اشاره کرده‌است.</string>
<string name="toggle_view_button">دکمه نمایش</string> <string name="toggle_view_button">دکمه نمایش</string>
<string name="nearby_directions">جهت‌ها</string>
<string name="nearby_wikidata">ویکی‌داده</string>
<string name="nearby_wikipedia">ویکی‌پدیا</string>
<string name="nearby_commons">ویکی‌انبار</string>
<string name="about_rate_us">&lt;u&gt;رتبه ما&lt;/u&gt;</string>
<string name="about_faq">&lt;u&gt;سوال‌های متداول&lt;/u&gt;</string>
<string name="welcome_skip_button">رهاکردن آموزش</string>
<string name="no_internet">اینترنت در دسترس نیست</string>
<string name="internet_established">اینترنت در دسترس است</string>
<string name="about_translate">&lt;u&gt;ترجمه&lt;/u&gt;</string>
<string name="about_translate_title">زبان‌ها</string>
<string name="about_translate_proceed">ادامه</string>
<string name="about_translate_cancel">لغو</string>
<string name="retry">سعى دوباره</string>
</resources> </resources>

View file

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Nike
* Olli
* Silvonen
-->
<resources> <resources>
<string name="crash_dialog_title">Commons app on kaatunut</string> <string name="crash_dialog_title">Commons app on kaatunut</string>
<string name="crash_dialog_text">Pahoittelemme, virhe tapahtui.</string> <string name="crash_dialog_text">Pahoittelemme, virhe tapahtui.</string>

View file

@ -1,4 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* Alluk.
* Crt
* Nike
* Olli
* Pahkiqaz
* Pyscowicz
* SMAUG
* Samoasambia
* Silvonen
* Stryn
-->
<resources> <resources>
<string name="preference_category_appearance">Ulkoasu</string> <string name="preference_category_appearance">Ulkoasu</string>
<string name="preference_category_general">Yleinen</string> <string name="preference_category_general">Yleinen</string>
@ -149,8 +161,8 @@
<string name="detail_description_empty">Ei kuvausta</string> <string name="detail_description_empty">Ei kuvausta</string>
<string name="detail_license_empty">Tuntematon lisenssi</string> <string name="detail_license_empty">Tuntematon lisenssi</string>
<string name="menu_refresh">Päivitä</string> <string name="menu_refresh">Päivitä</string>
<string name="read_storage_permission_rationale">Vaadittu oikeus: Ulkoisen tallennustilan luku. Appi ei toimi ilman tätä oikeutta.</string> <string name="read_storage_permission_rationale" fuzzy="true">Vaadittu oikeus: Ulkoisen tallennustilan luku. Appi ei toimi ilman tätä oikeutta.</string>
<string name="write_storage_permission_rationale">Vaadittava lupa: Kirjoita ulkoiseen tallennustilaan. Sovellus ei voi toimia ilman tätä.</string> <string name="write_storage_permission_rationale" fuzzy="true">Vaadittava lupa: Kirjoita ulkoiseen tallennustilaan. Sovellus ei voi toimia ilman tätä.</string>
<string name="location_permission_rationale">Valinnainen lupa: Saada tämänhetkinen sijainti loukkasuosituksia varten.</string> <string name="location_permission_rationale">Valinnainen lupa: Saada tämänhetkinen sijainti loukkasuosituksia varten.</string>
<string name="ok">OK</string> <string name="ok">OK</string>
<string name="title_activity_nearby">Lähellä olevat paikat</string> <string name="title_activity_nearby">Lähellä olevat paikat</string>
@ -231,6 +243,6 @@
<string name="notifications_thank_you_edit">Kiitos muokkaamisestasi</string> <string name="notifications_thank_you_edit">Kiitos muokkaamisestasi</string>
<string name="notifications_mention">%1$s mainitsi sinut %2$s.</string> <string name="notifications_mention">%1$s mainitsi sinut %2$s.</string>
<string name="toggle_view_button">Vaihda näkymä</string> <string name="toggle_view_button">Vaihda näkymä</string>
<string name="about_faq">Usein Kysytyt Kysymykset</string> <string name="about_faq" fuzzy="true">Usein Kysytyt Kysymykset</string>
<string name="welcome_skip_button">Ohita opetus</string> <string name="welcome_skip_button">Ohita opetus</string>
</resources> </resources>

Some files were not shown because too many files have changed in this diff Show more