diff --git a/CHANGELOG.md b/CHANGELOG.md index 035835839..7f3dfc30a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # 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 - Added null checks to prevent frequent crashes in ModificationsSyncAdapter diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ee7f42e06..0f1feeac7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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) diff --git a/CREDITS b/CREDITS index a4a4ae0f5..6847ac9b6 100644 --- a/CREDITS +++ b/CREDITS @@ -30,6 +30,16 @@ their contribution to the product. * Bruke Mekuria Mulugeta * Paul Hawke * 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: * Butterknife diff --git a/app/build.gradle b/app/build.gradle index 06996d5a6..46008d1c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,18 +11,19 @@ dependencies { implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' implementation 'in.yuvi:http.fluent:1.3' 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 'commons-codec:commons-codec:1.10' implementation 'com.github.pedrovgs:renderers:3.3.3' implementation 'com.google.code.gson:gson:2.8.1' implementation 'com.jakewharton.timber:timber:4.5.1' 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'){ transitive=true } - implementation "com.android.support:support-v4:$SUPPORT_LIB_VERSION" implementation "com.android.support:appcompat-v7:$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. implementation 'com.android.support:multidex:1.0.3' - testImplementation "org.robolectric:multidex:3.4.2" - implementation 'io.reactivex.rxjava2:rxjava:2.1.2' implementation 'com.jakewharton.rxbinding2:rxbinding: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-android-support:$DAGGER_VERSION" - kapt "com.google.dagger:dagger-android-processor:$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" - androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" - + testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" testImplementation 'junit:junit:4.12' 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' + + androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" androidTestImplementation 'com.squareup.okhttp3:mockwebserver:3.8.1' 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" releaseImplementation "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 { @@ -91,8 +82,8 @@ android { defaultConfig { applicationId 'fr.free.nrw.commons' - versionCode 82 - versionName '2.6.7' + versionCode 83 + versionName '2.7.0' setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) minSdkVersion project.minSdkVersion diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 253bdaea8..6aab09b55 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -91,6 +91,10 @@ android:name=".notification.NotificationActivity" android:label="@string/navigation_item_notification" /> + + languageAdapter = new ArrayAdapter(AboutActivity.this, diff --git a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java index 5638db97e..57cb5fad1 100644 --- a/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java +++ b/app/src/main/java/fr/free/nrw/commons/CommonsApplication.java @@ -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_SUBJECT = "Commons Android App (%s) Feedback"; + 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; diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java index a873136fe..a41a52139 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java @@ -280,8 +280,11 @@ public class CategorizationFragment extends CommonsDaggerSupportFragment { private Observable directCategories() { String directCategory = directPrefs.getString("Category", ""); + // Strip newlines to prevent blank categories, and to tidy existing categories + directCategory = directCategory.replace("\n", ""); + List categoryList = new ArrayList<>(); - Timber.d("Direct category found: " + directCategory); + Timber.d("Direct category found: " + "'" + directCategory + "'"); if (!directCategory.equals("")) { hasDirectCategories = true; diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDao.java b/app/src/main/java/fr/free/nrw/commons/category/CategoryDao.java index a5202046b..010e97095 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryDao.java +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDao.java @@ -105,6 +105,7 @@ public class CategoryDao { return items; } + @NonNull Category fromCursor(Cursor cursor) { // Hardcoding column positions! return new Category( diff --git a/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java b/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java index e4fb13427..f88f3b34a 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/ActivityBuilderModule.java @@ -7,6 +7,7 @@ import fr.free.nrw.commons.WelcomeActivity; import fr.free.nrw.commons.auth.LoginActivity; import fr.free.nrw.commons.auth.SignupActivity; import fr.free.nrw.commons.contributions.ContributionsActivity; +import fr.free.nrw.commons.featured.FeaturedImagesActivity; import fr.free.nrw.commons.nearby.NearbyActivity; import fr.free.nrw.commons.notification.NotificationActivity; import fr.free.nrw.commons.settings.SettingsActivity; @@ -46,4 +47,7 @@ public abstract class ActivityBuilderModule { @ContributesAndroidInjector abstract NotificationActivity bindNotificationActivity(); + + @ContributesAndroidInjector + abstract FeaturedImagesActivity bindFeaturedImagesActivity(); } diff --git a/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java b/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java index a94f46ca9..c5cdcb5a7 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java +++ b/app/src/main/java/fr/free/nrw/commons/di/FragmentBuilderModule.java @@ -4,6 +4,7 @@ import dagger.Module; import dagger.android.ContributesAndroidInjector; import fr.free.nrw.commons.category.CategorizationFragment; import fr.free.nrw.commons.contributions.ContributionsListFragment; +import fr.free.nrw.commons.featured.FeaturedImagesListFragment; import fr.free.nrw.commons.media.MediaDetailFragment; import fr.free.nrw.commons.media.MediaDetailPagerFragment; import fr.free.nrw.commons.nearby.NearbyListFragment; @@ -47,4 +48,7 @@ public abstract class FragmentBuilderModule { @ContributesAndroidInjector abstract SingleUploadFragment bindSingleUploadFragment(); + @ContributesAndroidInjector + abstract FeaturedImagesListFragment bindFeaturedImagesListFragment(); + } diff --git a/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImage.java b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImage.java new file mode 100644 index 000000000..853fba29e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImage.java @@ -0,0 +1,44 @@ +package fr.free.nrw.commons.featured; + + +import fr.free.nrw.commons.Media; + +/** + * Object to hold FeaturedImage + */ + +public class FeaturedImage { + private Media image; + private String author; + private String fileName; + + public FeaturedImage(Media image, String author, String fileName) { + this.image = image; + this.author = author; + this.fileName = fileName; + } + + public Media getImage() { + return image; + } + + public void setImage(Media image) { + this.image = image; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesActivity.java b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesActivity.java new file mode 100644 index 000000000..a2dc7b00b --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesActivity.java @@ -0,0 +1,114 @@ +package fr.free.nrw.commons.featured; + +import android.database.DataSetObserver; +import android.os.Bundle; +import android.support.v4.app.FragmentManager; +import android.view.View; +import android.widget.AdapterView; + +import butterknife.ButterKnife; +import fr.free.nrw.commons.Media; +import fr.free.nrw.commons.R; +import fr.free.nrw.commons.auth.AuthenticatedActivity; +import fr.free.nrw.commons.media.MediaDetailPagerFragment; + +/** + * This activity displays pic of the days of last xx days + */ + +public class FeaturedImagesActivity + extends AuthenticatedActivity + implements FragmentManager.OnBackStackChangedListener, + MediaDetailPagerFragment.MediaDetailProvider, + AdapterView.OnItemClickListener{ + + private FeaturedImagesListFragment featuredImagesListFragment; + private MediaDetailPagerFragment mediaDetails; + + @Override + protected void onAuthCookieAcquired(String authCookie) { + + } + + @Override + protected void onAuthFailure() { + + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_featured_images); + ButterKnife.bind(this); + + // Activity can call methods in the fragment by acquiring a + // reference to the Fragment from FragmentManager, using findFragmentById() + FragmentManager supportFragmentManager = getSupportFragmentManager(); + featuredImagesListFragment = (FeaturedImagesListFragment)supportFragmentManager + .findFragmentById(R.id.featuedListFragment); + + supportFragmentManager.addOnBackStackChangedListener(this); + if (savedInstanceState != null) { + mediaDetails = (MediaDetailPagerFragment)supportFragmentManager + .findFragmentById(R.id.featuredFragmentContainer); + + } + requestAuthToken(); + initDrawer(); + setTitle(getString(R.string.title_activity_featured_images)); + } + + @Override + public void onBackStackChanged() { + + } + + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + if (mediaDetails == null || !mediaDetails.isVisible()) { + // set isFeaturedImage true for featured images, to include author field on media detail + mediaDetails = new MediaDetailPagerFragment(false, true); + FragmentManager supportFragmentManager = getSupportFragmentManager(); + supportFragmentManager + .beginTransaction() + .replace(R.id.featuredFragmentContainer, mediaDetails) + .addToBackStack(null) + .commit(); + supportFragmentManager.executePendingTransactions(); + } + mediaDetails.showImage(i); + } + + @Override + public Media getMediaAtPosition(int i) { + if (featuredImagesListFragment.getAdapter() == null) { + // not yet ready to return data + return null; + } else { + return ((FeaturedImage)featuredImagesListFragment.getAdapter().getItem(i)).getImage(); + } + } + + @Override + public int getTotalMediaCount() { + if (featuredImagesListFragment.getAdapter() == null) { + return 0; + } + return featuredImagesListFragment.getAdapter().getCount(); + } + + @Override + public void notifyDatasetChanged() { + + } + + @Override + public void registerDataSetObserver(DataSetObserver observer) { + + } + + @Override + public void unregisterDataSetObserver(DataSetObserver observer) { + + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesListFragment.java b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesListFragment.java new file mode 100644 index 000000000..3e5c37bd6 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/featured/FeaturedImagesListFragment.java @@ -0,0 +1,57 @@ +package fr.free.nrw.commons.featured; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.GridView; +import android.widget.ListAdapter; + +import java.util.ArrayList; + +import butterknife.ButterKnife; +import dagger.android.support.DaggerFragment; +import fr.free.nrw.commons.Media; +import fr.free.nrw.commons.R; + + +/** + * Created by root on 09.01.2018. + */ + +public class FeaturedImagesListFragment extends DaggerFragment { + private GridView gridView; + private MockGridViewAdapter gridAdapter; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.fragment_featured_images, container, false); + ButterKnife.bind(this, v); + return v; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + gridView = getView().findViewById(R.id.featuredImagesList); + gridView.setOnItemClickListener((AdapterView.OnItemClickListener) getActivity()); + gridAdapter = new MockGridViewAdapter(this.getContext(), R.layout.layout_featured_images, getMockFeaturedImages()); + gridView.setAdapter(gridAdapter); + + } + + private ArrayList getMockFeaturedImages(){ + ArrayList featuredImages = new ArrayList<>(); + for (int i=0; i<10; i++){ + featuredImages.add(new FeaturedImage(new Media("test.jpg"), "username: test", "test file name")); + } + return featuredImages; + } + + public ListAdapter getAdapter() { + return gridView.getAdapter(); + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/featured/MockGridViewAdapter.java b/app/src/main/java/fr/free/nrw/commons/featured/MockGridViewAdapter.java new file mode 100644 index 000000000..7aa2a8892 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/featured/MockGridViewAdapter.java @@ -0,0 +1,50 @@ +package fr.free.nrw.commons.featured; + +import android.app.Activity; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import java.util.ArrayList; + +import fr.free.nrw.commons.MediaWikiImageView; +import fr.free.nrw.commons.R; + +/** + * This is created to only display UI implementation. Needs to be changed in real implementation + */ + +public class MockGridViewAdapter extends ArrayAdapter { + private Context context; + private int layoutResourceId; + private ArrayList data = new ArrayList(); + + public MockGridViewAdapter(Context context, int layoutResourceId, ArrayList data) { + super(context, layoutResourceId, data); + this.layoutResourceId = layoutResourceId; + this.context = context; + this.data = data; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + + if (convertView == null) { + LayoutInflater inflater = ((Activity) context).getLayoutInflater(); + convertView = inflater.inflate(R.layout.layout_featured_images, null); + } + + FeaturedImage item = data.get(position); + MediaWikiImageView imageView = convertView.findViewById(R.id.featuredImageView); + TextView fileName = convertView.findViewById(R.id.featuredImageTitle); + TextView author = convertView.findViewById(R.id.featuredImageAuthor); + fileName.setText("Test file name"); + author.setText("Uploaded by: Test user name"); + imageView.setMedia(item.getImage()); + return convertView; + } + +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java index b06869e8d..5acfb218e 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.java @@ -50,14 +50,16 @@ import static android.widget.Toast.LENGTH_SHORT; public class MediaDetailFragment extends CommonsDaggerSupportFragment { private boolean editable; + private boolean isFeaturedMedia; private MediaDetailPagerFragment.MediaDetailProvider detailProvider; private int index; - public static MediaDetailFragment forMedia(int index, boolean editable) { + public static MediaDetailFragment forMedia(int index, boolean editable, boolean isFeaturedMedia) { MediaDetailFragment mf = new MediaDetailFragment(); Bundle state = new Bundle(); state.putBoolean("editable", editable); + state.putBoolean("isFeaturedMedia", isFeaturedMedia); state.putInt("index", index); state.putInt("listIndex", 0); state.putInt("listTop", 0); @@ -79,12 +81,14 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { private TextView title; private TextView desc; + private TextView author; private TextView license; private TextView coordinates; private TextView uploadedDate; private TextView seeMore; private LinearLayout nominatedforDeletion; private LinearLayout categoryContainer; + private LinearLayout authorLayout; private Button delete; private ScrollView scrollView; private ArrayList categoryNames; @@ -101,6 +105,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { super.onSaveInstanceState(outState); outState.putInt("index", index); outState.putBoolean("editable", editable); + outState.putBoolean("isFeaturedMedia", isFeaturedMedia); getScrollPosition(); outState.putInt("listTop", initialListTop); @@ -116,13 +121,16 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { if (savedInstanceState != null) { editable = savedInstanceState.getBoolean("editable"); + isFeaturedMedia = savedInstanceState.getBoolean("isFeaturedMedia"); index = savedInstanceState.getInt("index"); initialListTop = savedInstanceState.getInt("listTop"); } else { editable = getArguments().getBoolean("editable"); + isFeaturedMedia = getArguments().getBoolean("isFeaturedMedia"); index = getArguments().getInt("index"); initialListTop = 0; } + categoryNames = new ArrayList<>(); categoryNames.add(getString(R.string.detail_panel_cats_loading)); @@ -135,6 +143,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { spacer = (MediaDetailSpacer) view.findViewById(R.id.mediaDetailSpacer); title = (TextView) view.findViewById(R.id.mediaDetailTitle); desc = (TextView) view.findViewById(R.id.mediaDetailDesc); + author = (TextView) view.findViewById(R.id.mediaDetailAuthor); license = (TextView) view.findViewById(R.id.mediaDetailLicense); coordinates = (TextView) view.findViewById(R.id.mediaDetailCoordinates); uploadedDate = (TextView) view.findViewById(R.id.mediaDetailuploadeddate); @@ -142,6 +151,13 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { nominatedforDeletion = (LinearLayout) view.findViewById(R.id.nominatedDeletionBanner); delete = (Button) view.findViewById(R.id.nominateDeletion); categoryContainer = (LinearLayout) view.findViewById(R.id.mediaDetailCategoryContainer); + authorLayout = (LinearLayout) view.findViewById(R.id.authorLinearLayout); + + if (isFeaturedMedia){ + authorLayout.setVisibility(View.VISIBLE); + } else { + authorLayout.setVisibility(View.GONE); + } licenseList = new LicenseList(getActivity()); @@ -304,9 +320,10 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { coordinates.setOnClickListener(v -> openMap(media.getCoordinates())); } if (delete.getVisibility() == View.VISIBLE) { + enableDeleteButton(true); + delete.setOnClickListener(v -> { - delete.setEnabled(false); - delete.setTextColor(getResources().getColor(R.color.deleteButtonLight)); + AlertDialog.Builder alert = new AlertDialog.Builder(getActivity()); alert.setMessage("Why should this file be deleted?"); final EditText input = new EditText(getActivity()); @@ -317,6 +334,7 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { String reason = input.getText().toString(); DeleteTask deleteTask = new DeleteTask(getActivity(), media, reason); deleteTask.execute(); + enableDeleteButton(false); } }); alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @@ -358,6 +376,15 @@ public class MediaDetailFragment extends CommonsDaggerSupportFragment { } } + 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() { categoryContainer.removeAllViews(); // @fixme add the category items diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index be7aea836..c0564c603 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -55,14 +55,16 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple private ViewPager pager; private Boolean editable; + private boolean isFeaturedImage; public MediaDetailPagerFragment() { - this(false); + this(false, false); } @SuppressLint("ValidFragment") - public MediaDetailPagerFragment(Boolean editable) { + public MediaDetailPagerFragment(Boolean editable, boolean isFeaturedImage) { this.editable = editable; + this.isFeaturedImage = isFeaturedImage; } @Override @@ -96,6 +98,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple super.onSaveInstanceState(outState); outState.putInt("current-page", pager.getCurrentItem()); outState.putBoolean("editable", editable); + outState.putBoolean("isFeaturedImage", isFeaturedImage); } @Override @@ -103,6 +106,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple super.onCreate(savedInstanceState); if (savedInstanceState != null) { editable = savedInstanceState.getBoolean("editable"); + isFeaturedImage = savedInstanceState.getBoolean("isFeaturedImage"); } setHasOptionsMenu(true); } @@ -291,7 +295,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple // See bug https://code.google.com/p/android/issues/detail?id=27526 pager.postDelayed(() -> getActivity().supportInvalidateOptionsMenu(), 5); } - return MediaDetailFragment.forMedia(i, editable); + return MediaDetailFragment.forMedia(i, editable, isFeaturedImage); } @Override diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/DirectUpload.java b/app/src/main/java/fr/free/nrw/commons/nearby/DirectUpload.java index b58afa82a..7ab427b2d 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/DirectUpload.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/DirectUpload.java @@ -8,6 +8,7 @@ import android.support.v7.app.AlertDialog; import fr.free.nrw.commons.R; import fr.free.nrw.commons.contributions.ContributionController; +import timber.log.Timber; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; @@ -23,46 +24,25 @@ class DirectUpload { this.controller = controller; } - void initiateCameraUpload() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - 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(); - } - } - + // These permission requests will be handled by the Fragments. + // Do not use requestCode 1 as it will conflict with NearbyActivity's requestCodes void initiateGalleryUpload() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 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()) .setMessage(fragment.getActivity().getString(R.string.read_storage_permission_rationale)) .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(); }) .setNegativeButton("Cancel", null) .create() .show(); } else { - fragment.getActivity().requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, - 1); + fragment.requestPermissions(new String[]{READ_EXTERNAL_STORAGE}, + 4); } } else { controller.startGalleryPick(); @@ -72,4 +52,28 @@ class DirectUpload { 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(); + } + } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java index 88d5880f5..ea88de341 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyActivity.java @@ -10,17 +10,14 @@ import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.BottomSheetBehavior; - import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AlertDialog; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.LinearLayout; import android.widget.ProgressBar; -import android.widget.Toast; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -31,7 +28,6 @@ import javax.inject.Inject; import butterknife.BindView; import butterknife.ButterKnife; - import fr.free.nrw.commons.R; import fr.free.nrw.commons.location.LatLng; import fr.free.nrw.commons.location.LocationServiceManager; @@ -39,13 +35,11 @@ import fr.free.nrw.commons.location.LocationUpdateListener; 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.ViewUtil; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; - import timber.log.Timber; @@ -68,7 +62,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp @Inject NearbyController nearbyController; - private LatLng curLatLang; + private LatLng curLatLng; private Bundle bundle; private Disposable placesDisposable; private boolean lockNearbyView; //Determines if the nearby places needs to be refreshed @@ -136,11 +130,17 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp @Override public boolean onOptionsItemSelected(MenuItem item) { + // Handle item selection switch (item.getItemId()) { case R.id.action_display_list: - bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN); - bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); + if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_COLLAPSED || bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_HIDDEN){ + bottomSheetBehaviorForDetails.setState(BottomSheetBehavior.STATE_HIDDEN); + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED); + }else if(bottomSheetBehavior.getState()==BottomSheetBehavior.STATE_EXPANDED){ + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); + } + return true; default: return super.onOptionsItemSelected(item); @@ -165,6 +165,11 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp showLocationPermissionDeniedErrorDialog(); } } + break; + + default: + // This is needed to allow the request codes from the Fragments to be routed appropriately + super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @@ -262,8 +267,6 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp @Override protected void onStop() { super.onStop(); - locationManager.removeLocationListener(this); - locationManager.unregisterLocationManager(); } @Override @@ -292,8 +295,13 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp // to the retained fragment object to perform its own cleanup. removeMapFragment(); removeListFragment(); - unregisterReceiver(broadcastReceiver); + } + unregisterReceiver(broadcastReceiver); + broadcastReceiver = null; + locationManager.removeLocationListener(this); + locationManager.unregisterLocationManager(); + } private void addNetworkBroadcastReceiver() { @@ -334,12 +342,12 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp locationManager.registerLocationManager(); 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; } - curLatLang = lastLocation; + curLatLng = lastLocation; - if (curLatLang == null) { + if (curLatLng == null) { Timber.d("Skipping update of nearby places as location is unavailable"); return; } @@ -348,7 +356,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp .equals(LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED)) { progressBar.setVisibility(View.VISIBLE); placesDisposable = Observable.fromCallable(() -> nearbyController - .loadAttractionsFromLocation(curLatLang)) + .loadAttractionsFromLocation(curLatLng)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::populatePlaces); @@ -357,7 +365,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriSerializer()) .create(); - String gsonCurLatLng = gson.toJson(curLatLang); + String gsonCurLatLng = gson.toJson(curLatLng); bundle.putString("CurLatLng", gsonCurLatLng); updateMapFragment(true); } @@ -370,7 +378,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp .registerTypeAdapter(Uri.class, new UriSerializer()) .create(); String gsonPlaceList = gson.toJson(placeList); - String gsonCurLatLng = gson.toJson(curLatLang); + String gsonCurLatLng = gson.toJson(curLatLng); String gsonBoundaryCoordinates = gson.toJson(boundaryCoordinates); if (placeList.size() == 0) { @@ -422,6 +430,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp if (nearbyMapFragment != null) { android.support.v4.app.FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().remove(nearbyMapFragment).commit(); + nearbyMapFragment = null; } } @@ -433,6 +442,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp if (nearbyListFragment != null) { android.support.v4.app.FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().remove(nearbyListFragment).commit(); + nearbyListFragment = null; } } @@ -447,34 +457,34 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp 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) /* * 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 * */ if (nearbyMapFragment.boundaryCoordinates != null - && (curLatLang.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude() - || curLatLang.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude() - || curLatLang.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude() - || curLatLang.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) { + && (curLatLng.getLatitude() <= nearbyMapFragment.boundaryCoordinates[0].getLatitude() + || curLatLng.getLatitude() >= nearbyMapFragment.boundaryCoordinates[1].getLatitude() + || curLatLng.getLongitude() <= nearbyMapFragment.boundaryCoordinates[2].getLongitude() + || curLatLng.getLongitude() >= nearbyMapFragment.boundaryCoordinates[3].getLongitude())) { // populate places placesDisposable = Observable.fromCallable(() -> nearbyController - .loadAttractionsFromLocation(curLatLang)) + .loadAttractionsFromLocation(curLatLng)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(this::populatePlaces); - nearbyMapFragment.setArguments(bundle); + nearbyMapFragment.setBundleForUpdtes(bundle); nearbyMapFragment.updateMapSignificantly(); updateListFragment(); return; } if (isSlightUpdate) { - nearbyMapFragment.setArguments(bundle); + nearbyMapFragment.setBundleForUpdtes(bundle); nearbyMapFragment.updateMapSlightly(); } else { - nearbyMapFragment.setArguments(bundle); + nearbyMapFragment.setBundleForUpdtes(bundle); nearbyMapFragment.updateMapSignificantly(); updateListFragment(); } @@ -488,7 +498,7 @@ public class NearbyActivity extends NavigationBaseActivity implements LocationUp } private void updateListFragment() { - nearbyListFragment.setArguments(bundle); + nearbyListFragment.setBundleForUpdates(bundle); nearbyListFragment.updateNearbyListSignificantly(); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java index 0ecf09160..015d22135 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyController.java @@ -54,41 +54,47 @@ public class NearbyController { } List places = nearbyPlaces.getFromWikidataQuery(curLatLng, Locale.getDefault().getLanguage()); - LatLng[] boundaryCoordinates = {places.get(0).location, // south - places.get(0).location, // north - places.get(0).location, // west - places.get(0).location};// east, init with a random location + if (places.size() > 0) { + LatLng[] boundaryCoordinates = {places.get(0).location, // south + places.get(0).location, // north + places.get(0).location, // west + places.get(0).location};// east, init with a random location - if (curLatLng != null) { - Timber.d("Sorting places by distance..."); - final Map distances = new HashMap<>(); - for (Place place: places) { - distances.put(place, computeDistanceBetween(place.location, curLatLng)); - // Find boundaries with basic find max approach - 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 (curLatLng != null) { + Timber.d("Sorting places by distance..."); + final Map distances = new HashMap<>(); + for (Place place : places) { + distances.put(place, computeDistanceBetween(place.location, curLatLng)); + // Find boundaries with basic find max approach + 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); + } + ); + } + nearbyPlacesInfo.placeList = places; + nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates; + return nearbyPlacesInfo; + } + else { + return null; } - nearbyPlacesInfo.placeList = places; - nearbyPlacesInfo.boundaryCoordinates = boundaryCoordinates; - return nearbyPlacesInfo; } /** diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java index dcc7f5e24..4a2be8476 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyListFragment.java @@ -33,6 +33,8 @@ import static android.app.Activity.RESULT_OK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; 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>() { }.getType(); private static final Type CUR_LAT_LNG_TYPE = new TypeToken() { @@ -80,8 +82,7 @@ public class NearbyListFragment extends DaggerFragment { } public void updateNearbyListSignificantly() { - Bundle bundle = this.getArguments(); - adapterFactory.updateAdapterData(getPlaceListFromBundle(bundle), + adapterFactory.updateAdapterData(getPlaceListFromBundle(bundleForUpdates), (RVRendererAdapter) recyclerView.getAdapter()); } @@ -106,8 +107,8 @@ public class NearbyListFragment extends DaggerFragment { Timber.d("onRequestPermissionsResult: req code = " + " perm = " + permissions + " grant =" + grantResults); switch (requestCode) { - // 1 = "Read external storage" allowed when gallery selected - case 1: { + // 4 = "Read external storage" allowed when gallery selected + case 4: { if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { Timber.d("Call controller.startGalleryPick()"); controller.startGalleryPick(); @@ -115,8 +116,8 @@ public class NearbyListFragment extends DaggerFragment { } break; - // 3 = "Write external storage" allowed when camera selected - case 3: { + // 5 = "Write external storage" allowed when camera selected + case 5: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Timber.d("Call controller.startCameraCapture()"); controller.startCameraCapture(); @@ -140,4 +141,8 @@ public class NearbyListFragment extends DaggerFragment { } } + public void setBundleForUpdates(Bundle bundleForUpdates) { + this.bundleForUpdates = bundleForUpdates; + } + } \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java index d541a8e45..b84e04a57 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/NearbyMapFragment.java @@ -53,8 +53,10 @@ import javax.inject.Named; import dagger.android.support.DaggerFragment; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.utils.UriDeserializer; +import fr.free.nrw.commons.utils.ViewUtil; import timber.log.Timber; import static android.app.Activity.RESULT_OK; @@ -97,6 +99,7 @@ public class NearbyMapFragment extends DaggerFragment { private Animation fab_open; private Animation rotate_forward; private ContributionController controller; + private DirectUpload directUpload; private Place place; private Marker selected; @@ -105,7 +108,10 @@ public class NearbyMapFragment extends DaggerFragment { private PolygonOptions currentLocationPolygonOptions; 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 @Named("prefs") @@ -120,6 +126,10 @@ public class NearbyMapFragment extends DaggerFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + controller = new ContributionController(this); + directUpload = new DirectUpload(this, controller); + Bundle bundle = this.getArguments(); Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriDeserializer()) @@ -184,14 +194,12 @@ public class NearbyMapFragment extends DaggerFragment { } public void updateMapSlightly() { - // Get arguments from bundle for new location - Bundle bundle = this.getArguments(); if (mapboxMap != null) { Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriDeserializer()) .create(); - if (bundle != null) { - String gsonLatLng = bundle.getString("CurLatLng"); + if (bundleForUpdtes != null) { + String gsonLatLng = bundleForUpdtes.getString("CurLatLng"); Type curLatLngType = new TypeToken() {}.getType(); curLatLng = gson.fromJson(gsonLatLng, curLatLngType); } @@ -201,17 +209,15 @@ public class NearbyMapFragment extends DaggerFragment { } public void updateMapSignificantly() { - - Bundle bundle = this.getArguments(); if (mapboxMap != null) { - if (bundle != null) { + if (bundleForUpdtes != null) { Gson gson = new GsonBuilder() .registerTypeAdapter(Uri.class, new UriDeserializer()) .create(); - String gsonPlaceList = bundle.getString("PlaceList"); - String gsonLatLng = bundle.getString("CurLatLng"); - String gsonBoundaryCoordinates = bundle.getString("BoundaryCoord"); + String gsonPlaceList = bundleForUpdtes.getString("PlaceList"); + String gsonLatLng = bundleForUpdtes.getString("CurLatLng"); + String gsonBoundaryCoordinates = bundleForUpdtes.getString("BoundaryCoord"); Type listType = new TypeToken>() {}.getType(); List placeList = gson.fromJson(gsonPlaceList, listType); Type curLatLngType = new TypeToken() {}.getType(); @@ -253,13 +259,28 @@ public class NearbyMapFragment extends DaggerFragment { } // Make camera to follow user on location change - CameraPosition position = new CameraPosition.Builder() - .target(isBottomListSheetExpanded ? - new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR, - curMapBoxLatLng.getLongitude()) - : curMapBoxLatLng ) // Sets the new camera position - .zoom(mapboxMap.getCameraPosition().zoom) // Same zoom level - .build(); + CameraPosition position ; + if(ViewUtil.isPortrait(getActivity())){ + position = new CameraPosition.Builder() + .target(isBottomListSheetExpanded ? + new LatLng(curMapBoxLatLng.getLatitude()- CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT, + 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(); + }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 .newCameraPosition(position), 1000); @@ -273,12 +294,21 @@ public class NearbyMapFragment extends DaggerFragment { if (mapboxMap != null && curLatLng != null) { if (isBottomListSheetExpanded) { // Make camera to follow user on location change - position = new CameraPosition.Builder() - .target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR, - curLatLng.getLongitude())) // Sets the new camera target above - // current to make it visible when sheet is expanded - .zoom(11) // Same zoom level - .build(); + if(ViewUtil.isPortrait(getActivity())) { + position = new CameraPosition.Builder() + .target(new LatLng(curLatLng.getLatitude() - CAMERA_TARGET_SHIFT_FACTOR_PORTRAIT, + curLatLng.getLongitude())) // Sets the new camera target above + // current to make it visible when sheet is expanded + .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 { // Make camera to follow user on location change @@ -344,10 +374,29 @@ public class NearbyMapFragment extends DaggerFragment { fabRecenter.setOnClickListener(view -> { if (curLatLng != null) { mapView.getMapAsync(mapboxMap -> { - CameraPosition position = new CameraPosition.Builder() - .target(new LatLng(curLatLng.getLatitude(), curLatLng.getLongitude())) // Sets the new camera position - .zoom(11) // Sets the zoom - .build(); // Creates a CameraPosition from the builder + CameraPosition position; + + if(ViewUtil.isPortrait(getActivity())){ + 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 .newCameraPosition(position), 1000); @@ -406,6 +455,8 @@ public class NearbyMapFragment extends DaggerFragment { private void setupMapView(Bundle savedInstanceState) { MapboxMapOptions options = new MapboxMapOptions() + .compassGravity(Gravity.BOTTOM | Gravity.LEFT) + .compassMargins(new int[]{12, 0, 0, 24}) .styleUrl(Style.OUTDOORS) .logoEnabled(false) .attributionEnabled(false) @@ -534,7 +585,9 @@ public class NearbyMapFragment extends DaggerFragment { transparentView.setAlpha(0); closeFabs(isFabOpen); hideFAB(); - this.getView().requestFocus(); + if (this.getView() != null) { + this.getView().requestFocus(); + } break; } } @@ -613,7 +666,7 @@ public class NearbyMapFragment extends DaggerFragment { directionsButton.setOnClickListener(view -> { //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) { startActivity(mapIntent); } @@ -633,9 +686,6 @@ public class NearbyMapFragment extends DaggerFragment { fabCamera.setOnClickListener(view -> { if (fabCamera.isShown()) { Timber.d("Camera button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); - controller = new ContributionController(this); - - DirectUpload directUpload = new DirectUpload(this, controller); storeSharedPrefs(); directUpload.initiateCameraUpload(); } @@ -644,9 +694,6 @@ public class NearbyMapFragment extends DaggerFragment { fabGallery.setOnClickListener(view -> { if (fabGallery.isShown()) { Timber.d("Gallery button tapped. Image title: " + place.getName() + "Image desc: " + place.getLongDescription()); - controller = new ContributionController(this); - - DirectUpload directUpload = new DirectUpload(this, controller); storeSharedPrefs(); directUpload.initiateGalleryUpload(); } @@ -665,9 +712,10 @@ public class NearbyMapFragment extends DaggerFragment { public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] 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) { - // 1 = "Read external storage" allowed when gallery selected - case 1: { + // 4 = "Read external storage" allowed when gallery selected + case 4: { if (grantResults.length > 0 && grantResults[0] == PERMISSION_GRANTED) { Timber.d("Call controller.startGalleryPick()"); controller.startGalleryPick(); @@ -675,8 +723,8 @@ public class NearbyMapFragment extends DaggerFragment { } break; - // 3 = "Write external storage" allowed when camera selected - case 3: { + // 5 = "Write external storage" allowed when camera selected + case 5: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Timber.d("Call controller.startCameraCapture()"); controller.startCameraCapture(); @@ -700,8 +748,7 @@ public class NearbyMapFragment extends DaggerFragment { } private void openWebView(Uri link) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, link); - startActivity(browserIntent); + Utils.handleWebUrl(getContext(), link); } private void animateFAB(boolean isFabOpen) { @@ -724,7 +771,7 @@ public class NearbyMapFragment extends DaggerFragment { } } - private void closeFabs ( boolean isFabOpen){ + private void closeFabs ( boolean isFabOpen){ if (isFabOpen) { fabPlus.startAnimation(rotate_backward); fabCamera.startAnimation(fab_close); @@ -735,6 +782,11 @@ public class NearbyMapFragment extends DaggerFragment { } } + public void setBundleForUpdtes(Bundle bundleForUpdtes) { + this.bundleForUpdtes = bundleForUpdtes; + } + + @Override public void onStart() { if (mapView != null) { @@ -776,6 +828,9 @@ public class NearbyMapFragment extends DaggerFragment { if (mapView != null) { mapView.onDestroy(); } + selected = null; + currentLocationMarker = null; + super.onDestroyView(); } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java index 5216dc36d..9cbe28db4 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java +++ b/app/src/main/java/fr/free/nrw/commons/nearby/PlaceRenderer.java @@ -27,6 +27,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.contributions.ContributionController; import fr.free.nrw.commons.di.ApplicationlessInjection; import timber.log.Timber; @@ -200,8 +201,7 @@ public class PlaceRenderer extends Renderer { } private void openWebView(Uri link) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, link); - view.getContext().startActivity(browserIntent); + Utils.handleWebUrl(getContext(), link); } private boolean showMenu() { diff --git a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java index 7c01a44b8..dc52f198a 100644 --- a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.java @@ -6,6 +6,7 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.support.design.widget.Snackbar; import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -15,6 +16,7 @@ import android.widget.RelativeLayout; import com.pedrogomez.renderers.RVRendererAdapter; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.List; @@ -25,6 +27,7 @@ import butterknife.ButterKnife; import fr.free.nrw.commons.R; import fr.free.nrw.commons.Utils; 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.android.schedulers.AndroidSchedulers; @@ -62,9 +65,23 @@ public class NotificationActivity extends NavigationBaseActivity { recyclerView.setLayoutManager(new LinearLayoutManager(this)); DividerItemDecoration itemDecor = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL); 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") private void addNotifications() { Timber.d("Add notifications"); @@ -124,4 +141,4 @@ public class NotificationActivity extends NavigationBaseActivity { .commit(); mNotificationWorkerFragment.setNotificationList(notificationList); } -} \ No newline at end of file +} diff --git a/app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java b/app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java index 73dcaf7b5..17a318e74 100644 --- a/app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java +++ b/app/src/main/java/fr/free/nrw/commons/notification/NotificationRenderer.java @@ -47,8 +47,8 @@ public class NotificationRenderer extends Renderer { @Override public void render() { Notification notification = getContent(); - StringBuilder str = new StringBuilder(notification.notificationText.trim()); - str.append(" "); + String str = notification.notificationText.trim(); + str = str.concat(" "); title.setText(str); time.setText(notification.date); switch (notification.notificationType) { diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java index 741905e30..037f0d792 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.java @@ -151,8 +151,9 @@ public class SettingsFragment extends PreferenceFragment { emailSelectorIntent.setData(Uri.parse("mailto:")); //initialize the emailIntent final Intent emailIntent = new Intent(Intent.ACTION_SEND); - emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{CommonsApplication.FEEDBACK_EMAIL}); - emailIntent.putExtra(Intent.EXTRA_SUBJECT, String.format(CommonsApplication.FEEDBACK_EMAIL_SUBJECT, BuildConfig.VERSION_NAME)); + // Logs must be sent to the PRIVATE email. Please do not modify this without good reason! + 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_WRITE_URI_PERMISSION); emailIntent.setSelector( emailSelectorIntent ); diff --git a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java index b65d6aa25..acd9b7646 100644 --- a/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/theme/NavigationBaseActivity.java @@ -28,6 +28,7 @@ import fr.free.nrw.commons.WelcomeActivity; import fr.free.nrw.commons.auth.AccountUtil; import fr.free.nrw.commons.auth.LoginActivity; import fr.free.nrw.commons.contributions.ContributionsActivity; +import fr.free.nrw.commons.featured.FeaturedImagesActivity; import fr.free.nrw.commons.nearby.NearbyActivity; import fr.free.nrw.commons.notification.NotificationActivity; import fr.free.nrw.commons.settings.SettingsActivity; @@ -154,6 +155,10 @@ public abstract class NavigationBaseActivity extends BaseActivity drawerLayout.closeDrawer(navigationView); NotificationActivity.startYourself(this); return true; + case R.id.action_featured_images: + drawerLayout.closeDrawer(navigationView); + startActivityWithFlags(this, FeaturedImagesActivity.class, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + return true; default: Timber.e("Unknown option [%s] selected from the navigation menu", itemId); return false; diff --git a/app/src/main/java/fr/free/nrw/commons/upload/DetectUnwantedPicturesAsync.java b/app/src/main/java/fr/free/nrw/commons/upload/DetectUnwantedPicturesAsync.java index b383601ec..ab9fa5602 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/DetectUnwantedPicturesAsync.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/DetectUnwantedPicturesAsync.java @@ -1,12 +1,18 @@ package fr.free.nrw.commons.upload; +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.graphics.BitmapRegionDecoder; import android.net.Uri; import android.os.AsyncTask; +import android.support.v7.app.AlertDialog; 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 timber.log.Timber; @@ -21,16 +27,13 @@ import timber.log.Timber; public class DetectUnwantedPicturesAsync extends AsyncTask { - interface Callback { - void onResult(ImageUtils.Result result); - } - - private final Callback callback; private final String imageMediaFilePath; + public final WeakReference activityWeakReference; - DetectUnwantedPicturesAsync(String imageMediaFilePath, Callback callback) { - this.callback = callback; + DetectUnwantedPicturesAsync(WeakReference activityWeakReference, String imageMediaFilePath) { + //this.callback = callback; this.imageMediaFilePath = imageMediaFilePath; + this.activityWeakReference = activityWeakReference; } @Override @@ -53,7 +56,29 @@ public class DetectUnwantedPicturesAsync extends AsyncTask { + //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(); + } + } } } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java index ac0afa979..5525f1ba7 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/MultipleShareActivity.java @@ -237,7 +237,7 @@ public class MultipleShareActivity extends AuthenticatedActivity private void showDetail(int i) { if (mediaDetails == null || !mediaDetails.isVisible()) { - mediaDetails = new MediaDetailPagerFragment(true); + mediaDetails = new MediaDetailPagerFragment(true, false); getSupportFragmentManager() .beginTransaction() .replace(R.id.uploadsFragmentContainer, mediaDetails) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java index f5e1820b8..aca17601c 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java @@ -415,31 +415,9 @@ public class ShareActivity private void performUnwantedPictureDetectionProcess() { String imageMediaFilePath = FileUtils.getPath(this,mediaUri); - DetectUnwantedPicturesAsync detectUnwantedPicturesAsync = new DetectUnwantedPicturesAsync(imageMediaFilePath, result -> { - - if (result != ImageUtils.Result.IMAGE_OK) { - //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 detectUnwantedPicturesAsync + = new DetectUnwantedPicturesAsync(new WeakReference(this) + , imageMediaFilePath); detectUnwantedPicturesAsync.execute(); } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java index 0fa98e530..a88d03c03 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/upload/SingleUploadFragment.java @@ -14,7 +14,9 @@ import android.support.annotation.NonNull; import android.support.v4.view.ViewCompat; import android.support.v7.app.AlertDialog; import android.text.Editable; +import android.text.Html; import android.text.TextWatcher; +import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -225,18 +227,6 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment { .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) void setTitleDescButton() { @@ -294,8 +284,10 @@ public class SingleUploadFragment extends CommonsDaggerSupportFragment { @SuppressLint("StringFormatInvalid") private void setLicenseSummary(String license) { - licenseSummaryView.setText(getString(R.string.share_license_summary, getString(Utils.licenseNameFor(license)))); - } + String licenseHyperLink = ""+ getString(Utils.licenseNameFor(license)) + "
"; + licenseSummaryView.setMovementMethod(LinkMovementMethod.getInstance()); + licenseSummaryView.setText(Html.fromHtml(getString(R.string.share_license_summary, licenseHyperLink))); + } @Override public void onActivityCreated(Bundle savedInstanceState) { diff --git a/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java b/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java index e934e53e5..b9da22e6e 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/NetworkUtils.java @@ -9,7 +9,7 @@ public class NetworkUtils { public static boolean isInternetConnectionEstablished(Context context) { ConnectivityManager cm = - (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); + (ConnectivityManager)context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); return activeNetwork != null && diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java b/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java index 91e2114a9..b4b26746b 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java +++ b/app/src/main/java/fr/free/nrw/commons/utils/ViewUtil.java @@ -1,7 +1,9 @@ package fr.free.nrw.commons.utils; +import android.app.Activity; import android.content.Context; import android.support.design.widget.Snackbar; +import android.view.Display; import android.view.View; import android.widget.Toast; @@ -16,4 +18,13 @@ public class ViewUtil { 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; + } + } + } diff --git a/app/src/main/res/drawable-mdpi/share.png b/app/src/main/res/drawable-mdpi/share.png new file mode 100644 index 000000000..17473572e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/share.png differ diff --git a/app/src/main/res/drawable/ic_share_black_24dp.xml b/app/src/main/res/drawable/ic_share_black_24dp.xml new file mode 100644 index 000000000..01c81322d --- /dev/null +++ b/app/src/main/res/drawable/ic_share_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_star_black_24dp.xml b/app/src/main/res/drawable/ic_star_black_24dp.xml new file mode 100644 index 000000000..a87ca098d --- /dev/null +++ b/app/src/main/res/drawable/ic_star_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml index 9551e6e64..60519f591 100644 --- a/app/src/main/res/layout/activity_about.xml +++ b/app/src/main/res/layout/activity_about.xml @@ -111,7 +111,7 @@ android:layout_marginTop="@dimen/standard_gap" android:gravity="center" android:textColor="@color/primaryColor" - android:text="@string/about_rate_us" /> + /> + /> + /> + /> - - diff --git a/app/src/main/res/layout/activity_featured_images.xml b/app/src/main/res/layout/activity_featured_images.xml new file mode 100644 index 000000000..755fe4983 --- /dev/null +++ b/app/src/main/res/layout/activity_featured_images.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml index 6fa7c7847..60e296fd0 100644 --- a/app/src/main/res/layout/activity_welcome.xml +++ b/app/src/main/res/layout/activity_welcome.xml @@ -14,6 +14,7 @@ android:id="@+id/welcomePagerIndicator" android:layout_height="@dimen/half_standard_height" android:layout_width="match_parent" - android:layout_gravity="bottom" /> + android:layout_gravity="bottom" + android:padding="5dp" /> \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_details.xml b/app/src/main/res/layout/bottom_sheet_details.xml index 2be0f6cf7..c964fda87 100644 --- a/app/src/main/res/layout/bottom_sheet_details.xml +++ b/app/src/main/res/layout/bottom_sheet_details.xml @@ -37,8 +37,11 @@ android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="16sp" /> - + android:textSize="16sp" + android:layout_marginRight="50dp" + android:maxLines="2" + android:ellipsize="end" + /> - + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_featured_images.xml b/app/src/main/res/layout/fragment_featured_images.xml new file mode 100644 index 000000000..ca45f44c3 --- /dev/null +++ b/app/src/main/res/layout/fragment_featured_images.xml @@ -0,0 +1,40 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_media_detail.xml b/app/src/main/res/layout/fragment_media_detail.xml index 190eb011d..f265bc3ea 100644 --- a/app/src/main/res/layout/fragment_media_detail.xml +++ b/app/src/main/res/layout/fragment_media_detail.xml @@ -80,6 +80,39 @@ android:textSize="@dimen/description_text_size" /> + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_single_upload.xml b/app/src/main/res/layout/fragment_single_upload.xml index a340e0213..7eb2ed38a 100644 --- a/app/src/main/res/layout/fragment_single_upload.xml +++ b/app/src/main/res/layout/fragment_single_upload.xml @@ -74,6 +74,8 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/standard_gap" android:gravity="center" + android:clickable="true" + android:textColorLink="@color/button_blue" android:text="@string/share_license_summary" /> \ No newline at end of file diff --git a/app/src/main/res/layout/layout_featured_images.xml b/app/src/main/res/layout/layout_featured_images.xml new file mode 100644 index 000000000..399321719 --- /dev/null +++ b/app/src/main/res/layout/layout_featured_images.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml index c7aac814a..f4e6d7cb4 100644 --- a/app/src/main/res/layout/toolbar.xml +++ b/app/src/main/res/layout/toolbar.xml @@ -9,4 +9,5 @@ android:minHeight="?attr/actionBarSize" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" android:background="?attr/colorPrimaryDark"> + \ No newline at end of file diff --git a/app/src/main/res/menu/drawer.xml b/app/src/main/res/menu/drawer.xml index 61c0739fe..ae6e0cce2 100644 --- a/app/src/main/res/menu/drawer.xml +++ b/app/src/main/res/menu/drawer.xml @@ -9,6 +9,12 @@ android:id="@+id/action_nearby" android:icon="@drawable/ic_location_black_24dp" android:title="@string/navigation_item_nearby" /> + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ab/error.xml b/app/src/main/res/values-ab/error.xml index 80c41ae0f..f532642b5 100644 --- a/app/src/main/res/values-ab/error.xml +++ b/app/src/main/res/values-ab/error.xml @@ -1,4 +1,7 @@ + Аиҧҟьара Иҭабуп! diff --git a/app/src/main/res/values-ab/strings.xml b/app/src/main/res/values-ab/strings.xml index 2474f35ea..76caf25de 100644 --- a/app/src/main/res/values-ab/strings.xml +++ b/app/src/main/res/values-ab/strings.xml @@ -1,4 +1,8 @@ + Архиарақәа Ахархәаҩ ихьӡ diff --git a/app/src/main/res/values-af/error.xml b/app/src/main/res/values-af/error.xml index 929624a87..28e9241ea 100644 --- a/app/src/main/res/values-af/error.xml +++ b/app/src/main/res/values-af/error.xml @@ -1,4 +1,7 @@ + Commons het omgeval Oeps. Er is iets misgegaan. diff --git a/app/src/main/res/values-ais/error.xml b/app/src/main/res/values-ais/error.xml index 85a4b4366..e34da7329 100644 --- a/app/src/main/res/values-ais/error.xml +++ b/app/src/main/res/values-ais/error.xml @@ -1,4 +1,7 @@ + kukay diff --git a/app/src/main/res/values-ar/error.xml b/app/src/main/res/values-ar/error.xml index 27612983b..a530cf38e 100644 --- a/app/src/main/res/values-ar/error.xml +++ b/app/src/main/res/values-ar/error.xml @@ -1,4 +1,8 @@ + لقد تعطل كومنز عفوا. حدث خطأ! diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index b9ad6a10a..6d9c94c1d 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1,4 +1,19 @@ + عام كومنز diff --git a/app/src/main/res/values-arc/error.xml b/app/src/main/res/values-arc/error.xml index ce31ff09b..7c57e2649 100644 --- a/app/src/main/res/values-arc/error.xml +++ b/app/src/main/res/values-arc/error.xml @@ -1,4 +1,7 @@ + ܬܘܕܝ ܠܟ! diff --git a/app/src/main/res/values-ast/error.xml b/app/src/main/res/values-ast/error.xml index e382e1176..8f03dc62e 100644 --- a/app/src/main/res/values-ast/error.xml +++ b/app/src/main/res/values-ast/error.xml @@ -1,4 +1,7 @@ + Commons colgóse Vaya. ¡Daqué funcionó mal! diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 062b34fe8..532a4897e 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -1,4 +1,7 @@ + Aspeutu Xeneral @@ -59,6 +62,7 @@ Guetar categoríes Guardar Refrescar + Llista El GPS ta desactiváu nel preséu. ¿Quiés activalu? Activar GPS Inda nun hai xubes @@ -151,8 +155,8 @@ Ensin descripción Llicencia desconocida Refrescar - Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él. - Permisu riquíu: escritura d\'almacenamientu esternu. L\'aplicación nun puede funcionar ensin él. + Permisu riquíu: llectura d\'almacenamientu esternu. L\'aplicación nun puede entrar na to galería ensin él. + Permisu necesariu: Escritura n\'almacenamientu esternu. L\'aplicación nun puede aportar a la cámara ensin él. Permisu opcional: llograr l\'allugamientu actual pa suxerir categoríes Aceutar Llugares cercanos @@ -211,6 +215,7 @@ nun s\'atoparon descripciones Páxina del ficheru en Commons Elementu de WikiData + Artículu de Wikipedia Error al poner les fotos na caché 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 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. @@ -224,6 +229,9 @@ Unviar ficheru de rexistru a los desendolcadores per corréu electrónicu Nun s\'alcontró un restolador p\'abrir la URL ¡Error! Nun s\'alcontró la URL + Marcada pa desaniciar + Esta imaxe marcóse pa desaniciar. + Ver nel restolador L\'allugamientu nun camudó. L\'allugamientu nun ta disponible. Ríquese permisu p\'amosar una llista de llugares cercanos @@ -234,6 +242,21 @@ Gracies por facer una edición %1$s te mentó en %2$s. Alternar vista - Entrugues más frecuentes + CÓMO LLEGAR + WIKIDATA + WIKIPEDIA + COMMONS + <u>Puntúanos</u> + <u>EMF</u> Saltar el tutorial + Internet nun ta disponible + Internet ta disponible + Error al llograr les notificaciones + Nun s\'alcontraron notificaciones + <u>Traducir</u> + Llingües + Escueye l\'idioma pal que quies unviar traducciones + Siguir + Encaboxar + Retentar diff --git a/app/src/main/res/values-az/error.xml b/app/src/main/res/values-az/error.xml index ec14bbe6a..e698eab9d 100644 --- a/app/src/main/res/values-az/error.xml +++ b/app/src/main/res/values-az/error.xml @@ -1,4 +1,8 @@ + Nasazlıq Uups. Nəsə düzgün çalışmır! diff --git a/app/src/main/res/values-azb/error.xml b/app/src/main/res/values-azb/error.xml index 3d3a4d5b5..260cb0ce3 100644 --- a/app/src/main/res/values-azb/error.xml +++ b/app/src/main/res/values-azb/error.xml @@ -1,4 +1,7 @@ + کامانز ایشدن دوشدو اوخ. بیر خطا قاباغا گلدی! diff --git a/app/src/main/res/values-b+be+tarask/error.xml b/app/src/main/res/values-b+be+tarask/error.xml index d39823584..8f37a7ccc 100644 --- a/app/src/main/res/values-b+be+tarask/error.xml +++ b/app/src/main/res/values-b+be+tarask/error.xml @@ -1,4 +1,7 @@ + Дзякуем! diff --git a/app/src/main/res/values-b+hif+Latn/error.xml b/app/src/main/res/values-b+hif+Latn/error.xml index 87f0c91a8..edd98b397 100644 --- a/app/src/main/res/values-b+hif+Latn/error.xml +++ b/app/src/main/res/values-b+hif+Latn/error.xml @@ -1,4 +1,7 @@ + Commons crash hoe gais Oops, Koi chij wrong hoe gais diff --git a/app/src/main/res/values-b+kk+Cyrl/error.xml b/app/src/main/res/values-b+kk+Cyrl/error.xml index 1b0279528..905077822 100644 --- a/app/src/main/res/values-b+kk+Cyrl/error.xml +++ b/app/src/main/res/values-b+kk+Cyrl/error.xml @@ -1,4 +1,7 @@ + Рақмет! diff --git a/app/src/main/res/values-b+nds+NL/error.xml b/app/src/main/res/values-b+nds+NL/error.xml index 8ef805a5c..e16b388e5 100644 --- a/app/src/main/res/values-b+nds+NL/error.xml +++ b/app/src/main/res/values-b+nds+NL/error.xml @@ -1,4 +1,7 @@ + Commons is vasteleupen Oeps. Der gung iets mis. diff --git a/app/src/main/res/values-b+roa+tara/error.xml b/app/src/main/res/values-b+roa+tara/error.xml index 7a575379f..1a3607129 100644 --- a/app/src/main/res/values-b+roa+tara/error.xml +++ b/app/src/main/res/values-b+roa+tara/error.xml @@ -1,4 +1,7 @@ + Commons ha sckattate Mudu. Quacchecose ha sciute male! diff --git a/app/src/main/res/values-b+sr+Latn/error.xml b/app/src/main/res/values-b+sr+Latn/error.xml index 80d668c8b..7c22f8337 100644 --- a/app/src/main/res/values-b+sr+Latn/error.xml +++ b/app/src/main/res/values-b+sr+Latn/error.xml @@ -1,4 +1,7 @@ + Ostava se srušila Ups! Nešto je pošlo naopako. diff --git a/app/src/main/res/values-b+sr+Latn/strings.xml b/app/src/main/res/values-b+sr+Latn/strings.xml index f11ee10ab..0cd72a167 100644 --- a/app/src/main/res/values-b+sr+Latn/strings.xml +++ b/app/src/main/res/values-b+sr+Latn/strings.xml @@ -1,4 +1,9 @@ + Ostava Podešavanja @@ -134,8 +139,8 @@ Nema opisa Nepoznata licenca Osveži - Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše. - Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga. + Potrebna dozvola: Provera spoljašnje memorije. Aplikacija bez ovoga ne može da funkcioniše. + Neophodna dozvola: Pisanje spoljašnjeg skladišta. Aplikacija ne može da funkcioniše bez ovoga. Opciona dozvola: Preuzmi trenutnu lokaciju za predloge kategorija U redu Mesta u blizini diff --git a/app/src/main/res/values-b+tg+Cyrl/error.xml b/app/src/main/res/values-b+tg+Cyrl/error.xml index 478aa98ea..6348c138a 100644 --- a/app/src/main/res/values-b+tg+Cyrl/error.xml +++ b/app/src/main/res/values-b+tg+Cyrl/error.xml @@ -1,4 +1,7 @@ + Ташаккур! diff --git a/app/src/main/res/values-ba/error.xml b/app/src/main/res/values-ba/error.xml index d57fd8936..1dbf89be0 100644 --- a/app/src/main/res/values-ba/error.xml +++ b/app/src/main/res/values-ba/error.xml @@ -1,4 +1,7 @@ + Рәхмәт! diff --git a/app/src/main/res/values-ba/strings.xml b/app/src/main/res/values-ba/strings.xml index b8ebc950b..293dd3f73 100644 --- a/app/src/main/res/values-ba/strings.xml +++ b/app/src/main/res/values-ba/strings.xml @@ -1,4 +1,9 @@ + Тышҡы күренеш Ғәҙәти @@ -149,8 +154,8 @@ Һүрәтләүе юҡ Билдәһеҙ лицензия Яңыртып алыу - Кәрәкле рөхсәт: тышҡы һаҡлағыстан алып уҡыу. Ҡушымта шунһыҙ эшләмәйәсәк. - Кәрәкле рөхсәт: тышҡы һаҡлағысҡа яҙыу. Ҡушымта шунһыҙ эшләмәйәсәк. + Кәрәкле рөхсәт: тышҡы һаҡлағыстан алып уҡыу. Ҡушымта шунһыҙ эшләмәйәсәк. + Кәрәкле рөхсәт: тышҡы һаҡлағысҡа яҙыу. Ҡушымта шунһыҙ эшләмәйәсәк. Мотлаҡ булмаған рөхсәт: категория тәҡдиме өсөн ошо урынды алыу Яҡындағы урындар Яҡындағы урындар табылманы diff --git a/app/src/main/res/values-bcl/error.xml b/app/src/main/res/values-bcl/error.xml index 06e509b92..502ca53b1 100644 --- a/app/src/main/res/values-bcl/error.xml +++ b/app/src/main/res/values-bcl/error.xml @@ -1,4 +1,7 @@ + Kagrugaringan nagkagarabá Oops. May bagay an napasala! diff --git a/app/src/main/res/values-bg/error.xml b/app/src/main/res/values-bg/error.xml index 8a51406c3..e20b5f568 100644 --- a/app/src/main/res/values-bg/error.xml +++ b/app/src/main/res/values-bg/error.xml @@ -1,4 +1,8 @@ + Неуспех с Общомедия Опа. Нещо се обърка! diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index dd5cbfe8f..cfaf021f9 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -1,4 +1,11 @@ + Общомедия Настройки diff --git a/app/src/main/res/values-bn/error.xml b/app/src/main/res/values-bn/error.xml index f972038e4..2c929f8b5 100644 --- a/app/src/main/res/values-bn/error.xml +++ b/app/src/main/res/values-bn/error.xml @@ -1,4 +1,9 @@ + কমন্স ক্র্যাশ করেছে ওহ, কিছু একটা ত্রুটি হয়েছে! diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index cbfd8e322..679c50803 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -1,4 +1,15 @@ + অবয়ব সাধারণ @@ -59,6 +70,7 @@ বিষয়শ্রেণী অনুসন্ধান সংরক্ষণ পুনঃসতেজ + তালিকা GPS আপনার ডিভাইসে অক্ষম করা আছে। আপনি কি এটি সক্ষম করতে চান? GPS সক্রিয় করুন এখনো কোন আপলোড নেই @@ -80,6 +92,7 @@ বিষয়শ্রেণীসমূহ সেটিং নিবন্ধন করুন + নির্বাচিত ছবি পরিচিতি উইকিমিডিয়া কমন্স অ্যাপ হচ্ছে একটি উন্মুক্ত উৎস সম্বলিত অ্যাপ যা উইকিমিডিয়া সম্প্রদায়ের ব্যবহারকারী ও সেচ্ছাসেবকবৃন্দ কর্তৃক তৈরিকৃত এবং পরিচালিত। উইকিমিডিয়া ফাউন্ডেশন এই অ্যাপ তৈরি, উন্নয়ন বা রক্ষণাবেক্ষণে জড়িত নয়। কোন সমস্যা ও পরামর্শের জন্য <a href=\"https://github.com/commons-app/apps-android-commons/issues\">গিটহাব ইস্যু</a> তৈরি করুন। @@ -150,8 +163,8 @@ বিবরণ নেই অজানা লাইসেন্স পুনঃসতেজ - প্রয়োজনীয় অনুমতি: বহিঃস্ত সঞ্চয়স্থান পড়া। এটি ছাড়া অ্যাপ কাজ করবে না। - অনুমতি প্রয়োজন: অালাদাভাবে সংযুক্ত স্টোরেজ লিখুন। এটি ছাড়া অ্যাপটি চলতে পারেনা। + প্রয়োজনীয় অনুমতি: বহিঃস্ত সঞ্চয়স্থান পড়া। এটি ছাড়া অ্যাপ কাজ করবে না। + অনুমতি প্রয়োজন: অালাদাভাবে সংযুক্ত স্টোরেজ লিখুন। এটি ছাড়া অ্যাপটি চলতে পারেনা। ঐচ্ছিক অনুমতি: বিষয়শ্রেণী পরামর্শের জন্য বর্তমান অবস্থান নেয় ঠিক আছে কাছাকাছি স্থান @@ -164,6 +177,7 @@ মিডিয়ার শিরোনাম বিবরণ মিডিয়ার বিবরণ এখানে যাবে। এই মোটামুটি দীর্ঘ হতে পারে এবং একাধিক লাইনে লিখতে হতে পারে। আমরা আশা করি এটি দেখতে সুন্দর হবে। + স্রষ্টা আপলোডের তারিখ লাইসেন্স স্থানাঙ্কসমূহ @@ -206,10 +220,12 @@ প্রস্থান ভূমিকা বিজ্ঞপ্তি + নির্বাচিত অবস্থানের অনুমতি ছাড়া কাছাকাছি জায়গাগুলি প্রদর্শন করা যাবে না কোন বিবরণ পাওয়া যায়নি কমন্সে ফাইলের পাতা উইকিউপাত্ত পদ + উইকিপিডিয়া নিবন্ধ ছবি আনার সময় ত্রুটি ফাইলের একটি স্বতন্ত্র বর্ণনামূলক নাম যা ফাইলের নাম হিসাবে কাজ করবে। অাপনি সাধারণ ভাষা ব্যবহার করতে পারেন শূন্যস্থানসহ। ফাইলের এক্সটেনশন যুক্ত করবেন না। যতটা সম্ভব মিডিয়াটি বর্ণনা করুন: এটি কোথায় ধারণ করা হয়েছিল? এটি কি প্রদর্শন করে? এটির প্রসঙ্গ কি? ধারণকৃত বস্তু অথবা ব্যক্তির বর্ণনা করুন। সহজে অনুমান করা যায়না সেরকম তথ্য উদঘাটন করুন, উদাহরণস্বরূপ, যদি ল্যান্ডস্কেপ হয় তাহলে দিবসকালের সময় দিন। @@ -222,6 +238,8 @@ লগ ফাইল পাঠান ইমেইলের মাধ্যমে উন্নয়নকারীর কাছে লগ ফাইল পাঠান ত্রুটি! ইউআরএল পাওয়া যায়নি + অপসারণের জন্য মনোনীত + ব্রাউজারে দেখুন অবস্থান পরিবর্তন হয়নি। অবস্থান উপলব্ধ নয়। কাছাকাছি স্থানসমূহের একটি তালিকা প্রদর্শন করতে অনুমতি প্রয়োজন @@ -231,6 +249,14 @@ %1$s আপনার আলাপ পাতায় একটি বার্তা দিয়েছেন একটি সম্পাদনা করার জন্য আপনাকে ধন্যবাদ %1$s আপনাকে %2$s-এ উল্লেখ করেছেন। - প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ + দিকনির্দেশ + উইকিউপাত্ত + উইকিপিডিয়া + কমন্স + প্রায়শই জিজ্ঞাসিত প্রশ্নসমূহ টিউটোরিয়াল এড়ান + ইন্টারনেট অনুপলব্ধ + ইন্টারনেট উপলব্ধ + কোন বিজ্ঞপ্তি পাওয়া যায়নি + পুনঃচেষ্টা করুন diff --git a/app/src/main/res/values-br/error.xml b/app/src/main/res/values-br/error.xml index b1dfa421e..bb219551f 100644 --- a/app/src/main/res/values-br/error.xml +++ b/app/src/main/res/values-br/error.xml @@ -1,4 +1,8 @@ + Commons zo aet er c\'hleuz Hopala ! Un dra bennak a-dreuz zo bet ! diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index bff5c79f8..8383f7cbe 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -1,4 +1,11 @@ + Neuz Hollek @@ -146,8 +153,8 @@ Deskrivadur ebet Aotre-implijout dizanv Freskaat - Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro. - Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se. + Aotre rekis : lenn ur stokañ diavaez. Hep se, n\'hall ket an arload mont en-dro. + Aotre ret ; skrivañ war al lec\'h stokañ diavaez. Ne c\'hall ket an arload mont en-dro hep an dra-se. Aotre diret : kaout al lec\'hiadur red evit kinnig rummadoù Mat eo Lec\'hioù nes diff --git a/app/src/main/res/values-bs/error.xml b/app/src/main/res/values-bs/error.xml index b266e3d6f..27a611f8b 100644 --- a/app/src/main/res/values-bs/error.xml +++ b/app/src/main/res/values-bs/error.xml @@ -1,4 +1,7 @@ + Commons se srušio Ups. Nešto je pošlo po zlu! diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 6efaf7898..6c0097089 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -1,4 +1,9 @@ + Commons Postavke @@ -133,7 +138,7 @@ Nema opisa Nepoznata licenca Osvježi - Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog. + Potrebna dozvola: Čitanje vanjske memorije. Aplikacija ne može raditi bez ovog. Neobavezna dozvola: Dobavljanje trenutne lokacije za predlaganje kategorija U redu Mjesta u blizini diff --git a/app/src/main/res/values-ca/error.xml b/app/src/main/res/values-ca/error.xml index 8bea1c50e..6752fa848 100644 --- a/app/src/main/res/values-ca/error.xml +++ b/app/src/main/res/values-ca/error.xml @@ -1,4 +1,8 @@ + El Commons s\'ha penjat Uups ! Quelcom ha anat malament ! diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index dcc406b73..f7f40f427 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -1,4 +1,14 @@ + Aparença Ubicació @@ -181,5 +191,5 @@ LLEGIU L’ARTICLE Gràcies per fer una modificació %1$s us ha mencionat a %2$s. - Preguntes freqüents + Preguntes freqüents diff --git a/app/src/main/res/values-ce/error.xml b/app/src/main/res/values-ce/error.xml index f8667a37d..75b00cf2f 100644 --- a/app/src/main/res/values-ce/error.xml +++ b/app/src/main/res/values-ce/error.xml @@ -1,4 +1,7 @@ + Баркалла! diff --git a/app/src/main/res/values-cs/error.xml b/app/src/main/res/values-cs/error.xml index 050ae78d7..e6677dedc 100644 --- a/app/src/main/res/values-cs/error.xml +++ b/app/src/main/res/values-cs/error.xml @@ -1,6 +1,11 @@ + - Commons spadly + Aplikace Commons spadla Něco se pokazilo! Řekněte nám, co jste dělali a dejte nám to vědět e-mailem. Pomůže sjednat nápravu! Děkujeme vám! diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index f8e24cc7c..6e2453d6d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -1,4 +1,19 @@ + Vzhled Obecné @@ -59,6 +74,7 @@ Hledání kategorií Uložit Obnovit + Seznam GPS ve vašem zařízení není povoleno. Chtěli byste ho spustit? Spustit GPS Žádné nahrané soubory @@ -151,8 +167,8 @@ Bez popisu Neznámá licence Obnovit - Požadováno oprávnění ke čtení externího úložiště. Aplikace bez toho nemůže pracovat. - Požadováno oprávnění k zápisu do externího úložiště. Aplikace bez toho nemůže pracovat. + Požadované oprávnění: Čtení externího úložiště. Bez něj nemůže aplikace číst vaši galerii. + Požadované oprávnění: Zapisování do externího úložiště. Bez něj nemůže aplikace používat vaši kameru. Volitelně: Umožněte aplikaci, aby získávala aktuální polohu a nabízela na jejím základě kategorie OK Místa v okolí @@ -211,6 +227,7 @@ nebyl nalezen žádný popisek Stránka souboru na Commons Položka Wikidat + Článek na Wikipedii Chyba při meziukládání obrázků 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. 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. @@ -225,6 +242,8 @@ Nebyl nalezen žádný webový prohlížeč k otevření URL Chyba! URL nenalezeno Navrhnout na smazání + Tento obrázek byl nominován na smazání. + Zobrazit v prohlížeči Vaše umístění se nezměnilo. Umístění není dostupné. @@ -236,6 +255,21 @@ Děkujeme za vaši editaci %1$s vás zmínil na %2$s. Přepnout pohled - Často kladené dotazy + POKYNY + WIKIDATA + WIKIPEDIE + COMMONS + <u>Ohodnoť nás</u> + <u>Často kladené otázky</u> Přeskočit úvod + Internet je nedostupný + Internet je dostupný + Při načítání oznámení došlo k chybě + Nebyly nalezeny žádné oznámení + <u>Přeložit</u> + Jazyky + Vyberte jazyk, pro který chcete odeslat překlady + Pokračovat + Zrušit + Zkusit znovu diff --git a/app/src/main/res/values-csb/error.xml b/app/src/main/res/values-csb/error.xml index c2aef4ccb..aeead2d27 100644 --- a/app/src/main/res/values-csb/error.xml +++ b/app/src/main/res/values-csb/error.xml @@ -1,4 +1,7 @@ + Pókôza sã fela Commons. Wejle! Cos je lëchò pòszłé! diff --git a/app/src/main/res/values-csb/strings.xml b/app/src/main/res/values-csb/strings.xml index 3e08dac99..2d7b99904 100644 --- a/app/src/main/res/values-csb/strings.xml +++ b/app/src/main/res/values-csb/strings.xml @@ -1,4 +1,7 @@ + Commons Nastôwë diff --git a/app/src/main/res/values-cy/error.xml b/app/src/main/res/values-cy/error.xml index e592ad506..6c4fe8370 100644 --- a/app/src/main/res/values-cy/error.xml +++ b/app/src/main/res/values-cy/error.xml @@ -1,4 +1,8 @@ + Aeth rhywbeth o\'i le yn Comin Wwwwps. Aeth rhywbeth o\'i le! diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index f9dec6333..ef56bc3b0 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -1,4 +1,9 @@ + Comin Wicimedia Gosodiadau diff --git a/app/src/main/res/values-da/error.xml b/app/src/main/res/values-da/error.xml index 54eb27b27..493de925d 100644 --- a/app/src/main/res/values-da/error.xml +++ b/app/src/main/res/values-da/error.xml @@ -1,4 +1,8 @@ + Commons gik ned Ups. Noget gik galt! diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 5edafa308..e10a93850 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -1,4 +1,12 @@ + Udseende Generelt @@ -151,8 +159,8 @@ Ingen beskrivelse Ukendt licens Opdater - Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse. - Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion. + Krævet tilladelse: Læs eksternt lager. Programmet kan ikke fungere uden denne tilladelse. + Krævet tilladelse: Skriv til eksternt lager. Program kan ikke fungere uden denne funktion. Valgfri tilladelse: Hent nuværende position for kategoriforslag O.k. Steder i nærheden @@ -236,6 +244,6 @@ Tak fordi du lavede en redigering %1$s nævnte dig på %2$s. Skift visning - Ofte stillede spørgsmål + Ofte stillede spørgsmål Udelad øvelse diff --git a/app/src/main/res/values-de/error.xml b/app/src/main/res/values-de/error.xml index 9e54e12d2..43bb64ae5 100644 --- a/app/src/main/res/values-de/error.xml +++ b/app/src/main/res/values-de/error.xml @@ -1,4 +1,7 @@ + Commons ist abgestürzt Huch! Etwas ist schiefgelaufen. diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0f9e56bd3..60339308c 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -1,4 +1,11 @@ + Erscheinung Allgemein @@ -81,6 +88,7 @@ Kategorien Einstellungen Registrieren + Vorgestellte Bilder Über Die Wikimedia-Commons-App ist eine Open-Source-App, entwickelt und gewartet von Freiwilligen der Wikimedia-Gemeinschaft. Die Wikimedia Foundation ist nicht bei der Erstellung, Entwicklung oder Wartung der App beteiligt. Einen neuen <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub-Eintrag</a> für Fehlerberichte und Vorschläge erstellen. @@ -152,8 +160,8 @@ Keine Beschreibung Unbekannte Lizenz Aktualisieren - Erforderliche Berechtigung: Externen Speicher lesen. Die App funktioniert ohne diese Berechtigung nicht. - Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne dies nicht funktionieren. + Erforderliche Berechtigung: Externen Speicher lesen. Die App kann ohne diese Berechtigung nicht auf deine Galerie zugreifen. + Erforderliche Berechtigung: Externen Speicher beschreiben. Die App kann ohne diese Berechtigung nicht auf deine Kamera zugreifen. Optionale Berechtigung: Ruft den aktuellen Standort für Kategorievorschläge ab Okay Orte in der Nähe @@ -166,6 +174,8 @@ Titel des Mediums Beschreibung Hier folgt die Beschreibung des Mediums. Diese kann möglicherweise ziemlich lang sein und erfordert dann einen Umbruch auf mehreren Zeilen. Wir hoffen, dass sie dennoch gut aussieht. + Autor + Hier steht der Benutzername des Autors des vorgestellten Bildes. Hochgeladen am Lizenz Koordinaten @@ -208,6 +218,7 @@ Abmelden Anleitung Benachrichtigungen + Vorgestellt Orte in der Nähe können ohne Berechtigung zur Standortbestimmung nicht ermittelt werden Keine Beschreibung gefunden Commons-Dateiseite @@ -227,6 +238,8 @@ Zum Öffnen der URL wurde kein Webbrowser gefunden Fehler! URL nicht gefunden Zur Löschung vorschlagen + Dieses Bild wurde zur Löschung vorgeschlagen. + Im Browser ansehen Der Standort hat sich nicht geändert. Der Standort ist nicht verfügbar. @@ -242,7 +255,17 @@ WIKIDATA WIKIPEDIA COMMONS - - Häufig gestellte Fragen + <u>Bewerte uns</u> + <u>Häufig gestellte Fragen</u> Tutorial überspringen + Internet nicht verfügbar + Internet verfügbar + Fehler beim Abruf der Benachrichtigungen + Keine Benachrichtigungen gefunden + <u>Übersetzen</u> + Sprachen + Wähle die Sprache aus, für die du Übersetzungen durchführen möchtest. + Fortfahren + Abbrechen + Erneut versuchen diff --git a/app/src/main/res/values-diq/error.xml b/app/src/main/res/values-diq/error.xml index 98e5e8d23..a9cbfb85a 100644 --- a/app/src/main/res/values-diq/error.xml +++ b/app/src/main/res/values-diq/error.xml @@ -1,7 +1,13 @@ + Commons lığiya Oops. Thebayo nigurweyino! Şıma se kerd bı, marê vacê. Dıma e-posta ra bırışê marê. Ney timar kerdışi de marê beno desteg! - Teşekur kena + Teşekur kenan! diff --git a/app/src/main/res/values-diq/strings.xml b/app/src/main/res/values-diq/strings.xml index f8b2e7033..b88e412e7 100644 --- a/app/src/main/res/values-diq/strings.xml +++ b/app/src/main/res/values-diq/strings.xml @@ -1,4 +1,13 @@ + Commons Eyari @@ -26,7 +35,7 @@ Barkerdışê mınê peyêni Ratneya - Nêbı + Ebe ser nêkewt %1$d%% temamya Bar beno Galeri ra diff --git a/app/src/main/res/values-dty/error.xml b/app/src/main/res/values-dty/error.xml index 08524cb53..9233ecdae 100644 --- a/app/src/main/res/values-dty/error.xml +++ b/app/src/main/res/values-dty/error.xml @@ -1,4 +1,7 @@ + हैत्मरा। केइचीज गलत भयो। धन्यवाद! diff --git a/app/src/main/res/values-el/error.xml b/app/src/main/res/values-el/error.xml index ee39f1a00..68b5922d4 100644 --- a/app/src/main/res/values-el/error.xml +++ b/app/src/main/res/values-el/error.xml @@ -1,4 +1,9 @@ + Τα Commons παρουσίασαν σφάλμα Ωχ. Κάτι πήγε στραβά! diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index c01f9ab3a..759c44920 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1,4 +1,15 @@ + Εμφάνιση Γενικά @@ -81,6 +92,7 @@ Κατηγορίες Ρυθμίσεις Εγγραφή + Προβεβλημμένες εικόνες Σχετικά Λογισμικό ανοικτού κωδικού που κυκλοφορεί υπό την <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Άδεια Apache v2</a>. Το Wikimedia Commons και το λογότυπο είναι εμπορικά σήματα του Ιδρύματος Wikimedia και χρησιμοποιούνται με άδεια από το Ίδρυμα Wikimedia. Δεν συμμετέχουμε στην δημιουργία, ανάπτυξη ή συντήρηση του Ιδρύματος Wikimedia. Δημιουργήστε ένα νέο <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub θέμα</a> για αναφορές σφαλμάτων και προτάσεις. @@ -152,8 +164,8 @@ Καμία περιγραφή Άγνωστη άδεια Ανανέωση - Απαιτούμενη άδεια: Ανάγνωση εξωτερικής αποθήκευσης. Η εφαρμογή δεν μπορεί να λειτουργήσει χωρίς αυτή. - Απαιτούμενη άδεια: Με εξωτερική αποθήκευση.Το πρόγραμμα δεν μπορεί να λειτουργήσει με αυτήν. + Απαιτούμενη άδεια: Ανάγνωση εξωτερικής αποθήκευσης. Η εφαρμογή δεν μπορεί να έχει πρόσβαση στην συλλογή σας χωρίς αυτή. + Απαιτούμενη άδεια: Με εξωτερική αποθήκευση. Το πρόγραμμα δεν μπορεί να έχει πρόσβαση στην κάμερα σας χωρίς αυτήν. Προαιρετική άδεια: Ανάκτηση τρέχουσας θέσης σας για προτάσεις κατηγοριών Εντάξει Κοντινοί Τόποι @@ -166,6 +178,8 @@ Τίτλος πολυμέσου Περιγραφή Η περιγραφή του πολυμέσου μπαίνει εδώ. Αυτή μπορεί να είναι σχετικά μεγάλη, και θα χρειαστεί να αναδιπλωθεί σε πολλές γραμμές. Ελπίζουμε ωστόσο ότι θα φαίνεται όμορφα. + Συγγραφέας + Το όνομα χρήστη του συγγραφέα της επιλεγμένης εικόνας πάει εδώ. Ημερομηνία φόρτωσης Άδεια Συντεταγμένες @@ -208,6 +222,7 @@ Αποσύνδεση Σεμινάριο Ενημερώσεις + Επιλεγμένο Οι κοντινές τοποθεσίες δεν μπορούν να προβληθούν δίχως τις άδειες τοποθεσίας δεν βρέθηκε περιγραφή Σελίδα φακέλλου κοινής χρήσης @@ -227,6 +242,8 @@ Δεν βρέθηκε φυλλομετρητής για το άνοιγμα της διευθύνσεως URL Σφάλμα! Η διεύθυνση URL δεν βρέθηκε Προτείνετε για διαγραφή + Αυτή εικόνα έχει προταθεί για διαγραφή. + Προβολή στον περιηγητή Ο εντοπισμός δεν έχει αλλάξει. Ο τόπος δεν είναι διαθέσιμος. @@ -242,7 +259,17 @@ Βικιδεδομένα Βικιπαίδεια Κοινά - - Συχνές ερωτήσεις + <u>Βαθμολογήστε μας</u> + <u>Συχνές ερωτήσεις</u> Παράβλεψη εισαγωγής + Το διαδίκτυο δεν είναι διαθέσιμο + Το διαδίκτυο είναι διαθέσιμο + Σφάλμα κατά την συγκέντρωση ειδοποιήσεων + Δεν βρέθηκαν ειδοποιήσεις + <u>Μεταφράστε</u> + Γλώσσες + Επιλέξτε την γλώσσα που θα θέλατε να υποβάλετε μεταφράσεις για αυτή + Συνέχεια + Ακύρωση + Ξαναπροσπαθήστε diff --git a/app/src/main/res/values-es/error.xml b/app/src/main/res/values-es/error.xml index a7bb0ac06..f10caf6e4 100644 --- a/app/src/main/res/values-es/error.xml +++ b/app/src/main/res/values-es/error.xml @@ -1,4 +1,9 @@ + Commons falló Vaya. ¡Algo salió mal! diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index ab044505c..c1a45b309 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1,4 +1,15 @@ + Apariencia Generales @@ -59,6 +70,7 @@ Buscar categorías Guardar Actualizar + Lista El GPS está desactivado en tu dispositivo. ¿Quieres activarlo? Activar GPS No hay subidas aún @@ -80,6 +92,7 @@ Categorías Ajustes Regístrate + Imágenes en destaque Acerca de La aplicación de código abierto Wikimedia Commons fue creada por, y recibe mantenimiento de, cesionarios y voluntarios de la comunidad de Wikimedia. La Fundación Wikimedia no está involucrada en la creación, el desarrollo ni el mantenimiento de la aplicación. Notifica de problemas y sugerencias en <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub</a>. @@ -125,7 +138,7 @@ Wikimedia Commons aloja la mayoría de las imágenes utilizadas en Wikipedia. ¡Tus imágenes ayudan a instruir a personas de todo el mundo! Carga únicamente imágenes capturadas o creadas por ti. - - 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) + 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) Naturaleza (flores, animales, montañas) Objetos utilitarios (bicicletas, estaciones de tren) Gente famosa (tu regente, algún atleta que hayas conocido…) @@ -138,6 +151,7 @@ - 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 Título: Ópera de Sídney Descripción: La Ópera de Sídney, vista desde el otro lado de la bahía + Categorías: Ópera de Sídney desde el oeste, Vistas a distancia de la Ópera de Sídney Contribuye con tus imágenes.\n¡Ayuda a que los artículos de Wikipedia tengan vida! Las imágenes en Wikipedia proceden de\nWikimedia Commons. Tus imágenes ayudan a educar a la gente\nalrededor del mundo. @@ -150,8 +164,8 @@ Sin descripción Licencia desconocida Actualizar - Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede funcionar sin él. - Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede funcionar sin él. + Permiso obligatorio: lectura de almacenamiento externo. La aplicación no puede acceder a la galería sin él. + Permiso necesario: Escribir en almacenamiento externo. La aplicación no puede acceder a la cámara sin él. Permiso opcional: obtener la ubicación actual para sugerir categorías Aceptar Lugares cercanos @@ -164,6 +178,7 @@ Título del multimedia Descripción Aquí va la descripción del archivo multimedia. Esta puede ser muy extensa, en cuyo caso deberá ajustarse en varios renglones. No obstante, esperamos que se vea bien. + Autor Fecha de subida Licencia Coordenadas @@ -206,10 +221,12 @@ Salir Tutorial Notificaciones + En destaque Los sitios cercanos no pueden mostrarse sin los permisos de ubicación no se encontró ninguna descripción Página del archivo en Commons Elemento de Wikidata + Artículo de Wikipedia Error al almacenar imágenes en la antememoria 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. 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. @@ -224,6 +241,7 @@ No se encontró ningún navegador con el que abrir el URL Error: no se encontró el URL Nominar para borrado + Se ha nominado esta imagen para su borrado. Ver en navegador La ubicación no ha cambiado. La ubicación no está disponible. @@ -234,5 +252,19 @@ %1$s dejó un mensaje en tu página de discusión Gracias por realizar una edición %1$s te ha mencionado en %2$s. - Preguntas frecuentes + CÓMO LLEGAR + WIKIDATA + WIKIPEDIA + COMMONS + <u>Preguntas frecuentes</u> + Omitir tutorial + Internet no disponible + Internet disponible + Error al recuperar las notificaciones + No se encontró ninguna notificación + <u>Traducir</u> + Idiomas + Selecciona el idioma en que quieres enviar traducciones + Cancelar + Reintentar diff --git a/app/src/main/res/values-eu/error.xml b/app/src/main/res/values-eu/error.xml index 003667ad2..ff745c32a 100644 --- a/app/src/main/res/values-eu/error.xml +++ b/app/src/main/res/values-eu/error.xml @@ -1,4 +1,7 @@ + Commons apurtu da Uiii. Zerbait gaizki dabil! diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index ba6c22cca..f44262e05 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -1,4 +1,12 @@ + Commons Hobespenak diff --git a/app/src/main/res/values-fa/error.xml b/app/src/main/res/values-fa/error.xml index 638e3906e..3dd4bec2b 100644 --- a/app/src/main/res/values-fa/error.xml +++ b/app/src/main/res/values-fa/error.xml @@ -1,4 +1,10 @@ + ویکی‌انبار متوقف شده‌است اوه. خطایی در کار است! diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 04f3832b6..d80b0772c 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -1,11 +1,27 @@ + + نمایش صفحه + عمومی + بازخورد + مکان ویکی‌انبار + تنظیمات نام کاربری گذرواژه به حساب کاربری ویکی‌انبار آزمایشی وارد شوید ورود + رمز خود را فراموش کرده‌اید؟ ثبت نام واردشدن شکیبا باشید... @@ -37,6 +53,7 @@ به اشتراک‌گذاشتن مشاهده در مرورگر عنوان + لطفاً نامی را برای این پرونده انتخاب کنید توضیحات قادر به ورود نیست - شکست شبکه‌ای ناتوانی در ورود - لطفاً نام کاربریتان را بررسی کنید @@ -52,6 +69,7 @@ جستجوی رده‌ها ذخیره تازه کردن + فهرست مکان‌یاب در دستگاه شما خاموش است. آیا دوست دارید فعال شود؟ فعال کردن مکان‌یاب هنوز هیچ بارگذاری @@ -72,8 +90,8 @@ درباره اپلیکیشن ویکی‌انبار بنیاد ویکی‌مدیا یک نرم‌افزار آزاد است که توسط کاربران داوطلب و پاداش‌بگیر ایجاد و نگهداری می‌شود. بنیاد ویکی‌مدیا در ایجاد، نگهداری و توسعهٔ آن دخالتی ندارد. ایجاد یک <a href=\"https://github.com/commons-app/apps-android-commons/issues\">درخواست در گیت‌هاب</a> برای گزارش باگ و یا پیشنهاد یک خصوصیت جدید. - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">سیاست حفظ حریم خصوصی</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">مجوز</a> + <u>سیاست حفظ حریم خصوصی</u> + <u>مجوز</u> درباره ارسال بازخورد (از طریق ایمیل) نرم‌افزار ایمیل نصب نیست @@ -85,7 +103,7 @@ این نگاره تحت مجوز %1$s است با بارگذاری این تصویر، تأیید می‌کنم که این اثر کار خودم است و از محتوای دارای حق تکثیر یا سلفی برای ایجاد آن استفاده نکرده‌ام و شرایط ذکر شده در 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 <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">سیاست‌های ویکی‌انبار</a> را رعایت می‌کند. دریافت - مجوز + مجوز پیش‌فرض از عنوان/توضیحات پیشین استفاده کنید دریافت خودکار موقعیت کنونی درحال دریافت موقعیت برای پیشنهاد رده در صورتی که برچسب جغرافیایی وجود نداشته باشد. @@ -114,7 +132,7 @@ ویکی‌انبار اکثر پرونده‌هایی که در ویکی‌پدیا استفاده می‌شوند را در خود نگه می‌دارد. تصاویر شما به مردم در اقصی نقاط دنیا کمک می‌کند! لطفاً تصاویری که توسط خودتان گرفته شده‌اند یا ایجاد شده‌اند را بارگذاری کنید: - -اجسام طبیعی (گیاه، جانور، کوه)\n-اجسام کاربردی (دوچرخه، ایستگاه قطار)\n-افراد مشهور (شهردار، قهرمانان المپیک) + •اجسام طبیعی (گیاه، جانور، کوه)\n•اجسام کاربردی (دوچرخه، ایستگاه قطار)\n•افراد مشهور (شهردار، قهرمانان المپیک) لطفاً بارگذاری نکنید: -سلفی خودتان یا تصویر دوستانتان\n-تصاویری که از اینترنت دانلود کردید\n-نماگرفت از دیگر اپلیکیشن‌‌ها نمونه بارگذاری: @@ -131,8 +149,8 @@ بدون توضیحات مجوز ناشناخته تازه‌کردن - اجازه‌های مورد نیاز: مطالعهٔ حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند. - اجازه‌های مورد نیاز: نوشتن حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند. + اجازه‌های مورد نیاز: مطالعهٔ حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند. + اجازه‌های مورد نیاز: نوشتن حافظهٔ خارجی. اپلیکیشن بدون آن نمی‌تواند کار کند. اجازه‌های اختیاری: دریافت موقعیت برای پیشنهاد رده تأیید مکان‌‌های اطراف @@ -202,6 +220,8 @@ ورود به حساب کاربریتان ارسال فایل سیاهه ارسال فایل سیاهه به‌وسیلهٔ ایمیل برای توسعه‌دهندگان + . + مشاهده در مرورگر مکان تغییر نکرده‌است. مکان موجود نیست. برای نمایش مکان‌ّای اطراف نیاز به اجازه است. @@ -212,4 +232,18 @@ برای ویرایش ممنون %1$s در %2$s به شما اشاره کرده‌است. دکمه نمایش + جهت‌ها + ویکی‌داده + ویکی‌پدیا + ویکی‌انبار + <u>رتبه ما</u> + <u>سوال‌های متداول</u> + رهاکردن آموزش + اینترنت در دسترس نیست + اینترنت در دسترس است + <u>ترجمه</u> + زبان‌ها + ادامه + لغو + سعى دوباره diff --git a/app/src/main/res/values-fi/error.xml b/app/src/main/res/values-fi/error.xml index c5c3bc768..bc47fa3fb 100644 --- a/app/src/main/res/values-fi/error.xml +++ b/app/src/main/res/values-fi/error.xml @@ -1,4 +1,9 @@ + Commons app on kaatunut Pahoittelemme, virhe tapahtui. diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index e69997922..dd1d37993 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -1,4 +1,16 @@ + Ulkoasu Yleinen @@ -149,8 +161,8 @@ Ei kuvausta Tuntematon lisenssi Päivitä - Vaadittu oikeus: Ulkoisen tallennustilan luku. Appi ei toimi ilman tätä oikeutta. - Vaadittava lupa: Kirjoita ulkoiseen tallennustilaan. Sovellus ei voi toimia ilman tätä. + Vaadittu oikeus: Ulkoisen tallennustilan luku. Appi ei toimi ilman tätä oikeutta. + Vaadittava lupa: Kirjoita ulkoiseen tallennustilaan. Sovellus ei voi toimia ilman tätä. Valinnainen lupa: Saada tämänhetkinen sijainti loukkasuosituksia varten. OK Lähellä olevat paikat @@ -231,6 +243,6 @@ Kiitos muokkaamisestasi %1$s mainitsi sinut %2$s. Vaihda näkymä - Usein Kysytyt Kysymykset + Usein Kysytyt Kysymykset Ohita opetus diff --git a/app/src/main/res/values-fo/error.xml b/app/src/main/res/values-fo/error.xml index 9c1462461..e06bb6e5e 100644 --- a/app/src/main/res/values-fo/error.xml +++ b/app/src/main/res/values-fo/error.xml @@ -1,4 +1,7 @@ + Commons er óvirkið í løtuni Ups. Okkurt gekk galið! diff --git a/app/src/main/res/values-fo/strings.xml b/app/src/main/res/values-fo/strings.xml index e5df10a2f..c4649407a 100644 --- a/app/src/main/res/values-fo/strings.xml +++ b/app/src/main/res/values-fo/strings.xml @@ -1,4 +1,7 @@ + Wikimedia Commons Innstillingar diff --git a/app/src/main/res/values-fr/error.xml b/app/src/main/res/values-fr/error.xml index 2cd1e09f3..743024b03 100644 --- a/app/src/main/res/values-fr/error.xml +++ b/app/src/main/res/values-fr/error.xml @@ -1,4 +1,7 @@ + Commons a planté Oups ! Quelque chose s’est mal passé ! diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7003515d8..8494a7a36 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,4 +1,22 @@ + Apparence Général @@ -28,8 +46,8 @@ Le téléversement de %1$s a échoué Appuyer pour afficher - %1$d fichier en cours de téléchargement - %1$d fichiers en cours de téléchargement + %1$d fichier en cours de téléversement + %1$d fichiers en cours de téléversement Mes téléversements récents Mis en file d\'attente @@ -59,27 +77,29 @@ Rechercher des catégories Enregistrer Rafraîchir + Liste Le GPS est désactivé sur votre appareil. Voulez-vous l’activer ? Activer le GPS Encore aucun téléversement \@string/contributions_subtitle_zero - %1$d téléchargement - %1$d téléchargements + %1$d téléversement + %1$d téléversements - %1$d téléchargement démarré - %1$d téléchargements démarrés + %1$d téléversement démarré + %1$d téléversements démarrés - %1$d téléchargement - %1$d téléchargements + %1$d téléversement + %1$d téléversements Aucune catégorie correspondant à %1$s trouvée Ajoutez des catégories pour rendre vos images plus simples à trouver sur Wikimedia Commons. \nCommencer à ajouter des catégories. Catégories Paramètres S’inscrire + Images en vedette À propos L’application Wikimedia Commons est une application open source créée et tenue à jour par les bénéficiaires et volontaires de la communauté Wikimedia. La fondation Wikimedia n’est pas associée à la création, le développement ou l’entretien de l’application. Créer un nouveau <a href=\"https://github.com/commons-app/apps-android-commons/issues\">signalement GitHub</a> pour signaler des bogues ou des suggestions. @@ -151,8 +171,8 @@ Aucune description Licence inconnue Rafraîchir - Autorisation nécessaire : Lire un stockage externe. L’application ne peut pas fonctionner sans cela. - Permission obligatoire : Écriture sur stockage externe. L’application ne peut pas fonctionner sans cela. + Autorisation nécessaire : Lire un stockage externe. L’application ne peut pas accéder à votre galerie sans cela. + Permission obligatoire : Écriture sur stockage externe. L’application ne peut pas accéder à votre appareil photo sans cela. Autorisation facultative : Obtenir l’emplacement actuel pour des suggestions de catégorie OK Endroits à proximité @@ -165,6 +185,8 @@ Titre du média Description La description du média vient ici. Cela peut être potentiellement assez long, et devra être réparti sur plusieurs lignes. Nous espérons que cela restera joli néanmoins. + Auteur + Le nom de l’utilisateur auteur d’une image en vedette va ici. Date de téléversement Licence Coordonnées @@ -207,10 +229,12 @@ Déconnexion Tutoriel Notifications + Mis en vedette Les endroits proches ne peuvent pas être affichés si vous ne partagez pas votre position géographique. aucune description trouvée Page des fichiers de Commons Élément de Wikidata + Article Wikipédia Erreur en mettant les images en cache Un titre descriptif unique pour le fichier, qui servira de nom de fichier. Vous pouvez utiliser un langage simple avec des espaces. N’incluez pas l’extension du fichier Veuillez décrire le média autant que possible : Où a-t-il été enregistré ? Que montre-t-il ? Quel est le contexte ? Veuillez décrire les objets ou les personnes. Révélez les informations qui ne peuvent pas être devinées facilement, par exemple l’heure de la journée si c’est un paysage. Si le média montre quelque chose d’inhabituel, veuillez expliquer ce qui le rend exceptionnel. @@ -225,6 +249,8 @@ Pas d\'afficheur web trouvé pour ouvrir l\'URL Erreur! URL non trouvée Proposer pour suppression + Cette image a été citée pour suppression. + Afficher dans le navigateur L\'emplacement n\'a pas changé. Emplacement non disponible. @@ -236,7 +262,21 @@ Merci de faire une modification %1$s vous a mentionné sur %2$s . Basculer l’affichage - - Questions posées fréquemment + DIRECTIONS + WIKIDATA + WIKIPÉDIA + COMMUNS + <u>Votre appréciation</u> + <u>FAQ</u> Sauter le tutoriel + Internet indisponible + Internet disponible + Erreur sur recherche des notifications + Pas de notification trouvée + <u>Traduire</u> + Langues + Sélectionner la langue pour laquelle vous voulez soumettre des traductions + Continuer + Annuler + Réessayer diff --git a/app/src/main/res/values-frp/error.xml b/app/src/main/res/values-frp/error.xml index f7a658562..f94b6d47c 100644 --- a/app/src/main/res/values-frp/error.xml +++ b/app/src/main/res/values-frp/error.xml @@ -1,4 +1,7 @@ + Grant-marci ! diff --git a/app/src/main/res/values-frr/error.xml b/app/src/main/res/values-frr/error.xml index f4ec61282..b00633c95 100644 --- a/app/src/main/res/values-frr/error.xml +++ b/app/src/main/res/values-frr/error.xml @@ -1,4 +1,7 @@ + Commons as ufstört Uups, diar as wat skiaf gingen! diff --git a/app/src/main/res/values-frr/strings.xml b/app/src/main/res/values-frr/strings.xml index 6cd088696..f4866e705 100644 --- a/app/src/main/res/values-frr/strings.xml +++ b/app/src/main/res/values-frr/strings.xml @@ -1,4 +1,8 @@ + Commons Iinstelangen @@ -133,7 +137,7 @@ Nian beskriiwang Ünbekäänd lisens Nei loose - Ferlangd rochten: Ekstern seekrang lees. Det app koon saner detdiar rocht ei werke. + Ferlangd rochten: Ekstern seekrang lees. Det app koon saner detdiar rocht ei werke. Mögelk rocht: Rept di aktuel plak för kategoriiföörslacher ap. OK Steeden naibi diff --git a/app/src/main/res/values-fur/error.xml b/app/src/main/res/values-fur/error.xml index 3f6f1ad21..0264c32b3 100644 --- a/app/src/main/res/values-fur/error.xml +++ b/app/src/main/res/values-fur/error.xml @@ -1,4 +1,7 @@ + Ops. Alc al è lât mal! Graziis! diff --git a/app/src/main/res/values-gl/error.xml b/app/src/main/res/values-gl/error.xml index b4c62454c..6a77c8d0c 100644 --- a/app/src/main/res/values-gl/error.xml +++ b/app/src/main/res/values-gl/error.xml @@ -1,4 +1,7 @@ + Commons fallou Vaites! Algo foi mal! diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 5b5f67f18..e7c3a37c2 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -1,11 +1,26 @@ + + Aparencia + Xeral + Comentarios + Localización Commons + Configuracións Nome de usuario Contrasinal Acceda á súa conta de Commons Beta Acceder ao sistema + Esqueceu o contrasinal? Rexistrarse Accedendo ao sistema Por favor, agarde… @@ -37,6 +52,7 @@ Compartir Mostrar no navegador Título + Por favor, proporcione un título para este ficheiro Descrición Erro ao acceder ao sistema: Fallou a rede Erro ao acceder ao sistema: Comprobe o seu nome de usuario @@ -52,6 +68,7 @@ Procurar categorías Gardar Refrescar + Lista O GPS está desactivado no seu dispositivo. Quere activalo? Activar GPS Aínda non hai subas @@ -76,8 +93,8 @@ Acerca de A aplicación Wikimedia Commons é unha aplicación de código aberto creada e mantida polos cesionarios e voluntarios da comunidade de Wikimedia. A Fundación Wikimedia non está involucrada na creación, desenvolvemento ou mantemento da aplicación. Crear unha nova <a href=\"https://github.com/commons-app/apps-android-commons/issues\">incidencia</a> para informar de problemas e suxestións. - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">Política de privacidade</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> + <u>Política de privacidade</u> + <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> Acerca de Enviar comentarios (por correo electrónico) Non hai instalado ningún cliente de correo @@ -89,7 +106,7 @@ Esta imaxe quedará baixo a licenza %1$s Publicando esta imaxe, declaro que é da miña obra, que non contén material con dereitos de autor ou selfies e que se adhire ás <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Políticas de Wikimedia Commons</a>. Descargar - Licenza + Licenza por defecto Usar o título ou a descrición anterior Obter automaticamente a localización actual Obter a localización actual para ofrecer suxestións de categoría se a imaxe non está xeolocalizada @@ -118,11 +135,20 @@ Wikimedia Commons alberga a maioría das imaxes usada en Wikipedia. As súas imaxes axudan a educar a persoas de todo o mundoǃ Por favor, suba unicamente imaxes capturadas ou creadas totalmente por vostedeː - - Obxectos naturais (flores, animais, montañas)\n- Obxectos útiles (bicicletas, estacións de tren)\n- Personaxes famosos (o seu alcalde, atletas olímpicos que coñeza) + Obxectos naturais (flores, animais, montañas)\n• Obxectos útiles (bicicletas, estacións de ferrocarril)\n• Persoas famosas (o seu alcalde, atletas olímpicos que coñeza) + Natureza (flores, animais, montañas) + Obxectos útiles (bicicletas, estacións de ferrocarril) + Persoas famosas (o seu alcalde, atletas olímpicos que coñeza) Por favor, NON subaː - Selfies ou imaxes dos seus amigos\n- Imaxes descargadas de Internet\n- Capturas de pantalla de aplicacións con dereitos de autor + Autorretratos ou fotos dos seus amigos + Imaxes descargadas de Internet + Capturas de pantalla de aplicacións privativas Exemplo de subaː - Título: Ópera de Sydney\n- Descrición: A Ópera de Sydney vista dende a baía\n- Categorías: Sydney Opera House from the west, Sydney Opera House remote views + Título: Ópera de Sydney + Descrición: A Ópera de Sydney, vista desde o outro lado da baía + Categorías: Ópera de Sydney desde o oeste, vistas a distancia da Ópera de Sydney Achegue as súas imaxes. Axude a que os artigos da Wikipedia cobren vida! As imaxes da Wikipedia veñen da Wikimedia Commons. As súas imaxes axudan a educar xente de todo o mundo. @@ -135,8 +161,8 @@ Sen descrición Licenza descoñecida Refrescar - Permiso necesarioː ler un almacenamento externo. A aplicación non pode funcionar sen isto. - Permiso necesario: Escribir en almacenamento externo. A aplicación non pode funcionar sen el. + Permiso necesarioː ler un almacenamento externo. A aplicación non pode acceder á súa galería sen isto. + Permiso necesario: Escribir en almacenamento externo. A aplicación non pode acceder á súa cámara sen el. Permiso opcionalː obter a localización actual para suxerir categorías Aceptar Lugares próximos @@ -195,6 +221,7 @@ non se atopou descrición Páxina do ficheiro en Commons Elemento en Wikidata + Artigo de Wikipedia Erro mentras se gardaban as imaxes na caché Un título único descritivo para o ficheiro, que servirá como un nome de ficheiro. Pode usar unha linguaxe clara con espazos. Non inclúa a extensión do ficheiro Por favor, describa o ficheiro todo o posibleː Onde se gravou? Cal é o contexto? Por favor, describa os obxectos ou persoas. Indique información que non pode ser adiviñada de forma doada, por exemplo, a hora do día se é unha paisaxe. Se o ficheiro amosa algo pouco habitual, por favor, explique que é o que o fai excepcional. @@ -206,6 +233,11 @@ Comezar sesión na súa conta Enviar ficheiro de rexistro Enviar ficheiro de rexistro ós desenvolvedores por correo electrónico + Non se atopou ningún navegador co que abrir a URL + Errorǃ Nos se atopou a URL + Nomear para borrado + Esta imaxe foi nomeada para borrar. + Ver en navegador A localización non cambiou. A localización non está dispoñible. Precísase permiso para amosar unha lista de lugares preto de aquí @@ -216,4 +248,21 @@ Grazas por realizar unha edición %1$s mencionouno en %2$s. Cambiar modo de visualización + COMO CHEGAR + WIKIDATA + WIKIPEDIA + COMMONS + <u>Avalíenos</u> + <u>FAQ</u> + Saltar titorial + Internet non dispoñible + Internet dispoñible + Erro ó recuperar as notificacións + Non se atopou ningunha notificación + <u>Traducir</u> + Linguas + Seleccione a lingua para a que quere enviar as traducións + Proceder + Cancelar + Reintentar diff --git a/app/src/main/res/values-gu/error.xml b/app/src/main/res/values-gu/error.xml index 81ff69fbe..7f9e3762e 100644 --- a/app/src/main/res/values-gu/error.xml +++ b/app/src/main/res/values-gu/error.xml @@ -1,4 +1,7 @@ + કોમન્સ ભાંગી પડ્યું છે ઉપ્સ. કંઇક ખરાબ થયું છે! diff --git a/app/src/main/res/values-haw/error.xml b/app/src/main/res/values-haw/error.xml index 3efc364c9..145f13a97 100644 --- a/app/src/main/res/values-haw/error.xml +++ b/app/src/main/res/values-haw/error.xml @@ -1,4 +1,7 @@ + Ua haki ʻO Kahilehulehu ʻAuwē. Loaʻa i ka pilikia! diff --git a/app/src/main/res/values-haw/strings.xml b/app/src/main/res/values-haw/strings.xml index 028661090..a81ab120d 100644 --- a/app/src/main/res/values-haw/strings.xml +++ b/app/src/main/res/values-haw/strings.xml @@ -1,4 +1,7 @@ + Kahilehulehu Wikimedia Makemake diff --git a/app/src/main/res/values-hi/error.xml b/app/src/main/res/values-hi/error.xml index d4a796db4..8a9254afc 100644 --- a/app/src/main/res/values-hi/error.xml +++ b/app/src/main/res/values-hi/error.xml @@ -1,4 +1,8 @@ + कॉमन्स क्रैश हो गया ओह, कुछ गलत हो गया! diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 869f6b72b..69bb67655 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -1,4 +1,19 @@ + कॉमन्स सेटिंग्स @@ -134,8 +149,8 @@ कोई विवरण नहीं अज्ञात लाइसेन्स ताजा करें - अनिवार्य अनुमति: बाहरी स्मृति पढ़ें। एप इसके बिना कार्य नहीं करेगा। - अनिवार्य अनुमति:बाहरी कंप्यूटर स्टोरेज लिखना|इसके बिना एप कार्य नहीं करेगा। + अनिवार्य अनुमति: बाहरी स्मृति पढ़ें। एप इसके बिना कार्य नहीं करेगा। + अनिवार्य अनुमति:बाहरी कंप्यूटर स्टोरेज लिखना|इसके बिना एप कार्य नहीं करेगा। वैकल्पिक अनुमति: श्रेणी सुझाव हेतु वर्तमान स्थान ज्ञात करें ठीक है आसपास के स्थान @@ -218,4 +233,12 @@ विकीडाटा विकीपीडिया कॉमन्स + इंटरनेट उपलब्ध नहीं + इंटरनेट उपलब्ध + सूचनाएं लाने में त्रुटि + कोई सूचनाएँ नहीं मिलीं + भाषाएँ + आगे बढ़ें + रद्द करें + पुनः प्रयास करें diff --git a/app/src/main/res/values-hrx/error.xml b/app/src/main/res/values-hrx/error.xml index b61ba334d..24d908c6d 100644 --- a/app/src/main/res/values-hrx/error.xml +++ b/app/src/main/res/values-hrx/error.xml @@ -1,4 +1,7 @@ + Commons (Allmend) ist abgestürzt Huch! Etwas ist schiefgeloof. diff --git a/app/src/main/res/values-hrx/strings.xml b/app/src/main/res/values-hrx/strings.xml index 51c9ed9ec..7905a92d7 100644 --- a/app/src/main/res/values-hrx/strings.xml +++ b/app/src/main/res/values-hrx/strings.xml @@ -1,4 +1,8 @@ + Wikimedia Commons (Wikimedia Allmend) Instellunge diff --git a/app/src/main/res/values-hsb/error.xml b/app/src/main/res/values-hsb/error.xml index 0bc699dfd..9846f0d65 100644 --- a/app/src/main/res/values-hsb/error.xml +++ b/app/src/main/res/values-hsb/error.xml @@ -1,4 +1,7 @@ + Commons je spadnył Hopla. Něšto je so nimokuliło! diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index bba30831c..97b0d1af5 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -1,4 +1,7 @@ + Wikimedia Commons Nastajenja diff --git a/app/src/main/res/values-hu/error.xml b/app/src/main/res/values-hu/error.xml index 6d42fad35..765b80670 100644 --- a/app/src/main/res/values-hu/error.xml +++ b/app/src/main/res/values-hu/error.xml @@ -1,4 +1,9 @@ + Az alkalmazás összeomlott Hoppá! Valami elromlott! diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 852f9b6c8..e17c0991a 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -1,11 +1,28 @@ + + Visszajelzés + Helyszín Commons + Beállítások Felhasználónév Jelszó Jelentkezz be a Commons Béta fiókoddal Bejelentkezés + Elfelejtett jelszó: Regisztráció Belépés… Kérlek várj… @@ -52,6 +69,7 @@ Keresés a kategóriák között Mentés Frissítés + Lista A GPS le van tiltva az eszközén. Szeretné engedélyezni? GPS engedélyezése Még nincsenek feltöltések @@ -89,7 +107,7 @@ Ez a kép %1$s licenc alatt kerül feltöltésre A kép feltöltésével kijelentem, hogy ez a saját munkám és nem tartalmaz jogvédett anyagot, nem szelfi és megfelel a<a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons irányelveinek</a>. Letöltés - Licenc + Alapértelmezett licenc Előző cím/leírás használata Automatikusan megkapja a jelenlegi helyet Lekéri a jelenlegi helyet, hogy lehetőség legyen kategóriajavaslatokra a nem földrajzi címkézett képeknél. @@ -123,6 +141,7 @@ - Szelfiket vagy képeket a barátaidról\n- Internetröl letöltött képeket\n- Kereskedelmi alkalmazások képernyőképeit Példa feltöltés: - Cím: Sydney-i Operaház\n- Leírás: A Sydney-i Operaház az öböl túlpartjáról\n- Kategóriák: Sydney Opera House from the west, Sydney Opera House remote views + Cím: Sydney-i Operaház Tedd közzé a képeidet! Segíts életre kelteni a Wikipédia-szócikkeket! A Wikipédián található képek a Wikimédia Commonsből származnak. A képeid segítenek a világ minden táján élő emberek oktatásában. @@ -135,8 +154,8 @@ Nincs leírás Ismeretlen licenc Frissítés - Szükséges engedély: Külső tárhely olvasása. Az alkalmazás nem működik enélkül. - Szükséges engedély: Külső tárhely írása. Az alkalmazás nem működik enélkül. + Szükséges engedély: Külső tárhely olvasása. Az alkalmazás nem működik enélkül. + Szükséges engedély: Külső tárhely írása. Az alkalmazás nem működik enélkül. Lehetséges engedély: Jelenlegi hely megszerzése, a kategóriajavaslatok lehetőségéért. OK Közeli helyek @@ -192,6 +211,7 @@ nincs leírás Commons leírólap Wikidata-elem + Wikipédia-cikk Hiba a képek gyorsítótárazásakor Egy egyedi, leíró cím a fájlnak, ami fájlnévként fog szolgálni. Egyszerű nyelvezetet használhatsz szóközökkel. Ne tedd bele a kiterjesztést. Kérlek a lehető legteljesebb módon írd le a fájlt: hol készült, mit ábrázol, mi a kontextus? Kérlek add meg az objektumokat vagy személyeket a képen, valamint a nehezen kitalálható információkat (például a kép készítésének dátumát, ha az egy tájkép). Amennyiben a média valami szokatlant ábrázol, kérlek fejtsd ki, hogy mi teszi szokatlanná. @@ -201,6 +221,8 @@ Bejelentkezés a fiókodba Naplófájlok küldése Naplófájlok küldése e-mailben a fejlesztőknek + Hiba! URL nem található. + Törlésre jelölés A hely nem változott. A hely nem érhető el. Üdvözlünk a Wikimedia Commonson, %1$s! Örülünk, hogy itt vagy. diff --git a/app/src/main/res/values-hy/error.xml b/app/src/main/res/values-hy/error.xml index f8289a6ff..93541a611 100644 --- a/app/src/main/res/values-hy/error.xml +++ b/app/src/main/res/values-hy/error.xml @@ -1,4 +1,7 @@ + Վաայ: Ինչ-որ բան սխալ գնաց Շնորհակալություն diff --git a/app/src/main/res/values-hyw/error.xml b/app/src/main/res/values-hyw/error.xml index 40393662f..14f0ff1c3 100644 --- a/app/src/main/res/values-hyw/error.xml +++ b/app/src/main/res/values-hyw/error.xml @@ -1,4 +1,7 @@ + Շնորհակալութիւն: diff --git a/app/src/main/res/values-ia/error.xml b/app/src/main/res/values-ia/error.xml index 6ca241fc3..877fcd28c 100644 --- a/app/src/main/res/values-ia/error.xml +++ b/app/src/main/res/values-ia/error.xml @@ -1,4 +1,7 @@ + Commons: crash Ups. Qualcosa ha facite fiasco! diff --git a/app/src/main/res/values-in/error.xml b/app/src/main/res/values-in/error.xml index 8279fe84f..0c7243d0a 100644 --- a/app/src/main/res/values-in/error.xml +++ b/app/src/main/res/values-in/error.xml @@ -1,4 +1,8 @@ + Commons mendadak kacau Ups. Ada yang tidak beres! diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 47d50d14a..16185f35d 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -1,4 +1,12 @@ + Commons Pengaturan diff --git a/app/src/main/res/values-is/error.xml b/app/src/main/res/values-is/error.xml index d4150af3c..93e65f581 100644 --- a/app/src/main/res/values-is/error.xml +++ b/app/src/main/res/values-is/error.xml @@ -1,4 +1,7 @@ + Commons-forritið hrundi Úbbs. Eitthvað fór úrskeiðis! diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index c766bf7b2..3985a654b 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -1,4 +1,7 @@ + Útlit Almennt @@ -59,6 +62,7 @@ Leita í flokkum Vista Endurlesa + Listi GPS er óvirkt í tækinu þínu. Viltu virkja það? Virkja GPS Engar innsendingar ennþá @@ -151,8 +155,8 @@ Engin lýsing Óþekkt notkunarleyfi Endurlesa - Nauðsynlegar heimildir: Lesa ytri gagnageymslu. Forritið virkar ekki án þess. - Nauðsynlegar heimildir: Skrifa í ytri gagnageymslu. Forritið virkar ekki án þess. + Nauðsynlegar heimildir: Lesa ytri gagnageymslu. Forritið fær ekki aðgang að myndasafni ekki án þessa. + Nauðsynlegar heimildir: Skrifa í ytri gagnageymslu. Forritið nær ekki sambandi við myndavél ekki án þessa. Nauðsynlegar heimildir: Lesa núverandi staðsetningu til að geta stungið upp á flokkum Í lagi Staðir í nágrenninu @@ -211,6 +215,7 @@ engin lýsing fannst Síða Commons-skrár Wikidata-atriði + Wikipedia-grein Villa kom upp í skyndiminni mynda Einstakur og lýsandi titill, sem mun verða skráarheiti. Þú mátt nota einfaldan texta með bilum. Ekki hafa með neina skráarendingu Lýstu gögnunum eins vel og auðið er: Hvar er myndin tekin? Hvað sýnir hún? Hvert er samhengið? Lýstu fólki og fyrirbærum. Gefðu upp þær upplýsingar sem ekki er auðvelt að giska á, til dæmis á hvaða tíma dags myndin er tekin ef hún sýnir landslag. Ef gögnin sýna eitthvað óvenjulegt, útskýrðu þá hvað það er sem sé sérstakt. @@ -224,6 +229,9 @@ Senda atvikaskrá til forritaranna með tölvupósti Gat ekki ræst vefvafra til að opna slóð Villa: Slóð fannst ekki + Tilnefna til eyðingar + Þessi mynd hefur verið valin til eyðingar. + Skoða í vafra Staðsetning hefur ekki breyst. Staðsetning ekki tiltæk. Heimild þarf til að birta lista yfir staði í nágrenninu @@ -234,6 +242,21 @@ Takk fyrir að hafa gert breytingar %1$s minntist á þig á %2$s. Víxla sýn - Algengar spurningar + STEFNUR + WIKIDATA + WIKIPEDIA + COMMONS + <u>Gefðu okkur einkunn</u> + <u>Algengar spurningar</u> Sleppa kennslu + Nettenging ekki tiltæk + Nettenging í boði + Villa við að sækja tilkynningar + Engar tilkynningar fundust + <u>Þýða</u> + Tungumál + Veldu tungumálið sem þú vill senda inn þýðingar fyrir + Halda áfram + Hætta við + Reyna aftur diff --git a/app/src/main/res/values-it/error.xml b/app/src/main/res/values-it/error.xml index 81389a530..ed0f872fd 100644 --- a/app/src/main/res/values-it/error.xml +++ b/app/src/main/res/values-it/error.xml @@ -1,4 +1,7 @@ + Commons è andato in errore Oops. Qualcosa è andato storto! diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b0dcce458..27968b8d7 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1,4 +1,13 @@ + Aspetto Generale @@ -56,6 +65,7 @@ Cerca categorie Salva Aggiorna + Elenco Il GPS è disabilitato nel dispositivo. Vuoi attivarlo? Attiva GPS Non è stato ancora caricato niente @@ -150,6 +160,7 @@ Titolo Titolo del file multimediale Descrizione + Autore Data di caricamento Licenza Coordinate @@ -186,9 +197,11 @@ nessuna descrizione trovata Pagina di Commons del file Elemento Wikidata + Voce Wikipedia Dai autorizzazione Accedi alla tua utenza Errore! URL non trovato + Questa immagine è stata proposta per la cancellazione. La posizione non è cambiata. Posizione non disponibile. OTTIENI DIREZIONI @@ -197,5 +210,13 @@ %1$s ti ha lasciato un messaggio nella tua pagina di discussione Grazie per aver fatto una modifica %1$s ti ha menzionato su %2$s. - Domande frequenti + WIKIDATA + WIKIPEDIA + COMMONS + <u>Domande frequenti</u> + Internet non disponibile + Internet disponibile + Lingue + Annulla + Riprova diff --git a/app/src/main/res/values-iw/error.xml b/app/src/main/res/values-iw/error.xml index 3f64d1789..949fd6772 100644 --- a/app/src/main/res/values-iw/error.xml +++ b/app/src/main/res/values-iw/error.xml @@ -1,4 +1,7 @@ + יישום ויקישיתוף קרס אוי, משהו השתבש! diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index ed94cdc29..186df118a 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -1,4 +1,16 @@ + מראה כללי @@ -58,6 +70,7 @@ חיפוש קטגוריות שמירה רענון + רשימה ה־GPS במכשיר שלך אינו מופעל. האם להפעיל אותו? הפעלת GPS לא הועלה עדיין שום דבר @@ -79,6 +92,7 @@ קטגוריות הגדרות רישום + תמונות מומלצות אודות יישום ויקישיתוף (Wikimedia Commons app) הוא יישום קוד פתוח שמפותח ומתוחזק על־ידי מקבלי מלגות ומתנדבים של קהילת ויקימדיה. קרן ויקימדיה אינה מעורבת ביצירה, פיתוח, או תחזוקה של היישום. נא ליצור <a href=\"https://github.com/commons-app/apps-android-commons/issues\">דיווח בגיטהאב</a> בשביל באגים והצעות. @@ -150,8 +164,8 @@ אין תיאור רישיון לא ידוע רענון - הרשאה מחייבת: אחסון. היישום לא יכול לעבוד בלי זה. - נדרשת הרשאה: כתיבה לאחסון חיצוני. היישום לא יכול לעבוד בלי זה. + נדרשת הרשאה: קריאת אחסון חיצוני. היישום לא יכול לגשת לגלריה שלך בלי זה. + נדרשת הרשאה: כתיבה לאחסון חיצוני. היישום לא יכול לגשת למצלמה שלך בלי זה. הרשאה לא מחייבת: קבלת מיקום נוכחי בשביל הצעות קטגוריות אישור מקומות בסביבה @@ -164,6 +178,8 @@ כותרת המדיה תיאור תיאור המדיה יהיה כאן. זה יכול להיות ארוך למדי, ולהתפרס על מספר שורות. אנחנו מקווים שזה נראה טוב. + יוצר + שם המשתמש של יוצר התמונה המומלצת. תאריך העלאה רישיון נקודות ציון @@ -205,6 +221,7 @@ יציאה מדריך הודעות + מומלץ אי־אפשר להציג מקומות בסביבה ללא הרשאות מיקום לא נמצא תיאור דף קובץ בוויקישיתוף @@ -221,6 +238,9 @@ שליחת קובץ יומן שליחת קובץ יומן למפתחים בדואר אלקטרוני לא נמצא דפדפן שיוכל לפתוח את הכתובת + להציע מחיקה + התמונה הזאת מועמדת למחיקה + הצגה בדפדפן המיקום לא השתנה. המיקום אינו זמין. נדרשת הרשאה כדי להציג רשימה של מקומות בסביבה @@ -231,6 +251,21 @@ תודה לך על העריכה אוזכרת על ידי %2$s ב{{GRAMMAR:תחילית|%1$s}}. החלפת מצב תצוגה - שאלות נפוצות + כיוונים + ויקינתונים + ויקיפדיה + ויקישיתוף + <u>תנו לנו ציון</u> + <u>שאלות נפוצות</u> לדלג על ההדרכה + האינטרנט אינו זמין + האינטרנט זמין + שגיאה באחזור התראות + לא נמצאו התראות + <u>תרגום</u> + שפות + נא לבחור את השפה שבה תשלחו את התרגומים + המשך + ביטול + לנסות שוב diff --git a/app/src/main/res/values-ja/error.xml b/app/src/main/res/values-ja/error.xml index e155388f2..9d95a7d2d 100644 --- a/app/src/main/res/values-ja/error.xml +++ b/app/src/main/res/values-ja/error.xml @@ -1,4 +1,7 @@ + コモンズがクラッシュしました エラーが発生しました! diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 2095f3d31..e34c98432 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,5 +1,19 @@ + + フィードバック + 場所 コモンズ 設定 利用者名 @@ -71,8 +85,8 @@ このアプリについて ウィキメディア・コモンズ・アプリはウィキメディア・コミュニティの助成金受給者とボランティアによって製作・メンテナンスされているオープンソースソフトウェアです。ウィキメディア財団はこのアプリの製作・開発・メンテナンスに関与していません。 バグとアイディアは <a href=\"https://github.com/commons-app/apps-android-commons/issues\">Github</a> へ。 - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/プライバシー・ポリシー\">プライバシー・ポリシー</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">クレジット</a> + <u>プライバシー・ポリシー</u> + <u>クレジット</u> このアプリについて フィードバックをメールで送信 メールアプリケーションが見つかりません @@ -83,7 +97,7 @@ キャンセル この画像が %1$s ライセンスでアップロードされます。 ダウンロード - ライセンス + 既定のライセンス 前回のタイトルと記述を使用 現在の位置を自動的に取得 画像にジオタグが付いていない場合、現在の位置を取得してカテゴリを提案 @@ -129,8 +143,8 @@ 説明はありません。 不明なライセンス 更新 - 必要な権限:外部ストレージを読み込みます。これがなければアプリは機能しません。 - 必要な権限:外部ストレージを作成します。これがなければアプリは機能しません。 + 必要な権限:外部ストレージを読み込みます。これがなければアプリは機能しません。 + 必要な権限:外部ストレージを作成します。これがなければアプリは機能しません。 オプションの権限:カテゴリ候補の現在の位置を取得する 承認 周りの場所 @@ -143,6 +157,7 @@ メディアのタイトル 記述 ここにメディアの説明が入ります。かなり長文になる場合には数行にわたることがあります。それでも見栄えがよいと願っています。 + 作者 アップロード日時 ライセンス 緯度経度 @@ -183,6 +198,7 @@ 場所の権限がないと、近くの場所を表示できません 説明がありません ウィキデータ項目 + ウィキペディアの記事 画像をキャッシュする際のエラー ファイル固有の説明的な表題。ファイル名として使われます。平易な言葉を使い、空白を入れることができます。拡張子は含めないでください。 可能な限りメディアを説明してください:どこで撮られましたか?それは何を示していますか?文脈とは何ですか?物や人を説明してください。容易に推測できない情報、例えば風景の場合の時刻を明らかにする。メディアに珍しいことがある場合は、何が珍しいのかを説明してください。 @@ -192,6 +208,15 @@ 自分のアカウントにログイン ログファイルを送信する メールで開発者にログファイルを送信する + ブラウザーで表示 場所は変更されていません。 位置が無効です。 + 記事を読む + <u>評価する</u> + <u>FAQ</u> + チュートリアルをスキップする + <u>翻訳</u> + 言語 + キャンセル + 再試行 diff --git a/app/src/main/res/values-ji/error.xml b/app/src/main/res/values-ji/error.xml index e0fd55abb..e61d3b67d 100644 --- a/app/src/main/res/values-ji/error.xml +++ b/app/src/main/res/values-ji/error.xml @@ -1,4 +1,7 @@ + קאמאנסט איז אײַנגעפֿאלן אוי, עפעס טויג נישט! diff --git a/app/src/main/res/values-ji/strings.xml b/app/src/main/res/values-ji/strings.xml index b5ddb6339..9122cc710 100644 --- a/app/src/main/res/values-ji/strings.xml +++ b/app/src/main/res/values-ji/strings.xml @@ -1,4 +1,7 @@ + קאמאנס איינשטעלונגען @@ -56,6 +59,7 @@ קאַטעגאריעס איינשטעלונגען + רעקאמענדירטע בילדער וועגן וועגן שיקן פֿידבעק (דורך בליצפאסט) @@ -92,6 +96,7 @@ ווארענונג יא ניין + מחבר ליצענץ קאארדינאטן טולפאן @@ -105,4 +110,5 @@ איינשטעלונגען פֿידבעק אַרויסלאָגירן + רעקאמנדירט diff --git a/app/src/main/res/values-jv/error.xml b/app/src/main/res/values-jv/error.xml index b968dbb2e..26d4c0431 100644 --- a/app/src/main/res/values-jv/error.xml +++ b/app/src/main/res/values-jv/error.xml @@ -1,4 +1,7 @@ + Commons lagi kaco Wadhuh. Ana sing luput! diff --git a/app/src/main/res/values-jv/strings.xml b/app/src/main/res/values-jv/strings.xml index 15949cde8..e051b6f97 100644 --- a/app/src/main/res/values-jv/strings.xml +++ b/app/src/main/res/values-jv/strings.xml @@ -1,4 +1,7 @@ + Commons Setèlan @@ -119,7 +122,7 @@ Tanpa katerangan Lisènsi ora kaweruhan Anyarana - Butuh palilah: Maca panyimpenan njaba. Aplikasi mokal mlaku yèn tanpa iki. + Butuh palilah: Maca panyimpenan njaba. Aplikasi mokal mlaku yèn tanpa iki. Palilah manasuka: Njupuk pernah saiki kanggo saran ing kategori Oké Papan Cedhak Kéné diff --git a/app/src/main/res/values-ka/error.xml b/app/src/main/res/values-ka/error.xml index 2e6b95c18..82ce98b94 100644 --- a/app/src/main/res/values-ka/error.xml +++ b/app/src/main/res/values-ka/error.xml @@ -1,4 +1,7 @@ + ვიკისაწყობი გაითიშა ვაი. რაღაც მოხდა! diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 7e3b77917..2bb1c5191 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -1,4 +1,8 @@ + ვიკისაწყობი კონფიგურაცია diff --git a/app/src/main/res/values-kab/error.xml b/app/src/main/res/values-kab/error.xml index 922edaad0..f2602e6a5 100644 --- a/app/src/main/res/values-kab/error.xml +++ b/app/src/main/res/values-kab/error.xml @@ -1,4 +1,7 @@ + Commons yeɣli Ihuh. Yella wayen yeḍran! diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index ec93fdd67..342c615b9 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -1,4 +1,8 @@ + Ayen yettwasnen Iɣewwaren @@ -134,8 +138,8 @@ Ulac aglam Turagt tarussint Smiren - Yesra tasiregt: Ɣeṛ asekles azɣaray. Asnas ur yezmir ara ad yeddu s war aya. - Ysera tasiregt: Aru deg usekles azɣaray. Asnas ur yezmir ara ad yeddu s war aya. + Yesra tasiregt: Ɣeṛ asekles azɣaray. Asnas ur yezmir ara ad yeddu s war aya. + Ysera tasiregt: Aru deg usekles azɣaray. Asnas ur yezmir ara ad yeddu s war aya. Tasiregt tafrayant: Awi adig amiran i yisumar n taggayt IH Idigen iqeṛben diff --git a/app/src/main/res/values-km/error.xml b/app/src/main/res/values-km/error.xml index 631b36024..14986df3b 100644 --- a/app/src/main/res/values-km/error.xml +++ b/app/src/main/res/values-km/error.xml @@ -1,4 +1,7 @@ + Commons ត្រូវបានគាំង Opps. មានអ្វីមួយកំពុងមានបញ្ហា-កំហុស! diff --git a/app/src/main/res/values-km/strings.xml b/app/src/main/res/values-km/strings.xml index d4fb12f16..c057e04c7 100644 --- a/app/src/main/res/values-km/strings.xml +++ b/app/src/main/res/values-km/strings.xml @@ -1,4 +1,8 @@ + Wikimedia Commons ការកំណត់​នានា diff --git a/app/src/main/res/values-kn/error.xml b/app/src/main/res/values-kn/error.xml index 16418bb1c..0916923c5 100644 --- a/app/src/main/res/values-kn/error.xml +++ b/app/src/main/res/values-kn/error.xml @@ -1,4 +1,7 @@ + ಧನ್ಯವಾದಗಳು! diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index 6631cd1fb..7eeaf2713 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -1,4 +1,9 @@ + ಕಾಮನ್ಸ್ ವ್ಯವಸ್ಥೆಗಳು diff --git a/app/src/main/res/values-ko-rKP/strings.xml b/app/src/main/res/values-ko-rKP/strings.xml index 7bb45e619..670479f75 100644 --- a/app/src/main/res/values-ko-rKP/strings.xml +++ b/app/src/main/res/values-ko-rKP/strings.xml @@ -1,4 +1,8 @@ + 공용 설정 diff --git a/app/src/main/res/values-ko/error.xml b/app/src/main/res/values-ko/error.xml index dfec407ec..f8ae08908 100644 --- a/app/src/main/res/values-ko/error.xml +++ b/app/src/main/res/values-ko/error.xml @@ -1,4 +1,8 @@ + 공용 애플리케이션이 작동을 멈췄습니다 이런. 무언가가 잘못됐습니다! diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 27c261d3d..11faee9c6 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1,4 +1,16 @@ + 보이기 일반 @@ -59,6 +71,7 @@ 분류 검색 저장 새로 고침 + 목록 장치에서 GPS가 꺼져 있습니다. 켜시겠습니까? GPS 사용 아직 올린 항목이 없습니다 @@ -78,9 +91,10 @@ 분류 설정 가입하기 + 알찬 그림 정보 위키미디어 공용 앱은 오픈 소스 애플리케이션이며 위키미디어 공동체 내의 자원봉사자에 의해 유지됩니다. 위키미디어 재단은 애플리케이션의 생성, 개발, 유지보수에 관여하지 않습니다. - 소스 코드는 <a href=\"https://github.com/commons-app/apps-android-commons\">GitHub</a>에 있으며, 웹사이트는 <a href=\"https://commons-app.github.io/\">GitHub</a>에 있습니다. 버그나 기타 제안은 <a href=\" https://github.com/commons-app/apps-android-commons/issues\">GitHub</a>에 보고해주세요. + 버그나 기타 제안은 <a href=\" https://github.com/commons-app/apps-android-commons/issues\">GitHub</a>에 보고해주세요. <u>개인정보 정책</u> <u>제작진</u> 정보 @@ -134,6 +148,9 @@ 사유 앱의 스크린샷 업로드 예시: - 제목: 시드니 오페라 하우스\n- 설명: 항만 건너편에서 바라본 시드니 오페라 하우스\n- 분류: 시드니 오페라 하우스, 서쪽에서 본 시드니 오페라 하우스, 시드니 오페라 하우스 원경 + 제목: 시드니 오페라 하우스 + 설명: 강 건너에서 바라본 시드니 오페라 하우스 + 분류: Sydney Opera House from the west, Sydney Opera House remote views 당신의 그림을 기여하세요. 위키백과 문서의 생명이 오는 데 도와주세요! 위키백과의 그림은 위키미디어 공용에서 옵니다. 당신의 그림은 전 세계 사람들을 교육하는 데 도움이 됩니다. @@ -146,8 +163,8 @@ 설명 없음 알 수 없는 라이선스 새로 고침 - 권한 필요: 외부 저장소 읽기. 이것이 없으면 앱은 동작하지 않습니다. - 권한 필요: 외부 저장소 쓰기. 이것이 없으면 앱은 동작하지 않습니다. + 권한 필요: 외부 저장소 읽기. 이것이 없으면 앱은 갤러리에 접근할 수 없습니다. + 권한 필요: 외부 저장소 쓰기. 이것이 없으면 앱은 카메라에 접근할 수 없습니다. 선택적 권한: 분류 추천을 위해 현재 위치 정보를 가져옵니다. 확인 근처의 장소 @@ -160,6 +177,8 @@ 미디어 제목 설명 여기에 미디어의 설명이 들어갑니다. 상당히 길어질 경우, 여러 줄에 걸쳐야 할 수 있습니다. 그래도 보기 좋았으면 좋겠네요. + 저자 + 알찬 그림 저자의 사용자 이름은 여기에.들어갑니다. 올린 날짜 라이선스 좌표 @@ -175,6 +194,8 @@ 정말 로그아웃하시겠습니까? 공용 로고 공용 웹사이트 + 공용 페이스북 페이지 + 공용 GitHub 소스 코드 배경 그림 미디어 그림 실패 그림이 없습니다 @@ -200,12 +221,16 @@ 로그아웃 강좌 알림 + 알참 위치 권한이 없으면 주변 장소를 표시할 수 없습니다 설명이 없습니다 공용 파일 문서 위키데이터 항목 + 위키백과 문서 그림 캐시 처리 오류 이 파일을 설명할 수 있는 제목으로, 파일 이름으로 사용됩니다. 띄어쓰기를 포함한 일반적인 단어를 사용할 수 있습니다. 파일 확장자는 포함하지 마세요 + 사진이 너무 어둡습니다. 정말 업로드하겠습니까? 위키미디어 공용은 사전적인 가치가 있는 사진을 위한 공간입니다. + 사진이 흐릿합니다. 정말 업로드하겠습니까? 위키미디어 공용은 사전적인 가치가 있는 사진을 위한 공간입니다. 권한 부여 외부 저장소 사용하기 장치의 인앱 카메라로 찍은 사진 저장하기 @@ -214,6 +239,8 @@ 이메일로 개발자에게 로그 파일 보내기 URL을 열기 위한 웹 브라우저를 찾지 못했습니다 오류! URL을 찾을 수 없습니다 + 삭제 신청 + 이 그림은 삭제가 신청되었습니다. 브라우저에서 보기 위치가 변경되지 않았습니다. 위치를 사용할 수 없습니다. @@ -222,6 +249,21 @@ %1$s님이 당신의 사용자 토론 문서에 글을 남겼습니다 편집해 주셔서 감사합니다 %1$s님이 %2$s에서 나를 언급했습니다. - 자주 묻는 질문 + 방향 + 위키데이터 + 위키백과 + 공용 + <u>평가</u> + <u>FAQ</u> 강좌 건너뛰기 + 인터넷 사용 불가 + 인터넷 사용 가능 + 알림 가져오기 오류 + 알림이 없습니다 + <u>번역</u> + 언어 + 번역 제출을 위한 언어를 선택하십시오 + 진행 + 취소 + 다시 시도 diff --git a/app/src/main/res/values-krc/error.xml b/app/src/main/res/values-krc/error.xml index f1393fc50..53c96d2c5 100644 --- a/app/src/main/res/values-krc/error.xml +++ b/app/src/main/res/values-krc/error.xml @@ -1,4 +1,7 @@ + Халат Не эсе да табсыз барды. diff --git a/app/src/main/res/values-krc/strings.xml b/app/src/main/res/values-krc/strings.xml index 3530f9454..5e0b33b98 100644 --- a/app/src/main/res/values-krc/strings.xml +++ b/app/src/main/res/values-krc/strings.xml @@ -1,4 +1,8 @@ + Викигёзен Джарашдырыула diff --git a/app/src/main/res/values-ku/error.xml b/app/src/main/res/values-ku/error.xml index a1785ef1c..2dc0c29fa 100644 --- a/app/src/main/res/values-ku/error.xml +++ b/app/src/main/res/values-ku/error.xml @@ -1,4 +1,8 @@ + Commons xira bû Haho. Tiştek nerast bû! diff --git a/app/src/main/res/values-ku/strings.xml b/app/src/main/res/values-ku/strings.xml index 9e2ce9c71..16ba9fe2f 100644 --- a/app/src/main/res/values-ku/strings.xml +++ b/app/src/main/res/values-ku/strings.xml @@ -1,4 +1,10 @@ + Xuyabûn Giştî @@ -70,6 +76,6 @@ Paşragihandin Derkeve Destûr bide - Pirsên ku pir têne pirsîn + <u>Pirsên ku pir têne pirsîn</u> Rênîşandanê derbas bike diff --git a/app/src/main/res/values-kum/error.xml b/app/src/main/res/values-kum/error.xml index 706bdae51..fdf9e56db 100644 --- a/app/src/main/res/values-kum/error.xml +++ b/app/src/main/res/values-kum/error.xml @@ -1,4 +1,7 @@ + Вагь. Бир зат чы терс гетди! Этгенигизни язып бизге электрон почгъа йибери. О масъаланы чечме кёмек этежек! diff --git a/app/src/main/res/values-ky/error.xml b/app/src/main/res/values-ky/error.xml index 3e2d281c7..22687ad26 100644 --- a/app/src/main/res/values-ky/error.xml +++ b/app/src/main/res/values-ky/error.xml @@ -1,4 +1,7 @@ + Кыйроо Уупс. Бир нерсе туура эмес болду! diff --git a/app/src/main/res/values-ky/strings.xml b/app/src/main/res/values-ky/strings.xml index d16cdbaca..6d78e91fe 100644 --- a/app/src/main/res/values-ky/strings.xml +++ b/app/src/main/res/values-ky/strings.xml @@ -1,4 +1,8 @@ + Уикиказына Ырастоолор diff --git a/app/src/main/res/values-la/error.xml b/app/src/main/res/values-la/error.xml index 38942512c..82a85d3b5 100644 --- a/app/src/main/res/values-la/error.xml +++ b/app/src/main/res/values-la/error.xml @@ -1,4 +1,7 @@ + Error Error diff --git a/app/src/main/res/values-lag/error.xml b/app/src/main/res/values-lag/error.xml index a486a36be..49824dea8 100644 --- a/app/src/main/res/values-lag/error.xml +++ b/app/src/main/res/values-lag/error.xml @@ -1,4 +1,7 @@ + Kuusa! diff --git a/app/src/main/res/values-lb/error.xml b/app/src/main/res/values-lb/error.xml index 075c16835..92d13b5b5 100644 --- a/app/src/main/res/values-lb/error.xml +++ b/app/src/main/res/values-lb/error.xml @@ -1,4 +1,7 @@ + Commons ass down Ups. Elo ass eppes schif gaang! diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml index 3a642b8d1..321d2a189 100644 --- a/app/src/main/res/values-lb/strings.xml +++ b/app/src/main/res/values-lb/strings.xml @@ -1,4 +1,9 @@ + Ausgesinn Allgemeng @@ -57,6 +62,7 @@ Kategorie sichen Späicheren Aktualiséieren + Lëscht GPS ass op Ärem Apparat ausgeschalt. Wëllt Dir en aktivéieren? GPS aktivéieren Nach keng eropgeluede Fichieren @@ -78,6 +84,7 @@ Kategorien Astellungen Mellt Iech un + Bemierkenswäert Biller Iwwer D\'App Wikimedia Commons ass eng \'Open-Source-App\' déi vu Fräiwëllege vun der Wikimedia Foundation entwéckelt gouf an och vun hinnen ënnerhal gëtt. D\'Wikimedia Foundation ass net an d\'Entwécklung oder den Ënnerhalt vun der App implizéiert. Leet w.e.g. <a href=\"https://github.com/commons-app/apps-android-commons/issues\"> e GitHub Problem</a> fir Problemer ze mellen a Proposen ze maachen. @@ -132,6 +139,7 @@ Biller déi Dir aus dem Internet erofgelueden hutt Beispill-Upload: - Titel: Sydney Opera House\n- Beschreiwung: Sydney Opera House vun der Bay aus gesinn\n- Kategorien: Sydney Opera House, Sydney Opera House vu Westen, Sydney Opera House vu wäitem + Titel: Oper vu Sydney Beschreiwung:Oper vu Sydney esou wéi ee se vun der Bucht aus gesäit Maacht mat mat Äre Biller. Hëlleft Wikipedia-Artikele méi lieweg ze maachen! Biller op Wikipedia komme vu Wikimedia Commons. @@ -145,7 +153,7 @@ Keng Beschreiwung Onbekannt Lizenz Aktualiséieren - Obligatoresch Autorisatioun: Externe Späicher liesen. D\'App kann net ouni dat funktionéieren. + Obligatoresch Autorisatioun: Externe Späicher liesen. D\'App kann ouni dat net op d\'Galerie zougräifen. Fakultativ Autorisatioun: Déi aktuell Plaz kréie fir Propose fir Kategorien OK Plazen nobäi @@ -158,6 +166,7 @@ Titel vum Medium Beschreiwung D\' Beschreiwung vum Medium kënnt hei. Dëst ka méiglecherweis laang sinn a gëtt eventuell op méi Zeile verdeelt. Mir hoffen et gesäit trotzdeem gutt aus. + Auteur Datum vum Eroplueden Lizenz Koordinaten @@ -193,10 +202,12 @@ Ausloggen Uleedung Notifikatiounen + Bemierkenswäert Plazen nobäi kënnen net gewise ginn ouni Rechter fir d\'Lokalisatioun keng Beschreiwung fonnt Commons-Fichierssäit Wikidata-Element + Wikipedia-Artikel Autorisatioun ginn Externe Späicher benotzen Biller späicheren déi mat der in-app Kamera vun Ärem Apparat gemaach goufen @@ -205,6 +216,7 @@ Log-Fichier per E-Mail un d\'Entwéckler schécken Feeler! URL net fonnt Nominéiere fir ze Läschen + Dëst Bild gouf virgeschloe fir geläscht ze ginn. Am Browser weisen De Plaz huet net geännert. Plaz ass net disponibel. @@ -212,5 +224,20 @@ Wëllkomm op Wikimedia Commons, %1$s! Mir si frou datt Dir hei sidd. Merci datt Dir eng Ännerung gemaach hutt %1$s huet Iech op %2$s ernimmt. - Dacks gestallt Froen + RICHTUNGEN + WIKIDATA + WIKIPEDIA + COMMONS + <u>Bewäert eis</u> + <u>FAQ</u> + Internet net disponibel + Internet disponibel + Feeler beim Ofruffe vun den Notifikatiounen + Keng Notifikatioune fonnt + <u>Iwwersetzen</u> + Sproochen + Sicht déi Sprooch eraus Fir déi Dir Iwwersetzunge maache wëllt + Virufueren + Ofbriechen + Nach eng Kéier probéieren diff --git a/app/src/main/res/values-lez/error.xml b/app/src/main/res/values-lez/error.xml index b8d73c3b0..6f921fb3a 100644 --- a/app/src/main/res/values-lez/error.xml +++ b/app/src/main/res/values-lez/error.xml @@ -1,4 +1,7 @@ + Чlурукl хьана Ёъ, вуч-ятlани масакl фена diff --git a/app/src/main/res/values-li/error.xml b/app/src/main/res/values-li/error.xml index 648886712..bffea09e0 100644 --- a/app/src/main/res/values-li/error.xml +++ b/app/src/main/res/values-li/error.xml @@ -1,4 +1,7 @@ + Commons is vasgeloupe Oj. Get góng verkieërdj! diff --git a/app/src/main/res/values-li/strings.xml b/app/src/main/res/values-li/strings.xml new file mode 100644 index 000000000..59dc53188 --- /dev/null +++ b/app/src/main/res/values-li/strings.xml @@ -0,0 +1,113 @@ + + + + Uterlik + Algemein + Feedback + Locatie + Commons + + Instèllinge + Gebroekersnaam + Wachwaord + Meld dich aan mit diene Commons-Bètakonto + Melj dich aan + Wachwaord vergaete? + Teiken dich in + Aan \'nt melje... + Wach estebleef... + Aanmelje gelök! + Aanmelje mislök! + Bestandj neet gevónje. Perbeer \'n anger bestandj. + Verificatie mislök! + Upload begós! + %1$s upgeloadj! + Wies aan veur dienen upload te betrachte + Upload van %1$s aan \'nt vange + %1$s up \'nt loade + d\'n Upload van %1$s is vaerdig + d\'n Upload van %1$s is mislök + Wies aan veur te betrachte + + %1$d bestandj up \'nt loade + %1$d bestenj up \'nt loade + + Mien recènte uploads + Inne wachrie + Mislök + %1$d%% vaerdig + Up \'nt loade + Oete gallerie + Trèk foto aaf + Kórtbie + Mien uploads + Deil + Tuin in browser + Titel + Gaef estebleef \'ne naam veur dit bestandj + Besjrieving + Kan zich neet aanmelde - netwirkfout + Kan zich neet aanmelde - controleer de gebroekersnaam + Kan zich neet aanmelde - controleer die wachwaord + Te väöl mislökde kieëre geperbeerd. Perbeer estebleef oppernuuj euver e paar menuut. + Deze gebroeker is geblokkeerd op Commons + Doe mós diene twieëfaktorische bevestigingscode opgaeve. + Aanmelje mislök + Upload + Gaef dees verzameling \'ne naam + Aanpassinge + Upload + Zeuk categorieje + Slaon op + Vernuuj + Lies + GPS steit oet op die toestèl. Wils se \'t aanzètte? + Zèt GPS aan + Nag gein uploads + + \@string/contributions_subtitle_zero + %1$d upload + %1$d uploads + + + Beginnendj mit %1$d upload + Beginnendj mit %1$d uploads + + + %1$d upload + %1$d uploads + + Gein categorieje die euvereinkómme mit %1$s gevónje + Veug categorieje toe veur dien plaetjes mekkeliker te kinne vinje op Wikimedia Commons.\nBegin mit tikke veur categorieje toe te veuge. + Categorieje + Instèllinge + Registreer + Oetgeleechde plaetjes + Euver + Naamsvermeljing-GeliekDeile 4.0 + Naamsvermeljing 4.0 + Naamsvermeljing-GeliekDeile 3.0 + Naamsvermeljing 3.0 + CC0 + CC BY-SA 3.0 + CC BY-SA 3.0 (Oeësteriek) + CC BY-SA 3.0 (Duutsjlandj) + CC BY-SA 3.0 (Eslandj) + CC BY-SA 3.0 (Spaanje) + CC BY-SA 3.0 (Kroatië) + CC BY-SA 3.0 (Luxemburg) + CC BY-SA 3.0 (Nederlandj) + CC BY-SA 3.0 (Noorwaeg) + CC BY-SA 3.0 (Pole) + CC BY-SA 3.0 (Roemenië) + CC BY 3.0 + CC BY-SA 4.0 + CC BY-4.0 + CC Zero + Op Wikimedia Commons staon de meiste plaetjes die waere gebroek op Wikipedia. + Dien plaetjes helpe luuj oppe ganse werreld mit \'t opdoon van kènnis! + Vernuuj + diff --git a/app/src/main/res/values-lrc/error.xml b/app/src/main/res/values-lrc/error.xml index e7c9b89ec..59bceed8b 100644 --- a/app/src/main/res/values-lrc/error.xml +++ b/app/src/main/res/values-lrc/error.xml @@ -1,4 +1,7 @@ + دتو منمونیم! diff --git a/app/src/main/res/values-lt/error.xml b/app/src/main/res/values-lt/error.xml index ce344ed36..379c762cc 100644 --- a/app/src/main/res/values-lt/error.xml +++ b/app/src/main/res/values-lt/error.xml @@ -1,4 +1,9 @@ + Vikiteka užstrigo Oi. Kažkas nutiko! diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 375734dee..c5c0813ab 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -1,4 +1,11 @@ + Vikiteka Nustatymai @@ -109,7 +116,7 @@ Nėra aprašymo Nežinoma licencija Atnaujinti - Reikalinga teisė: Skaityti išorinę talpyklą. Programėle be to negali funkcionuoti. + Reikalinga teisė: Skaityti išorinę talpyklą. Programėle be to negali funkcionuoti. Neprivaloma teisė: Gauti dabartinę vietovę, kad būtų pasiūlomos kategorijos Gerai Netoliese Esančios Vietos diff --git a/app/src/main/res/values-lv/error.xml b/app/src/main/res/values-lv/error.xml index 5e0f9edbe..f49d27f00 100644 --- a/app/src/main/res/values-lv/error.xml +++ b/app/src/main/res/values-lv/error.xml @@ -1,4 +1,7 @@ + Ups. Kaut kas nogāja greizi! Paldies! diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 5dfd96a47..d73312361 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -1,4 +1,9 @@ + Commons @@ -100,4 +105,7 @@ LASĪT RAKSTU Paldies par labojumu Pārslēgt skatu + Valodas + Turpināt + Atcelt diff --git a/app/src/main/res/values-mg/error.xml b/app/src/main/res/values-mg/error.xml index 3da2ac057..46d92fbd2 100644 --- a/app/src/main/res/values-mg/error.xml +++ b/app/src/main/res/values-mg/error.xml @@ -1,4 +1,7 @@ + Misaotra indrindra! diff --git a/app/src/main/res/values-mk/error.xml b/app/src/main/res/values-mk/error.xml index 6e6e33a9e..938dd05cf 100644 --- a/app/src/main/res/values-mk/error.xml +++ b/app/src/main/res/values-mk/error.xml @@ -1,4 +1,7 @@ + Ризницата се урна Упс. Нешто не е во ред! diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index 0325dcf80..dd1e6f03e 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -1,4 +1,7 @@ + Изглед Општи @@ -81,6 +84,7 @@ Категории Нагодувања Регистрација + Избрани слики За извршникот Прилогот на Ризницата има отворен код. Негови творци и одржувачи се примателите на наменските средства од Викимедиината заедница како и членовите на заедницата. Фондацијата Викимедија нема учество во нејзиното создавање, разработка и одржување. Создајте нов <a href=\"https://github.com/commons-app/apps-android-commons/issues\">проблем на GitHub</a> за пријавување на грешки и давање предлози. @@ -152,8 +156,8 @@ Нема опис Непозната лиценца Превчитај - Потребна дозвола: Треба да се прочита од надворешен склад. Прилогот не може да работи без ова. - Потребна дозвола: Треба да се запише на надворешен склад. Прилогот не може да работи без ова. + Потребна дозвола: Треба да се прочита од надворешен склад. Прилогот без ова нема пристап до вашата галерија. + Потребна дозвола: Треба да се запише на надворешен склад. Прилогот без ова нема пристап до вашата камера. Дозвола по желба: Утврдување на тековната местоположба за предлагање категории ОК Околни места @@ -166,6 +170,8 @@ Наслов на податотеката Опис Тука оди описот на податотеката. Ова потенцијално може да биде прилично долго, и ќе треба да се преломи во неколку реда. Се надеваме дека ќе изгледа добро. + Автор + Тука оди корисничкото име на авторот на избраната слика. Датум на подигање Лиценца Координати @@ -208,6 +214,7 @@ Одјава Упатства Известувања + Избрана Местата во близина не можат да се прикажат без дозволи за местоположба. не најдов описи Податотечна страница @@ -227,6 +234,7 @@ Не најдов прелистувач за да ја отворам URL Грешка! Не ја пронајдов URL Предложи за бришење + Сликава е предложена за бришење. Погледај во прелистувач Местоположбата не е сменета. Местоположбата е недостапна. @@ -242,6 +250,17 @@ ВИКИПОДАТОЦИ ВИКИПЕДИЈА РИЗНИЦА - Често поставувани прашања + <u>Оценете нè</u> + <u>ЧПП</u> Прескокни упатство + Нема семрежен пристап + Има семрежен пристап + Грешка при добивањето на известувањата + Не пронајдов известувања + <u>Преведи</u> + Јазици + Изберете за кој јазик сакате да поднесете преводи + Продолжи + Откажи + Пробај пак diff --git a/app/src/main/res/values-ml/error.xml b/app/src/main/res/values-ml/error.xml index b7ce3d08e..f1f80ba30 100644 --- a/app/src/main/res/values-ml/error.xml +++ b/app/src/main/res/values-ml/error.xml @@ -1,4 +1,7 @@ + കോമൺസ് തകർന്നു അയ്യോ. എന്തോ പ്രശ്നമുണ്ടായി! diff --git a/app/src/main/res/values-ml/strings.xml b/app/src/main/res/values-ml/strings.xml index c41148b5b..485e66acc 100644 --- a/app/src/main/res/values-ml/strings.xml +++ b/app/src/main/res/values-ml/strings.xml @@ -1,4 +1,9 @@ + വിക്കിമീഡിയ കോമൺസ് സജ്ജീകരണങ്ങൾ diff --git a/app/src/main/res/values-mn/error.xml b/app/src/main/res/values-mn/error.xml index 15872699e..4703516b3 100644 --- a/app/src/main/res/values-mn/error.xml +++ b/app/src/main/res/values-mn/error.xml @@ -1,4 +1,7 @@ + Баярлалаа! diff --git a/app/src/main/res/values-mr/error.xml b/app/src/main/res/values-mr/error.xml index 81aa24b8e..453028dd9 100644 --- a/app/src/main/res/values-mr/error.xml +++ b/app/src/main/res/values-mr/error.xml @@ -1,4 +1,7 @@ + कॉमन्स कोसळले आहे ओह. काहीतरी गडबड झाली! diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 90f8f6a0b..b88e021e7 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -1,4 +1,12 @@ + स्वरूप सामान्य @@ -151,8 +159,8 @@ वर्णन नाही. अनोळखी परवाना ताजेतवाने करा - परवानगी आवश्यक:बाह्य भंडारण वाचन. याशिवाय अॅप काम करू शकत नाही. - परवानगी आवश्यक:बाह्य भंडारण वाचन. याशिवाय अॅप काम करू शकत नाही. + परवानगी आवश्यक:बाह्य भंडारण वाचन. याशिवाय अॅप काम करू शकत नाही. + परवानगी आवश्यक:बाह्य भंडारण वाचन. याशिवाय अॅप काम करू शकत नाही. ऐच्छिक परवानगी:वर्ग सुचवण्यांसाठी सध्याचे स्थान मिळवा ठीक आहे जवळपासची स्थाने @@ -234,7 +242,7 @@ तुमच्या संपादनासाठी तुमचे आभार ! %1$s यांनी तुमचा उल्लेख %2$s येथे केला. टॉगल दृश्य - - सतत विचारले जाणारे प्रश्न + + सतत विचारले जाणारे प्रश्न ट्यूटोरियल वगळा diff --git a/app/src/main/res/values-ms/error.xml b/app/src/main/res/values-ms/error.xml index 185c2c977..3517a3ba6 100644 --- a/app/src/main/res/values-ms/error.xml +++ b/app/src/main/res/values-ms/error.xml @@ -1,4 +1,7 @@ + Commons telah runtuh Maaf, berlakunya ralat! diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index 45d5acf60..c5c0f18ab 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -1,4 +1,9 @@ + Wikimedia Commons Tetapan diff --git a/app/src/main/res/values-mt/error.xml b/app/src/main/res/values-mt/error.xml index 097f11c0f..611f79520 100644 --- a/app/src/main/res/values-mt/error.xml +++ b/app/src/main/res/values-mt/error.xml @@ -1,4 +1,7 @@ + Commons waqaf jaħdem Oops. Xi ħaġa marret ħażin! diff --git a/app/src/main/res/values-nb/error.xml b/app/src/main/res/values-nb/error.xml index 2ee9c302a..6cc0c1422 100644 --- a/app/src/main/res/values-nb/error.xml +++ b/app/src/main/res/values-nb/error.xml @@ -1,4 +1,7 @@ + Commons har kræsjet Oisann. Noe gikk galt! diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index d1499536f..9774035ee 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -1,4 +1,12 @@ + Utseende Tilbakemelding @@ -143,8 +151,8 @@ Ingen beskrivelse Ukjent lisens Gjenoppfrisk - Nødvendig tillatelse: Lese ekstern lagring. Appen virker ikke uten dette. - Påkrevd tillatelse: Skriv til ekstern lagring. Appen fungerer ikke uten dette. + Nødvendig tillatelse: Lese ekstern lagring. Appen virker ikke uten dette. + Påkrevd tillatelse: Skriv til ekstern lagring. Appen fungerer ikke uten dette. Valgfri tillatelse: Hent nåværende posisjon for kategoriforslag OK Plasser i nærheten @@ -225,5 +233,8 @@ Takk for at du har gjort en redigering %1$s nevnte deg på %2$s. Skift visning - Ofte stilte spørsmål + Ofte stilte spørsmål + Internett er utilgjengelig + <u>Oversett</u> + Prøv igjen diff --git a/app/src/main/res/values-ne/error.xml b/app/src/main/res/values-ne/error.xml index 4a182573c..832b90733 100644 --- a/app/src/main/res/values-ne/error.xml +++ b/app/src/main/res/values-ne/error.xml @@ -1,4 +1,8 @@ + कमन्स दुर्घटनाग्रस्त भएको छ ओहो। केही गल्ती भयो! diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 168d95f99..be0d2f69f 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1,4 +1,10 @@ + कमन्स सेटिङहरू diff --git a/app/src/main/res/values-nl/error.xml b/app/src/main/res/values-nl/error.xml index 34e295ff1..79f631d2e 100644 --- a/app/src/main/res/values-nl/error.xml +++ b/app/src/main/res/values-nl/error.xml @@ -1,4 +1,8 @@ + Commons is gecrasht Oeps. Er is iets misgegaan. diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 421a8e8bc..f2688cffa 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -1,4 +1,13 @@ + Commons Instellingen @@ -50,18 +59,19 @@ Categorieën zoeken Opslaan Vernieuwen + Lijst Nog geen uploads - - Nog geen uploads - 1 upload + + \@string/contributions_subtitle_zero + %1$d upload %1$d uploads Bezig met 1 upload Bezig met %1$d uploads - - 1 upload + + %1$d upload %1$d uploads Er zijn geen categorieën met \"%1$s\" gevonden @@ -129,7 +139,7 @@ Geen beschrijving Onbekende licentie Vernieuwen - Benodigde toestemming: Lees externe opslag. Zonder deze toestemming kan de app niet functioneren. + Benodigde toestemming: Lees externe opslag. Zonder deze toestemming kan de app niet functioneren. Optionele toestemming: Huidige locatie ophalen voor categoriesuggesties OK Plaatsen in de buurt @@ -152,5 +162,20 @@ Instellingen Terugkoppeling Afmelden + Wikipedia-artikel Error tijdens het laden van de afbeeldingen + Nomineer voor Verwijdering + Deze afbeelding is genomineerd voor verwijdering. + Bekijk in Browser + VERWIJZINGEN + WIKIDATA + Vaak gestelde vragen + Geen internet + Internet beschikbaar + Fout bij ophalen berichten. + Geen berichten. + Talen + Selecteer de taal waarvoor u vertalingen wil indienen + Ga door + Annuleren diff --git a/app/src/main/res/values-oc/error.xml b/app/src/main/res/values-oc/error.xml index f4134a9d7..a66e07397 100644 --- a/app/src/main/res/values-oc/error.xml +++ b/app/src/main/res/values-oc/error.xml @@ -1,4 +1,7 @@ + Commons a fracassat Ops! Quicòm a trucat ! diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index ee4f65da8..803293a55 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -1,4 +1,9 @@ + Commons Paramètres @@ -124,4 +129,14 @@ Títol del mèdia Descripcion Venir un bèta-testaire + Aqueste imatge es estat designat per supression + <u>Nos notar</u> + <u>FAQ</u> + Internet pas disponible + Internet disponible + Error en anant cercar las notificacions. + Cap de notificacion trobada. + <u>Revirar</u> + Seleccionatz la lenga dins la quala volriatz sometre de traduccions + Tornar ensajar diff --git a/app/src/main/res/values-or/error.xml b/app/src/main/res/values-or/error.xml index b474d76ff..88a2ad188 100644 --- a/app/src/main/res/values-or/error.xml +++ b/app/src/main/res/values-or/error.xml @@ -1,4 +1,7 @@ + କମନ୍ସ ଅକାମୀ ହୋଇଗଲା କିଛି ଗୋଟେ ଅଘଟଣ ଘଟିଲା! diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index 43bd74832..c1bc2b73f 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -1,4 +1,8 @@ + ଉଇକିମିଡ଼ିଆ କମନ୍ସ ସଂରଚନା diff --git a/app/src/main/res/values-pa/error.xml b/app/src/main/res/values-pa/error.xml index 219ec0084..5837b6f9e 100644 --- a/app/src/main/res/values-pa/error.xml +++ b/app/src/main/res/values-pa/error.xml @@ -1,4 +1,7 @@ + ਕਾਮਨਜ਼ ਖ਼ਰਾਬ ਹੋ ਗਿਆ ਹੈ ਓ ਹੋ। ਕੁਝ ਗ਼ਲਤ ਹੋ ਗਿਆ! diff --git a/app/src/main/res/values-pa/strings.xml b/app/src/main/res/values-pa/strings.xml index 1a24b278d..6937ab75d 100644 --- a/app/src/main/res/values-pa/strings.xml +++ b/app/src/main/res/values-pa/strings.xml @@ -1,4 +1,10 @@ + ਵਿਕੀਮੀਡੀਆ ਕਾਮਨਜ਼ ਸੈਟਿੰਗ @@ -131,7 +137,7 @@ ਕੋਈ ਵੇਰਵਾ ਨਹੀਂ ਅਣਜਾਣ ਲਸੰਸ ਤਾਜ਼ਾ ਕਰੋ - ਆਗਿਆ ਚਾਹੀਦੀ ਹੈ: ਬਾਹਰੀ ਸਟੋਰੇਜ ਬਾਰੇ। ਇਸ ਤੋਂ ਬਿਨਾਂ ਐਪ ਕਾਰਜ ਨਹੀਂ ਕਰ ਸਕੇਗੀ। + ਆਗਿਆ ਚਾਹੀਦੀ ਹੈ: ਬਾਹਰੀ ਸਟੋਰੇਜ ਬਾਰੇ। ਇਸ ਤੋਂ ਬਿਨਾਂ ਐਪ ਕਾਰਜ ਨਹੀਂ ਕਰ ਸਕੇਗੀ। ਠੀਕ ਹੈ ਨਜ਼ਦੀਕੀ ਥਾਵਾਂ ਕੋਈ ਨਜ਼ਦੀਕੀ ਥਾਵਾਂ ਨਹੀਂ ਮਿਲੀਆਂ diff --git a/app/src/main/res/values-pl/error.xml b/app/src/main/res/values-pl/error.xml index ab4cea30b..fe4ce8933 100644 --- a/app/src/main/res/values-pl/error.xml +++ b/app/src/main/res/values-pl/error.xml @@ -1,4 +1,9 @@ + Wystąpił błąd Commons. Ups. Coś poszło nie tak! diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 009c00b9e..d19dfc7c8 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -1,4 +1,20 @@ + Wygląd Ogólne @@ -80,7 +96,7 @@ Ustawienia Zarejestruj się O aplikacji - Oprogramowanie Open Source, wydane na licencji <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a>. Wikimedia Commons i jego logo są znakami towarowymi Wikimedia Foundation i są wykorzystywane za zgodą Wikimedia Foundation. Nie jesteśmy powiązani z Wikimedia Foundation. + Aplikacja Wikimedia Commons jest oprogramowaniem typu open-source tworzonym i rozwijanym przez stypendystów i wolontariuszy ze społeczności Wikimedii. Fundacja Wikimedia nie bierze udziału w tworzeniu, rozwijaniu ani utrzymywaniu aplikacji. <a href=\"https://github.com/commons-app/apps-android-commons\">Kod źródłowy</a> oraz <a href=\"https://commons-app.github.io/\">strona internetowa</a> na GitHub. Aby zgłosić błąd lub sugestię, utwórz nowe <a href=\"https://github.com/commons-app/apps-android-commons/issues\">zgłoszenie na GitHub</a>. <u>Polityka prywatności</u> <u>Twórcy</u> @@ -143,7 +159,7 @@ Brak opisu Nieznana licencja Odśwież - Wymagane uprawnienia: odczyt z dysku zewnętrznego. Aplikacja nie będzie w stanie funkcjonować bez tego. + Wymagane uprawnienia: odczyt z dysku zewnętrznego. Aplikacja nie będzie w stanie funkcjonować bez tego. Opcjonalne zezwolenie: uzyskiwanie bieżącej lokalizacji dla wygenerowania propozycji kategorii OK Pobliskie miejsca @@ -195,6 +211,8 @@ Podaj krótką, opisową i unikalną nazwę, która będzie służyła jako nazwa pliku. Możesz używać prostego języka i spacji. Nie dodawaj rozszerzenia pliku. Zaloguj się na swoje konto Błąd! Nie znaleziono adresu URL + Ta grafika została zgłoszona do usunięcia. + Otwórz w przeglądarce Witamy w Wikimedia Commons, %1$s! Cieszymy się, że tu jesteś. Dziękujemy za dokonanie edycji %1$s wspomniał o Tobie w %2$s. @@ -203,6 +221,9 @@ WIKIDANE WIKIPEDIA POWSZECHNE - Najczęściej zadawane pytania + <u>FAQ</u> Pomiń samouczek + Nie znaleziono powiadomień + Języki + Anuluj diff --git a/app/src/main/res/values-pms/error.xml b/app/src/main/res/values-pms/error.xml index 68e222238..189f84be5 100644 --- a/app/src/main/res/values-pms/error.xml +++ b/app/src/main/res/values-pms/error.xml @@ -1,4 +1,7 @@ + Commons a l\'é piantasse Contacc! Cheicòs a l\'é andàit mal! diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index 9f577aba2..0cd748031 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -1,4 +1,7 @@ + Aparensa General @@ -59,6 +62,7 @@ Sërché dle categorìe Argistré Agiorné + Lista Ël GPS a l\'é disabilità su sò angign. Veul-lo ativelo? Ativé ël GPS Ancor gnun cariament @@ -80,6 +84,7 @@ Categorìe Paràmeter Marchesse + Plance an evidensa A propòsit L\'aplicassion Wikimedia Commons a l\'é n\'aplicassion a sorgiss duverta creà e mantnùa da \'d përson-e pagà e da \'d volontari ëd la comunità Wikimedia. La Fondassion Wikimedia a l\'é nen amplicà ant la creassion, ël dësvlup, o la manutension dl\'aplicassion. Creé na neuva <a href=\"https://github.com/commons-app/apps-android-commons/issues\">signalassion GitHub</a> për signalé dij givo e dij sugeriment. @@ -151,8 +156,8 @@ Gnun-a descrission Licensa sconossùa Rinfrësché - Autorisassion necessaria: Lese n\'anmagasinament estern. L\'aplicassion a peul pa marcé sensa lòn. - Autorisassion necessaria: Scrive n\'anmagasinament estern. L\'aplicassion a peul pa marcé sensa \'d lòn. + Autorisassion necessaria: Lese n\'anmagasinament estern. L\'aplicassion a peul pa acede a soa galarìa sensa \'d lòn. + Autorisassion necessaria: Scrive an sn\'anmagasinament estern. L\'aplicassion a peul pa acede a soa màchina fòto sensa \'d lòn. Autorisassion facoltativa: Oten-e la posission atual për dij sugeriment ëd categorìa Va bin Pòst davzin @@ -165,6 +170,8 @@ Tìtol dël mojen Descrission La descrission dël mojen a va ambelessì. Sòn a podrìa esse potensialman longh, e a dovrà esse spantià su vàire linie. I speroma comsëssìa ch\'a ven-a grassios. + Autor + Lë stranòm ëd l\'autor ëd na plancia an evidensa a va ambelessì. Dàita ëd cariament Licensa Coordinà @@ -207,10 +214,12 @@ Seurte dal sistema Cors d\'antrodussion Notìfiche + Butà an evidensa Ij pòst ant j\'anviron a peulo nen esse smonù sensa ij përmess ëd localisassion gnun-a descrission trovà Pàgina dj\'archivi ëd Comun Element ëd WikiData + Artìcol ëd Wikipedia Eror antramentre ch\'as butavo le plance an memòria local Un tìtol dëscritiv ùnich për l\'archivi, che a servirà com nòm d\'archivi. A peul dovré un lengagi sempi con djë spassi. Ch\'a ancluda pa l\'estension dl\'archivi Për piasì, ch\'a descriva ël mojen mej ch\'a peul: Andoa a l\'é stàit fàit? Për piasì, ch\'a descriva j\'oget o le përson-e. Ch\'a arvela j\'anformassion ch\'a l\'é nen belfé andviné, për esempi l\'ora dël dì, s\'a l\'é un panorama. Si ël mojen a smon cheicòs ëd foravìa, për piasì ch\'a spiega lòn ch\'a lo rend foravìa. @@ -225,6 +234,7 @@ Gnun navigador trovà për duverté l\'adrëssa an sl\'aragnà Eror! Liura nen trovà Propon-e për la scancelassion + Sa plancia a l\'é stàita nominà për ël dëscancelament. Smon-e ant ël navigador Ël leu a l\'é nen cangià. Leu nen disponìbil. @@ -236,6 +246,21 @@ Mersì d\'avèj fàit na modìfica %1$s a l\'ha massionalo su %2$s . Cangé la visualisassion - Chestion frequente + DIRESSION + WIKIDATA + WIKIPEDIA + COMUN + <u>Ch\'an vàluta</u> + <u>Chestion frequente</u> Sauté lë spiegon + Aragnà nen disponìbil + Aragnà disponìbil + Eror an sl\'arserca dle notìfiche + Gnun-e notìfiche trovà + <u>Volté</u> + Lenghe + Selessioné la lenga për la qual a veul mandé dle tradussion + Andé anans + Anulé + Prové torna diff --git a/app/src/main/res/values-ps/error.xml b/app/src/main/res/values-ps/error.xml index 6fc0f00bb..94bb26441 100644 --- a/app/src/main/res/values-ps/error.xml +++ b/app/src/main/res/values-ps/error.xml @@ -1,4 +1,7 @@ + مننه! diff --git a/app/src/main/res/values-ps/strings.xml b/app/src/main/res/values-ps/strings.xml index 7d67160e4..3e2b499e6 100644 --- a/app/src/main/res/values-ps/strings.xml +++ b/app/src/main/res/values-ps/strings.xml @@ -1,4 +1,10 @@ + ځای ويکي خونديځ diff --git a/app/src/main/res/values-pt-rBR/error.xml b/app/src/main/res/values-pt-rBR/error.xml index 04f295559..6ccec407e 100644 --- a/app/src/main/res/values-pt-rBR/error.xml +++ b/app/src/main/res/values-pt-rBR/error.xml @@ -1,4 +1,7 @@ + Commons travou Opa. Algo deu errado! diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 762e45c0b..4bc478527 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1,4 +1,19 @@ + Aparência Geral @@ -59,6 +74,7 @@ Procurar categorias Salvar Atualizar + Lista O GPS está desligado no seu aparelho. Gostarias de ligá-lo ? GPS inapto. Ainda não carregado @@ -80,6 +96,7 @@ Categorias Configurações Criar conta + Imagens destacadas Sobre O Wikimedia Commons é um aplicativo de código aberto criado e mantido por beneficiários e voluntários da comunidade Wikimedia. A Wikimedia Foundation não está envolvida na criação, desenvolvimento ou manutenção do aplicativo. Criar uma nova <a href=\"https://github.com/commons-app/apps-android-commons/issues\">publicação no GitHub</a> para informar erros e sugestões. @@ -151,8 +168,8 @@ Sem descrição Licença desconhecida Atualizar - Permissão necessária: Ler armazenamento externo. O aplicativo não pode funcionar sem isso. - Permissão necessária: Escreva armazenamento externo. A aplicação não pode funcionar sem isso. + Permissão necessária: leia o armazenamento externo. App não pode acessar sua galeria sem isso. + Permissão necessária: escreva o armazenamento externo. App não pode acessar sua câmera sem isso. Permissão opcional: Obter a localização atual de sugestões de categoria OK Lugares próximos @@ -165,6 +182,8 @@ Título da mídia Descrição Descrição da mídia aqui. Isso pode ser potencialmente longo e precisará envolver múltiplas linhas. Esperamos que seja agradável. + Autor + O nome de usuário do autor da imagem destacada fica aqui. Data de envio. Licença Coordenadas @@ -207,10 +226,12 @@ Sair Tutorial Notificações + Destacado Os locais próximos não podem ser exibidos sem permissões de localização Nenhuma descrição encontrada Página de arquivo do Commons Item do Wikidata + Artigo na Wikipédia Erro durante o cache de imagens Um título descritivo exclusivo para o arquivo, que servirá como um nome de arquivo. Você pode usar linguagem simples com espaços. Não inclua a extensão do arquivo Por favor, descreva a mídia tanto quanto possível: onde foi tomada? O que isso mostra? Qual é o contexto? Descreva os objetos ou pessoas. Revelar informações que não podem ser facilmente adivinhadas, por exemplo, a hora do dia, se for uma paisagem. Se a mídia mostrar algo incomum, explique o que torna incomum. @@ -225,6 +246,7 @@ Nenhum navegador da Web foi encontrado para abrir o URL Erro! URL não encontrado Nomear para a exclusão + Esta imagem foi nomeada para eliminação. Exibir no navegador O local não mudou. Localização não disponível. @@ -236,6 +258,21 @@ Obrigado por ter realizado uma edição %1$s fez menção a você em %2$s. Visualização de alternância - Perguntas mais frequentes + DIREÇÕES + WIKIDATA + WIKIPÉDIA + COMMONS + <u>Avalie-nos</u> + <u>FAQ</u> Pular tutoril + A Internet não está disponível + A Internet está disponível + Erro ao tentar obter as notificações + Não foram encontradas notificações + <u>Traduzir</u> + Idiomas + Selecione o idioma para a qual quer enviar as traduções + Avançar + Cancelar + Tentar novamente diff --git a/app/src/main/res/values-pt/error.xml b/app/src/main/res/values-pt/error.xml index 45e439e92..36f02c778 100644 --- a/app/src/main/res/values-pt/error.xml +++ b/app/src/main/res/values-pt/error.xml @@ -1,4 +1,7 @@ + O Commons falhou Ups! Algo correu mal. diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 954c3f99f..5e4862ecb 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -1,11 +1,29 @@ + + Aparência + Geral + Comentários + Localização Wikimedia Commons + Configurações Nome de utilizador(a) Palavra-passe Entre com a sua conta do Commons Beta Iniciar sessão + Esqueceu-se da palavra-passe? Registar-se A iniciar sessão Aguarde, por favor… @@ -37,6 +55,7 @@ Partilhar Ver no navegador Título + Forneça um título para este ficheiro, por favor Descrição Não foi possível iniciar sessão - falha de rede Não foi possível iniciar sessão - verifique o seu nome de utilizador(a) @@ -52,6 +71,7 @@ Pesquisar categorias Gravar Atualizar + Lista O GPS está desativado no seu dispositivo. Gostarias de ativá-lo? Ativar GPS Ainda não foram enviados ficheiros @@ -73,11 +93,12 @@ Categorias Configurações Registar-se + Imagens destacadas Sobre A aplicação do Wikimedia Commons é uma aplicação de código aberto criada e mantida por bolseiros e voluntários da comunidade Wikimedia. A Wikimedia Foundation não está envolvida na criação, desenvolvimento ou manutenção da aplicação. Criar uma nova <a href=\"https://github.com/commons-app/apps-android-commons/issues\">incidência no GitHub</a> para reportar erros e sugestões. - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">Política de privacidade</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Créditos</a> + <u>Política de privacidade</u> + <u>Créditos</u> Sobre Enviar comentários (por e-mail) Não foi instalado nenhum cliente de correio eletrónico @@ -89,7 +110,7 @@ Essa imagem será licenciada sob %1$s Ao carregar esta imagem, declaro que esta é a minha própria obra, que não contém material protegido ou selfies, e que adere às <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines/pt\">políticas do Wikimedia Commons</a>. Descarregar - Licença + Licença padrão Usar título/descrição anteriores Obter automaticamente a localização atual Recuperar localização atual para oferecer sugestões da categoria se a imagem não é georreferenciada @@ -118,11 +139,20 @@ Wikimedia Commons armazena a maioria das imagens que são usadas na Wikipédia. As suas imagens ajudam a educar pessoas em todo o mundo! Por favor, carregue apenas imagens tiradas ou criadas exclusivamente por si: - - Objetos naturais (flores, animais, montanhas)\n- Objetos úteis (bicicletas, estações de comboio)\n- Pessoas famosas (o seu presidente da câmara, atletas olímpicos que conheça) + Objetos naturais (flores, animais, montanhas)\n• Objetos úteis (bicicletas, estações de comboio)\n• Pessoas famosas (o seu presidente da câmara, atletas olímpicos que conheça) + Objetos naturais (flores, animais, montanhas) + Objetos úteis (bicicletas, estações de comboio) + Pessoas famosas (o seu presidente da câmara, atletas olímpicos que conheça) Por favor, NÃO carregue: - Autorretratos ou imagens dos seus amigos\n- Imagens descarregadas da Internet\n- Capturas de ecrã de aplicações com direitos de autor + Autorretratos ou fotografias dos seus amigos + As imagens que descarregou da Internet + Capturas de ecrã de aplicações proprietárias Exemplo de carregamento: - Título: Ópera de Sydney\n- Descrição: A Ópera de Sydney vista do outro lado da baía\n- Categorias: Ópera de Sydney vista do ocidente, Vistas à distância da Ópera de Sydney + Título: Ópera de Sydney + Descrição: A Ópera de Sydney vista do outro lado da baía + Categorias: Ópera de Sydney vista do ocidente, vistas à distância da Ópera de Sydney Contribua com as suas imagens. Ajude os artigos da Wikipédia a ganhar vida! As imagens na Wikipédia provêm do Wikimedia Commons. As suas imagens ajudam a educar as pessoas em todo o mundo. @@ -135,8 +165,8 @@ Sem descrição Licença desconhecida Actualizar - Permissão necessária: Ler a armazenagem externa. A aplicação não pode funcionar sem isto. - Permissão necessária: Escrever na armazenagem externa. A aplicação não pode funcionar sem isto. + Permissão necessária: Ler a armazenagem externa. A aplicação não pode aceder à sua galeria sem isto. + Permissão necessária: Escrever na armazenagem externa. A aplicação não pode aceder à sua câmara sem isto. Permissão opcional: Obter a localização atual para sugestões de categoria OK Locais Próximos @@ -149,6 +179,8 @@ Título do ficheiro multimédia Descrição A descrição do ficheiro multimédia é colocada aqui. Ela pode ser bastante longa e precisar de ser dividida em várias linhas. No entanto, esperamos que tenha bom aspeto. + Autor + O nome de utilizador do autor da imagem destacada fica aqui. Data de carregamento Licença Coordenadas @@ -191,10 +223,12 @@ Sair Tutorial Notificações + Destacadas Os sítios aqui perto não podem ser apresentados sem permissões de localização não foi encontrada nenhuma descrição Página do ficheiro no Commons Item do Wikidata + Artigo na Wikipédia Erro ao colocar imagens na cache Um título descritivo exclusivo para o ficheiro, que servirá como um nome de ficheiro. Pode utilizar uma linguagem simples com espaços. Não inclua a extensão do ficheiro Por favor, descreva o ficheiro da melhor forma possível: Onde foi tirado? O que isso mostra? Qual é o contexto? Por favor, descreva os objetos ou as pessoas. Indique as informações que não podem ser facilmente adivinhadas, por exemplo, a hora do dia, se for uma paisagem. Se o ficheiro mostrar algo incomum, explique o que torna incomum. @@ -206,6 +240,12 @@ Inicie sessão na sua conta Enviar ficheiro de registo Enviar o ficheiro de registo aos programadores por correio eletrónico + Não foi encontrado nenhum navegador da Internet para abrir o URL + Erro! Não foi possível encontrar o URL + Nomear para eliminação + Esta imagem foi nomeada para eliminação. + + Ver no navegador A localização não foi alterada. A localização não está disponível. É necessária a permissão para mostrar uma lista dos sítios aqui perto @@ -216,4 +256,21 @@ Obrigado por ter realizado uma edição %1$s fez menção a si em %2$s. Alternar modo de visionamento + DIREÇÕES + WIKIDATA + WIKIPÉDIA + COMMONS + <u>Avalie-nos</u> + <u>FAQ</u> + Saltar a explicação + A Internet não está disponível + A Internet está disponível + Erro ao tentar obter as notificações + Não foram encontradas notificações + <u>Traduzir</u> + Línguas + Selecione a língua para a qual quer enviar as traduções + Avançar + Cancelar + Tentar novamente diff --git a/app/src/main/res/values-qq/error.xml b/app/src/main/res/values-qq/error.xml index 0bc9e2f24..d6002a6a1 100644 --- a/app/src/main/res/values-qq/error.xml +++ b/app/src/main/res/values-qq/error.xml @@ -1,4 +1,7 @@ + Title of dialog to show when the app crashes Prompt asking people to enter info about what they were doing when the app crashed diff --git a/app/src/main/res/values-qq/strings.xml b/app/src/main/res/values-qq/strings.xml index 6312deb40..37c2978bf 100644 --- a/app/src/main/res/values-qq/strings.xml +++ b/app/src/main/res/values-qq/strings.xml @@ -1,4 +1,16 @@ + {{Identical|General}} The name of the application. A short form of \"Wikimedia Commons\". It is used in the app\'s launcher icon.\n{{Identical|Wikimedia Commons}} @@ -50,6 +62,7 @@ This message is followed by a list of the categories.\n{{Identical|Search category}} Hint text on menu item to save selected categories.\n{{Identical|Save}} {{Identical|Refresh}} + {{Identical|List}} {{Identical|Upload}} Message shown to the user when no category matching what they searched for was found. %1$s represents the category name Text explaining to users why and how to add categories to images. Users can also tap this message to skip adding categories. @@ -97,6 +110,7 @@ {{Identical|No}} {{Identical|Title}} {{Identical|Description}} + {{Identical|Author}} {{Identical|License}} {{Identical|Coordinate}} Describes \"coordinates\". @@ -114,5 +128,13 @@ {{Identical|Upload}} {{Identical|Nearby}} {{Identical|Tutorial}} - \'\'This message is empty, and it\'s probably invalid. See bug report: https://github.com/commons-app/apps-android-commons/issues/1333 .\'\' + {{Identical|Notification}} + \'\'This message is empty, and it\'s probably invalid. See bug report: https://github.com/commons-app/apps-android-commons/issues/1333 .\'\' + {{Identical|Wikidata}} + {{Identical|Wikipedia}} + Link text with underline. + Link text with underline.\n{{Identical|Translate}} + {{Identical|Language}} + {{Identical|Cancel}} + {{Identical|Retry}} diff --git a/app/src/main/res/values-ro/error.xml b/app/src/main/res/values-ro/error.xml index e4dc60913..7d5c88c85 100644 --- a/app/src/main/res/values-ro/error.xml +++ b/app/src/main/res/values-ro/error.xml @@ -1,4 +1,7 @@ + Commons s-a blocat Hopa! Ceva nu a mers bine! diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index a8e58ca46..b87abfbbf 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -1,4 +1,9 @@ + Commons Setări diff --git a/app/src/main/res/values-ru/error.xml b/app/src/main/res/values-ru/error.xml index ca0ece65e..647d7884d 100644 --- a/app/src/main/res/values-ru/error.xml +++ b/app/src/main/res/values-ru/error.xml @@ -1,4 +1,7 @@ + Сбой Ой. Что-то пошло не так! diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1c7c29231..c649398bb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1,4 +1,23 @@ + Внешний вид Общие @@ -60,6 +79,7 @@ Выбор категорий Сохранить Обновить + Список GPS отключён в вашем устройстве. Хотите включить его? Включить GPS Загрузок пока нет @@ -84,6 +104,7 @@ Категории Настройки Зарегистрироваться + Избранные изображения О приложении Приложение «Викисклад» - это программа с открытым кодом, которую создали волонтёры и участники грантов Викимедиа. Фонд Викимедиа не участвует в создании, разработке или обслуживании этого приложения. Вы можете создать <a href=\"https://github.com/commons-app/apps-android-commons/issues\">запрос на GitHub</a>, чтобы сообщить об ошибке или внести предложение. @@ -126,7 +147,7 @@ CC BY-SA 4.0 CC BY 4.0 CC Zero - Викисклад содержит большую часть изображений, которые используются в Википедии. + Викисклад содержит бо́льшую часть изображений, которые используются в Википедии. Ваши изображения помогают образованию людей во всём мире! Пожалуйста, загрузите фотографии, которые были сняты или созданы исключительно вами: Природные объекты (например, цветы, животные, горы)\n• Полезные предметы (например, велосипеды, вокзалы)\n• Известные люди (например, ваш мэр, спортсмены-олимпийцы, которых вы встретили) @@ -155,8 +176,8 @@ Нет описания Неизвестная лицензия Обновить - Требуемые разрешения: чтение с внешнего хранилища. Приложение не сможет функционировать без этого. - Требуемые разрешения: запись на внешнее хранилище. Приложение не сможет функционировать без этого. + Требуемые разрешения: чтение с внешнего хранилища. Приложение не сможет получить доступ к вашей галерее без этого разрешения. + Требуемые разрешения: запись на внешнее хранилище. Приложение не сможет получить доступ к камере без этого разрешения. Необязательное разрешение: получение текущего местоположения для предложения категорий OK Места поблизости @@ -166,9 +187,11 @@ Да Нет Название - Заголовок носителя информации + Заголовок медиафайла Описание - Здесь располагается описание носителя информации. Оно потенциально может быть весьма длинным и даже располагаться в несколько строк. Однако мы надеемся, что это выглядит симпатично + Здесь располагается описание медиафайла. Оно может быть весьма длинным и даже располагаться в несколько строк. Однако, надеемся, будет выглядеть приемлемо. + Автор + Здесь указывается имя автора избранного изображения Дата загрузки Лицензия Координаты @@ -194,7 +217,7 @@ Ламы Радужный мост Тюльпан - Нет сэлфи + Без селфи Несвободное изображение Добро пожаловать в Википедию Добро пожаловать — авторские права @@ -211,10 +234,12 @@ Выйти Руководство Уведомления + Избранное Места поблизости не могут быть отображены без разрешения на геолокацию описание не найдено Страница файла на Викискладе Элемент Викиданных + Статья Википедии Ошибка при кэшировании картинок Уникальное описание, которое будет сохранено как имя файла. Вы можете использовать естественный язык, разделяя слова пробелами. Пожалуйста, не указывайте расширение файла. Пожалуйста, подробно опишите загружаемый файл: где он был снят? что на нём изображено? каков его контекст? Пожалуйста опишите изображённых персон или объекты. Добавьте информацию, о которой нельзя легко догадаться, например, время суток, когда снимался файл. Если снято что-то необычное, постарайтесь пояснить, что именно в этом необычного. @@ -229,6 +254,8 @@ Не найден браузер, чтобы открыть ссылку Ошибка! Ссылка не найдена Номинировать к удалению + Этот файл был вынесен на удаление. + Просмотреть в браузере Местоположение не изменено. Местоположение недоступно. @@ -240,7 +267,21 @@ Спасибо за правку %1$s упомянул вас на %2$s. Переключить режим просмотра - * - Часто задаваемые вопросы + НАПРАВЛЕНИЯ + ВИКИДАННЫЕ + ВИКИПЕДИЯ + ВИКИСКЛАД + <u>Оцените нас</u> + <u>Часто задаваемые вопросы</u> Пропустить руководство + Интернет недоступен + Интернет доступен + Ошибка при получении уведомления + Уведомлений нет + <u>Перевести</u> + Языки + Выберите язык локализации, на который сможете перевести элементы интерфейса приложения + Выполняется + Отмена + Повторить diff --git a/app/src/main/res/values-sat/error.xml b/app/src/main/res/values-sat/error.xml index 8a52aebfb..e82212892 100644 --- a/app/src/main/res/values-sat/error.xml +++ b/app/src/main/res/values-sat/error.xml @@ -1,4 +1,7 @@ + ᱥᱟᱨᱦᱟᱣ! diff --git a/app/src/main/res/values-sd/error.xml b/app/src/main/res/values-sd/error.xml index f793f50a8..11f7e484a 100644 --- a/app/src/main/res/values-sd/error.xml +++ b/app/src/main/res/values-sd/error.xml @@ -1,4 +1,7 @@ + العام ڪريش ٿي پيو آھي اڙي. ڪجھ غلط ٿي ويو! diff --git a/app/src/main/res/values-sd/strings.xml b/app/src/main/res/values-sd/strings.xml index 3ae6c2efe..3ccc39dd3 100644 --- a/app/src/main/res/values-sd/strings.xml +++ b/app/src/main/res/values-sd/strings.xml @@ -1,4 +1,8 @@ + العام ترتيبون @@ -128,7 +132,7 @@ ڪا تشريح ناھي اڻڄاتل لائسنس تازو ڪريو - گھربل اجازت: خارجي اسٽوريج پڙھڻ. ايپ ھن کانسواءِ فنڪشن نٿي ڪري سگھي. + گھربل اجازت: خارجي اسٽوريج پڙھڻ. ايپ ھن کانسواءِ فنڪشن نٿي ڪري سگھي. چونڊ اجازت: زمرن جي تجويزن لاءِ ھاڻوڪي مڪانيت وٺو ٺيڪ ويجھڙائيءَ ۾ جڳھون diff --git a/app/src/main/res/values-si/error.xml b/app/src/main/res/values-si/error.xml index 9ff0e5094..24f06d1b0 100644 --- a/app/src/main/res/values-si/error.xml +++ b/app/src/main/res/values-si/error.xml @@ -1,4 +1,7 @@ + කොමන්ස් බිඳ වැටී ඇත අපොයි. යමක් වැරදිලා ගිහින්! diff --git a/app/src/main/res/values-si/strings.xml b/app/src/main/res/values-si/strings.xml index fd263b89a..4ae0db17c 100644 --- a/app/src/main/res/values-si/strings.xml +++ b/app/src/main/res/values-si/strings.xml @@ -1,4 +1,10 @@ + කොමන්ස් සැකසුම් diff --git a/app/src/main/res/values-sk/error.xml b/app/src/main/res/values-sk/error.xml index 9e7e6b605..8e61e5c1f 100644 --- a/app/src/main/res/values-sk/error.xml +++ b/app/src/main/res/values-sk/error.xml @@ -1,4 +1,7 @@ + Commons sa zrútil Hups. Niečo sa pokazilo! diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 8662b9a81..90fac7f16 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -1,10 +1,22 @@ + + Vzhľad + Všeobecné + Spätná väzba + Poloha Commons + Nastavenia Používateľské meno Heslo + Prihláste sa do svojho účtu Commons Beta Prihlásiť sa + Zabudli ste heslo? Zaregistrovať sa Prihlasovanie Čakajte prosím… @@ -36,6 +48,7 @@ Zdieľať Otvoriť v prehliadači Názov + Prosím, dajte tomuto súboru názov Opis prihlásenie zlyhalo - zlyhanie siete Prihlásenie zlyhalo - skontrolujte vaše používateľské meno @@ -59,7 +72,7 @@ O aplikácii Open Source softvér dostupný za podmienok <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/COPYING\">Apache License v2</a> Zdroj na <a href=\"https://github.com/commons-app/apps-android-commons\">GitHub</a>. Bugy na <a href=\" https://github.com/commons-app/apps-android-commons/issues\">Github</a>. - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">Zásady ochrany súkromia</a> + <u>Zásady ochrany súkromia</u> O aplikácii Odoslať spätnú väzbu (emailom) Nemáte nainštalovaného žiadneho e-mailového klienta @@ -70,7 +83,7 @@ Zrušiť Tento obrázok bude licencovaný podľa %1$s Stiahnuť - Licencia + Predvolená licencia Použiť predchádzajúci názov/popis Automaticky získať súčasnú polohu Nočný režim @@ -98,11 +111,20 @@ Na Wikimedia Commons sa nachádza väčšina obrázkov, ktoré sa používajú na Wikipédii. Váš obrázok pomáha vzdelávať ľudí po celom svete! Prosím, nahrávajte obrázky, ktoré ste odfotili alebo vytvorili vy: - - Prírodu (kvety, zvieratá, hory)\n- Užitočné objekty (bicykle, železničné stanice)\n- Slávni ľudia (starosta, olympionici, s ktorými ste sa stretli) + Prírodu (kvety, zvieratá, hory)\n• Užitočné objekty (bicykle, železničné stanice)\n• Slávnych ľudí (starosta, olympionici, s ktorými ste sa stretli) + Prírodu (kvety, zvieratá, hory) + Užitočné objekty (bicykle, železničné stanice) + Slávnych ľudí (starosta, olympionici, s ktorými ste sa stretli) Prosím NENAHRÁVAJTE: - Selfies alebo fotky vašich priateľov\n- Obrázky prevzaté z internetu\n- Snímky obrazovky proprietárnych aplikácii + Selfies alebo fotky vašich priateľov + Obrázky prevzaté z internetu + Snímky obrazovky proprietárnych aplikácii Príklad nahratia: - Názov: Opera v Sydney\n- Opis: Opera v Sydney - pohľad spoza zátoky\n- Kategórie: Sydney Opera House from the west, Sydney Opera House remote views + Názov: Opera v Sydney + Popis: Opera v Sydney - pohľad spoza zátoky + Kategórie: Sydney Opera House from the west, Sydney Opera House remote views Prispejte svojimi obrázkami. Pomôžte oživiť články na Wikipédií. Obrázky na Wikipédií pochádzajú z Wikimedia Commons. Vaše obrázky pomáhajú vzdelávať ľudí po celom svete. @@ -125,14 +147,20 @@ Názov Názov média Popis + Autor + Dátum nahrania Licencia Súradnice neposkytnuté Staňte sa beta testerom Naozaj sa chcete odhlásiť? Logo Commons + Webová stránka Commons + Facebooková stránka Commons + Zdrojový kód Commons na Githube Obrázok pozadia Nenašiel sa žiaden obrázok + Nahrať obrázok Hora Zaó Lamy Dúhový most @@ -152,4 +180,15 @@ Návod Upozornenia nenašiel sa žiaden popis + Otvoriť v prehliadači + WIKIÚDAJE + WIKIPÉDIA + COMMONS + <u>Ohodnoťte nás</u> + <u>FAQ</u> + <u>Preložiť</u> + Jazyky + Pokračovať + Zrušiť + Obnoviť diff --git a/app/src/main/res/values-skr/error.xml b/app/src/main/res/values-skr/error.xml index 1061a7b8c..4829c95c2 100644 --- a/app/src/main/res/values-skr/error.xml +++ b/app/src/main/res/values-skr/error.xml @@ -1,4 +1,7 @@ + شکریہ! diff --git a/app/src/main/res/values-skr/strings.xml b/app/src/main/res/values-skr/strings.xml index 5ff73b3fa..d1d1d5d87 100644 --- a/app/src/main/res/values-skr/strings.xml +++ b/app/src/main/res/values-skr/strings.xml @@ -1,4 +1,7 @@ + شکل و صورت عمومی @@ -10,6 +13,7 @@ ورتݨ آلا ناں پاس ورڈ لاگ ان تھیوو + پاسورڈ بھل ڳئے ہو؟ سائن اپ لاگ ان تھیندا پئے انتظار کرو۔۔۔ @@ -45,6 +49,7 @@ قسماں دی ڳول بچاؤ سجرا، تازہ کرو + فہرست جی پی ایس چلاؤ اڄݨ ککھ وی اپ لوڈ نی تھیا قسماں، زمرے @@ -109,7 +114,17 @@ لاگ آؤٹ ٹیٹوریل وکی ڈیٹا آئٹم + وکی پیڈیا دا مضمون اجازت ݙیوو آپݨے کھاتے وچ لاگ ان تھیوو لاگ فائل بھیجو + وکی ڈیٹا + وکی پیڈیا + عام + <u>عام طور تے پچھے ونڄݨ آلے سوال</u> + <u>ترجمہ کرو</u> + زباناں + اڳوں تے تھیوو + منسوخ + ولدا کوشش کرو diff --git a/app/src/main/res/values-sr/error.xml b/app/src/main/res/values-sr/error.xml index f8287ca14..a1c22c874 100644 --- a/app/src/main/res/values-sr/error.xml +++ b/app/src/main/res/values-sr/error.xml @@ -1,4 +1,8 @@ + Остава се срушила Упс! Нешто је пошло наопако. diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index 39fc19325..925b8a5ce 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -1,4 +1,15 @@ + Изглед Опште @@ -151,8 +162,8 @@ Нема описа Непозната лиценца Освежи - Потребна дозвола: читање спољашње меморије. \nАпликација не може да функционише без овога. - Потребна дозвола: писање у спољашњој меморији. \nАпликација не може да функционише без овога. + Потребна дозвола: читање спољашње меморије. \nАпликација не може да функционише без овога. + Потребна дозвола: писање у спољашњој меморији. \nАпликација не може да функционише без овога. Необавезна дозвола: преузми тренутну локацију за предлоге категорија У реду Места у близини @@ -234,7 +245,7 @@ Хвала Вам за прављење измене %1$s Вас је поменуо на страници %2$s. Пребаци приказ - - Често постављана питања + <u>Оцените нас</u> + Често постављана питања Прескочи туторијал diff --git a/app/src/main/res/values-su/error.xml b/app/src/main/res/values-su/error.xml index e85d8dd1c..8b8d77543 100644 --- a/app/src/main/res/values-su/error.xml +++ b/app/src/main/res/values-su/error.xml @@ -1,4 +1,8 @@ + Commons ruksak Euh. Aya masalah! diff --git a/app/src/main/res/values-su/strings.xml b/app/src/main/res/values-su/strings.xml index 5b09c3f63..b2604eefd 100644 --- a/app/src/main/res/values-su/strings.xml +++ b/app/src/main/res/values-su/strings.xml @@ -1,4 +1,9 @@ + Commons Séting @@ -134,8 +139,8 @@ Tanpa pedaran Lisénsi teu dipikanyaho Segerkeun - Merlukeun widi: Baca simpenan éksternal. Aplikasi teu bisa jalan tanpa ieu. - Merlukeun widi: Baca simpenan éksternal. Aplikasi teu bisa jalan tanpa ieu. + Merlukeun widi: Baca simpenan éksternal. Aplikasi teu bisa jalan tanpa ieu. + Merlukeun widi: Baca simpenan éksternal. Aplikasi teu bisa jalan tanpa ieu. Idin pilihan: Paké lokasi kiwari pikeun usulan kategori Oké Tempat Sabudeureun diff --git a/app/src/main/res/values-sv/error.xml b/app/src/main/res/values-sv/error.xml index 7ac3bea5e..124154ad6 100644 --- a/app/src/main/res/values-sv/error.xml +++ b/app/src/main/res/values-sv/error.xml @@ -1,4 +1,8 @@ + Commons har kraschat Oj. Något gick fel! diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index e7b16edca..fa5174ced 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -1,4 +1,13 @@ + Utseende Allmänt @@ -59,6 +68,7 @@ Sök kategorier Spara Uppdatera + Lista GPS:en är inaktiverad på denna enhet. Vill du aktivera den? Aktivera GPS Inga uppladdningar ännu @@ -80,6 +90,7 @@ Kategorier Inställningar Registrera + Utvalda bild Om Wikimedia Commons är en app med öppen källkod som skapas och underhålls av frivilliga från Wikimedias gemenskap. Wikimedia Foundation är inte involverad i skapandet, utvecklingen eller underhållet av appen. Skapa ett nytt <a href=\"https://github.com/commons-app/apps-android-commons/issues\">ärende på GitHub</a> för att rapportera buggar och förslag. @@ -151,8 +162,8 @@ Ingen beskrivning Okänd licens Uppdatera - Nödvändig behörighet: Läsa extern lagring. Appen fungerar inte utan detta. - Nödvändig behörighet: Skriva till extern lagring. Appen kan inte fungera så här. + Nödvändig behörighet: Läsa extern lagring. Appen kan inte komma åt ditt galleri utan detta. + Nödvändig behörighet: Skriva till extern lagring. Appen kan inte komma åt din kamera utan detta. Valfri behörighet: Hämta aktuell plats för kategoriförslag OK Platser i närheten @@ -165,6 +176,8 @@ Mediatitel Beskrivning Beskrivningen för mediafilen ska vara här. Den kan vara riktig lång och kommer att behöva sträcka sig över flera rader. Vi hoppas i alla fall att det kommer se bra ut. + Skapare + Användarnamnet för den utvalda bildens skapare ska stå här. Uppladdningsdatum Licens Koordinater @@ -207,10 +220,12 @@ Logga ut Guide Meddelanden + Utvald Platser i närheten kan inte visas utan platsbehörigheter ingen beskrivning hittades Commons-filsida Wikidata-objekt + Wikipedia-artikel Fel uppstod när bilder cachelagras En unik beskrivande titel för filen, som kommer att fungera som ett filnamn. Du kan använda klarspråk med mellanslag. Ta inte med filändelsen Beskriv mediafilen så mycket som möjligt. Var togs den? Vad visar den? Vad är sammanhanget? Beskriv föremålen eller personerna. Ge information som inte kan gissas fram, t.ex. tidpunkten om det är ett landskap. Om mediafilen visar någonting ovanligt, förklara vad som gör den ovanlig. @@ -225,6 +240,8 @@ Ingen webbläsare hittades för att öppna webbadressen Fel! Webbadressen hittades inte Nominera för radering + Denna bild har nominerats för radering. + Visa i webbläsare Platsen har inte ändrats. Platsen är inte tillgänglig. @@ -236,7 +253,21 @@ Tack för att du gjorde en redigering %1$s nämnde dig på %2$s. Växla vy - - Vanliga frågor och svar + VÄGBESKRIVNING + WIKIDATA + WIKIPEDIA + COMMONS + <u>Betygsätt oss</u> + <u>Vanliga frågor</u> Hoppa över övning + Uppkopplingen bröts + Uppkopplingen återupprättades + Fel uppstod när aviseringar hämtades + Inga aviseringar hittades + <u>Översätt</u> + Språk + Välj språket som du vill skicka in översättningar för + Fortsätt + Avbryt + Försök igen diff --git a/app/src/main/res/values-sw/error.xml b/app/src/main/res/values-sw/error.xml index 5a1d03889..8c5feb5a1 100644 --- a/app/src/main/res/values-sw/error.xml +++ b/app/src/main/res/values-sw/error.xml @@ -1,4 +1,7 @@ + Commons wa kuvunjika Asante! diff --git a/app/src/main/res/values-ta/error.xml b/app/src/main/res/values-ta/error.xml index 0ad08846c..57a83c13a 100644 --- a/app/src/main/res/values-ta/error.xml +++ b/app/src/main/res/values-ta/error.xml @@ -1,4 +1,7 @@ + நன்றி! diff --git a/app/src/main/res/values-tcy/error.xml b/app/src/main/res/values-tcy/error.xml index a8b78fa41..7e3086af6 100644 --- a/app/src/main/res/values-tcy/error.xml +++ b/app/src/main/res/values-tcy/error.xml @@ -1,4 +1,7 @@ + ಉಸಬ್ಬಾ. ದಾದೋನಾ ತೊಂದರೆ ಅಂಡ್! ಸೊಲ್ಮೆಲೋ diff --git a/app/src/main/res/values-tcy/strings.xml b/app/src/main/res/values-tcy/strings.xml index 85f56bdf6..c6469511e 100644 --- a/app/src/main/res/values-tcy/strings.xml +++ b/app/src/main/res/values-tcy/strings.xml @@ -1,4 +1,8 @@ + ಕಾಮನ್ಸ್ ಸಂಯೋಜನೆಲು diff --git a/app/src/main/res/values-te/error.xml b/app/src/main/res/values-te/error.xml index bc25e3999..b52c3fdd0 100644 --- a/app/src/main/res/values-te/error.xml +++ b/app/src/main/res/values-te/error.xml @@ -1,4 +1,7 @@ + కామన్స్ క్రాషయింది అడెడె.. ఎక్కడో తప్పు జరిగింది! diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index bb47f6bf4..b2ad478b0 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -1,4 +1,9 @@ + కామన్స్ అమరికలు diff --git a/app/src/main/res/values-th/error.xml b/app/src/main/res/values-th/error.xml index bdacb80a8..1932cef87 100644 --- a/app/src/main/res/values-th/error.xml +++ b/app/src/main/res/values-th/error.xml @@ -1,4 +1,7 @@ + คอมมอนส์หยุดทำงาน อ๊ะ มีบางอย่างผิดพลาดไป! diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index aa816cfc8..29b29d804 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -1,10 +1,22 @@ + + การแสดงผล + ทั่วไป + คำติชม + ที่ตั้ง คอมมอนส์ + การตั้งค่า ชื่อผู้ใช้ รหัสผ่าน - เข้าสู่ระบบ + ลงชื่อเข้าระบบบัญชีคอมมอนส์บีตาของคุณ + ลงชื่อเข้า + ลืมรหัสผ่านหรือ? สมัครสมาชิก กำลังเข้าสู่ระบบ กรุณารอสักครู่… @@ -33,6 +45,7 @@ แชร์ ดูในเบราว์เซอร์ ชื่อเรื่อง + กรุณาระบุชืิ่อเรื่องของไฟล์นี้ คำอธิบาย ไม่สามารถเข้าสู่ระบบได้ - ความล้มเหลวของเครือข่าย ไม่สามารถเข้าสู่ระบบได้ - กรุณาตรวจสอบชื่อผู้ใช้ของคุณ @@ -48,6 +61,7 @@ ค้นหาหมวดหมู่ บันทึก รีเฟรช + รายการ GPS ถูกปิดใช้งานในอุปกรณ์ของคุณอยู่ คุณต้องการเปิดใช้งานหรือไม่? เปิดใช้งาน GPS ยังไม่มีการอัปโหลด @@ -61,15 +75,15 @@ การอัปโหลด %1$d รายการ ไม่พบหมวดหมู่ที่ตรงกับ %$1s - เพิ่มหมวดหมู่เพื่อทำให้รูปภาพของคุณค้นพบได้ง่ายขึ้นบน Wikimedia Commons\nเริ่มพิมพ์เพื่อเพิ่มหมวดหมู่ + เพิ่มหมวดหมู่เพื่อทำให้รูปภาพของคุณค้นพบได้ง่ายขึ้นบนวิกิมีเดียคอมมอนส์\nเริ่มพิมพ์เพื่อเพิ่มหมวดหมู่ หมวดหมู่ การตั้งค่า สมัครใช้งาน เกี่ยวกับ - แอป Wikimedia Commons เป็นแอปโอเพนซอร์สที่สร้างขึ้นและดูแลโดยผู้มีสิทธิและอาสาสมัครของชุมชนวิกิมีเดีย มูลนิธิวิกิมีเดียไม่มีส่วนเกี่ยวข้องในการสร้าง พัฒนา หรือการบำรุงรักษาแอปใดๆ ทั้งสิ้น + แอปวิกิมีเดียคอมมอนส์เป็นแอปโอเพนซอร์สที่สร้างขึ้นและดูแลโดยผู้มีสิทธิและอาสาสมัครของชุมชนวิกิมีเดีย มูลนิธิวิกิมีเดียไม่มีส่วนเกี่ยวข้องในการสร้าง พัฒนา หรือการบำรุงรักษาแอปใดๆ ทั้งสิ้น สร้าง <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub issue</a> ใหม่เพื่อรายงานบั๊กและส่งข้อเสนอแนะ - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">นโยบายความเป็นส่วนตัว</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">เครดิต</a> + <u>นโยบายความเป็นส่วนตัว</u> + <u>เครดิต</u> เกี่ยวกับ ส่งคำติชม (ผ่านทางอีเมล) ไม่ได้ติดตั้งไคลเอนต์อีเมล @@ -81,17 +95,54 @@ รูปภาพนี้จะอนุญาตให้ใช้ได้ภายใต้สัญญาอนุญาต %1$s โดยการส่งรูปภาพนี้ ฉันยืนยันว่านี่เป็นงานของฉันเอง ซึ่งไม่ประกอบด้วยเนื้อหาที่ละเมิดลิขสิทธิ์หรือภาพเซลฟี หรืออื่นๆ ตามที่ระบุใน<a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">นโยบายของ Wikimedia Commons</a> ดาวน์โหลด - สัญญาอนุญาต + สัญญาอนุญาตปริยาย ใช้ชื่อเรื่อง/คำอธิบายก่อนหน้านี้ รับข้อมูลตำแหน่งที่ตั้งปัจจุบันโดยอัตโนมัติ ดึงข้อมูลตำแหน่งที่ตั้งปัจจุบันเพื่อรับข้อเสนอแนะเกี่ยวกับหมวดหมู่ถ้ารูปภาพไม่ได้ติดแท็กตำแหน่งที่ตั้งเอาไว้ โหมดกลางคืน ใช้ธีมสีเข้ม + Attribution-ShareAlike 4.0 + Attribution 4.0 + Attribution-ShareAlike 3.0 + Attribution 3.0 + CC0 + CC BY-SA 3.0 + CC BY-SA 3.0 (ออสเตรีย) + CC BY-SA 3.0 (เยอรมนี) + CC BY-SA 3.0 (เอสโตเนีย) + CC BY-SA 3.0 (สเปน) + CC BY-SA 3.0 (โครเอเชีย) + CC BY-SA 3.0 (ลักเซมเบิร์ก) + CC BY-SA 3.0 (เนเธอร์แลนด์) + CC BY-SA 3.0 (นอร์เวย์) + CC BY-SA 3.0 (โปแลนด์) + CC BY-SA 3.0 (โรมาเนีย) + CC BY 3.0 + CC BY-SA 4.0 + CC BY 4.0 + CC Zero + วิกิมีเดียคอมมอนส์เก็บรูปภาพทั้งหมดที่ถูกใช้ในวิกิพีเดีย + รูปภาพของคุณช่วยให้ความรู้แก่ผู้คนทั่วโลก! โปรดอัปโหลดรูปภาพที่ถ่ายหรือสร้างด้วยตัวคุณเองทั้งหมด: - - วัตถุธรรมชาติ (ดอกไม้ สัตว์ ภูเขา)\n- วัตถุที่สามารถใช้งานได้ (จักรยาน สถานีรถไฟ)\n- บุคคลที่มีชื่อเสียง (นายกเทศมนตรีของคุณ นักกีฬาโอลิมปิกที่คุณรู้จัก) + วัตถุธรรมชาติ (ดอกไม้ สัตว์ ภูเขา)\n• วัตถุที่สามารถใช้งานได้ (จักรยาน สถานีรถไฟ)\n• บุคคลที่มีชื่อเสียง (นายกเทศมนตรีของคุณ นักกีฬาโอลิมปิกที่คุณรู้จัก) + วัตถุธรรมชาติ (ดอกไม้ สัตว์ ภูเขา) + วัตถุที่สามารถใช้งานได้ (จักรยาน สถานีรถไฟ) + บุคคลที่มีชื่อเสียง (นายกเทศมนตรีของคุณ นักกีฬาโอลิมปิกที่คุณรู้จัก) โปรดอย่าอัปโหลด: - ภาพเซลฟีหรือภาพที่มีเพื่อนของคุณ\n- ภาพที่คุณดาวน์โหลดจากอินเทอร์เน็ต\n- ภาพหน้าจอแอปที่เป็นซอฟต์แวร์กรรมสิทธิ์ + ภาพเซลฟีหรือภาพที่มีเพื่อนของคุณ + ภาพที่คุณดาวน์โหลดจากอินเทอร์เน็ต + ภาพหน้าจอแอปที่เป็นซอฟต์แวร์กรรมสิทธิ์ ตัวอย่างการอัปโหลด: + - ชื่อเรื่อง: โรงอุปรากรซิดนีย์\n- คำอธิบาย: โรงอุปรากรซิดนีย์เมื่อมองจากบริเวณอ่าวซิดนีย์\n- หมวดหมู่: โรงอุปรากรเมื่อมองจากทิศตะวันตก, ทิวทัศน์โรงอุปรากรซิดนีย์จากระยะไกล + ชื่อเรื่อง: โรงอุปรากรซิดนีย์ + คำอธิบาย: โรงอุปรากรซิดนีย์เมื่อมองจากบริเวณอ่าวซิดนีย์ + หมวดหมู่: โรงอุปรากรเมื่อมองจากทิศตะวันตก, ทิวทัศน์โรงอุปรากรซิดนีย์จากระยะไกล + ลงรูปของคุณ ช่วยให้บทความวิกิพีเดียมีชีวิตชีวา! + รูปภาพบนวิกิพีเดียมาจากวิกิพีเดียคอมมอนส์ + รูปภาพของคุณช่วยให้การศึกษาแก่ผู้คนทั่วโลก + หลีกเลี่ยงเนื้อหาที่คุณพบในอินเทอร์เน็ต เช่น รูปภาพในโปสเตอร์ ปกหนังสือ ฯลฯ + คุณคิดว่าคุณเข้าใจแล้วใช่ไหม? ใช่! หมวดหมู่ กำลังโหลด… @@ -99,8 +150,8 @@ ไม่มีคำอธิบาย สัญญาอนุญาตที่ไม่รู้จัก รีเฟรช - สิทธิที่ต้องการ: อ่านที่เก็บข้อมูลภายนอก แอปไม่สามารถทำงานได้โดยไม่มีสิทธินี้ - สิทธิที่ต้องการ: เขียนที่เก็บข้อมูลภายนอก แอปไม่สามารถทำงานได้โดยไม่มีสิทธินี้ + สิทธิที่ต้องการ: อ่านที่เก็บข้อมูลภายนอก แอปไม่สามารถเข้าถึงคลังภาพได้โดยไม่มีสิทธินี้ + สิทธิที่ต้องการ: เขียนที่เก็บข้อมูลภายนอก แอปไม่สามารถเข้าถึงกล้องของคุณได้โดยไม่มีสิทธินี้ สิทธิทางเลือก: รับข้อมูลตำแหน่งที่ตั้งปัจจุบันสำหรับข้อเสนอแนะหมวดหมู่ ตกลง สถานที่ใกล้เคียง @@ -109,4 +160,99 @@ ไฟล์นี้มีอยู่แล้วบนคอมมอนส์ คุณแน่ใจหรือว่าคุณต้องการดำเนินการต่อ? ใช่ ไม่ + ชื่อเรื่อง + ชื่อเรื่องสื่อ + คำอธิบาย + ป้อนคำอธิบายสื่อที่นี่ คำอธิบายที่มีความยาวมากอาจมีหลายบรรทัด เราหวังว่ามันจะดูดี + ผู้สร้างสรรค์ + วันที่อัปโหลด + สัญญาอนุญาต + พิกัด + ไม่ได้ระบุ + มาเป็นผู้ร่วมทดสอบบีตา + สมัครเข้าร่วมช่องทางบีตาบน Google Play และเข้าถึงคุณลักษณะใหม่ ๆ และการแก้ไขบั๊กก่อนเปิดตัว + รหัส 2FA + ขีดจำกัดการอัปโหลดล่าสุดของฉัน + ขีดจำกัดสูงสุด + ไม่สามารถแสดงมากกว่า 500 รายการได้ + กำหนดขีดจำกัดการอัปโหลดล่าสุด + ไม่รองรับการยืนยันตัวบุคคลแบบสองขั้นตอนในขณะนี้ + คุณต้องการออกจากระบบจริง ๆ หรือไม่? + โลโก้คอมมอนส์ + เว็บไซต์คอมมอนส์ + หน้าเฟซบุ๊กคอมมอนส์ + ซอร์สโค้ดคอมมอนส์บน GitHub + ภาพพื้นหลัง + ภาพสื่อล้มเหลว + ไม่พบรูปภาพ + อัปโหลดรูปภาพ + ภูเขาซะโอ + ยามา + สะพานสายรุ้ง + ทิวลิป + ไม่มีภาพเซลฟี + ภาพกรรมสิทธิ์ + ยินดีต้อนรับสู่วิกิพีเดีย + ลิขสิทธิ์ต้อนรับ + โรงอุปรากรซิดนีย์ + ยกเลิก + เปิด + ปิด + หน้าหลัก + อัปโหลด + ใกล้เคียง + เกี่ยวกับ + การตั้งค่า + คำติชม + ลงชื่อออก + บทช่วยสอน + การแจ้งเตือน + ไม่สามารถแสดงสถานที่ใกล้เคียงได้โดยขาดสิทธิ์การเข้าถึงตำแหน่ง + ไม่พบคำอธิบาย + หน้าไฟล์คอมมอนส์ + รายการวิกิสนเทศ + บทความวิกิพีเดีย + ข้อผิดพลาดขณะแคชภาพ + ชื่อเรื่องที่อธิบายลักษณะเฉพาะของไฟล์ ซึ่งจะใช้เป็นชื่อไฟล์ คุณอาจใช้ภาษาธรรมดาที่มีเว้นวรรคก็ได้ อย่ารวมนามสกุลไฟล์ + โปรดอธิบายสื่อดังกล่าวให้มากที่สุดเท่าที่จะได้: สื่อนี้ถูกถ่ายที่ไหน? สื่อนี้แสดงถึงอะไร? บริบทคืออะไร? โปรดอธิบายถึงวัตถุหรือบุคคล เปิดเผยข้อมูลที่ไม่อาจคาดเดาได้อย่างง่ายดาย เช่น เวลาที่ถ่าย หากเป็นภาพทิวทัศน์ หากสื่อแสดงถึงสิ่งที่ไม่ธรรมดา โปรดอธิบายว่าอะไรทำให้สื่อดังกล่าวไม่ธรรมดา + ภาพนี้มืดเกินไป คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น + ภาพนี้มัว คุณแน่ใจหรือว่าคุณต้องการอัปโหลดภาพนี้? วิกิมีเดียคอมมอนส์นั้นมีไว้สำหรับรูปภาพที่มีคุณค่าในทางสารานุกรมเท่านั้น + ให้สิทธิ์ + ใช้ที่จัดเก็บข้อมูลภายนอก + บันทึกรูปภาพที่ถ่ายด้วยกล้องในแอปบนอุปกรณ์ของคุณ + ลงชื่อเข้าใช้บัญชีของคุณ + ส่งไฟล์ปูม + ส่งไฟล์ปูมไปยังนักพัฒนาผ่านทางอีเมล + ไม่พบเว็บเบราว์เซอร์ที่จะเปิด URL + ข้อผิดพลาด! ไม่พบ URL + เสนอการลบ + ภาพนี้ถูกเสนอการลบแล้ว + ดูในเบราว์เซอร์ + ไม่ได้เปลี่ยนตำแหน่งที่ตั้ง + ตำแหน่งที่ตั้งไม่พร้อมใช้งาน + ต้องการสิทธิเพื่อแสดงรายการสถานที่ใกล้เคียง + สอบถามเส้นทาง + อ่านบทความ + ยินดีต้อนรับสู่วิกิมีเดียคอมมอนส์ %1$s! เราดีใจที่คุณอยู่ที่นี่ + %1$s ส่งสารบนหน้าคุยของคุณ + ขอบคุณที่ร่วมแก้ไข + %1$s ได้กล่าวถึงคุณบน %2$s + สลับมุมมอง + เส้นทาง + วิกิสนเทศ + วิกิพีเดีย + คอมมอนส์ + <u>ให้คะแนนเรา</u> + <u>FAQ</u> + ข้ามบทช่วยสอน + อินเทอร์เน็ตไม่พร้อมใช้งาน + อินเทอร์เน็ตพร้อมใช้งาน + เกิดข้อผิดพลาดในการดึงข้อมูลการแจ้งความ + ไม่พบการแจ้งความ + <u>แปล</u> + ภาษา + เลือกภาษาที่คุณต้องการส่งการแปล + ดำเนินการต่อ + ยกเลิก + ลองใหม่ diff --git a/app/src/main/res/values-tr/error.xml b/app/src/main/res/values-tr/error.xml index 79c4c7768..7bfd32902 100644 --- a/app/src/main/res/values-tr/error.xml +++ b/app/src/main/res/values-tr/error.xml @@ -1,4 +1,8 @@ + Commons çöktü Hay Aksi! Bir şeyler yanlış gitti! diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index e0aa79c1e..94d383ff9 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -1,10 +1,27 @@ + + Görünüm + Genel + Geri bildirim + Konum Commons Ayarlar Kullanıcı adı Parola + Commons Beta hesabına giriş yap Oturum aç + Parolamı Unuttum Kaydol Oturum açılıyor Lütfen bekleyin… @@ -36,6 +53,7 @@ Paylaş Tarayıcıda görüntüle Başlık + Lütfen bu dosya için bir başlık ekleyin Açıklama Oturum açılamıyor - ağ hatası Oturum açılamıyor - lütfen kullanıcı adınızı kontrol edin @@ -51,19 +69,20 @@ Kategorileri ara Kaydet Yenile + Liste GPS, cihazınızda devre dışı bırakılmıştır. Etkinleştirmek ister misiniz? GPS\'i etkinleştir Henüz yüklenmedi - + \@string/contributions_subtitle_zero %1$d yükleme %1$d yükleme - + %1$d yüklenmeye başlanıyor %1$d yüklenmeye başlanıyor - + %1$d yükleme %1$d yükleme @@ -74,9 +93,9 @@ Kaydol Hakkında Wikimedia Commons uygulaması, Wikimedia topluluğunun imtiyaz sahibi ve gönüllüleri tarafından oluşturulmuş ve sürdürülmüş açık kaynak kodlu bir uygulamadır. Vikipedi Vakfı, uygulamanın oluşturulması, geliştirilmesi veya bakımına dahil değildir. - GitHub üzerinde <a href=\"https://github.com/commons-app/apps-android-commons\">Kaynak</a> ve <a href=\"https://commons-app.github.io/\">website</a>. Hata raporları ve önerileri için yeni bir <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub sorunu</a> oluştur. - <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">Gizlilik Politikası</a> - <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Katkıda bulunanlar</a> + GitHub üzerinde <a href=\"https://github.com/commons-app/apps-android-commons\">Kaynak</a> ve <a href=\"https://commons-app.github.io/\">website</a>. Hata raporları ve önerileri için yeni bir <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub sorunu</a> oluştur. + <a href=\"https://github.com/commons-app/apps-android-commons/wiki/Privacy-policy\">Gizlilik Politikası</a> + <a href=\"https://github.com/commons-app/apps-android-commons/blob/master/CREDITS\">Katkıda bulunanlar</a> Hakkında Geri Bildirim Gönder (E-posta ile) Yüklü bir e-posta istemcisi yok @@ -88,7 +107,7 @@ Bu resmi %1$s lisansı altında olacak. Bu resmi göndererek bunun kendi eserim olduğumu, telif hakkıyla korunan materyal veya selfie içermediğini ve aksi takdirde <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Wikimedia Commons politikalarına</a> uyduğunu beyan ederim. İndir - Lisans + Varsayılan lisans Önceki başlığı/açıklamayı kullan Otomatik olarak mevcut konumu al Resim koordinat olarak etiketlendirilmemişse kategori önerileri için mevcut konum bulun @@ -117,11 +136,19 @@ Wikimedia Commons, Vikipedi\'de kullanılan resimlerin çoğunu barındırır. Resimleriniz dünyanın dört bir yanındaki insanlara eğitim vermeye yardımcı olur! Lütfen tamamen kendiniz çektiğiniz veya oluşturduğunuz resimleri yükleyin: - - Doğal nesneler (çiçekler, hayvanlar, dağlar)\n- Faydalı nesneler (bisiklet, tren istasyonları)\n- Ünlü insanlar (belediye başkanınız, tanıştığınız Olimpik atletler) + Doğal nesneler (çiçekler, hayvanlar, dağlar)\n- Faydalı nesneler (bisiklet, tren istasyonları)\n- Ünlü insanlar (belediye başkanınız, tanıştığınız Olimpik atletler) + Doğal objeler (çiçekler, hayvanlar, dağlar) + Kullanışlı objeler (bisikletler, tren istasyonları) + Ünlü kişiler (belediye başkanınız, tanıştığınız Olimpik atletler) Lütfen şunları YÜKLEMEYİN: - Öz çekimlerinizi ya da arkadaşlarınızın fotoğraflarını\n- İnternetten indirdiğiniz resimleri\n- Tescilli uygulamaların ekran görüntülerini + Selfiler veya arkadaşlarınızın fotoğrafları + İnternet\'ten indirdiğiniz fotoğraflar + Özel mülk uygulamaların ekran görüntüleri Yüklenebileceklere örnekler: - Başlık: Sydney Opera Binası\n- Tanım: Körfezin genelinden bakıldığında Sydney Opera Binası\n- Kategoriler: Sydney Opera Binası, batıdan Sydney Opera Binası + Başlık: Sidney Opera Binası + Açıklama: Sidney Opera Binası\'nın körfezin karşısından görünümü Resimleriniz ile Vikipedi maddelerinin canlandırılmasına katkıda bulunabilirsiniz! Vikipedi\'ye Wikimedia Commons\'tan gelen görüntüler. Görüntüler dünya insanlarının eğitiminde yardımcı olur. @@ -134,8 +161,8 @@ Açıklama yok Bilinmeyen lisans Yenile - Gerekli izinler: Harici depolama biriminin okunması. Uygulama buna izin verilmeden çalışmaz. - Gerekli izin: Harici depolama birimi üzerine yazma. Uygulama buna izin verilmeden çalışmaz. + Gerekli izinler: Harici depolama biriminin okunması. Uygulama buna izin verilmeden çalışmaz. + Gerekli izin: Harici depolama birimi üzerine yazma. Uygulama buna izin verilmeden çalışmaz. İsteğe bağlı izin: Kategori önerileri için geçerli konum alma Tamam Yakındaki yerler @@ -162,6 +189,9 @@ İki faktörlü kimlik doğrulama şu anda desteklenmiyor. Gerçekten çıkış yapmak istiyor musunuz? Commons Logo + Commons Websitesi + Commons Facebook Sayfası + Commons Github Kaynak Kodu Arka plan görüntüsü Medya Görüntüsü Başarısız Oldu Resim Bulunamadı @@ -191,18 +221,30 @@ hiçbir açıklama bulunamadı Commons dosya sayfası Vikiveri ögesi + Wikipedia makalesi Resimler önbelleğe alınırken hata oluştu Dosya için dosya adı olarak kullanılacak benzersiz açıklayıcı bir başlık olmalıdır. Boşluk bırakarak sade bir dil kullanabilirsiniz. Dosya uzantısını dahil etmeyin Lütfen medyayı mümkün olduğunca açıklayın: Nerede çekildi? Ne gösteriyor? Bağlam nedir? Lütfen nesneleri veya kişileri tanımlayın. Kolay tahmin edilemeyen bilgileri açıklayın, örneğin bir manzara ise günün saatini belirtin. Medya alışılmadık bir şey gösteriyorsa lütfen olağandışı yapan şeyleri açıklayın. + Bu fotoğraf çok karanlık, yine de yüklemek istiyor musunuz? Wikimedia Commons yalnızca ansiklopedik değeri olan fotoğraflar içindir. + Bu fotoğraf bulanık, yine de yüklemek istiyor musunuz? Wikimedia Commons yalnızca ansiklopedik değeri olan fotoğraflar içindir. İzin ver Harici depolamayı kullanın Uygulama kamerası kullanıldığında çekilen fotoğrafları cihazına kaydedin Hesabınızda oturum açın Kayıt dosyasını gönder Kayıt dosyasını, e-posta aracılığıyla geliştiricilere gönderin + URL\'yi açabilecek bir tarayıcı bulunamadı + Hata! URL bulunamadı + Silinmesi için aday göster + Bu görsel silinmesi için aday gösterildi. + Tarayıcıda görüntüle Konum değiştirilmedi Konum kullanılamıyor. Yakındaki yerler listesini görüntülemek için izin vermeniz gerekiyor TALİMATLAR MADDE OKU + Wikimedia Commons\'a hoşgedin %1$s! Burada olduğun için mutluyuz. + Düzenlemeniz için teşekkürler + %1$s , %2$s \'de senden bahsetti + YOL TARİFİ diff --git a/app/src/main/res/values-ug/error.xml b/app/src/main/res/values-ug/error.xml index 8b2c00876..b3107c966 100644 --- a/app/src/main/res/values-ug/error.xml +++ b/app/src/main/res/values-ug/error.xml @@ -1,4 +1,8 @@ + بايلىقتىن ئورتاق بەھرىمەن بولۇش ، ھالاك بولدى رەھمەت سىزگە! diff --git a/app/src/main/res/values-ug/strings.xml b/app/src/main/res/values-ug/strings.xml index 373766c44..3c180fbf2 100644 --- a/app/src/main/res/values-ug/strings.xml +++ b/app/src/main/res/values-ug/strings.xml @@ -1,4 +1,9 @@ + بايلىق ھەمبەھىرلەش تەڭشەكلەر diff --git a/app/src/main/res/values-uk/error.xml b/app/src/main/res/values-uk/error.xml index 8efa8f8f9..c5f14b12d 100644 --- a/app/src/main/res/values-uk/error.xml +++ b/app/src/main/res/values-uk/error.xml @@ -1,4 +1,9 @@ + Крах додатку Ой. Щось пішло не так! diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index cf5aeede7..a4ed20320 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -1,4 +1,14 @@ + Зовнішній вигляд Загальні @@ -45,6 +55,7 @@ Поділитися Відкрити у браузері Назва + Будь ласка, вкажіть назву цього файлу Опис Неможливо увійти — збій у мережі Неможливо увійти — будь ласка, перевірте своє ім\'я користувача @@ -60,6 +71,7 @@ Пошук категорій Зберегти Оновити + Список GPS вимкнено на Вашому пристрої. Бажаєте увімкнути його? Увімкнути GPS Ще нема завантажень @@ -87,6 +99,7 @@ Категорії Налаштування Зареєструватися + Вибрані зображення Про програму Додаток «Вікісховище» — це програма з відкритим кодом, яку створили отримувачі грантів та волонтери спільноти Вікімедіа. Фонд Вікімедіа не брав участі у створенні, розробці чи обслуговуванні цього додатка. Ви можете створити новий <a href=\"https://github.com/commons-app/apps-android-commons/issues\">запит на GitHub</a>, щоб повідомити про помилки, або висловити пропозиції. @@ -133,10 +146,19 @@ Ваші зображення допомагають освіті людей по всьому світу! Будь ласка, завантажуйте зображення, повністю виконані або створені Вами: Природні об\'єкти (квіти, тварини, гори) \n• Корисні об\'єкти (велосипеди, залізничні вокзали) \n• Відомі люди (Ваш мер, олімпійські атлети, яких Ви зустрічали) + Природні об\'єкти (квіти, тварини, гори) + Корисні об\'єкти (велосипеди, залізничні станції) + Відомі люди (ваш мер, спортсмен-олімпієць, якого ви зустріли) Будь ласка, НЕ завантажуйте: u2022 Селфі або фото своїх друзів \nu2022 Зображення, які Ви завантажили з інтернету \nu2022 Скріншоти патентованих програм + Селфі чи фото ваших друзів + Зображення, які ви завантажили з інтернету + Знімки екрану пропрієтарних програм Приклад завантаження: - Назва: Сіднейський оперний театр \n- Опис: Вид на Сіднейський оперний театр з боку бухти \n- Категорії: Sydney Opera House, Sydney Opera House from the west, Sydney Opera House remote views + Назва: Сіднейський оперний театр + Опис: Сіднейський оперний театр, вид через затоку + Категорії: Sydney Opera House from the west, Sydney Opera House remote views Надсилайте Ваші зображення. Допоможіть оживити статті Вікіпедії! Зображення у Вікіпедії надходять з Вікісховища. Ваші зображення допомагають освіті людей у всьому світі. @@ -149,8 +171,8 @@ Немає опису Невідома ліцензія Оновити - Обов\'язковий дозвіл: читання зовнішньої пам\'яті. Програма не може працювати без цього. - Обов\'язковий дозвіл: записування на зовнішнє сховище. Програма не може працювати без цього. + Обов\'язковий дозвіл: читання зовнішньої пам\'яті. Без цього дозволу програма не зможе отримати доступ до вашої галереї. + Обов\'язковий дозвіл: записування на зовнішнє сховище. Програма не зможе отримати доступ до камери без цього дозволу. Додатковий дозвіл: отримувати поточне розташування для підказок категорій Гаразд Місця поблизу @@ -163,6 +185,8 @@ Назва медіафайлу Опис Сюди потрапляє опис медіафайлу. Він потенційно може бути досить довгим і розтягнутися на декілька рядків. Однак ми сподіваємось, що він виглядатиме гарно. + Автор + Тут вказується ім\'я автора вибраного зображеня Дата завантаження Ліцензія Координати @@ -205,10 +229,12 @@ Вийти Посібник Сповіщення + Вибране Місця поблизу неможливо показати без дозволу на визначення місця розташування. опис не знайдено Сторінка файлу у Вікісховищі Елемент Вікіданих + Стаття Вікіпедії Помилка кешування зображень Унікальна описова назва файлу. Ви можете використовувати простий текст з пробілами. Не вказуйте розширення файлу Будь ласка, докладно опишіть файл: де його було зроблено? що на ньому зображено? який контекст? Будь ласка, опишіть об\'єкти чи осіб. Додайте інформацію, яку не можна легко здогадатися, наприклад, пору доби для фотографії пейзажу. Якщо зображено щось незвичайне, постарайтеся пояснити, що робить його незвичайним. @@ -220,6 +246,12 @@ Увійдіть у свій обліковий запис Надіслати лог-файл Надіслати лог-файл розробникам електронною поштою + Не знайдено браузера, щоб відкрити посилання + Помилка! Посилання не знайдено + Номінувати на вилучення + Цей файл номіновано на вилучення. + + Переглянути в браузері Розташування не змінено Місцезнаходження недоступне Потрібний дозвіл для показу списку місць поблизу @@ -230,4 +262,21 @@ Дякуємо за правку %1$s згадав вас на %2$s. Перемкнути режим перегляду + НАПРЯМКИ + ВІКІДАНІ + ВІКІПЕДІЯ + ВІКІСХОВИЩЕ + <u>Оцініть нас</u> + Часті запитання + Пропустити інструкцію + Інтернет недоступний + Інтернет доступний + Помилка при отриманні сповіщення + Сповіщень немає + <u>Перекласти</u> + Мови + Виберіть мову, переклади якою ви хочете відправити + Виконується + Скасувати + Повторити diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index f6dda9945..4fdd67514 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -1,4 +1,11 @@ + کامنز ترتیبات @@ -51,6 +58,7 @@ زمرہ جات تلاش کریں محفوظ کریں تازہ کریں + فہرست جی پی ایس آپ کے آلے میں غیر فعال ہے۔ آپ اس کو فعال کرنا چاہینگے؟ جی پی ایس فعال کریں ابھی تک کوئی اپلوڈ نہیں @@ -124,4 +132,9 @@ آپ کی رائے لاگ آوٹ معلمی + ہدایات + عام + انٹرنیٹ دستیاب نہیں + انٹرنیٹ دستیاب + دوبارہ کوشش کریں diff --git a/app/src/main/res/values-vi/error.xml b/app/src/main/res/values-vi/error.xml index 9d513aacb..2fcd46031 100644 --- a/app/src/main/res/values-vi/error.xml +++ b/app/src/main/res/values-vi/error.xml @@ -1,4 +1,8 @@ + Commons đã có sự cố Oái, đã có trục trặc xảy ra! diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 118bd6aee..4cff15064 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -1,4 +1,10 @@ + Commons Thiết lập @@ -124,8 +130,8 @@ Không miêu tả Giấy phép không rõ Làm tươi - Yêu cầu cấp phép: Đọc thiết bị lưu trữ bên ngoài. Ứng dụng cần được phép đọc thiết bị lưu trữ bên ngoài để hoạt động. - Yêu cầu cấp phép: Ghi vào thiết bị lưu trữ bên ngoài. Ứng dụng cần được phép ghi vào thiết bị lưu trữ bên ngoài để hoạt động. + Yêu cầu cấp phép: Đọc thiết bị lưu trữ bên ngoài. Ứng dụng cần được phép đọc thiết bị lưu trữ bên ngoài để hoạt động. + Yêu cầu cấp phép: Ghi vào thiết bị lưu trữ bên ngoài. Ứng dụng cần được phép ghi vào thiết bị lưu trữ bên ngoài để hoạt động. Tùy chọn cấp phép: Định vị hiện tại để nhận gợi ý thể loại OK Nơi Lân cận diff --git a/app/src/main/res/values-xmf/error.xml b/app/src/main/res/values-xmf/error.xml index 850dde9fd..dd0c2adaf 100644 --- a/app/src/main/res/values-xmf/error.xml +++ b/app/src/main/res/values-xmf/error.xml @@ -1,4 +1,7 @@ + ვიკიოწკარუექ აკორთუ უი. მუდგაინქ ქჷმოხვადუǃ diff --git a/app/src/main/res/values-xmf/strings.xml b/app/src/main/res/values-xmf/strings.xml index 8cf2a7851..b9689f9e2 100644 --- a/app/src/main/res/values-xmf/strings.xml +++ b/app/src/main/res/values-xmf/strings.xml @@ -1,4 +1,7 @@ + ვიკიოწკარუე პარამეტრეფი diff --git a/app/src/main/res/values-yue/error.xml b/app/src/main/res/values-yue/error.xml index 081685201..82520f7e5 100644 --- a/app/src/main/res/values-yue/error.xml +++ b/app/src/main/res/values-yue/error.xml @@ -1,4 +1,7 @@ + 同享壞咗 哎呀。出咗錯! diff --git a/app/src/main/res/values-zh-rTW/error.xml b/app/src/main/res/values-zh-rTW/error.xml index dfd90899b..de2dd34f1 100644 --- a/app/src/main/res/values-zh-rTW/error.xml +++ b/app/src/main/res/values-zh-rTW/error.xml @@ -1,4 +1,8 @@ + 共享資源已當機 哎呀。出了錯 ! diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c41f82d81..4966d9c08 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,4 +1,15 @@ + 外觀 一般 @@ -81,6 +92,7 @@ 分類 設定 註冊 + 特色圖片 關於 維基共享資源應用程式是透過維基媒體社群上的受讓人,與志願者們所建立及維護的開放原始碼應用程式。維基媒體基金會並不涉及此應用程式的建立、開發,與維護方面。 建立新的<a href=\"https://github.com/commons-app/apps-android-commons/issues\"> GitHub 問題</a>來回報程式錯誤和提出建議。 @@ -152,8 +164,8 @@ 無說明 不明授權 重新整理 - 必要權限:讀取外部存儲裝置。應用程式必須此功能,才能進行正確運作。 - 必要權限:寫入外部存儲裝置。應用程式必須此功能,才能進行正確運作。 + 必要權限:讀取外部存儲裝置。否則應用程式無法存取您的圖庫。 + 必要權限:寫入外部存儲裝置。否則應用程式無法取用您的相機。 可有可無的權限:獲取目前的地理位置,以用於分類建議 附近地點 @@ -166,6 +178,8 @@ 媒體標題 說明 本媒體的說明。若內容很長,請換行,會好看一些。 + 作者 + 特色圖片作者使用者名稱於此。 上傳日期 授權協議 座標 @@ -208,6 +222,7 @@ 登出 教程 通知 + 特色 附近地點需要位置權限才可顯示 找不到說明 共享資源檔案頁面 @@ -226,7 +241,8 @@ 經由電子郵件寄送日誌檔案給開發人員 找不到可以打開 URL 的網頁瀏覽器 錯誤!查無 URL - 刪除指定 + 提名刪除 + 此圖片已被提名刪除。 於瀏覽器檢視 位置無法更改。 位置無效。 @@ -242,6 +258,17 @@ 維基數據 維基百科 維基共享資源 - 常見問題 + <u>為我們評分</u> + <u>常見問題</u> 跳過敎程 + 網路不可用 + 網路可用 + 索取通知時錯誤 + 查無通知 + <u>翻譯</u> + 語言 + 選擇您想要提交翻譯的語言 + 已進行 + 取消 + 重試 diff --git a/app/src/main/res/values-zh/error.xml b/app/src/main/res/values-zh/error.xml index f6fbb12c1..b82eba5cc 100644 --- a/app/src/main/res/values-zh/error.xml +++ b/app/src/main/res/values-zh/error.xml @@ -1,4 +1,9 @@ + 共享资源已崩溃 呀。出错啦! diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index aac4e06cc..83650b408 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1,4 +1,13 @@ + 外观 一般 @@ -59,6 +68,7 @@ 搜索分类 保存 刷新 + 列表 您的设备禁用了GPS。您是否要启用它? 启用GPS 尚无上传 @@ -80,6 +90,7 @@ 分类 设置 注册 + 特色图片 关于 维基共享资源应用程序是由维基媒体社区的受助者和志愿者创建和维护的开源应用程序。维基媒体基金会不参与该应用程序的创立,开发或维护。 创建新的<a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub问题</a>以发送错误报告和建议。 @@ -151,8 +162,8 @@ 没有说明 未知许可协议 刷新 - 需要权限:读取外部存储。应用不能在没有它的情况下运行。 - 需要权限:写入外部存储。应用不能在没有它的情况下运行。 + 需要权限:读取外部存储。应用不能在没有它的情况下访问您的图册。 + 需要权限:写入外部存储。应用不能在没有它的情况下访问您的图册。 可选权限:获取当前位置以提供分类建议 确定 附近地点 @@ -165,6 +176,8 @@ 媒体的标题 说明 在此填写媒体的说明。这可能会相当长,并将需要包裹在多行中。我们希望它看起来很好。 + 作者 + 这里有特色图片作者的用户名。 上传日期 许可协议 坐标 @@ -207,10 +220,12 @@ 退出 教程 通知 + 特色 附近地点不能在没有位置权限的情况下显示 找不到描述 共享资源文件页面 维基数据项 + 维基百科条目 缓存图片时出错 用于文件的唯一描述性标题,它将作为文件名使用。您可以使用有空格的简明语言。请不要包含文件扩展名 请尽可能详细地描述媒体:拍摄在何地?显示什么?例文是什么?请描述对象或个人。透露一些不易猜想到的信息,例如这幅风景画的具体日期时间。如果媒体显示了一些不寻常的事物,请说明为什么它显得不寻常。 @@ -225,6 +240,7 @@ 找不到可以打开URL的网页浏览器 错误!找不到URL 提交删除 + 此图片已被提交删除。 在浏览器中预览 位置没有更新。 位置不可用。 @@ -236,6 +252,21 @@ 感谢您做出编辑 %1$s在%2$s提到了您。 切换视图 - 常见问题 + 方向 + 维基数据 + 维基百科 + 共享资源 + <u>评价我们</u> + <u>常见问题</u> 跳过指导 + 互联网不可用 + 互联网可用 + 检索通知时出错 + 找不到通知 + <u>翻译</u> + 语言 + 选择您希望提交翻译的语言 + 已处理 + 取消 + 重试 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7b3931624..28ecaeb8f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -82,12 +82,13 @@ Categories Settings Sign Up + Featured Images About The Wikimedia Commons app is an open-source app created and maintained by grantees and volunteers of the Wikimedia community. The Wikimedia Foundation is not involved in the creation, development, or maintenance of the app. Wikimedia Commons Create a new <a href=\"https://github.com/commons-app/apps-android-commons/issues\">GitHub issue</a> for bug reports and suggestions. - Privacy policy - Credits + Privacy policy]]> + Credits]]> About Send Feedback (via Email) No email client installed @@ -154,8 +155,8 @@ No description Unknown license Refresh - Required permission: Read external storage. App cannot function without this. - Required permission: Write external storage. App cannot function without this. + Required permission: Read external storage. App cannot access your gallery without this. + Required permission: Write external storage. App cannot access your camera without this. Optional permission: Get current location for category suggestions OK Nearby Places @@ -168,6 +169,8 @@ Title of the media Description Description of the media goes here. This can potentially be fairly long, and will need to wrap across multiple lines. We hope it looks nice though. + Author + Featured image author user name goes here. Uploaded date License Coordinates @@ -214,6 +217,7 @@ Logout Tutorial Notifications + Featured Nearby places cannot be displayed without location permissions no description found Commons file page @@ -252,20 +256,17 @@ WIKIDATA WIKIPEDIA COMMONS - - Rate us - FAQ + Rate us]]> + FAQ]]> Skip Tutorial - Internet unavailable Internet available Error fetching notifications No notifications found - - Translate + Translate]]> Languages Select the language that you would like to submit translations for Proceed Cancel - + Retry diff --git a/app/src/test/java/fr/free/nrw/commons/FileUtilsTest.java b/app/src/test/java/fr/free/nrw/commons/FileUtilsTest.java deleted file mode 100644 index c6febc1e4..000000000 --- a/app/src/test/java/fr/free/nrw/commons/FileUtilsTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Assert; -import org.junit.Test; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import fr.free.nrw.commons.upload.FileUtils; - -import static org.hamcrest.CoreMatchers.is; - -public class FileUtilsTest { - @Test public void copiedFileIsIdenticalToSource() throws IOException { - File source = File.createTempFile("temp", ""); - File dest = File.createTempFile("temp", ""); - writeToFile(source, "Hello, World"); - FileUtils.copy(new FileInputStream(source), new FileOutputStream(dest)); - Assert.assertThat(getString(dest), is(getString(source))); - } - - private static void writeToFile(File file, String s) throws IOException { - BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream(file)); - buf.write(s.getBytes()); - buf.close(); - } - - private static String getString(File file) throws IOException { - int size = (int) file.length(); - byte[] bytes = new byte[size]; - BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file)); - buf.read(bytes, 0, bytes.length); - buf.close(); - return new String(bytes); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/LatLngTests.java b/app/src/test/java/fr/free/nrw/commons/LatLngTests.java deleted file mode 100644 index c2fb1b159..000000000 --- a/app/src/test/java/fr/free/nrw/commons/LatLngTests.java +++ /dev/null @@ -1,64 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Assert; -import org.junit.Test; - -import fr.free.nrw.commons.location.LatLng; - -import static org.hamcrest.CoreMatchers.is; - -public class LatLngTests { - @Test public void testZeroZero() { - LatLng place = new LatLng(0, 0, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("0.0 N, 0.0 E")); - } - - @Test public void testAntipode() { - LatLng place = new LatLng(0, 180, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("0.0 N, 180.0 W")); - } - - @Test public void testNorthPole() { - LatLng place = new LatLng(90, 0, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("90.0 N, 0.0 E")); - } - - @Test public void testSouthPole() { - LatLng place = new LatLng(-90, 0, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("90.0 S, 0.0 E")); - } - - @Test public void testLargerNumbers() { - LatLng place = new LatLng(120, 380, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("90.0 N, 20.0 E")); - } - - @Test public void testNegativeNumbers() { - LatLng place = new LatLng(-120, -30, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("90.0 S, 30.0 W")); - } - - @Test public void testTooBigWestValue() { - LatLng place = new LatLng(20, -190, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("20.0 N, 170.0 E")); - } - - @Test public void testRounding() { - LatLng place = new LatLng(0.1234567, -0.33333333, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("0.1235 N, 0.3333 W")); - } - - @Test public void testRoundingAgain() { - LatLng place = new LatLng(-0.000001, -0.999999, 0); - String prettyString = place.getPrettyCoordinateString(); - Assert.assertThat(prettyString, is("0.0 S, 1.0 W")); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java b/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java deleted file mode 100644 index 561f3f0e6..000000000 --- a/app/src/test/java/fr/free/nrw/commons/LengthUtilsTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Assert; -import org.junit.Test; - -import fr.free.nrw.commons.location.LatLng; -import fr.free.nrw.commons.utils.LengthUtils; - -import static org.hamcrest.CoreMatchers.is; - -public class LengthUtilsTest { - @Test public void testZeroDistance() { - LatLng pointA = new LatLng(0, 0, 0); - LatLng pointB = new LatLng(0, 0, 0); - String distance = LengthUtils.formatDistanceBetween(pointA, pointB); - Assert.assertThat(distance, is("0m")); - } - - @Test public void testOneDegreeOnEquator() { - LatLng pointA = new LatLng(0, 0, 0); - LatLng pointB = new LatLng(0, 1, 0); - String distance = LengthUtils.formatDistanceBetween(pointA, pointB); - Assert.assertThat(distance, is("111.2km")); - } - - @Test public void testOneDegreeFortyFiveDegrees() { - LatLng pointA = new LatLng(45, 0, 0); - LatLng pointB = new LatLng(45, 1, 0); - String distance = LengthUtils.formatDistanceBetween(pointA, pointB); - Assert.assertThat(distance, is("78.6km")); - } - - @Test public void testOneDegreeSouthPole() { - LatLng pointA = new LatLng(-90, 0, 0); - LatLng pointB = new LatLng(-90, 1, 0); - String distance = LengthUtils.formatDistanceBetween(pointA, pointB); - Assert.assertThat(distance, is("0m")); - } - - @Test public void testPoleToPole() { - LatLng pointA = new LatLng(90, 0, 0); - LatLng pointB = new LatLng(-90, 0, 0); - String distance = LengthUtils.formatDistanceBetween(pointA, pointB); - Assert.assertThat(distance, is("20,015.1km")); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/MediaTest.java b/app/src/test/java/fr/free/nrw/commons/MediaTest.java deleted file mode 100644 index 4f53351ad..000000000 --- a/app/src/test/java/fr/free/nrw/commons/MediaTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class MediaTest { - @Test - public void displayTitleShouldStripExtension() { - Media m = new Media("File:Example.jpg"); - assertThat(m.getDisplayTitle(), is("Example")); - } - - @Test - public void displayTitleShouldUseSpaceForUnderscore() { - Media m = new Media("File:Example 1_2.jpg"); - assertThat(m.getDisplayTitle(), is("Example 1 2")); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/NearbyControllerTest.java b/app/src/test/java/fr/free/nrw/commons/NearbyControllerTest.java deleted file mode 100644 index 752b7404d..000000000 --- a/app/src/test/java/fr/free/nrw/commons/NearbyControllerTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.util.ArrayList; -import java.util.List; - -import fr.free.nrw.commons.location.LatLng; -import fr.free.nrw.commons.nearby.NearbyBaseMarker; -import fr.free.nrw.commons.nearby.Place; - -import static fr.free.nrw.commons.nearby.NearbyController.loadAttractionsFromLocationToBaseMarkerOptions; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class NearbyControllerTest { - - @Test - public void testNullAttractions() { - LatLng location = new LatLng(0, 0, 0); - - List options = loadAttractionsFromLocationToBaseMarkerOptions( - location, null, RuntimeEnvironment.application); - - assertThat(options.size(), is(0)); - } - - @Test - public void testEmptyList() { - LatLng location = new LatLng(0, 0, 0); - List emptyList = new ArrayList<>(); - - List options = loadAttractionsFromLocationToBaseMarkerOptions( - location, emptyList, RuntimeEnvironment.application); - - assertThat(options.size(), is(0)); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/PageTitleTest.java b/app/src/test/java/fr/free/nrw/commons/PageTitleTest.java deleted file mode 100644 index 16336b1b0..000000000 --- a/app/src/test/java/fr/free/nrw/commons/PageTitleTest.java +++ /dev/null @@ -1,70 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.net.URLEncoder; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class PageTitleTest { - @Test - public void displayTextShouldNotBeUnderscored() { - assertThat(new PageTitle("Ex_1 ").getDisplayText(), - is("Ex 1")); - } - - @Test - public void moreThanTwoColons() { - assertThat(new PageTitle("File:sample:a.jpg").getPrefixedText(), - is("File:Sample:a.jpg")); - } - - @Test - public void getTextShouldReturnWithoutNamespace() { - assertThat(new PageTitle("File:sample.jpg").getText(), - is("Sample.jpg")); - } - - - @Test - public void capitalizeNameAfterNamespace() { - assertThat(new PageTitle("File:sample.jpg").getPrefixedText(), - is("File:Sample.jpg")); - } - - @Test - public void prefixedTextShouldBeUnderscored() { - assertThat(new PageTitle("Ex 1 ").getPrefixedText(), - is("Ex_1")); - } - - @Test - public void getMobileUriForTest() { - assertThat(new PageTitle("Test").getMobileUri().toString(), - is(BuildConfig.MOBILE_HOME_URL + "Test")); - } - - @Test - public void spaceBecomesUnderscoreInUri() { - assertThat(new PageTitle("File:Ex 1.jpg").getCanonicalUri().toString(), - is(BuildConfig.HOME_URL + "File:Ex_1.jpg")); - } - - @Test - public void leaveSubpageNamesUncapitalizedInUri() { - assertThat(new PageTitle("User:Ex/subpage").getCanonicalUri().toString(), - is(BuildConfig.HOME_URL + "User:Ex/subpage")); - } - - @Test - public void unicodeUri() throws Throwable { - assertThat(new PageTitle("User:例").getCanonicalUri().toString(), - is(BuildConfig.HOME_URL + "User:" + URLEncoder.encode("例", "utf-8"))); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/TestCommonsApplication.java b/app/src/test/java/fr/free/nrw/commons/TestCommonsApplication.java deleted file mode 100644 index 9f7bc6184..000000000 --- a/app/src/test/java/fr/free/nrw/commons/TestCommonsApplication.java +++ /dev/null @@ -1,181 +0,0 @@ -package fr.free.nrw.commons; - -import android.content.Context; -import android.content.SharedPreferences; -import android.support.v4.util.LruCache; - -import com.squareup.leakcanary.RefWatcher; - -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import javax.inject.Named; - -import dagger.Provides; -import fr.free.nrw.commons.auth.AccountUtil; -import fr.free.nrw.commons.auth.SessionManager; -import fr.free.nrw.commons.caching.CacheController; -import fr.free.nrw.commons.data.DBOpenHelper; -import fr.free.nrw.commons.di.CommonsApplicationComponent; -import fr.free.nrw.commons.di.CommonsApplicationModule; -import fr.free.nrw.commons.di.DaggerCommonsApplicationComponent; -import fr.free.nrw.commons.location.LocationServiceManager; -import fr.free.nrw.commons.mwapi.MediaWikiApi; -import fr.free.nrw.commons.nearby.NearbyPlaces; -import fr.free.nrw.commons.upload.UploadController; - -public class TestCommonsApplication extends CommonsApplication { - - CommonsApplicationComponent mockApplicationComponent; - - @Mock - CommonsApplicationModule commonsApplicationModule; - @Mock - AccountUtil accountUtil; - @Mock - SharedPreferences appSharedPreferences; - @Mock - SharedPreferences defaultSharedPreferences; - @Mock - SharedPreferences otherSharedPreferences; - @Mock - UploadController uploadController; - @Mock - SessionManager sessionManager; - @Mock - MediaWikiApi mediaWikiApi; - @Mock - LocationServiceManager locationServiceManager; - @Mock - CacheController cacheController; - @Mock - DBOpenHelper dbOpenHelper; - @Mock - NearbyPlaces nearbyPlaces; - @Mock - LruCache lruCache; - - @Override - public void onCreate() { - MockitoAnnotations.initMocks(this); - if (mockApplicationComponent == null) { - mockApplicationComponent = DaggerCommonsApplicationComponent.builder() - .appModule(new CommonsApplicationModule(this) { - @Override - public AccountUtil providesAccountUtil(Context context) { - return accountUtil; - } - - @Override - public SharedPreferences providesApplicationSharedPreferences(Context context) { - return appSharedPreferences; - } - - @Override - public SharedPreferences providesDefaultSharedPreferences(Context context) { - return defaultSharedPreferences; - } - - @Override - public SharedPreferences providesOtherSharedPreferences(Context context) { - return otherSharedPreferences; - } - - @Override - public UploadController providesUploadController(SessionManager sessionManager, SharedPreferences sharedPreferences, Context context) { - return uploadController; - } - - @Override - public SessionManager providesSessionManager(Context context, MediaWikiApi mediaWikiApi, SharedPreferences sharedPreferences) { - return sessionManager; - } - - @Override - public MediaWikiApi provideMediaWikiApi(Context context, SharedPreferences sharedPreferences) { - return mediaWikiApi; - } - - @Override - public LocationServiceManager provideLocationServiceManager(Context context) { - return locationServiceManager; - } - - @Override - public CacheController provideCacheController() { - return cacheController; - } - - @Override - public DBOpenHelper provideDBOpenHelper(Context context) { - return dbOpenHelper; - } - - @Override - public NearbyPlaces provideNearbyPlaces() { - return nearbyPlaces; - } - - @Override - public LruCache provideLruCache() { - return lruCache; - } - }).build(); - } - super.onCreate(); - } - - @Override - protected RefWatcher setupLeakCanary() { - // No leakcanary in unit tests. - return RefWatcher.DISABLED; - } - - public AccountUtil getAccountUtil() { - return accountUtil; - } - - public SharedPreferences getAppSharedPreferences() { - return appSharedPreferences; - } - - public SharedPreferences getDefaultSharedPreferences() { - return defaultSharedPreferences; - } - - public SharedPreferences getOtherSharedPreferences() { - return otherSharedPreferences; - } - - public UploadController getUploadController() { - return uploadController; - } - - public SessionManager getSessionManager() { - return sessionManager; - } - - public MediaWikiApi getMediaWikiApi() { - return mediaWikiApi; - } - - public LocationServiceManager getLocationServiceManager() { - return locationServiceManager; - } - - public CacheController getCacheController() { - return cacheController; - } - - public DBOpenHelper getDbOpenHelper() { - return dbOpenHelper; - } - - public NearbyPlaces getNearbyPlaces() { - return nearbyPlaces; - } - - public LruCache getLruCache() { - return lruCache; - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java b/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java deleted file mode 100644 index 186f30df9..000000000 --- a/app/src/test/java/fr/free/nrw/commons/UtilsFixExtensionTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package fr.free.nrw.commons; - -import org.junit.Assert; -import org.junit.Test; - -import static org.hamcrest.CoreMatchers.is; - -public class UtilsFixExtensionTest { - - @Test public void jpegResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpeg", "jpeg"), is("SampleFile.jpg")); - } - - @Test public void capitalJpegWithNoHintResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.JPEG", null), is("SampleFile.jpg")); - } - - @Test public void jpegWithBogusHintResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpeg", null), is("SampleFile.jpg")); - } - - @Test public void jpegToCapitalJpegResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpeg", "JPEG"), is("SampleFile.jpg")); - } - - @Test public void jpgToJpegResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpg", "jpeg"), is("SampleFile.jpg")); - } - - @Test public void jpegToJpgResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpeg", "jpg"), is("SampleFile.jpg")); - } - - @Test public void jpgRemainsJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile.jpg", "jpg"), is("SampleFile.jpg")); - } - - @Test public void pngRemainsPng() { - Assert.assertThat(Utils.fixExtension("SampleFile.png", "png"), is("SampleFile.png")); - } - - @Test public void jpgHintResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile", "jpg"), is("SampleFile.jpg")); - } - - @Test public void jpegHintResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SampleFile", "jpeg"), is("SampleFile.jpg")); - } - - @Test public void dotLessJpgToJpgResultsInJpg() { - Assert.assertThat(Utils.fixExtension("SAMPLEjpg", "jpg"), is("SAMPLEjpg.jpg")); - } - - @Test public void inWordJpegToJpgResultsInJpg() { - Assert.assertThat(Utils.fixExtension("X.jpeg.SAMPLE", "jpg"),is("X.jpeg.SAMPLE.jpg")); - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/category/CategoryDaoTest.java b/app/src/test/java/fr/free/nrw/commons/category/CategoryDaoTest.java deleted file mode 100644 index 1cf0c338b..000000000 --- a/app/src/test/java/fr/free/nrw/commons/category/CategoryDaoTest.java +++ /dev/null @@ -1,294 +0,0 @@ -package fr.free.nrw.commons.category; - -import android.content.ContentProviderClient; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.RemoteException; -import android.support.annotation.NonNull; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import fr.free.nrw.commons.BuildConfig; -import fr.free.nrw.commons.TestCommonsApplication; -import fr.free.nrw.commons.category.CategoryDao.Table; - -import static fr.free.nrw.commons.category.CategoryContentProvider.BASE_URI; -import static fr.free.nrw.commons.category.CategoryContentProvider.uriForId; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class CategoryDaoTest { - - @Mock - private ContentProviderClient client; - @Mock - private SQLiteDatabase database; - @Captor - private ArgumentCaptor captor; - @Captor - private ArgumentCaptor queryCaptor; - - private CategoryDao testObject; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - testObject = new CategoryDao(() -> client); - } - - @Test - public void createTable() { - Table.onCreate(database); - verify(database).execSQL(Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void deleteTable() { - Table.onDelete(database); - InOrder inOrder = Mockito.inOrder(database); - inOrder.verify(database).execSQL(Table.DROP_TABLE_STATEMENT); - inOrder.verify(database).execSQL(Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void migrateTableVersionFrom_v1_to_v2() { - Table.onUpdate(database, 1, 2); - // Table didnt exist before v5 - verifyZeroInteractions(database); - } - - @Test - public void migrateTableVersionFrom_v2_to_v3() { - Table.onUpdate(database, 2, 3); - // Table didnt exist before v5 - verifyZeroInteractions(database); - } - - @Test - public void migrateTableVersionFrom_v3_to_v4() { - Table.onUpdate(database, 3, 4); - // Table didnt exist before v5 - verifyZeroInteractions(database); - } - - @Test - public void migrateTableVersionFrom_v4_to_v5() { - Table.onUpdate(database, 4, 5); - verify(database).execSQL(Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void migrateTableVersionFrom_v5_to_v6() { - Table.onUpdate(database, 5, 6); - // Table didnt change in version 6 - verifyZeroInteractions(database); - } - - @Test - public void createFromCursor() { - MatrixCursor cursor = createCursor(1); - cursor.moveToFirst(); - Category category = testObject.fromCursor(cursor); - - assertEquals(uriForId(1), category.getContentUri()); - assertEquals("foo", category.getName()); - assertEquals(123, category.getLastUsed().getTime()); - assertEquals(2, category.getTimesUsed()); - } - - @Test - public void saveExistingCategory() throws Exception { - MatrixCursor cursor = createCursor(1); - cursor.moveToFirst(); - Category category = testObject.fromCursor(cursor); - - testObject.save(category); - - verify(client).update(eq(category.getContentUri()), captor.capture(), isNull(String.class), isNull(String[].class)); - ContentValues cv = captor.getValue(); - assertEquals(3, cv.size()); - assertEquals(category.getName(), cv.getAsString(Table.COLUMN_NAME)); - assertEquals(category.getLastUsed().getTime(), cv.getAsLong(Table.COLUMN_LAST_USED).longValue()); - assertEquals(category.getTimesUsed(), cv.getAsInteger(Table.COLUMN_TIMES_USED).intValue()); - } - - @Test - public void saveNewCategory() throws Exception { - Uri contentUri = CategoryContentProvider.uriForId(111); - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Category category = new Category(null, "foo", new Date(234L), 1); - - testObject.save(category); - - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - assertEquals(3, cv.size()); - assertEquals(category.getName(), cv.getAsString(Table.COLUMN_NAME)); - assertEquals(category.getLastUsed().getTime(), cv.getAsLong(Table.COLUMN_LAST_USED).longValue()); - assertEquals(category.getTimesUsed(), cv.getAsInteger(Table.COLUMN_TIMES_USED).intValue()); - assertEquals(contentUri, category.getContentUri()); - } - - @Test(expected = RuntimeException.class) - public void testSaveTranslatesRemoteExceptions() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenThrow(new RemoteException("")); - testObject.save(new Category()); - } - - @Test - public void whenTheresNoDataFindReturnsNull_nullCursor() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(null); - - assertNull(testObject.find("foo")); - } - - @Test - public void whenTheresNoDataFindReturnsNull_emptyCursor() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(createCursor(0)); - - assertNull(testObject.find("foo")); - } - - @Test - public void cursorsAreClosedAfterUse() throws Exception { - Cursor mockCursor = mock(Cursor.class); - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(mockCursor); - when(mockCursor.moveToFirst()).thenReturn(false); - - testObject.find("foo"); - - verify(mockCursor).close(); - } - - @Test - public void findCategory() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(createCursor(1)); - - Category category = testObject.find("foo"); - - assertEquals(uriForId(1), category.getContentUri()); - assertEquals("foo", category.getName()); - assertEquals(123, category.getLastUsed().getTime()); - assertEquals(2, category.getTimesUsed()); - - verify(client).query( - eq(BASE_URI), - eq(Table.ALL_FIELDS), - eq(Table.COLUMN_NAME + "=?"), - queryCaptor.capture(), - isNull(String.class) - ); - assertEquals("foo", queryCaptor.getValue()[0]); - } - - @Test(expected = RuntimeException.class) - public void findCategoryTranslatesExceptions() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenThrow(new RemoteException("")); - testObject.find("foo"); - } - - @Test(expected = RuntimeException.class) - public void recentCategoriesTranslatesExceptions() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenThrow(new RemoteException("")); - testObject.recentCategories(1); - } - - @Test - public void recentCategoriesReturnsEmptyList_nullCursor() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(null); - - assertTrue(testObject.recentCategories(1).isEmpty()); - } - - @Test - public void recentCategoriesReturnsEmptyList_emptyCursor() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(createCursor(0)); - - assertTrue(testObject.recentCategories(1).isEmpty()); - } - - @Test - public void cursorsAreClosedAfterRecentCategoriesQuery() throws Exception { - Cursor mockCursor = mock(Cursor.class); - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(mockCursor); - when(mockCursor.moveToFirst()).thenReturn(false); - - testObject.recentCategories(1); - - verify(mockCursor).close(); - } - - @Test - public void recentCategoriesReturnsLessThanLimit() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(createCursor(1)); - - List result = testObject.recentCategories(10); - - assertEquals(1, result.size()); - assertEquals("foo", result.get(0)); - - verify(client).query( - eq(BASE_URI), - eq(Table.ALL_FIELDS), - isNull(String.class), - queryCaptor.capture(), - eq(Table.COLUMN_LAST_USED + " DESC") - ); - assertEquals(0, queryCaptor.getValue().length); - } - - @Test - public void recentCategoriesHomorsLimit() throws Exception { - when(client.query(any(), any(), anyString(), any(), anyString())).thenReturn(createCursor(10)); - - List result = testObject.recentCategories(5); - - assertEquals(5, result.size()); - } - - @NonNull - private MatrixCursor createCursor(int rowCount) { - MatrixCursor cursor = new MatrixCursor(new String[]{ - Table.COLUMN_ID, - Table.COLUMN_NAME, - Table.COLUMN_LAST_USED, - Table.COLUMN_TIMES_USED - }, rowCount); - - for (int i = 0; i < rowCount; i++) { - cursor.addRow(Arrays.asList("1", "foo", "123", "2")); - } - - return cursor; - } - -} \ No newline at end of file diff --git a/app/src/test/java/fr/free/nrw/commons/contributions/ContributionDaoTest.java b/app/src/test/java/fr/free/nrw/commons/contributions/ContributionDaoTest.java deleted file mode 100644 index 15e37e640..000000000 --- a/app/src/test/java/fr/free/nrw/commons/contributions/ContributionDaoTest.java +++ /dev/null @@ -1,370 +0,0 @@ -package fr.free.nrw.commons.contributions; - -import android.content.ContentProviderClient; -import android.content.ContentValues; -import android.database.MatrixCursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.RemoteException; -import android.support.annotation.NonNull; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.util.Arrays; -import java.util.Date; - -import fr.free.nrw.commons.BuildConfig; -import fr.free.nrw.commons.TestCommonsApplication; -import fr.free.nrw.commons.Utils; - -import static fr.free.nrw.commons.contributions.Contribution.SOURCE_CAMERA; -import static fr.free.nrw.commons.contributions.Contribution.SOURCE_GALLERY; -import static fr.free.nrw.commons.contributions.Contribution.STATE_COMPLETED; -import static fr.free.nrw.commons.contributions.Contribution.STATE_QUEUED; -import static fr.free.nrw.commons.contributions.ContributionDao.Table; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI; -import static fr.free.nrw.commons.contributions.ContributionsContentProvider.uriForId; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class ContributionDaoTest { - - private static final String LOCAL_URI = "http://example.com/"; - @Mock - private ContentProviderClient client; - @Mock - private SQLiteDatabase database; - @Captor - private ArgumentCaptor captor; - - private Uri contentUri; - private ContributionDao testObject; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - contentUri = uriForId(111); - - testObject = new ContributionDao(() -> client); - } - - @Test - public void createTable() { - Table.onCreate(database); - verify(database).execSQL(Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void deleteTable() { - Table.onDelete(database); - - InOrder inOrder = Mockito.inOrder(database); - inOrder.verify(database).execSQL(Table.DROP_TABLE_STATEMENT); - inOrder.verify(database).execSQL(Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void upgradeDatabase_v1_to_v2() { - Table.onUpdate(database, 1, 2); - - InOrder inOrder = Mockito.inOrder(database); - inOrder.verify(database).execSQL(Table.ADD_DESCRIPTION_FIELD); - inOrder.verify(database).execSQL(Table.ADD_CREATOR_FIELD); - } - - @Test - public void upgradeDatabase_v2_to_v3() { - Table.onUpdate(database, 2, 3); - - InOrder inOrder = Mockito.inOrder(database); - inOrder.verify(database).execSQL(Table.ADD_MULTIPLE_FIELD); - inOrder.verify(database).execSQL(Table.SET_DEFAULT_MULTIPLE); - } - - @Test - public void upgradeDatabase_v3_to_v4() { - Table.onUpdate(database, 3, 4); - - // No changes - verifyZeroInteractions(database); - } - - @Test - public void upgradeDatabase_v4_to_v5() { - Table.onUpdate(database, 4, 5); - - // No changes - verifyZeroInteractions(database); - } - - @Test - public void upgradeDatabase_v5_to_v6() { - Table.onUpdate(database, 5, 6); - - InOrder inOrder = Mockito.inOrder(database); - inOrder.verify(database).execSQL(Table.ADD_WIDTH_FIELD); - inOrder.verify(database).execSQL(Table.SET_DEFAULT_WIDTH); - inOrder.verify(database).execSQL(Table.ADD_HEIGHT_FIELD); - inOrder.verify(database).execSQL(Table.SET_DEFAULT_HEIGHT); - inOrder.verify(database).execSQL(Table.ADD_LICENSE_FIELD); - inOrder.verify(database).execSQL(Table.SET_DEFAULT_LICENSE); - } - - @Test - public void saveNewContribution_nonNullFields() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(true, null, null, null, null); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - // Long fields - assertEquals(222L, cv.getAsLong(Table.COLUMN_LENGTH).longValue()); - assertEquals(321L, cv.getAsLong(Table.COLUMN_TIMESTAMP).longValue()); - assertEquals(333L, cv.getAsLong(Table.COLUMN_TRANSFERRED).longValue()); - - // Integer fields - assertEquals(STATE_COMPLETED, cv.getAsInteger(Table.COLUMN_STATE).intValue()); - assertEquals(640, cv.getAsInteger(Table.COLUMN_WIDTH).intValue()); - assertEquals(480, cv.getAsInteger(Table.COLUMN_HEIGHT).intValue()); - - // String fields - assertEquals(SOURCE_CAMERA, cv.getAsString(Table.COLUMN_SOURCE)); - assertEquals("desc", cv.getAsString(Table.COLUMN_DESCRIPTION)); - assertEquals("create", cv.getAsString(Table.COLUMN_CREATOR)); - assertEquals("007", cv.getAsString(Table.COLUMN_LICENSE)); - } - - @Test - public void saveNewContribution_nullableFieldsAreNull() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(true, null, null, null, null); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - // Nullable fields are absent if null - assertFalse(cv.containsKey(Table.COLUMN_LOCAL_URI)); - assertFalse(cv.containsKey(Table.COLUMN_IMAGE_URL)); - assertFalse(cv.containsKey(Table.COLUMN_UPLOADED)); - } - - @Test - public void saveNewContribution_nullableImageUrlUsesFileAsBackup() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(true, null, null, null, "file"); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - // Nullable fields are absent if null - assertFalse(cv.containsKey(Table.COLUMN_LOCAL_URI)); - assertFalse(cv.containsKey(Table.COLUMN_UPLOADED)); - - assertEquals(Utils.makeThumbBaseUrl("file"), cv.getAsString(Table.COLUMN_IMAGE_URL)); - } - - @Test - public void saveNewContribution_nullableFieldsAreNonNull() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(true, Uri.parse(LOCAL_URI), - "image", new Date(456L), null); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - assertEquals(LOCAL_URI, cv.getAsString(Table.COLUMN_LOCAL_URI)); - assertEquals("image", cv.getAsString(Table.COLUMN_IMAGE_URL)); - assertEquals(456L, cv.getAsLong(Table.COLUMN_UPLOADED).longValue()); - } - - @Test - public void saveNewContribution_booleanEncodesTrue() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(true, null, null, null, null); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - // Boolean true --> 1 for ths encoding scheme - assertEquals("Boolean true should be encoded as 1", 1, - cv.getAsInteger(Table.COLUMN_MULTIPLE).intValue()); - } - - @Test - public void saveNewContribution_booleanEncodesFalse() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(contentUri); - Contribution contribution = createContribution(false, null, null, null, null); - - testObject.save(contribution); - - assertEquals(contentUri, contribution.getContentUri()); - verify(client).insert(eq(BASE_URI), captor.capture()); - ContentValues cv = captor.getValue(); - - // Boolean true --> 1 for ths encoding scheme - assertEquals("Boolean false should be encoded as 0", 0, - cv.getAsInteger(Table.COLUMN_MULTIPLE).intValue()); - } - - @Test - public void saveExistingContribution() throws Exception { - Contribution contribution = createContribution(false, null, null, null, null); - contribution.setContentUri(contentUri); - - testObject.save(contribution); - - verify(client).update(eq(contentUri), isA(ContentValues.class), isNull(String.class), isNull(String[].class)); - } - - @Test(expected = RuntimeException.class) - public void saveTranslatesExceptions() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenThrow(new RemoteException("")); - - testObject.save(createContribution(false, null, null, null, null)); - } - - @Test(expected = RuntimeException.class) - public void deleteTranslatesExceptions() throws Exception { - when(client.delete(isA(Uri.class), any(), any())).thenThrow(new RemoteException("")); - - Contribution contribution = createContribution(false, null, null, null, null); - contribution.setContentUri(contentUri); - testObject.delete(contribution); - } - - @Test(expected = RuntimeException.class) - public void exceptionThrownWhenAttemptingToDeleteUnsavedContribution() { - testObject.delete(createContribution(false, null, null, null, null)); - } - - @Test - public void deleteExistingContribution() throws Exception { - Contribution contribution = createContribution(false, null, null, null, null); - contribution.setContentUri(contentUri); - - testObject.delete(contribution); - - verify(client).delete(eq(contentUri), isNull(String.class), isNull(String[].class)); - } - - @Test - public void createFromCursor() { - long created = 321L; - long uploaded = 456L; - MatrixCursor mc = createCursor(created, uploaded, false, LOCAL_URI); - - Contribution c = testObject.fromCursor(mc); - - assertEquals(uriForId(111), c.getContentUri()); - assertEquals("file", c.getFilename()); - assertEquals(LOCAL_URI, c.getLocalUri().toString()); - assertEquals("image", c.getImageUrl()); - assertEquals(created, c.getTimestamp().getTime()); - assertEquals(created, c.getDateCreated().getTime()); - assertEquals(STATE_QUEUED, c.getState()); - assertEquals(222L, c.getDataLength()); - assertEquals(uploaded, c.getDateUploaded().getTime()); - assertEquals(88L, c.getTransferred()); - assertEquals(SOURCE_GALLERY, c.getSource()); - assertEquals("desc", c.getDescription()); - assertEquals("create", c.getCreator()); - assertEquals(640, c.getWidth()); - assertEquals(480, c.getHeight()); - assertEquals("007", c.getLicense()); - } - - @Test - public void createFromCursor_nullableTimestamps() { - MatrixCursor mc = createCursor(0L, 0L, false, LOCAL_URI); - - Contribution c = testObject.fromCursor(mc); - - assertNull(c.getTimestamp()); - assertNull(c.getDateCreated()); - assertNull(c.getDateUploaded()); - } - - @Test - public void createFromCursor_nullableLocalUri() { - MatrixCursor mc = createCursor(0L, 0L, false, ""); - - Contribution c = testObject.fromCursor(mc); - - assertNull(c.getLocalUri()); - assertNull(c.getDateCreated()); - assertNull(c.getDateUploaded()); - } - - @Test - public void createFromCursor_booleanEncoding() { - MatrixCursor mcFalse = createCursor(0L, 0L, false, LOCAL_URI); - assertFalse(testObject.fromCursor(mcFalse).getMultiple()); - - MatrixCursor mcHammer = createCursor(0L, 0L, true, LOCAL_URI); - assertTrue(testObject.fromCursor(mcHammer).getMultiple()); - } - - @NonNull - private MatrixCursor createCursor(long created, long uploaded, boolean multiple, String localUri) { - MatrixCursor mc = new MatrixCursor(Table.ALL_FIELDS, 1); - mc.addRow(Arrays.asList("111", "file", localUri, "image", - created, STATE_QUEUED, 222L, uploaded, 88L, SOURCE_GALLERY, "desc", - "create", multiple ? 1 : 0, 640, 480, "007")); - mc.moveToFirst(); - return mc; - } - - @NonNull - private Contribution createContribution(boolean multiple, Uri localUri, - String imageUrl, Date dateUploaded, String filename) { - Contribution contribution = new Contribution(localUri, imageUrl, filename, "desc", 222L, - new Date(321L), dateUploaded, "create", "edit", "coords"); - contribution.setState(STATE_COMPLETED); - contribution.setTransferred(333L); - contribution.setSource(SOURCE_CAMERA); - contribution.setLicense("007"); - contribution.setMultiple(multiple); - contribution.setTimestamp(new Date(321L)); - contribution.setWidth(640); - contribution.setHeight(480); // VGA should be enough for anyone, right? - return contribution; - } -} \ No newline at end of file diff --git a/app/src/test/java/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.java b/app/src/test/java/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.java deleted file mode 100644 index ef290500d..000000000 --- a/app/src/test/java/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.java +++ /dev/null @@ -1,181 +0,0 @@ -package fr.free.nrw.commons.modifications; - -import android.content.ContentProviderClient; -import android.content.ContentValues; -import android.database.MatrixCursor; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.RemoteException; -import android.support.annotation.NonNull; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -import java.util.Arrays; - -import fr.free.nrw.commons.BuildConfig; -import fr.free.nrw.commons.TestCommonsApplication; - -import static fr.free.nrw.commons.modifications.ModificationsContentProvider.BASE_URI; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; -import static org.mockito.Matchers.isNull; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class ModifierSequenceDaoTest { - - private static final String EXPECTED_MEDIA_URI = "http://example.com/"; - - @Mock - ContentProviderClient client; - @Mock - SQLiteDatabase database; - @Captor - ArgumentCaptor contentValuesCaptor; - - private ModifierSequenceDao testObject; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - testObject = new ModifierSequenceDao(() -> client); - } - - @Test - public void createFromCursorWithEmptyModifiers() { - MatrixCursor cursor = createCursor(""); - - ModifierSequence seq = testObject.fromCursor(cursor); - - assertEquals(EXPECTED_MEDIA_URI, seq.getMediaUri().toString()); - assertEquals(BASE_URI.buildUpon().appendPath("1").toString(), seq.getContentUri().toString()); - assertTrue(seq.getModifiers().isEmpty()); - } - - @Test - public void createFromCursorWtihCategoryModifier() { - MatrixCursor cursor = createCursor("{\"name\": \"CategoriesModifier\", \"data\": {}}"); - - ModifierSequence seq = testObject.fromCursor(cursor); - - assertEquals(1, seq.getModifiers().size()); - assertTrue(seq.getModifiers().get(0) instanceof CategoryModifier); - } - - @Test - public void createFromCursorWithRemoveModifier() { - MatrixCursor cursor = createCursor("{\"name\": \"TemplateRemoverModifier\", \"data\": {}}"); - - ModifierSequence seq = testObject.fromCursor(cursor); - - assertEquals(1, seq.getModifiers().size()); - assertTrue(seq.getModifiers().get(0) instanceof TemplateRemoveModifier); - } - - @Test - public void deleteSequence() throws Exception { - when(client.delete(isA(Uri.class), isNull(String.class), isNull(String[].class))).thenReturn(1); - ModifierSequence seq = testObject.fromCursor(createCursor("")); - - testObject.delete(seq); - - verify(client).delete(eq(seq.getContentUri()), isNull(String.class), isNull(String[].class)); - } - - @Test(expected = RuntimeException.class) - public void deleteTranslatesRemoteExceptions() throws Exception { - when(client.delete(isA(Uri.class), isNull(String.class), isNull(String[].class))).thenThrow(new RemoteException("")); - ModifierSequence seq = testObject.fromCursor(createCursor("")); - - testObject.delete(seq); - } - - @Test - public void saveExistingSequence() throws Exception { - String modifierJson = "{\"name\":\"CategoriesModifier\",\"data\":{}}"; - String expectedData = "{\"modifiers\":[" + modifierJson + "]}"; - MatrixCursor cursor = createCursor(modifierJson); - - testObject.save(testObject.fromCursor(cursor)); - - verify(client).update(eq(testObject.fromCursor(cursor).getContentUri()), contentValuesCaptor.capture(), isNull(String.class), isNull(String[].class)); - ContentValues cv = contentValuesCaptor.getValue(); - assertEquals(2, cv.size()); - assertEquals(EXPECTED_MEDIA_URI, cv.get(ModifierSequenceDao.Table.COLUMN_MEDIA_URI)); - assertEquals(expectedData, cv.get(ModifierSequenceDao.Table.COLUMN_DATA)); - } - - @Test - public void saveNewSequence() throws Exception { - Uri expectedContentUri = BASE_URI.buildUpon().appendPath("1").build(); - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenReturn(expectedContentUri); - - ModifierSequence seq = new ModifierSequence(Uri.parse(EXPECTED_MEDIA_URI)); - testObject.save(seq); - - verify(client).insert(eq(ModificationsContentProvider.BASE_URI), contentValuesCaptor.capture()); - ContentValues cv = contentValuesCaptor.getValue(); - assertEquals(2, cv.size()); - assertEquals(EXPECTED_MEDIA_URI, cv.get(ModifierSequenceDao.Table.COLUMN_MEDIA_URI)); - assertEquals("{\"modifiers\":[]}", cv.get(ModifierSequenceDao.Table.COLUMN_DATA)); - assertEquals(expectedContentUri.toString(), seq.getContentUri().toString()); - } - - @Test(expected = RuntimeException.class) - public void saveTranslatesRemoteExceptions() throws Exception { - when(client.insert(isA(Uri.class), isA(ContentValues.class))).thenThrow(new RemoteException("")); - - testObject.save(new ModifierSequence(Uri.parse(EXPECTED_MEDIA_URI))); - } - - @Test - public void createTable() { - ModifierSequenceDao.Table.onCreate(database); - - verify(database).execSQL(ModifierSequenceDao.Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void updateTable() { - ModifierSequenceDao.Table.onUpdate(database, 1, 2); - - InOrder inOrder = inOrder(database); - inOrder.verify(database).execSQL(ModifierSequenceDao.Table.DROP_TABLE_STATEMENT); - inOrder.verify(database).execSQL(ModifierSequenceDao.Table.CREATE_TABLE_STATEMENT); - } - - @Test - public void deleteTable() { - ModifierSequenceDao.Table.onDelete(database); - - InOrder inOrder = inOrder(database); - inOrder.verify(database).execSQL(ModifierSequenceDao.Table.DROP_TABLE_STATEMENT); - inOrder.verify(database).execSQL(ModifierSequenceDao.Table.CREATE_TABLE_STATEMENT); - } - - @NonNull - private MatrixCursor createCursor(String modifierJson) { - MatrixCursor cursor = new MatrixCursor(new String[]{ - ModifierSequenceDao.Table.COLUMN_ID, - ModifierSequenceDao.Table.COLUMN_MEDIA_URI, - ModifierSequenceDao.Table.COLUMN_DATA - }, 1); - cursor.addRow(Arrays.asList("1", EXPECTED_MEDIA_URI, "{\"modifiers\": [" + modifierJson + "]}")); - cursor.moveToFirst(); - return cursor; - } -} \ No newline at end of file diff --git a/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java b/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java deleted file mode 100644 index e2c8b82f6..000000000 --- a/app/src/test/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package fr.free.nrw.commons.mwapi; - -import android.content.SharedPreferences; -import android.os.Build; -import android.preference.PreferenceManager; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import fr.free.nrw.commons.BuildConfig; -import fr.free.nrw.commons.TestCommonsApplication; -import io.reactivex.observers.TestObserver; -import okhttp3.HttpUrl; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 21, application = TestCommonsApplication.class) -public class ApacheHttpClientMediaWikiApiTest { - - private ApacheHttpClientMediaWikiApi testObject; - private MockWebServer server; - private SharedPreferences sharedPreferences; - - @Before - public void setUp() throws Exception { - server = new MockWebServer(); - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application); - testObject = new ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.getHostName() + ":" + server.getPort() + "/", sharedPreferences); - testObject.setWikiMediaToolforgeUrl("http://" + server.getHostName() + ":" + server.getPort() + "/"); - } - - @After - public void teardown() throws IOException { - server.shutdown(); - } - - @Test - public void authCookiesAreHandled() { - assertEquals("", testObject.getAuthCookie()); - - testObject.setAuthCookie("cookie=chocolate-chip"); - - assertEquals("cookie=chocolate-chip", testObject.getAuthCookie()); - } - - @Test - public void simpleLoginWithWrongPassword() throws Exception { - server.enqueue(new MockResponse().setBody("")); - server.enqueue(new MockResponse().setBody("")); - - String result = testObject.login("foo", "bar"); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "POST"); - Map body = parseBody(loginTokenRequest.getBody().readUtf8()); - assertEquals("xml", body.get("format")); - assertEquals("query", body.get("action")); - assertEquals("login", body.get("type")); - assertEquals("tokens", body.get("meta")); - - RecordedRequest loginRequest = assertBasicRequestParameters(server, "POST"); - body = parseBody(loginRequest.getBody().readUtf8()); - assertEquals("1", body.get("rememberMe")); - assertEquals("foo", body.get("username")); - assertEquals("bar", body.get("password")); - assertEquals("baz", body.get("logintoken")); - assertEquals("https://commons.wikimedia.org", body.get("loginreturnurl")); - assertEquals("xml", body.get("format")); - - assertEquals("wrongpassword", result); - } - - @Test - public void simpleLogin() throws Exception { - server.enqueue(new MockResponse().setBody("")); - server.enqueue(new MockResponse().setBody("")); - - String result = testObject.login("foo", "bar"); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "POST"); - Map body = parseBody(loginTokenRequest.getBody().readUtf8()); - assertEquals("xml", body.get("format")); - assertEquals("query", body.get("action")); - assertEquals("login", body.get("type")); - assertEquals("tokens", body.get("meta")); - - RecordedRequest loginRequest = assertBasicRequestParameters(server, "POST"); - body = parseBody(loginRequest.getBody().readUtf8()); - assertEquals("1", body.get("rememberMe")); - assertEquals("foo", body.get("username")); - assertEquals("bar", body.get("password")); - assertEquals("baz", body.get("logintoken")); - assertEquals("https://commons.wikimedia.org", body.get("loginreturnurl")); - assertEquals("xml", body.get("format")); - - assertEquals("PASS", result); - } - - @Test - public void twoFactorLogin() throws Exception { - server.enqueue(new MockResponse().setBody("")); - server.enqueue(new MockResponse().setBody("")); - - String result = testObject.login("foo", "bar", "2fa"); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "POST"); - Map body = parseBody(loginTokenRequest.getBody().readUtf8()); - assertEquals("xml", body.get("format")); - assertEquals("query", body.get("action")); - assertEquals("login", body.get("type")); - assertEquals("tokens", body.get("meta")); - - RecordedRequest loginRequest = assertBasicRequestParameters(server, "POST"); - body = parseBody(loginRequest.getBody().readUtf8()); - assertEquals("true", body.get("rememberMe")); - assertEquals("foo", body.get("username")); - assertEquals("bar", body.get("password")); - assertEquals("baz", body.get("logintoken")); - assertEquals("true", body.get("logincontinue")); - assertEquals("2fa", body.get("OATHToken")); - assertEquals("xml", body.get("format")); - - assertEquals("PASS", result); - } - - @Test - public void validateLoginForLoggedInUser() throws Exception { - server.enqueue(new MockResponse().setBody("")); - - boolean result = testObject.validateLogin(); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "GET"); - Map body = parseQueryParams(loginTokenRequest); - assertEquals("xml", body.get("format")); - assertEquals("query", body.get("action")); - assertEquals("userinfo", body.get("meta")); - - assertTrue(result); - } - - @Test - public void validateLoginForLoggedOutUser() throws Exception { - server.enqueue(new MockResponse().setBody("")); - - boolean result = testObject.validateLogin(); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "GET"); - Map params = parseQueryParams(loginTokenRequest); - assertEquals("xml", params.get("format")); - assertEquals("query", params.get("action")); - assertEquals("userinfo", params.get("meta")); - - assertFalse(result); - } - - @Test - public void editToken() throws Exception { - server.enqueue(new MockResponse().setBody("")); - - String result = testObject.getEditToken(); - - RecordedRequest loginTokenRequest = assertBasicRequestParameters(server, "GET"); - Map params = parseQueryParams(loginTokenRequest); - assertEquals("xml", params.get("format")); - assertEquals("tokens", params.get("action")); - assertEquals("edit", params.get("type")); - - assertEquals("baz", result); - } - - @Test - public void fileExistsWithName_FileNotFound() throws Exception { - server.enqueue(new MockResponse().setBody(" ")); - - boolean result = testObject.fileExistsWithName("foo"); - - RecordedRequest request = assertBasicRequestParameters(server, "GET"); - Map params = parseQueryParams(request); - assertEquals("xml", params.get("format")); - assertEquals("query", params.get("action")); - assertEquals("imageinfo", params.get("prop")); - assertEquals("File:foo", params.get("titles")); - - assertFalse(result); - } - - @Test - public void getUploadCount() throws InterruptedException { - server.enqueue(new MockResponse().setBody("23\n")); - - TestObserver testObserver = testObject.getUploadCount("testUsername").test(); - - RecordedRequest request = server.takeRequest(); - Map params = parseQueryParams(request); - assertEquals("testUsername", params.get("user")); - - assertEquals(1, testObserver.valueCount()); - assertEquals(23, (int)testObserver.values().get(0)); - } - - private RecordedRequest assertBasicRequestParameters(MockWebServer server, String method) throws InterruptedException { - RecordedRequest request = server.takeRequest(); - assertEquals("/", request.getRequestUrl().encodedPath()); - assertEquals(method, request.getMethod()); - assertEquals("Commons/" + BuildConfig.VERSION_NAME + " (https://mediawiki.org/wiki/Apps/Commons) Android/" + Build.VERSION.RELEASE, request.getHeader("User-Agent")); - if ("POST".equals(method)) { - assertEquals("application/x-www-form-urlencoded", request.getHeader("Content-Type")); - } - return request; - } - - private Map parseQueryParams(RecordedRequest request) { - Map result = new HashMap<>(); - HttpUrl url = request.getRequestUrl(); - Set params = url.queryParameterNames(); - for (String name : params) { - result.put(name, url.queryParameter(name)); - } - return result; - } - - private Map parseBody(String body) throws UnsupportedEncodingException { - String[] props = body.split("&"); - Map result = new HashMap<>(); - for (String prop : props) { - String[] pair = prop.split("="); - result.put(pair[0], URLDecoder.decode(pair[1], "utf-8")); - } - return result; - } -} diff --git a/app/src/test/java/fr/free/nrw/commons/utils/StringSortingUtilsTest.java b/app/src/test/java/fr/free/nrw/commons/utils/StringSortingUtilsTest.java deleted file mode 100644 index 6384fb096..000000000 --- a/app/src/test/java/fr/free/nrw/commons/utils/StringSortingUtilsTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.free.nrw.commons.utils; - -import org.junit.Assert; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public class StringSortingUtilsTest { - - @Test - public void testSortingNumbersBySimilarity() throws Exception { - List actualList = Arrays.asList("1234567", "4567", "12345", "123", "1234"); - List expectedList = Arrays.asList("1234", "12345", "123", "1234567", "4567"); - - Collections.sort(actualList, StringSortingUtils.sortBySimilarity("1234")); - Assert.assertEquals(expectedList, actualList); - } - - @Test - public void testSortingTextBySimilarity() throws Exception { - List actualList = Arrays.asList("The quick brown fox", - "quick brown fox", - "The", - "The quick ", - "The fox", - "brown fox", - "fox"); - List expectedList = Arrays.asList("The", - "The fox", - "The quick ", - "The quick brown fox", - "quick brown fox", - "brown fox", - "fox"); - - Collections.sort(actualList, StringSortingUtils.sortBySimilarity("The")); - Assert.assertEquals(expectedList, actualList); - } -} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/FileUtilsTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/FileUtilsTest.kt new file mode 100644 index 000000000..8be291d4d --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/FileUtilsTest.kt @@ -0,0 +1,33 @@ +package fr.free.nrw.commons + +import fr.free.nrw.commons.upload.FileUtils +import org.junit.Assert.assertEquals +import org.junit.Test +import java.io.* + +class FileUtilsTest { + @Test + fun copiedFileIsIdenticalToSource() { + val source = File.createTempFile("temp", "") + val dest = File.createTempFile("temp", "") + writeToFile(source, "Hello, World") + + FileUtils.copy(FileInputStream(source), FileOutputStream(dest)) + + assertEquals(getString(source), getString(dest)) + } + + private fun writeToFile(file: File, s: String) { + val buf = BufferedOutputStream(FileOutputStream(file)) + buf.write(s.toByteArray()) + buf.close() + } + + private fun getString(file: File): String { + val bytes = ByteArray(file.length().toInt()) + val buf = BufferedInputStream(FileInputStream(file)) + buf.read(bytes, 0, bytes.size) + buf.close() + return String(bytes) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/LatLngTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/LatLngTests.kt new file mode 100644 index 000000000..efafa4e3a --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/LatLngTests.kt @@ -0,0 +1,64 @@ +package fr.free.nrw.commons + +import fr.free.nrw.commons.location.LatLng +import org.junit.Assert.assertEquals +import org.junit.Test + +class LatLngTests { + @Test + fun testZeroZero() { + val place = LatLng(0.0, 0.0, 0f) + assertPrettyCoordinateString("0.0 N, 0.0 E", place) + } + + @Test + fun testAntipode() { + val place = LatLng(0.0, 180.0, 0f) + assertPrettyCoordinateString("0.0 N, 180.0 W", place) + } + + @Test + fun testNorthPole() { + val place = LatLng(90.0, 0.0, 0f) + assertPrettyCoordinateString("90.0 N, 0.0 E", place) + } + + @Test + fun testSouthPole() { + val place = LatLng(-90.0, 0.0, 0f) + assertPrettyCoordinateString("90.0 S, 0.0 E", place) + } + + @Test + fun testLargerNumbers() { + val place = LatLng(120.0, 380.0, 0f) + assertPrettyCoordinateString("90.0 N, 20.0 E", place) + } + + @Test + fun testNegativeNumbers() { + val place = LatLng(-120.0, -30.0, 0f) + assertPrettyCoordinateString("90.0 S, 30.0 W", place) + } + + @Test + fun testTooBigWestValue() { + val place = LatLng(20.0, -190.0, 0f) + assertPrettyCoordinateString("20.0 N, 170.0 E", place) + } + + @Test + fun testRounding() { + val place = LatLng(0.1234567, -0.33333333, 0f) + assertPrettyCoordinateString("0.1235 N, 0.3333 W", place) + } + + @Test + fun testRoundingAgain() { + val place = LatLng(-0.000001, -0.999999, 0f) + assertPrettyCoordinateString("0.0 S, 1.0 W", place) + } + + private fun assertPrettyCoordinateString(expected: String, place: LatLng) = + assertEquals(expected, place.prettyCoordinateString) +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/LengthUtilsTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/LengthUtilsTest.kt new file mode 100644 index 000000000..63b0b4d0a --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/LengthUtilsTest.kt @@ -0,0 +1,46 @@ +package fr.free.nrw.commons + +import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.utils.LengthUtils +import org.junit.Assert.assertEquals +import org.junit.Test + +class LengthUtilsTest { + @Test + fun testZeroDistance() { + val pointA = LatLng(0.0, 0.0, 0f) + val pointB = LatLng(0.0, 0.0, 0f) + assertDistanceBetween("0m", pointA, pointB) + } + + @Test + fun testOneDegreeOnEquator() { + val pointA = LatLng(0.0, 0.0, 0f) + val pointB = LatLng(0.0, 1.0, 0f) + assertDistanceBetween("111.2km", pointA, pointB) + } + + @Test + fun testOneDegreeFortyFiveDegrees() { + val pointA = LatLng(45.0, 0.0, 0f) + val pointB = LatLng(45.0, 1.0, 0f) + assertDistanceBetween("78.6km", pointA, pointB) + } + + @Test + fun testOneDegreeSouthPole() { + val pointA = LatLng(-90.0, 0.0, 0f) + val pointB = LatLng(-90.0, 1.0, 0f) + assertDistanceBetween("0m", pointA, pointB) + } + + @Test + fun testPoleToPole() { + val pointA = LatLng(90.0, 0.0, 0f) + val pointB = LatLng(-90.0, 0.0, 0f) + assertDistanceBetween("20,015.1km", pointA, pointB) + } + + private fun assertDistanceBetween(expected: String, pointA: LatLng, pointB: LatLng) = + assertEquals(expected, LengthUtils.formatDistanceBetween(pointA, pointB)) +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/MediaTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/MediaTest.kt new file mode 100644 index 000000000..f75c34568 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/MediaTest.kt @@ -0,0 +1,23 @@ +package fr.free.nrw.commons + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class) +class MediaTest { + @Test + fun displayTitleShouldStripExtension() { + val m = Media("File:Example.jpg") + assertEquals("Example", m.displayTitle) + } + + @Test + fun displayTitleShouldUseSpaceForUnderscore() { + val m = Media("File:Example 1_2.jpg") + assertEquals("Example 1 2", m.displayTitle) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/NearbyControllerTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/NearbyControllerTest.kt new file mode 100644 index 000000000..fc0be84d0 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/NearbyControllerTest.kt @@ -0,0 +1,35 @@ +package fr.free.nrw.commons + +import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.nearby.NearbyController.loadAttractionsFromLocationToBaseMarkerOptions +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class) +class NearbyControllerTest { + + @Test + fun testNullAttractions() { + val location = LatLng(0.0, 0.0, 0f) + + val options = loadAttractionsFromLocationToBaseMarkerOptions( + location, null, RuntimeEnvironment.application) + + assertEquals(0, options.size.toLong()) + } + + @Test + fun testEmptyList() { + val location = LatLng(0.0, 0.0, 0f) + + val options = loadAttractionsFromLocationToBaseMarkerOptions( + location, emptyList(), RuntimeEnvironment.application) + + assertEquals(0, options.size.toLong()) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/PageTitleTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/PageTitleTest.kt new file mode 100644 index 000000000..28112b196 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/PageTitleTest.kt @@ -0,0 +1,67 @@ +package fr.free.nrw.commons + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import java.net.URLEncoder + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class) +class PageTitleTest { + @Test + fun displayTextShouldNotBeUnderscored() { + val pageTitle = PageTitle("Ex_1 ") + assertEquals("Ex 1", pageTitle.displayText) + } + + @Test + fun moreThanTwoColons() { + val pageTitle = PageTitle("File:sample:a.jpg") + assertEquals("File:Sample:a.jpg", pageTitle.prefixedText) + } + + @Test + fun getTextShouldReturnWithoutNamespace() { + val pageTitle = PageTitle("File:sample.jpg") + assertEquals("Sample.jpg", pageTitle.text) + } + + + @Test + fun capitalizeNameAfterNamespace() { + val pageTitle = PageTitle("File:sample.jpg") + assertEquals("File:Sample.jpg", pageTitle.prefixedText) + } + + @Test + fun prefixedTextShouldBeUnderscored() { + val pageTitle = PageTitle("Ex 1 ") + assertEquals("Ex_1", pageTitle.prefixedText) + } + + @Test + fun getMobileUriForTest() { + val pageTitle = PageTitle("Test") + assertEquals(BuildConfig.MOBILE_HOME_URL + "Test", pageTitle.mobileUri.toString()) + } + + @Test + fun spaceBecomesUnderscoreInUri() { + val pageTitle = PageTitle("File:Ex 1.jpg") + assertEquals(BuildConfig.HOME_URL + "File:Ex_1.jpg", pageTitle.canonicalUri.toString()) + } + + @Test + fun leaveSubpageNamesUncapitalizedInUri() { + val pageTitle = PageTitle("User:Ex/subpage") + assertEquals(BuildConfig.HOME_URL + "User:Ex/subpage", pageTitle.canonicalUri.toString()) + } + + @Test + fun unicodeUri() { + val pageTitle = PageTitle("User:例") + assertEquals(BuildConfig.HOME_URL + "User:" + URLEncoder.encode("例", "utf-8"), pageTitle.canonicalUri.toString()) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/TestCommonsApplication.kt b/app/src/test/kotlin/fr/free/nrw/commons/TestCommonsApplication.kt new file mode 100644 index 000000000..73760dd40 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/TestCommonsApplication.kt @@ -0,0 +1,72 @@ +package fr.free.nrw.commons + +import android.content.Context +import android.content.SharedPreferences +import android.support.v4.util.LruCache +import com.nhaarman.mockito_kotlin.mock +import com.squareup.leakcanary.RefWatcher +import fr.free.nrw.commons.auth.AccountUtil +import fr.free.nrw.commons.auth.SessionManager +import fr.free.nrw.commons.caching.CacheController +import fr.free.nrw.commons.data.DBOpenHelper +import fr.free.nrw.commons.di.CommonsApplicationComponent +import fr.free.nrw.commons.di.CommonsApplicationModule +import fr.free.nrw.commons.di.DaggerCommonsApplicationComponent +import fr.free.nrw.commons.location.LocationServiceManager +import fr.free.nrw.commons.mwapi.MediaWikiApi +import fr.free.nrw.commons.nearby.NearbyPlaces +import fr.free.nrw.commons.upload.UploadController + +class TestCommonsApplication : CommonsApplication() { + private var mockApplicationComponent: CommonsApplicationComponent? = null + + override fun onCreate() { + if (mockApplicationComponent == null) { + mockApplicationComponent = DaggerCommonsApplicationComponent.builder() + .appModule(MockCommonsApplicationModule(this)).build() + } + super.onCreate() + } + + // No leakcanary in unit tests. + override fun setupLeakCanary(): RefWatcher = RefWatcher.DISABLED +} + +class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModule(appContext) { + val accountUtil: AccountUtil = mock() + val appSharedPreferences: SharedPreferences = mock() + val defaultSharedPreferences: SharedPreferences = mock() + val otherSharedPreferences: SharedPreferences = mock() + val uploadController: UploadController = mock() + val mockSessionManager: SessionManager = mock() + val mediaWikiApi: MediaWikiApi = mock() + val locationServiceManager: LocationServiceManager = mock() + val cacheController: CacheController = mock() + val mockDbOpenHelper: DBOpenHelper = mock() + val nearbyPlaces: NearbyPlaces = mock() + val lruCache: LruCache = mock() + + override fun providesAccountUtil(context: Context): AccountUtil = accountUtil + + override fun providesApplicationSharedPreferences(context: Context): SharedPreferences = appSharedPreferences + + override fun providesDefaultSharedPreferences(context: Context): SharedPreferences = defaultSharedPreferences + + override fun providesOtherSharedPreferences(context: Context): SharedPreferences = otherSharedPreferences + + override fun providesUploadController(sessionManager: SessionManager, sharedPreferences: SharedPreferences, context: Context): UploadController = uploadController + + override fun providesSessionManager(context: Context, mediaWikiApi: MediaWikiApi, sharedPreferences: SharedPreferences): SessionManager = mockSessionManager + + override fun provideMediaWikiApi(context: Context, sharedPreferences: SharedPreferences): MediaWikiApi = mediaWikiApi + + override fun provideLocationServiceManager(context: Context): LocationServiceManager = locationServiceManager + + override fun provideCacheController(): CacheController = cacheController + + override fun provideDBOpenHelper(context: Context): DBOpenHelper = mockDbOpenHelper + + override fun provideNearbyPlaces(): NearbyPlaces = nearbyPlaces + + override fun provideLruCache(): LruCache = lruCache +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/UtilsFixExtensionTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/UtilsFixExtensionTest.kt new file mode 100644 index 000000000..0082b9d28 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/UtilsFixExtensionTest.kt @@ -0,0 +1,68 @@ +package fr.free.nrw.commons + +import fr.free.nrw.commons.Utils.fixExtension +import org.junit.Assert.assertEquals +import org.junit.Test + +class UtilsFixExtensionTest { + + @Test + fun jpegResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpeg", "jpeg")) + } + + @Test + fun capitalJpegWithNoHintResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.JPEG", null)) + } + + @Test + fun jpegWithBogusHintResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpeg", null)) + } + + @Test + fun jpegToCapitalJpegResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpeg", "JPEG")) + } + + @Test + fun jpgToJpegResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpg", "jpeg")) + } + + @Test + fun jpegToJpgResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpeg", "jpg")) + } + + @Test + fun jpgRemainsJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile.jpg", "jpg")) + } + + @Test + fun pngRemainsPng() { + assertEquals("SampleFile.png", fixExtension("SampleFile.png", "png")) + } + + @Test + fun jpgHintResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile", "jpg")) + } + + @Test + fun jpegHintResultsInJpg() { + assertEquals("SampleFile.jpg", fixExtension("SampleFile", "jpeg")) + } + + @Test + fun dotLessJpgToJpgResultsInJpg() { + assertEquals("SAMPLEjpg.jpg", fixExtension("SAMPLEjpg", "jpg")) + } + + @Test + fun inWordJpegToJpgResultsInJpg() { + assertEquals("X.jpeg.SAMPLE.jpg", fixExtension("X.jpeg.SAMPLE", "jpg")) + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt new file mode 100644 index 000000000..b64d3b8aa --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/category/CategoryDaoTest.kt @@ -0,0 +1,257 @@ +package fr.free.nrw.commons.category + +import android.content.ContentProviderClient +import android.content.ContentValues +import android.database.Cursor +import android.database.MatrixCursor +import android.database.sqlite.SQLiteDatabase +import android.os.RemoteException +import com.nhaarman.mockito_kotlin.* +import fr.free.nrw.commons.BuildConfig +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.category.CategoryContentProvider.BASE_URI +import fr.free.nrw.commons.category.CategoryContentProvider.uriForId +import fr.free.nrw.commons.category.CategoryDao.Table.* +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import java.util.* + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = [21], application = TestCommonsApplication::class) +class CategoryDaoTest { + + private val columns = arrayOf(COLUMN_ID, COLUMN_NAME, COLUMN_LAST_USED, COLUMN_TIMES_USED) + private val client: ContentProviderClient = mock() + private val database: SQLiteDatabase = mock() + private val captor = argumentCaptor() + private val queryCaptor = argumentCaptor>() + + private lateinit var testObject: CategoryDao + + @Before + fun setUp() { + testObject = CategoryDao { client } + } + + @Test + fun createTable() { + onCreate(database) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + + @Test + fun deleteTable() { + onDelete(database) + inOrder(database) { + verify(database).execSQL(DROP_TABLE_STATEMENT) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + } + + @Test + fun migrateTableVersionFrom_v1_to_v2() { + onUpdate(database, 1, 2) + // Table didnt exist before v5 + verifyZeroInteractions(database) + } + + @Test + fun migrateTableVersionFrom_v2_to_v3() { + onUpdate(database, 2, 3) + // Table didnt exist before v5 + verifyZeroInteractions(database) + } + + @Test + fun migrateTableVersionFrom_v3_to_v4() { + onUpdate(database, 3, 4) + // Table didnt exist before v5 + verifyZeroInteractions(database) + } + + @Test + fun migrateTableVersionFrom_v4_to_v5() { + onUpdate(database, 4, 5) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + + @Test + fun migrateTableVersionFrom_v5_to_v6() { + onUpdate(database, 5, 6) + // Table didnt change in version 6 + verifyZeroInteractions(database) + } + + @Test + fun createFromCursor() { + createCursor(1).let { cursor -> + cursor.moveToFirst() + testObject.fromCursor(cursor).let { + assertEquals(uriForId(1), it.contentUri) + assertEquals("foo", it.name) + assertEquals(123, it.lastUsed.time) + assertEquals(2, it.timesUsed) + } + } + } + + @Test + fun saveExistingCategory() { + createCursor(1).let { + val category = testObject.fromCursor(it.apply { moveToFirst() }) + + testObject.save(category) + + verify(client).update(eq(category.contentUri), captor.capture(), isNull(), isNull()) + captor.firstValue.let { cv -> + assertEquals(3, cv.size()) + assertEquals(category.name, cv.getAsString(COLUMN_NAME)) + assertEquals(category.lastUsed.time, cv.getAsLong(COLUMN_LAST_USED)) + assertEquals(category.timesUsed, cv.getAsInteger(COLUMN_TIMES_USED)) + } + } + } + + @Test + fun saveNewCategory() { + val contentUri = CategoryContentProvider.uriForId(111) + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val category = Category(null, "foo", Date(234L), 1) + + testObject.save(category) + + verify(client).insert(eq(BASE_URI), captor.capture()) + captor.firstValue.let { cv -> + assertEquals(3, cv.size()) + assertEquals(category.name, cv.getAsString(COLUMN_NAME)) + assertEquals(category.lastUsed.time, cv.getAsLong(COLUMN_LAST_USED)) + assertEquals(category.timesUsed, cv.getAsInteger(COLUMN_TIMES_USED)) + assertEquals(contentUri, category.contentUri) + } + } + + @Test(expected = RuntimeException::class) + fun testSaveTranslatesRemoteExceptions() { + whenever(client.insert(isA(), isA())).thenThrow(RemoteException("")) + testObject.save(Category()) + } + + @Test + fun whenTheresNoDataFindReturnsNull_nullCursor() { + whenever(client.query(any(), any(), any(), any(), any())).thenReturn(null) + assertNull(testObject.find("foo")) + } + + @Test + fun whenTheresNoDataFindReturnsNull_emptyCursor() { + whenever(client.query(any(), any(), any(), any(), any())).thenReturn(createCursor(0)) + assertNull(testObject.find("foo")) + } + + @Test + fun cursorsAreClosedAfterUse() { + val mockCursor: Cursor = mock() + whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(mockCursor) + whenever(mockCursor.moveToFirst()).thenReturn(false) + + testObject.find("foo") + + verify(mockCursor).close() + } + + @Test + fun findCategory() { + whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenReturn(createCursor(1)) + + val category = testObject.find("foo") + assertNotNull(category) + + assertEquals(uriForId(1), category?.contentUri) + assertEquals("foo", category?.name) + assertEquals(123L, category?.lastUsed?.time) + assertEquals(2, category?.timesUsed) + + verify(client).query( + eq(BASE_URI), + eq(ALL_FIELDS), + eq("$COLUMN_NAME=?"), + queryCaptor.capture(), + isNull() + ) + assertEquals("foo", queryCaptor.firstValue[0]) + } + + @Test(expected = RuntimeException::class) + fun findCategoryTranslatesExceptions() { + whenever(client.query(any(), any(), any(), any(), anyOrNull())).thenThrow(RemoteException("")) + testObject.find("foo") + } + + @Test(expected = RuntimeException::class) + fun recentCategoriesTranslatesExceptions() { + whenever(client.query(any(), any(), anyOrNull(), any(), any())).thenThrow(RemoteException("")) + testObject.recentCategories(1) + } + + @Test + fun recentCategoriesReturnsEmptyList_nullCursor() { + whenever(client.query(any(), any(), anyOrNull(), any(), any())).thenReturn(null) + assertTrue(testObject.recentCategories(1).isEmpty()) + } + + @Test + fun recentCategoriesReturnsEmptyList_emptyCursor() { + whenever(client.query(any(), any(), any(), any(), any())).thenReturn(createCursor(0)) + assertTrue(testObject.recentCategories(1).isEmpty()) + } + + @Test + fun cursorsAreClosedAfterRecentCategoriesQuery() { + val mockCursor: Cursor = mock() + whenever(client.query(any(), any(), anyOrNull(), any(), any())).thenReturn(mockCursor) + whenever(mockCursor.moveToFirst()).thenReturn(false) + + testObject.recentCategories(1) + + verify(mockCursor).close() + } + + @Test + fun recentCategoriesReturnsLessThanLimit() { + whenever(client.query(any(), any(), anyOrNull(), any(), any())).thenReturn(createCursor(1)) + + val result = testObject.recentCategories(10) + + assertEquals(1, result.size) + assertEquals("foo", result[0]) + + verify(client).query( + eq(BASE_URI), + eq(ALL_FIELDS), + isNull(), + queryCaptor.capture(), + eq("$COLUMN_LAST_USED DESC") + ) + assertEquals(0, queryCaptor.firstValue.size) + } + + @Test + fun recentCategoriesHonorsLimit() { + whenever(client.query(any(), any(), anyOrNull(), any(), any())).thenReturn(createCursor(10)) + + val result = testObject.recentCategories(5) + + assertEquals(5, result.size) + } + + private fun createCursor(rowCount: Int) = MatrixCursor(columns, rowCount).apply { + for (i in 0 until rowCount) { + addRow(listOf("1", "foo", "123", "2")) + } + } + +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionDaoTest.kt new file mode 100644 index 000000000..762e0bb85 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionDaoTest.kt @@ -0,0 +1,335 @@ +package fr.free.nrw.commons.contributions + +import android.content.ContentProviderClient +import android.content.ContentValues +import android.database.MatrixCursor +import android.database.sqlite.SQLiteDatabase +import android.net.Uri +import android.os.RemoteException +import com.nhaarman.mockito_kotlin.* +import fr.free.nrw.commons.BuildConfig +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.Utils +import fr.free.nrw.commons.contributions.Contribution.* +import fr.free.nrw.commons.contributions.ContributionDao.Table +import fr.free.nrw.commons.contributions.ContributionsContentProvider.BASE_URI +import fr.free.nrw.commons.contributions.ContributionsContentProvider.uriForId +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import java.util.* + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = [21], application = TestCommonsApplication::class) +class ContributionDaoTest { + private val localUri = "http://example.com/" + private val client: ContentProviderClient = mock() + private val database: SQLiteDatabase = mock() + private val captor = argumentCaptor() + + private lateinit var contentUri: Uri + private lateinit var testObject: ContributionDao + + @Before + fun setUp() { + contentUri = uriForId(111) + testObject = ContributionDao { client } + } + + @Test + fun createTable() { + Table.onCreate(database) + verify(database).execSQL(Table.CREATE_TABLE_STATEMENT) + } + + @Test + fun deleteTable() { + Table.onDelete(database) + + inOrder(database) { + verify(database).execSQL(Table.DROP_TABLE_STATEMENT) + verify(database).execSQL(Table.CREATE_TABLE_STATEMENT) + } + } + + @Test + fun upgradeDatabase_v1_to_v2() { + Table.onUpdate(database, 1, 2) + + inOrder(database) { + verify(database).execSQL(Table.ADD_DESCRIPTION_FIELD) + verify(database).execSQL(Table.ADD_CREATOR_FIELD) + } + } + + @Test + fun upgradeDatabase_v2_to_v3() { + Table.onUpdate(database, 2, 3) + + inOrder(database) { + verify(database).execSQL(Table.ADD_MULTIPLE_FIELD) + verify(database).execSQL(Table.SET_DEFAULT_MULTIPLE) + } + } + + @Test + fun upgradeDatabase_v3_to_v4() { + Table.onUpdate(database, 3, 4) + + // No changes + verifyZeroInteractions(database) + } + + @Test + fun upgradeDatabase_v4_to_v5() { + Table.onUpdate(database, 4, 5) + + // No changes + verifyZeroInteractions(database) + } + + @Test + fun upgradeDatabase_v5_to_v6() { + Table.onUpdate(database, 5, 6) + + inOrder(database) { + verify(database).execSQL(Table.ADD_WIDTH_FIELD) + verify(database).execSQL(Table.SET_DEFAULT_WIDTH) + verify(database).execSQL(Table.ADD_HEIGHT_FIELD) + verify(database).execSQL(Table.SET_DEFAULT_HEIGHT) + verify(database).execSQL(Table.ADD_LICENSE_FIELD) + verify(database).execSQL(Table.SET_DEFAULT_LICENSE) + } + } + + @Test + fun saveNewContribution_nonNullFields() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(true, null, null, null, null) + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + captor.firstValue.let { + // Long fields + assertEquals(222L, it.getAsLong(Table.COLUMN_LENGTH)) + assertEquals(321L, it.getAsLong(Table.COLUMN_TIMESTAMP)) + assertEquals(333L, it.getAsLong(Table.COLUMN_TRANSFERRED)) + + // Integer fields + assertEquals(STATE_COMPLETED, it.getAsInteger(Table.COLUMN_STATE)) + assertEquals(640, it.getAsInteger(Table.COLUMN_WIDTH)) + assertEquals(480, it.getAsInteger(Table.COLUMN_HEIGHT)) + + // String fields + assertEquals(SOURCE_CAMERA, it.getAsString(Table.COLUMN_SOURCE)) + assertEquals("desc", it.getAsString(Table.COLUMN_DESCRIPTION)) + assertEquals("create", it.getAsString(Table.COLUMN_CREATOR)) + assertEquals("007", it.getAsString(Table.COLUMN_LICENSE)) + } + } + + @Test + fun saveNewContribution_nullableFieldsAreNull() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(true, null, null, null, null) + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + captor.firstValue.let { + // Nullable fields are absent if null + assertFalse(it.containsKey(Table.COLUMN_LOCAL_URI)) + assertFalse(it.containsKey(Table.COLUMN_IMAGE_URL)) + assertFalse(it.containsKey(Table.COLUMN_UPLOADED)) + } + } + + @Test + fun saveNewContribution_nullableImageUrlUsesFileAsBackup() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(true, null, null, null, "file") + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + captor.firstValue.let { + // Nullable fields are absent if null + assertFalse(it.containsKey(Table.COLUMN_LOCAL_URI)) + assertFalse(it.containsKey(Table.COLUMN_UPLOADED)) + assertEquals(Utils.makeThumbBaseUrl("file"), it.getAsString(Table.COLUMN_IMAGE_URL)) + } + } + + @Test + fun saveNewContribution_nullableFieldsAreNonNull() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(true, Uri.parse(localUri), + "image", Date(456L), null) + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + captor.firstValue.let { + assertEquals(localUri, it.getAsString(Table.COLUMN_LOCAL_URI)) + assertEquals("image", it.getAsString(Table.COLUMN_IMAGE_URL)) + assertEquals(456L, it.getAsLong(Table.COLUMN_UPLOADED)) + } + } + + @Test + fun saveNewContribution_booleanEncodesTrue() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(true, null, null, null, null) + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + + // Boolean true --> 1 for ths encoding scheme + assertEquals("Boolean true should be encoded as 1", 1, + captor.firstValue.getAsInteger(Table.COLUMN_MULTIPLE)) + } + + @Test + fun saveNewContribution_booleanEncodesFalse() { + whenever(client.insert(isA(), isA())).thenReturn(contentUri) + val contribution = createContribution(false, null, null, null, null) + + testObject.save(contribution) + + assertEquals(contentUri, contribution.contentUri) + verify(client).insert(eq(BASE_URI), captor.capture()) + + // Boolean true --> 1 for ths encoding scheme + assertEquals("Boolean false should be encoded as 0", 0, + captor.firstValue.getAsInteger(Table.COLUMN_MULTIPLE)) + } + + @Test + fun saveExistingContribution() { + val contribution = createContribution(false, null, null, null, null) + contribution.contentUri = contentUri + + testObject.save(contribution) + + verify(client).update(eq(contentUri), isA(), isNull(), isNull()) + } + + @Test(expected = RuntimeException::class) + fun saveTranslatesExceptions() { + whenever(client.insert(isA(), isA())).thenThrow(RemoteException("")) + + testObject.save(createContribution(false, null, null, null, null)) + } + + @Test(expected = RuntimeException::class) + fun deleteTranslatesExceptions() { + whenever(client.delete(anyOrNull(), anyOrNull(), anyOrNull())).thenThrow(RemoteException("")) + + val contribution = createContribution(false, null, null, null, null) + contribution.contentUri = contentUri + testObject.delete(contribution) + } + + @Test(expected = RuntimeException::class) + fun exceptionThrownWhenAttemptingToDeleteUnsavedContribution() { + testObject.delete(createContribution(false, null, null, null, null)) + } + + @Test + fun deleteExistingContribution() { + val contribution = createContribution(false, null, null, null, null) + contribution.contentUri = contentUri + + testObject.delete(contribution) + + verify(client).delete(eq(contentUri), isNull(), isNull()) + } + + @Test + fun createFromCursor() { + val created = 321L + val uploaded = 456L + createCursor(created, uploaded, false, localUri).let { mc -> + testObject.fromCursor(mc).let { + assertEquals(uriForId(111), it.contentUri) + assertEquals("file", it.filename) + assertEquals(localUri, it.localUri.toString()) + assertEquals("image", it.imageUrl) + assertEquals(created, it.timestamp.time) + assertEquals(created, it.dateCreated.time) + assertEquals(STATE_QUEUED, it.state) + assertEquals(222L, it.dataLength) + assertEquals(uploaded, it.dateUploaded?.time) + assertEquals(88L, it.transferred) + assertEquals(SOURCE_GALLERY, it.source) + assertEquals("desc", it.description) + assertEquals("create", it.creator) + assertEquals(640, it.width) + assertEquals(480, it.height) + assertEquals("007", it.license) + } + } + } + + @Test + fun createFromCursor_nullableTimestamps() { + createCursor(0L, 0L, false, localUri).let { mc -> + testObject.fromCursor(mc).let { + assertNull(it.timestamp) + assertNull(it.dateCreated) + assertNull(it.dateUploaded) + } + } + } + + @Test + fun createFromCursor_nullableLocalUri() { + createCursor(0L, 0L, false, "").let { mc -> + testObject.fromCursor(mc).let { + assertNull(it.localUri) + assertNull(it.dateCreated) + assertNull(it.dateUploaded) + } + } + } + + @Test + fun createFromCursor_booleanEncoding() { + val mcFalse = createCursor(0L, 0L, false, localUri) + assertFalse(testObject.fromCursor(mcFalse).multiple) + + val mcHammer = createCursor(0L, 0L, true, localUri) + assertTrue(testObject.fromCursor(mcHammer).multiple) + } + + private fun createCursor(created: Long, uploaded: Long, multiple: Boolean, localUri: String) = + MatrixCursor(Table.ALL_FIELDS, 1).apply { + addRow(listOf("111", "file", localUri, "image", + created, STATE_QUEUED, 222L, uploaded, 88L, SOURCE_GALLERY, "desc", + "create", if (multiple) 1 else 0, 640, 480, "007")) + moveToFirst() + } + + private fun createContribution(isMultiple: Boolean, localUri: Uri?, imageUrl: String?, dateUploaded: Date?, filename: String?) = + Contribution(localUri, imageUrl, filename, "desc", 222L, Date(321L), dateUploaded, + "create", "edit", "coords").apply { + state = STATE_COMPLETED + transferred = 333L + source = SOURCE_CAMERA + license = "007" + multiple = isMultiple + timestamp = Date(321L) + width = 640 + height = 480 // VGA should be enough for anyone, right? + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.kt new file mode 100644 index 000000000..bf0ddf772 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/modifications/ModifierSequenceDaoTest.kt @@ -0,0 +1,156 @@ +package fr.free.nrw.commons.modifications + +import android.content.ContentProviderClient +import android.content.ContentValues +import android.database.MatrixCursor +import android.database.sqlite.SQLiteDatabase +import android.net.Uri +import android.os.RemoteException +import com.nhaarman.mockito_kotlin.* +import fr.free.nrw.commons.BuildConfig +import fr.free.nrw.commons.TestCommonsApplication +import fr.free.nrw.commons.modifications.ModificationsContentProvider.BASE_URI +import fr.free.nrw.commons.modifications.ModifierSequenceDao.Table.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = [21], application = TestCommonsApplication::class) +class ModifierSequenceDaoTest { + + private val mediaUrl = "http://example.com/" + private val columns = arrayOf(COLUMN_ID, COLUMN_MEDIA_URI, COLUMN_DATA) + private val client: ContentProviderClient = mock() + private val database: SQLiteDatabase = mock() + private val contentValuesCaptor = argumentCaptor() + + private lateinit var testObject: ModifierSequenceDao + + @Before + fun setUp() { + testObject = ModifierSequenceDao { client } + } + + @Test + fun createFromCursorWithEmptyModifiers() { + testObject.fromCursor(createCursor("")).let { + assertEquals(mediaUrl, it.mediaUri.toString()) + assertEquals(BASE_URI.buildUpon().appendPath("1").toString(), it.contentUri.toString()) + assertTrue(it.modifiers.isEmpty()) + } + } + + @Test + fun createFromCursorWtihCategoryModifier() { + val cursor = createCursor("{\"name\": \"CategoriesModifier\", \"data\": {}}") + + val seq = testObject.fromCursor(cursor) + + assertEquals(1, seq.modifiers.size) + assertTrue(seq.modifiers[0] is CategoryModifier) + } + + @Test + fun createFromCursorWithRemoveModifier() { + val cursor = createCursor("{\"name\": \"TemplateRemoverModifier\", \"data\": {}}") + + val seq = testObject.fromCursor(cursor) + + assertEquals(1, seq.modifiers.size) + assertTrue(seq.modifiers[0] is TemplateRemoveModifier) + } + + @Test + fun deleteSequence() { + whenever(client.delete(isA(), isNull(), isNull())).thenReturn(1) + val seq = testObject.fromCursor(createCursor("")) + + testObject.delete(seq) + + verify(client).delete(eq(seq.contentUri), isNull(), isNull()) + } + + @Test(expected = RuntimeException::class) + fun deleteTranslatesRemoteExceptions() { + whenever(client.delete(isA(), isNull(), isNull())).thenThrow(RemoteException("")) + val seq = testObject.fromCursor(createCursor("")) + + testObject.delete(seq) + } + + @Test + fun saveExistingSequence() { + val modifierJson = "{\"name\":\"CategoriesModifier\",\"data\":{}}" + val expectedData = "{\"modifiers\":[$modifierJson]}" + val cursor = createCursor(modifierJson) + val seq = testObject.fromCursor(cursor) + + testObject.save(seq) + + verify(client).update(eq(seq.contentUri), contentValuesCaptor.capture(), isNull(), isNull()) + contentValuesCaptor.firstValue.let { + assertEquals(2, it.size()) + assertEquals(mediaUrl, it.get(COLUMN_MEDIA_URI)) + assertEquals(expectedData, it.get(COLUMN_DATA)) + } + } + + @Test + fun saveNewSequence() { + val expectedContentUri = BASE_URI.buildUpon().appendPath("1").build() + whenever(client.insert(isA(), isA())).thenReturn(expectedContentUri) + val seq = ModifierSequence(Uri.parse(mediaUrl)) + + testObject.save(seq) + + assertEquals(expectedContentUri.toString(), seq.contentUri.toString()) + verify(client).insert(eq(ModificationsContentProvider.BASE_URI), contentValuesCaptor.capture()) + contentValuesCaptor.firstValue.let { + assertEquals(2, it.size()) + assertEquals(mediaUrl, it.get(COLUMN_MEDIA_URI)) + assertEquals("{\"modifiers\":[]}", it.get(COLUMN_DATA)) + } + } + + @Test(expected = RuntimeException::class) + fun saveTranslatesRemoteExceptions() { + whenever(client.insert(isA(), isA())).thenThrow(RemoteException("")) + testObject.save(ModifierSequence(Uri.parse(mediaUrl))) + } + + @Test + fun createTable() { + onCreate(database) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + + @Test + fun updateTable() { + onUpdate(database, 1, 2) + + inOrder(database) { + verify(database).execSQL(DROP_TABLE_STATEMENT) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + } + + @Test + fun deleteTable() { + onDelete(database) + + inOrder(database) { + verify(database).execSQL(DROP_TABLE_STATEMENT) + verify(database).execSQL(CREATE_TABLE_STATEMENT) + } + } + + private fun createCursor(modifierJson: String) = MatrixCursor(columns, 1).apply { + addRow(listOf("1", mediaUrl, "{\"modifiers\": [$modifierJson]}")) + moveToFirst() + } +} \ No newline at end of file diff --git a/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt new file mode 100644 index 000000000..c51d354c2 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApiTest.kt @@ -0,0 +1,246 @@ +package fr.free.nrw.commons.mwapi + +import android.content.SharedPreferences +import android.os.Build +import android.preference.PreferenceManager +import fr.free.nrw.commons.BuildConfig +import fr.free.nrw.commons.TestCommonsApplication +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest +import org.junit.After +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import org.robolectric.annotation.Config +import java.net.URLDecoder +import java.util.* + +@RunWith(RobolectricTestRunner::class) +@Config(constants = BuildConfig::class, sdk = intArrayOf(21), application = TestCommonsApplication::class) +class ApacheHttpClientMediaWikiApiTest { + + private lateinit var testObject: ApacheHttpClientMediaWikiApi + private lateinit var server: MockWebServer + private lateinit var sharedPreferences: SharedPreferences + + @Before + fun setUp() { + server = MockWebServer() + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(RuntimeEnvironment.application) + testObject = ApacheHttpClientMediaWikiApi(RuntimeEnvironment.application, "http://" + server.hostName + ":" + server.port + "/", sharedPreferences) + testObject.setWikiMediaToolforgeUrl("http://" + server.hostName + ":" + server.port + "/") + } + + @After + fun teardown() { + server.shutdown() + } + + @Test + fun authCookiesAreHandled() { + assertEquals("", testObject.authCookie) + + testObject.authCookie = "cookie=chocolate-chip" + + assertEquals("cookie=chocolate-chip", testObject.authCookie) + } + + @Test + fun simpleLoginWithWrongPassword() { + server.enqueue(MockResponse().setBody("")) + server.enqueue(MockResponse().setBody("")) + + val result = testObject.login("foo", "bar") + + assertBasicRequestParameters(server, "POST").let { loginTokenRequest -> + parseBody(loginTokenRequest.body.readUtf8()).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("login", body["type"]) + assertEquals("tokens", body["meta"]) + } + } + + assertBasicRequestParameters(server, "POST").let { loginRequest -> + parseBody(loginRequest.body.readUtf8()).let { body -> + assertEquals("1", body["rememberMe"]) + assertEquals("foo", body["username"]) + assertEquals("bar", body["password"]) + assertEquals("baz", body["logintoken"]) + assertEquals("https://commons.wikimedia.org", body["loginreturnurl"]) + assertEquals("xml", body["format"]) + } + } + + assertEquals("wrongpassword", result) + } + + @Test + fun simpleLogin() { + server.enqueue(MockResponse().setBody("")) + server.enqueue(MockResponse().setBody("")) + + val result = testObject.login("foo", "bar") + + assertBasicRequestParameters(server, "POST").let { loginTokenRequest -> + parseBody(loginTokenRequest.body.readUtf8()).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("login", body["type"]) + assertEquals("tokens", body["meta"]) + } + } + + assertBasicRequestParameters(server, "POST").let { loginRequest -> + parseBody(loginRequest.body.readUtf8()).let { body -> + assertEquals("1", body["rememberMe"]) + assertEquals("foo", body["username"]) + assertEquals("bar", body["password"]) + assertEquals("baz", body["logintoken"]) + assertEquals("https://commons.wikimedia.org", body["loginreturnurl"]) + assertEquals("xml", body["format"]) + } + } + + assertEquals("PASS", result) + } + + @Test + fun twoFactorLogin() { + server.enqueue(MockResponse().setBody("")) + server.enqueue(MockResponse().setBody("")) + + val result = testObject.login("foo", "bar", "2fa") + + assertBasicRequestParameters(server, "POST").let { loginTokenRequest -> + parseBody(loginTokenRequest.body.readUtf8()).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("login", body["type"]) + assertEquals("tokens", body["meta"]) + } + } + + assertBasicRequestParameters(server, "POST").let { loginRequest -> + parseBody(loginRequest.body.readUtf8()).let { body -> + assertEquals("true", body["rememberMe"]) + assertEquals("foo", body["username"]) + assertEquals("bar", body["password"]) + assertEquals("baz", body["logintoken"]) + assertEquals("true", body["logincontinue"]) + assertEquals("2fa", body["OATHToken"]) + assertEquals("xml", body["format"]) + } + } + + assertEquals("PASS", result) + } + + @Test + fun validateLoginForLoggedInUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.validateLogin() + + assertBasicRequestParameters(server, "GET").let { loginTokenRequest -> + parseQueryParams(loginTokenRequest).let { body -> + assertEquals("xml", body["format"]) + assertEquals("query", body["action"]) + assertEquals("userinfo", body["meta"]) + } + } + + assertTrue(result) + } + + @Test + fun validateLoginForLoggedOutUser() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.validateLogin() + + assertBasicRequestParameters(server, "GET").let { loginTokenRequest -> + parseQueryParams(loginTokenRequest).let { params -> + assertEquals("xml", params["format"]) + assertEquals("query", params["action"]) + assertEquals("userinfo", params["meta"]) + } + } + + assertFalse(result) + } + + @Test + fun editToken() { + server.enqueue(MockResponse().setBody("")) + + val result = testObject.editToken + + assertBasicRequestParameters(server, "GET").let { loginTokenRequest -> + parseQueryParams(loginTokenRequest).let { params -> + assertEquals("xml", params["format"]) + assertEquals("tokens", params["action"]) + assertEquals("edit", params["type"]) + } + } + + assertEquals("baz", result) + } + + @Test + fun fileExistsWithName_FileNotFound() { + server.enqueue(MockResponse().setBody(" ")) + + val result = testObject.fileExistsWithName("foo") + + assertBasicRequestParameters(server, "GET").let { request -> + parseQueryParams(request).let { params -> + assertEquals("xml", params["format"]) + assertEquals("query", params["action"]) + assertEquals("imageinfo", params["prop"]) + assertEquals("File:foo", params["titles"]) + } + } + + assertFalse(result) + } + + @Test + fun getUploadCount() { + server.enqueue(MockResponse().setBody("23\n")) + + val testObserver = testObject.getUploadCount("testUsername").test() + + assertEquals("testUsername", parseQueryParams(server.takeRequest())["user"]) + assertEquals(1, testObserver.valueCount()) + assertEquals(23, testObserver.values()[0]) + } + + private fun assertBasicRequestParameters(server: MockWebServer, method: String): RecordedRequest = server.takeRequest().let { + assertEquals("/", it.requestUrl.encodedPath()) + assertEquals(method, it.method) + assertEquals("Commons/${BuildConfig.VERSION_NAME} (https://mediawiki.org/wiki/Apps/Commons) Android/${Build.VERSION.RELEASE}", + it.getHeader("User-Agent")) + if ("POST" == method) { + assertEquals("application/x-www-form-urlencoded", it.getHeader("Content-Type")) + } + return it + } + + private fun parseQueryParams(request: RecordedRequest) = HashMap().apply { + request.requestUrl.let { + it.queryParameterNames().forEach { name -> put(name, it.queryParameter(name)) } + } + } + + private fun parseBody(body: String): Map = HashMap().apply { + body.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray().forEach { prop -> + val pair = prop.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + put(pair[0], URLDecoder.decode(pair[1], "utf-8")) + } + } +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/utils/StringSortingUtilsTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/utils/StringSortingUtilsTest.kt new file mode 100644 index 000000000..83e2f7169 --- /dev/null +++ b/app/src/test/kotlin/fr/free/nrw/commons/utils/StringSortingUtilsTest.kt @@ -0,0 +1,41 @@ +package fr.free.nrw.commons.utils + +import fr.free.nrw.commons.utils.StringSortingUtils.sortBySimilarity +import org.junit.Assert.assertEquals +import org.junit.Test +import java.util.Collections.sort + +class StringSortingUtilsTest { + + @Test + fun testSortingNumbersBySimilarity() { + val actualList = listOf("1234567", "4567", "12345", "123", "1234") + val expectedList = listOf("1234", "12345", "123", "1234567", "4567") + + sort(actualList, sortBySimilarity("1234")) + + assertEquals(expectedList, actualList) + } + + @Test + fun testSortingTextBySimilarity() { + val actualList = listOf("The quick brown fox", + "quick brown fox", + "The", + "The quick ", + "The fox", + "brown fox", + "fox") + val expectedList = listOf("The", + "The fox", + "The quick ", + "The quick brown fox", + "quick brown fox", + "brown fox", + "fox") + + sort(actualList, sortBySimilarity("The")) + + assertEquals(expectedList, actualList) + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index b0e8b6718..42dfeec75 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.1.51' + ext.kotlin_version = '1.2.31' repositories { jcenter() mavenCentral()