diff --git a/app/build.gradle b/app/build.gradle index 567ac156c..aa9cb5411 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -676,8 +676,8 @@ dependencies { implementation ComponentsDependencies.androidx_paging implementation ComponentsDependencies.androidx_preferences implementation ComponentsDependencies.androidx_fragment - implementation FenixDependencies.androidx_navigation_fragment - implementation FenixDependencies.androidx_navigation_ui + implementation ComponentsDependencies.androidx_navigation_fragment + implementation ComponentsDependencies.androidx_navigation_ui implementation ComponentsDependencies.androidx_compose_navigation implementation ComponentsDependencies.androidx_recyclerview diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml index b4ce2b38e..c9eb994da 100644 --- a/app/lint-baseline.xml +++ b/app/lint-baseline.xml @@ -1101,6 +1101,16 @@ column="1"/> + + + + + + + + diff --git a/app/messaging-evergreen-messages.fml.yaml b/app/messaging-evergreen-messages.fml.yaml index 927fb8bee..faeb27232 100644 --- a/app/messaging-evergreen-messages.fml.yaml +++ b/app/messaging-evergreen-messages.fml.yaml @@ -25,6 +25,7 @@ import: - value: messages: default-browser: + title: default_browser_experiment_card_title text: default_browser_experiment_card_text surface: homescreen action: "MAKE_DEFAULT_BROWSER" diff --git a/app/metrics.yaml b/app/metrics.yaml index 92a892dc6..636f46ff2 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -843,6 +843,17 @@ events: metadata: tags: - Search + first_session_ping_cancelled: + type: event + description: | + First session ping cancelled because Adjust metrics were empty. + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1875514 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/5223 + notification_emails: + - android-probes@mozilla.com + expires: never splash_screen: first_launch_extended: @@ -1061,78 +1072,6 @@ onboarding: metadata: tags: - Onboarding - notif_ppp_impression: - type: event - description: | - Notification pre permission prompt was shown to the user. - bugs: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1810115 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/28529 - - https://github.com/mozilla-mobile/firefox-android/pull/4039 - data_sensitivity: - - interaction - notification_emails: - - android-probes@mozilla.com - expires: never - metadata: - tags: - - Notifications - - Onboarding - notif_ppp_close_click: - type: event - description: | - User clicked the close button on the notification pre permission prompt. - bugs: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1810115 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/28529 - - https://github.com/mozilla-mobile/firefox-android/pull/4039 - data_sensitivity: - - interaction - notification_emails: - - android-probes@mozilla.com - expires: never - metadata: - tags: - - Notifications - - Onboarding - notif_ppp_positive_btn_click: - type: event - description: | - User clicked the positive button on notification pre permission prompt. - bugs: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1810115 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/28529 - - https://github.com/mozilla-mobile/firefox-android/pull/4039 - data_sensitivity: - - interaction - notification_emails: - - android-probes@mozilla.com - expires: never - metadata: - tags: - - Notifications - - Onboarding - notif_ppp_negative_btn_click: - type: event - description: | - User clicked the negative button on notification pre permission prompt. - bugs: - - https://bugzilla.mozilla.org/show_bug.cgi?id=1810115 - data_reviews: - - https://github.com/mozilla-mobile/fenix/pull/28529 - - https://github.com/mozilla-mobile/firefox-android/pull/4039 - data_sensitivity: - - interaction - notification_emails: - - android-probes@mozilla.com - expires: never - metadata: - tags: - - Notifications - - Onboarding set_to_default_card: type: event description: | @@ -9265,8 +9204,10 @@ awesomebar: A sponsored suggestion was visible when the user finished interacting with the awesomebar. bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1871156 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1878434 data_reviews: - https://github.com/mozilla-mobile/firefox-android/pull/4914#issuecomment-1874271848 + - https://github.com/mozilla-mobile/firefox-android/pull/5438#issuecomment-1930970336 data_sensitivity: - interaction notification_emails: @@ -9277,12 +9218,6 @@ awesomebar: expires: never extra_keys: provider: *sponsored_suggestion_provider - engagement_abandoned: &awesomebar_engagement_abandoned - description: | - If `true`, the user dismissed the awesomebar without navigating to a destination. If - `false`, the user finished engaging with the awesomebar by navigating to a destination, - like a URL, a search results page, or a suggestion. - type: boolean metadata: tags: - Search @@ -9292,8 +9227,10 @@ awesomebar: A non-sponsored suggestion was visible when the user finished interacting with the awesomebar. bugs: - https://bugzilla.mozilla.org/show_bug.cgi?id=1871156 + - https://bugzilla.mozilla.org/show_bug.cgi?id=1878434 data_reviews: - https://github.com/mozilla-mobile/firefox-android/pull/4914#issuecomment-1874271848 + - https://github.com/mozilla-mobile/firefox-android/pull/5438#issuecomment-1930970336 data_sensitivity: - interaction notification_emails: @@ -9304,10 +9241,49 @@ awesomebar: expires: never extra_keys: provider: *non_sponsored_suggestion_provider - engagement_abandoned: *awesomebar_engagement_abandoned metadata: tags: - Search + engagement: + type: event + description: | + The user completed their search session by tapping a search result, + or entering a URL or a search term. + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1878434 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/5438#issuecomment-1930970336 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - lina@mozilla.com + - ttran@mozilla.com + - najiang@mozilla.com + expires: never + metadata: + tags: + - Search + abandonment: + type: event + description: | + The user dismissed the awesomebar without completing their search. + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1878434 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/5438#issuecomment-1930970336 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + - lina@mozilla.com + - ttran@mozilla.com + - najiang@mozilla.com + expires: never + metadata: + tags: + - Search + android_autofill: supported: type: boolean @@ -11414,3 +11390,19 @@ fx_suggest: expires: never send_in_pings: - fx-suggest +debug_drawer: + debug_drawer_enabled: + type: boolean + description: | + Whether or not the user has enabled the Debug Drawer feature. + send_in_pings: + - metrics + bugs: + - https://bugzilla.mozilla.org/show_bug.cgi?id=1876596 + data_reviews: + - https://github.com/mozilla-mobile/firefox-android/pull/5356 + data_sensitivity: + - interaction + notification_emails: + - android-probes@mozilla.com + expires: never diff --git a/app/nimbus.fml.yaml b/app/nimbus.fml.yaml index 946012bee..b0a7dd423 100644 --- a/app/nimbus.fml.yaml +++ b/app/nimbus.fml.yaml @@ -32,6 +32,7 @@ import: - value: available-suggestion-types: { "amp": true, + "ampMobile": false, "wikipedia": true, } @@ -238,14 +239,6 @@ features: type: Int default: 0 - pre-permission-notification-prompt: - description: A feature that shows the pre-permission notification prompt. - variables: - enabled: - description: if true, the pre-permission notification prompt is shown to the user. - type: Boolean - default: false - onboarding: description: "A feature that configures the new user onboarding page. Note that onboarding is a **first run** feature, and should only be modified by first run experiments." diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt index 4ef27f9e9..bc10b79ab 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt @@ -14,11 +14,11 @@ import android.content.pm.PackageManager import android.content.res.Configuration import android.net.Uri import android.os.Build +import android.os.Environment import android.os.storage.StorageManager import android.os.storage.StorageVolume import android.provider.Settings import android.util.Log -import androidx.annotation.RequiresApi import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.test.espresso.Espresso import androidx.test.espresso.IdlingRegistry @@ -33,6 +33,7 @@ import androidx.test.uiautomator.UiObject import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import junit.framework.AssertionFailedError +import kotlinx.coroutines.runBlocking import org.junit.Assert import org.junit.Assert.assertEquals import org.mozilla.fenix.Config @@ -60,46 +61,88 @@ object AppAndSystemHelper { } } - @RequiresApi(Build.VERSION_CODES.R) + /** + * Checks if a specific download file is inside the device storage and deletes it. + * Different implementation needed for newer API levels, + * as Environment.getExternalStorageDirectory() is deprecated starting with API 29. + * + */ fun deleteDownloadedFileOnStorage(fileName: String) { - val storageManager: StorageManager? = TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager? - val storageVolumes = storageManager!!.storageVolumes - val storageVolume: StorageVolume = storageVolumes[0] - val file = File(storageVolume.directory!!.path + "/Download/" + fileName) - try { - if (file.exists()) { + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + val storageManager: StorageManager? = + TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager? + val storageVolumes = storageManager!!.storageVolumes + val storageVolume: StorageVolume = storageVolumes[0] + val file = File(storageVolume.directory!!.path + "/Download/" + fileName) + try { + if (file.exists()) { + file.delete() + Log.d("TestLog", "File delete try 1") + Assert.assertFalse("The file was not deleted", file.exists()) + } + } catch (e: AssertionError) { file.delete() - Log.d("TestLog", "File delete try 1") + Log.d("TestLog", "File delete retried") Assert.assertFalse("The file was not deleted", file.exists()) } - } catch (e: AssertionError) { - file.delete() - Log.d("TestLog", "File delete retried") - Assert.assertFalse("The file was not deleted", file.exists()) + } else { + runBlocking { + val downloadedFile = File( + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), + fileName, + ) + + if (downloadedFile.exists()) { + Log.i(TAG, "deleteDownloadedFileOnStorage: Verifying if $downloadedFile exists.") + downloadedFile.delete() + Log.i(TAG, "deleteDownloadedFileOnStorage: $downloadedFile deleted.") + } + } } } - @RequiresApi(Build.VERSION_CODES.R) + /** + * Checks if there are download files inside the device storage and deletes all of them. + * Different implementation needed for newer API levels, as + * Environment.getExternalStorageDirectory() is deprecated starting with API 29. + */ fun clearDownloadsFolder() { - val storageManager: StorageManager? = TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager? - val storageVolumes = storageManager!!.storageVolumes - val storageVolume: StorageVolume = storageVolumes[0] - val downloadsFolder = File(storageVolume.directory!!.path + "/Download/") - - // Check if the downloads folder exists - if (downloadsFolder.exists() && downloadsFolder.isDirectory) { - Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists") - val files = downloadsFolder.listFiles() - - // Check if the folder is not empty - if (files != null && files.isNotEmpty()) { - Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder is not empty") - // Delete all files in the folder - for (file in files) { - file.delete() - Log.i(TAG, "clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder") + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + Log.i(TAG, "clearDownloadsFolder: API > 29") + val storageManager: StorageManager? = + TestHelper.appContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager? + val storageVolumes = storageManager!!.storageVolumes + val storageVolume: StorageVolume = storageVolumes[0] + val downloadsFolder = File(storageVolume.directory!!.path + "/Download/") + + // Check if the downloads folder exists + if (downloadsFolder.exists() && downloadsFolder.isDirectory) { + Log.i(TAG, "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder exists") + val files = downloadsFolder.listFiles() + + // Check if the folder is not empty + if (files != null && files.isNotEmpty()) { + Log.i( + TAG, + "clearDownloadsFolder: Verified that \"DOWNLOADS\" folder is not empty", + ) + // Delete all files in the folder + for (file in files) { + file.delete() + Log.i(TAG, "clearDownloadsFolder: Deleted $file from \"DOWNLOADS\" folder") + } } } + } else { + runBlocking { + Log.i(TAG, "clearDownloadsFolder: API <= 29") + Log.i(TAG, "clearDownloadsFolder: Verifying if any download files exist.") + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + .listFiles()?.forEach { + it.delete() + Log.i(TAG, "clearDownloadsFolder: Download file $it deleted.") + } + } } } @@ -135,11 +178,12 @@ object AppAndSystemHelper { } fun isPackageInstalled(packageName: String): Boolean { + Log.i(TAG, "isPackageInstalled: Trying to verify that $packageName is installed") return try { val packageManager = InstrumentationRegistry.getInstrumentation().context.packageManager packageManager.getApplicationInfo(packageName, 0).enabled } catch (e: PackageManager.NameNotFoundException) { - Log.i(TAG, "isPackageInstalled: Catch block - ${e.message}") + Log.i(TAG, "isPackageInstalled: $packageName is not installed - ${e.message}") false } } @@ -183,6 +227,7 @@ object AppAndSystemHelper { * @return Boolean value that helps us know if the current activity supports custom tabs or PWAs. */ fun isExternalAppBrowserActivityInCurrentTask(): Boolean { + Log.i(TAG, "Trying to verify that the latest activity of the application is used for custom tabs or PWAs") val activityManager = TestHelper.appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager mDevice.waitForIdle(TestAssetHelper.waitingTimeShort) diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/Experimentation.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/Experimentation.kt index 3b4ba4ee1..34f4d15e6 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/Experimentation.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/Experimentation.kt @@ -4,7 +4,7 @@ package org.mozilla.fenix.helpers -import org.mozilla.experiments.nimbus.GleanPlumbMessageHelper +import org.mozilla.experiments.nimbus.NimbusMessagingHelperInterface import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.TestHelper.appContext @@ -12,7 +12,7 @@ object Experimentation { val experiments = appContext.components.analytics.experiments - fun withHelper(block: GleanPlumbMessageHelper.() -> Unit) { + fun withHelper(block: NimbusMessagingHelperInterface.() -> Unit) { val helper = experiments.createMessageHelper() block(helper) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt index d638e762f..fb90e772f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestAssetHelper.kt @@ -17,6 +17,7 @@ object TestAssetHelper { val waitingTime: Long = TimeUnit.SECONDS.toMillis(15) val waitingTimeLong = TimeUnit.SECONDS.toMillis(25) val waitingTimeShort: Long = TimeUnit.SECONDS.toMillis(3) + val waitingTimeVeryShort: Long = TimeUnit.SECONDS.toMillis(1) data class TestAsset(val url: Uri, val content: String, val title: String) diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt index 06bc94ee6..2a06b0990 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestHelper.kt @@ -34,9 +34,12 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.TAG +import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists +import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeVeryShort import org.mozilla.fenix.helpers.ext.waitNotNull import org.mozilla.fenix.ui.robots.clickPageObject @@ -49,8 +52,10 @@ object TestHelper { fun scrollToElementByText(text: String): UiScrollable { val appView = UiScrollable(UiSelector().scrollable(true)) + Log.i(TAG, "scrollToElementByText: Waiting for app view") appView.waitForExists(waitingTime) appView.scrollTextIntoView(text) + Log.i(TAG, "scrollToElementByText: Scrolled to element with text: $text") return appView } @@ -101,14 +106,7 @@ object TestHelper { ).waitUntilGone(waitingTime) } - fun verifySnackBarText(expectedText: String) { - assertTrue( - mDevice.findObject( - UiSelector() - .textContains(expectedText), - ).waitForExists(waitingTime), - ) - } + fun verifySnackBarText(expectedText: String) = assertUIObjectExists(itemContainingText(expectedText)) fun verifyUrl(urlSubstring: String, resourceName: String, resId: Int) { waitUntilObjectIsFound(resourceName) @@ -145,4 +143,10 @@ object TestHelper { assertFalse("Light theme not selected", expected) fun verifyDarkThemeApplied(expected: Boolean) = assertTrue("Dark theme not selected", expected) + + fun waitForAppWindowToBeUpdated() { + Log.i(TAG, "waitForAppWindowToBeUpdated: Waiting for $waitingTimeVeryShort ms for $packageName window to be updated") + mDevice.waitForWindowUpdate(packageName, waitingTimeVeryShort) + Log.i(TAG, "waitForAppWindowToBeUpdated: Waited for $waitingTimeVeryShort ms for $packageName window to be updated") + } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/helpers/TestSetup.kt b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestSetup.kt new file mode 100644 index 000000000..b080154c4 --- /dev/null +++ b/app/src/androidTest/java/org/mozilla/fenix/helpers/TestSetup.kt @@ -0,0 +1,52 @@ +package org.mozilla.fenix.helpers + +import android.util.Log +import kotlinx.coroutines.runBlocking +import mozilla.appservices.places.BookmarkRoot +import mozilla.components.browser.storage.sync.PlacesBookmarksStorage +import okhttp3.mockwebserver.MockWebServer +import org.junit.Before +import org.mozilla.fenix.helpers.Constants.TAG +import org.mozilla.fenix.helpers.TestHelper.appContext +import org.mozilla.fenix.ui.robots.notificationShade + +open class TestSetup { + lateinit var mockWebServer: MockWebServer + private val bookmarksStorage = PlacesBookmarksStorage(appContext.applicationContext) + + @Before + fun setUp() { + Log.i(TAG, "TestSetup: Starting the @Before setup") + // Clear pre-existing notifications + notificationShade { + cancelAllShownNotifications() + } + runBlocking { + // Reset locale to EN-US if needed. + AppAndSystemHelper.resetSystemLocaleToEnUS() + // Check and clear the downloads folder + AppAndSystemHelper.clearDownloadsFolder() + // Make sure the Wifi and Mobile Data connections are on + AppAndSystemHelper.setNetworkEnabled(true) + // Clear bookmarks left after a failed test + val bookmarks = bookmarksStorage.getTree(BookmarkRoot.Mobile.id)?.children + Log.i(TAG, "Before cleanup: Bookmarks storage contains: $bookmarks") + bookmarks?.forEach { + bookmarksStorage.deleteNode(it.guid) + // TODO: Follow-up with a method to handle the DB update; the logs will still show the bookmarks in the storage before the test starts. + Log.i(TAG, "After cleanup: Bookmarks storage contains: $bookmarks") + } + } + mockWebServer = MockWebServer().apply { + dispatcher = AndroidAssetDispatcher() + } + try { + Log.i(TAG, "Try starting mockWebServer") + mockWebServer.start() + } catch (e: Exception) { + Log.i(TAG, "Exception caught. Re-starting mockWebServer") + mockWebServer.shutdown() + mockWebServer.start() + } + } +} diff --git a/app/src/androidTest/java/org/mozilla/fenix/syncintegration/Pipfile.lock b/app/src/androidTest/java/org/mozilla/fenix/syncintegration/Pipfile.lock index 3e3d538a0..b42b86bfb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/syncintegration/Pipfile.lock +++ b/app/src/androidTest/java/org/mozilla/fenix/syncintegration/Pipfile.lock @@ -95,7 +95,7 @@ "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" ], - "markers": "python_version >= '3.8'", + "markers": "platform_python_implementation != 'PyPy'", "version": "==1.16.0" }, "charset-normalizer": { @@ -196,33 +196,42 @@ }, "cryptography": { "hashes": [ - "sha256:068bc551698c234742c40049e46840843f3d98ad7ce265fd2bd4ec0d11306596", - "sha256:0f27acb55a4e77b9be8d550d762b0513ef3fc658cd3eb15110ebbcbd626db12c", - "sha256:2132d5865eea673fe6712c2ed5fb4fa49dba10768bb4cc798345748380ee3660", - "sha256:3288acccef021e3c3c10d58933f44e8602cf04dba96d9796d70d537bb2f4bbc4", - "sha256:35f3f288e83c3f6f10752467c48919a7a94b7d88cc00b0668372a0d2ad4f8ead", - "sha256:398ae1fc711b5eb78e977daa3cbf47cec20f2c08c5da129b7a296055fbb22aed", - "sha256:422e3e31d63743855e43e5a6fcc8b4acab860f560f9321b0ee6269cc7ed70cc3", - "sha256:48783b7e2bef51224020efb61b42704207dde583d7e371ef8fc2a5fb6c0aabc7", - "sha256:4d03186af98b1c01a4eda396b137f29e4e3fb0173e30f885e27acec8823c1b09", - "sha256:5daeb18e7886a358064a68dbcaf441c036cbdb7da52ae744e7b9207b04d3908c", - "sha256:60e746b11b937911dc70d164060d28d273e31853bb359e2b2033c9e93e6f3c43", - "sha256:742ae5e9a2310e9dade7932f9576606836ed174da3c7d26bc3d3ab4bd49b9f65", - "sha256:7e00fb556bda398b99b0da289ce7053639d33b572847181d6483ad89835115f6", - "sha256:85abd057699b98fce40b41737afb234fef05c67e116f6f3650782c10862c43da", - "sha256:8efb2af8d4ba9dbc9c9dd8f04d19a7abb5b49eab1f3694e7b5a16a5fc2856f5c", - "sha256:ae236bb8760c1e55b7a39b6d4d32d2279bc6c7c8500b7d5a13b6fb9fc97be35b", - "sha256:afda76d84b053923c27ede5edc1ed7d53e3c9f475ebaf63c68e69f1403c405a8", - "sha256:b27a7fd4229abef715e064269d98a7e2909ebf92eb6912a9603c7e14c181928c", - "sha256:b648fe2a45e426aaee684ddca2632f62ec4613ef362f4d681a9a6283d10e079d", - "sha256:c5a550dc7a3b50b116323e3d376241829fd326ac47bc195e04eb33a8170902a9", - "sha256:da46e2b5df770070412c46f87bac0849b8d685c5f2679771de277a422c7d0b86", - "sha256:f39812f70fc5c71a15aa3c97b2bbe213c3f2a460b79bd21c40d033bb34a9bf36", - "sha256:ff369dd19e8fe0528b02e8df9f2aeb2479f89b1270d90f96a63500afe9af5cae" + "sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b", + "sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd", + "sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94", + "sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221", + "sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e", + "sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513", + "sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d", + "sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc", + "sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0", + "sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2", + "sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87", + "sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01", + "sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0", + "sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4", + "sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b", + "sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81", + "sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3", + "sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4", + "sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf", + "sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec", + "sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce", + "sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0", + "sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f", + "sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f", + "sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3", + "sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689", + "sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08", + "sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139", + "sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434", + "sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17", + "sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8", + "sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440" ], "index": "pypi", "markers": "python_version >= '3.7'", - "version": "==41.0.6" + "version": "==42.0.0" }, "distro": { "hashes": [ diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/AddressAutofillTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/AddressAutofillTest.kt index 4631b8a7a..b8b675778 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/AddressAutofillTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/AddressAutofillTest.kt @@ -4,27 +4,22 @@ package org.mozilla.fenix.ui -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.packageName +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.autofillScreen import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar -class AddressAutofillTest { - private lateinit var mockWebServer: MockWebServer - +class AddressAutofillTest : TestSetup() { object FirstAddressAutofillDetails { var navigateToAutofillSettings = true var isAddressAutofillEnabled = true @@ -58,19 +53,6 @@ class AddressAutofillTest { @get:Rule val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides() - @Before - fun setUp() { - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1836845 @SmokeTest @Test diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt index e99e0fc12..8b7b220ce 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/BookmarksTest.kt @@ -8,20 +8,13 @@ import androidx.compose.ui.test.junit4.AndroidComposeTestRule import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.Espresso.pressBack import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation -import androidx.test.uiautomator.UiDevice import kotlinx.coroutines.runBlocking -import mozilla.appservices.places.BookmarkRoot -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.R import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.ext.bookmarkStorage import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.MockBrowserDataHelper.createBookmarkItem @@ -31,7 +24,10 @@ import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.appContext import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem +import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.restartApp +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.bookmarksMenu import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen @@ -41,9 +37,7 @@ import org.mozilla.fenix.ui.robots.navigationToolbar /** * Tests for verifying basic functionality of bookmarks */ -class BookmarksTest { - private lateinit var mockWebServer: MockWebServer - private lateinit var mDevice: UiDevice +class BookmarksTest : TestSetup() { private val bookmarksFolderName = "New Folder" private val testBookmark = object { var title: String = "Bookmark title" @@ -60,26 +54,6 @@ class BookmarksTest { @JvmField val retryTestRule = RetryTestRule(3) - @Before - fun setUp() { - mDevice = UiDevice.getInstance(getInstrumentation()) - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - // Clearing all bookmarks data after each test to avoid overlapping data - val bookmarksStorage = activityTestRule.activity?.bookmarkStorage - runBlocking { - val bookmarks = bookmarksStorage?.getTree(BookmarkRoot.Mobile.id)?.children - bookmarks?.forEach { bookmarksStorage.deleteNode(it.guid) } - } - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/522919 @Test fun verifyEmptyBookmarksMenuTest() { @@ -137,7 +111,7 @@ class BookmarksTest { clickAddFolderButton() addNewFolderName(bookmarksFolderName) navigateUp() - verifyKeyboardHidden() + verifyKeyboardHidden(isExpectedToBeVisible = false) verifyBookmarkFolderIsNotCreated(bookmarksFolderName) } } @@ -209,7 +183,7 @@ class BookmarksTest { ) {} }.openThreeDotMenu(defaultWebPage.title) { }.clickCopy { - verifyCopySnackBarText() + verifySnackBarText(expectedText = "URL copied") navigateUp() } @@ -496,7 +470,7 @@ class BookmarksTest { } bookmarksMenu { - verifyDeleteMultipleBookmarksSnackBar() + verifySnackBarText(expectedText = "Bookmarks deleted") clickUndoDeleteButton() verifyBookmarkedURL(firstWebPage.url.toString()) verifyBookmarkedURL(secondWebPage.url.toString()) @@ -514,7 +488,7 @@ class BookmarksTest { } bookmarksMenu { - verifyDeleteMultipleBookmarksSnackBar() + verifySnackBarText(expectedText = "Bookmarks deleted") } } @@ -602,7 +576,7 @@ class BookmarksTest { RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list)), ) { longTapDesktopFolder("Desktop Bookmarks") - verifySelectDefaultFolderSnackBarText() + verifySnackBarText(expectedText = "Can’t edit default folders") } } } @@ -625,7 +599,7 @@ class BookmarksTest { cancelDeletion() clickDeleteInEditModeButton() confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") verifyBookmarkIsDeleted("Test_Page_1") } } @@ -786,13 +760,13 @@ class BookmarksTest { }.openThreeDotMenu("My Folder") { }.clickDelete { confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") clickUndoDeleteButton() verifyFolderTitle("My Folder") }.openThreeDotMenu("My Folder") { }.clickDelete { confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") verifyBookmarkIsDeleted("My Folder") verifyBookmarkIsDeleted("My Folder 2") verifyBookmarkIsDeleted("Test_Page_1") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt index de05a516a..608c0e919 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/BrowsingErrorPagesTest.kt @@ -5,20 +5,17 @@ package org.mozilla.fenix.ui import androidx.core.net.toUri -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mozilla.fenix.R import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.AppAndSystemHelper.setNetworkEnabled import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.navigationToolbar @@ -26,13 +23,12 @@ import org.mozilla.fenix.ui.robots.navigationToolbar /** * Tests that verify errors encountered while browsing websites: unsafe pages, connection errors, etc */ -class BrowsingErrorPagesTest { +class BrowsingErrorPagesTest : TestSetup() { private val malwareWarning = getStringResource(R.string.mozac_browser_errorpages_safe_browsing_malware_uri_title) private val phishingWarning = getStringResource(R.string.mozac_browser_errorpages_safe_phishing_uri_title) private val unwantedSoftwareWarning = getStringResource(R.string.mozac_browser_errorpages_safe_browsing_unwanted_uri_title) private val harmfulSiteWarning = getStringResource(R.string.mozac_browser_errorpages_safe_harmful_uri_title) - private lateinit var mockWebServer: MockWebServer @get: Rule val mActivityTestRule = HomeActivityTestRule.withDefaultSettingsOverrides() @@ -41,21 +37,6 @@ class BrowsingErrorPagesTest { @JvmField val retryTestRule = RetryTestRule(3) - @Before - fun setUp() { - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - // Restoring network connection - setNetworkEnabled(true) - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2326774 @SmokeTest @Test diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt index bf73f1682..74e7b136c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CollectionTest.kt @@ -5,19 +5,16 @@ package org.mozilla.fenix.ui import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.uiautomator.UiDevice -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton +import org.mozilla.fenix.helpers.TestHelper.mDevice +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.collectionRobot import org.mozilla.fenix.ui.robots.homeScreen @@ -29,9 +26,7 @@ import org.mozilla.fenix.ui.robots.tabDrawer * */ -class CollectionTest { - private lateinit var mDevice: UiDevice - private lateinit var mockWebServer: MockWebServer +class CollectionTest : TestSetup() { private val firstCollectionName = "testcollection_1" private val secondCollectionName = "testcollection_2" private val collectionName = "First Collection" @@ -50,20 +45,6 @@ class CollectionTest { ), ) { it.activity } - @Before - fun setUp() { - mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/353823 @SmokeTest @Test @@ -490,7 +471,7 @@ class CollectionTest { selectTab(secondWebPage.title, numOfTabs = 2) }.clickSaveCollection { typeCollectionNameAndSave(collectionName) - verifySnackBarText("Tabs saved!") + verifySnackBarText("Collection saved!") } tabDrawer { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeBookmarksTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeBookmarksTest.kt index dbfd9afda..26d31d920 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeBookmarksTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeBookmarksTest.kt @@ -28,6 +28,7 @@ import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.bookmarksMenu import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen @@ -111,7 +112,7 @@ class ComposeBookmarksTest { clickAddFolderButton() addNewFolderName(bookmarksFolderName) navigateUp() - verifyKeyboardHidden() + verifyKeyboardHidden(isExpectedToBeVisible = false) verifyBookmarkFolderIsNotCreated(bookmarksFolderName) } } @@ -183,7 +184,7 @@ class ComposeBookmarksTest { ) {} }.openThreeDotMenu(defaultWebPage.title) { }.clickCopy { - verifyCopySnackBarText() + verifySnackBarText(expectedText = "URL copied") navigateUp() } @@ -469,7 +470,7 @@ class ComposeBookmarksTest { } bookmarksMenu { - verifyDeleteMultipleBookmarksSnackBar() + verifySnackBarText(expectedText = "Bookmarks deleted") clickUndoDeleteButton() verifyBookmarkedURL(firstWebPage.url.toString()) verifyBookmarkedURL(secondWebPage.url.toString()) @@ -487,7 +488,7 @@ class ComposeBookmarksTest { } bookmarksMenu { - verifyDeleteMultipleBookmarksSnackBar() + verifySnackBarText(expectedText = "Bookmarks deleted") } } @@ -575,7 +576,7 @@ class ComposeBookmarksTest { RecyclerViewIdlingResource(activityTestRule.activity.findViewById(R.id.bookmark_list)), ) { longTapDesktopFolder("Desktop Bookmarks") - verifySelectDefaultFolderSnackBarText() + verifySnackBarText(expectedText = "Can’t edit default folders") } } } @@ -598,7 +599,7 @@ class ComposeBookmarksTest { cancelDeletion() clickDeleteInEditModeButton() confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") verifyBookmarkIsDeleted("Test_Page_1") } } @@ -764,13 +765,13 @@ class ComposeBookmarksTest { }.openThreeDotMenu("My Folder") { }.clickDelete { confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") clickUndoDeleteButton() verifyFolderTitle("My Folder") }.openThreeDotMenu("My Folder") { }.clickDelete { confirmDeletion() - verifyDeleteSnackBarText() + verifySnackBarText(expectedText = "Deleted") verifyBookmarkIsDeleted("My Folder") verifyBookmarkIsDeleted("My Folder 2") verifyBookmarkIsDeleted("Test_Page_1") diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeCollectionTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeCollectionTest.kt index 990b02c89..a18366cc7 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeCollectionTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeCollectionTest.kt @@ -475,7 +475,7 @@ class ComposeCollectionTest { verifyTabsMultiSelectionCounter(2) }.clickSaveCollection { typeCollectionNameAndSave(collectionName) - verifySnackBarText("Tabs saved!") + verifySnackBarText("Collection saved!") } composeTabDrawer(composeTestRule) { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeContextMenusTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeContextMenusTest.kt index 85a3e0c4c..5e554b49d 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeContextMenusTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeContextMenusTest.kt @@ -23,6 +23,7 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithText import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.clickContextMenuItem import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.downloadRobot diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeHistoryTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeHistoryTest.kt index 5a2fed714..138ffa7c3 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeHistoryTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeHistoryTest.kt @@ -28,6 +28,7 @@ import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.historyMenu import org.mozilla.fenix.ui.robots.homeScreen @@ -128,7 +129,7 @@ class ComposeHistoryTest { ) { clickDeleteHistoryButton(firstWebPage.url.toString()) } - verifyDeleteSnackbarText("Deleted") + verifySnackBarText(expectedText = "Deleted") verifyEmptyHistoryView() } } @@ -153,7 +154,7 @@ class ComposeHistoryTest { verifyDeleteConfirmationMessage() selectEverythingOption() confirmDeleteAllHistory() - verifyDeleteSnackbarText("Browsing data deleted") + verifySnackBarText(expectedText = "Browsing data deleted") verifyEmptyHistoryView() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeSearchTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeSearchTest.kt index 71391b522..27f46d84f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeSearchTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeSearchTest.kt @@ -31,6 +31,7 @@ import org.mozilla.fenix.helpers.SearchDispatcher import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.clickContextMenuItem import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen @@ -472,7 +473,7 @@ class ComposeSearchTest { }.openRecentlyVisitedSearchGroupHistoryList(queryString) { clickDeleteAllHistoryButton() confirmDeleteAllHistory() - verifyDeleteSnackbarText("Group deleted") + verifySnackBarText(expectedText = "Group deleted") verifyHistoryItemExists(shouldExist = false, firstPageUrl.toString()) }.goBack {} homeScreen { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeTopSitesTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeTopSitesTest.kt index 5168ef1c7..50bfadce1 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeTopSitesTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ComposeTopSitesTest.kt @@ -20,8 +20,10 @@ import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone import org.mozilla.fenix.ui.robots.browserScreen +import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.homeScreenWithComposeTopSites import org.mozilla.fenix.ui.robots.navigationToolbar @@ -66,8 +68,12 @@ class ComposeTopSitesTest { fun addAWebsiteAsATopSiteTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(true) @@ -84,8 +90,12 @@ class ComposeTopSitesTest { fun openTopSiteInANewTabTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(true) @@ -112,8 +122,12 @@ class ComposeTopSitesTest { fun openTopSiteInANewPrivateTabTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(true) @@ -135,6 +149,9 @@ class ComposeTopSitesTest { val defaultWebPage = getGenericAsset(mockWebServer, 1) val newPageTitle = generateRandomString(5) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { waitForPageToLoad() @@ -159,8 +176,12 @@ class ComposeTopSitesTest { fun removeTopSiteUsingMenuButtonTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(true) @@ -186,8 +207,12 @@ class ComposeTopSitesTest { fun removeTopSiteFromMainMenuTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreenWithComposeTopSites(composeTestRule) { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(true) @@ -236,9 +261,11 @@ class ComposeTopSitesTest { verifyExistingTopSitesList() verifyExistingTopSiteItem(defaultWebPage.title) }.openContextMenuOnTopSitesWithTitle(defaultWebPage.title) { - }.deleteTopSiteFromHistory { + }.removeTopSite { verifySnackBarText(getStringResource(R.string.snackbar_top_site_removed)) waitUntilSnackbarGone() + } + homeScreen { }.openThreeDotMenu { }.openHistory { verifyEmptyHistoryView() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt index 4e95fba11..80f2d2a75 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/ContextMenusTest.kt @@ -5,15 +5,8 @@ package org.mozilla.fenix.ui import androidx.core.net.toUri -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.uiautomator.UiDevice -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test -import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.AppAndSystemHelper.assertExternalAppOpens import org.mozilla.fenix.helpers.Constants.PackageName.YOUTUBE_APP import org.mozilla.fenix.helpers.HomeActivityIntentTestRule @@ -22,6 +15,9 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithText import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton +import org.mozilla.fenix.helpers.TestHelper.mDevice +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.clickContextMenuItem import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.downloadRobot @@ -43,32 +39,15 @@ import org.mozilla.fenix.ui.robots.shareOverlay * */ -class ContextMenusTest { - private lateinit var mDevice: UiDevice - private lateinit var mockWebServer: MockWebServer +class ContextMenusTest : TestSetup() { @get:Rule - val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides() + val activityIntentTestRule = HomeActivityIntentTestRule(isJumpBackInCFREnabled = false) @Rule @JvmField val retryTestRule = RetryTestRule(3) - @Before - fun setUp() { - activityIntentTestRule.activity.applicationContext.settings().shouldShowJumpBackInCFR = false - mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/243837 @Test fun verifyOpenLinkNewTabContextMenuOptionTest() { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CookieBannerBlockerTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CookieBannerBlockerTest.kt index 7ff48e390..cc9fff3d1 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CookieBannerBlockerTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CookieBannerBlockerTest.kt @@ -12,13 +12,14 @@ import org.mozilla.fenix.ext.settings import org.mozilla.fenix.helpers.AppAndSystemHelper.runWithCondition import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.TestHelper.appContext +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar /** * Tests for verifying the new Cookie banner blocker option and functionality. */ -class CookieBannerBlockerTest { +class CookieBannerBlockerTest : TestSetup() { @get:Rule val activityTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides(skipOnboarding = true) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CrashReportingTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CrashReportingTest.kt index f246930bd..be99ebe8a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CrashReportingTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CrashReportingTest.kt @@ -5,29 +5,23 @@ package org.mozilla.fenix.ui import androidx.compose.ui.test.junit4.AndroidComposeTestRule -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.uiautomator.UiDevice -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.mozilla.fenix.R import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.packageName +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar -class CrashReportingTest { - private lateinit var mDevice: UiDevice - private lateinit var mockWebServer: MockWebServer +class CrashReportingTest : TestSetup() { private val tabCrashMessage = getStringResource(R.string.tab_crash_title_2) @get:Rule @@ -40,20 +34,6 @@ class CrashReportingTest { ), ) { it.activity } - @Before - fun setUp() { - mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/308906 @Test fun closeTabFromCrashedTabReporterTest() { @@ -105,7 +85,7 @@ class CrashReportingTest { verifyPageContent(tabCrashMessage) }.openTabDrawer { verifyExistingOpenTabs(firstWebPage.title) - verifyExistingOpenTabs(secondWebPage.title) + verifyExistingOpenTabs("about:crashcontent") }.closeTabDrawer { }.goToHomescreen { verifyExistingTopSitesList() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CreditCardAutofillTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CreditCardAutofillTest.kt index f9eb0891b..9a9b5697b 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CreditCardAutofillTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CreditCardAutofillTest.kt @@ -4,13 +4,9 @@ package org.mozilla.fenix.ui -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.AppAndSystemHelper.bringAppToForeground import org.mozilla.fenix.helpers.AppAndSystemHelper.putAppToBackground import org.mozilla.fenix.helpers.HomeActivityIntentTestRule @@ -19,14 +15,13 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.packageName +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar import java.time.LocalDate -class CreditCardAutofillTest { - private lateinit var mockWebServer: MockWebServer - +class CreditCardAutofillTest : TestSetup() { object MockCreditCard1 { const val MOCK_CREDIT_CARD_NUMBER = "5555555555554444" const val MOCK_LAST_CARD_DIGITS = "4444" @@ -48,19 +43,6 @@ class CreditCardAutofillTest { @get:Rule val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides() - @Before - fun setUp() { - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/1512792 @SmokeTest @Test diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/CustomTabsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/CustomTabsTest.kt index b014dbb61..1e2aa93e8 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/CustomTabsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/CustomTabsTest.kt @@ -7,25 +7,20 @@ package org.mozilla.fenix.ui import androidx.core.net.toUri -import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.ActivityTestRule -import androidx.test.uiautomator.UiDevice -import okhttp3.mockwebserver.MockWebServer -import org.junit.After -import org.junit.Before import org.junit.Rule import org.junit.Test import org.mozilla.fenix.IntentReceiverActivity import org.mozilla.fenix.customannotations.SmokeTest -import org.mozilla.fenix.helpers.AndroidAssetDispatcher import org.mozilla.fenix.helpers.AppAndSystemHelper.openAppFromExternalLink import org.mozilla.fenix.helpers.DataGenerationHelper.createCustomTabIntent -import org.mozilla.fenix.helpers.FeatureSettingsHelperDelegate import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText import org.mozilla.fenix.helpers.MatcherHelper.itemWithText import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu +import org.mozilla.fenix.helpers.TestHelper.mDevice +import org.mozilla.fenix.helpers.TestSetup import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.customTabScreen @@ -36,9 +31,7 @@ import org.mozilla.fenix.ui.robots.notificationShade import org.mozilla.fenix.ui.robots.openEditURLView import org.mozilla.fenix.ui.robots.searchScreen -class CustomTabsTest { - private lateinit var mDevice: UiDevice - private lateinit var mockWebServer: MockWebServer +class CustomTabsTest : TestSetup() { private val customMenuItem = "TestMenuItem" private val customTabActionButton = "CustomActionButton" @@ -58,23 +51,6 @@ class CustomTabsTest { false, ) - private val featureSettingsHelper = FeatureSettingsHelperDelegate() - - @Before - fun setUp() { - mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()) - mockWebServer = MockWebServer().apply { - dispatcher = AndroidAssetDispatcher() - start() - } - } - - @After - fun tearDown() { - mockWebServer.shutdown() - featureSettingsHelper.resetAllFeatureFlags() - } - // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/249659 @SmokeTest @Test diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/FirefoxSuggestTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/FirefoxSuggestTest.kt index b019b8c39..ae384d063 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/FirefoxSuggestTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/FirefoxSuggestTest.kt @@ -48,9 +48,9 @@ class FirefoxSuggestTest { "Nike.com - Official Site", "nike.com/?cp=16423867261_search_318370984us128${getSponsoredFxSuggestPlaceHolder()}&mfadid=adm", ), - "Macy" to listOf( - "macys.com - Official Site", - "macys.com/?cm_mmc=Google_AdMarketPlace-_-Privacy_Instant%20Suggest-_-319101130_Broad-_-kclickid__kenshoo_clickid_&m_sc=sem&m_sb=Admarketplace&m_tp=Search&m_ac=Admarketplace&m_ag=Instant%20Suggest&m_cn=Privacy&m_pi=kclickid__kenshoo_clickid__319101130us1201${getSponsoredFxSuggestPlaceHolder()}&mfadid=adm", + "Houzz" to listOf( + "Houzz.com - Official Site", + "houzz.com/products?m_refid=us-dsp-mpl-admp-219577_15416306_kwd-353208810&adcid=319104989us1287${getSponsoredFxSuggestPlaceHolder()}&mfadid=adm", ), "Spanx" to listOf( "SPANX® - Official Site", @@ -101,7 +101,7 @@ class FirefoxSuggestTest { private val nonSponsoredKeyWord = nonSponsoredKeyWords.keys.random() // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348361 - @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1874831") + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @SmokeTest @Test fun verifyFirefoxSuggestSponsoredSearchResultsTest() { @@ -123,7 +123,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348362 - @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1874831") + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Test fun verifyFirefoxSuggestSponsoredSearchResultsWithPartialKeywordTest() { runWithCondition(TestHelper.appContext.settings().enableFxSuggest) { @@ -144,7 +144,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348363 - @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1874831") + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Test fun openFirefoxSuggestSponsoredSearchResultsTest() { runWithCondition(TestHelper.appContext.settings().enableFxSuggest) { @@ -168,7 +168,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348369 - @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1874831") + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Test fun verifyFirefoxSuggestSponsoredSearchResultsWithEditedKeywordTest() { runWithCondition(TestHelper.appContext.settings().enableFxSuggest) { @@ -192,6 +192,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348374 + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1882035") @SmokeTest @Test @@ -219,6 +220,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348375 + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1882035") @Test fun verifyFirefoxSuggestNonSponsoredSearchResultsWithPartialKeywordTest() { @@ -239,6 +241,7 @@ class FirefoxSuggestTest { } // TestRail link: https://testrail.stage.mozaws.net/index.php?/cases/view/2348376 + // Known bug that might affect this UI test: https://bugzilla.mozilla.org/show_bug.cgi?id=1813587 @Ignore("Failing, see: https://bugzilla.mozilla.org/show_bug.cgi?id=1882035") @Test fun openFirefoxSuggestNonSponsoredSearchResultsTest() { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt index ec76f4419..f29372c63 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/HistoryTest.kt @@ -29,6 +29,7 @@ import org.mozilla.fenix.helpers.RecyclerViewIdlingResource import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.historyMenu import org.mozilla.fenix.ui.robots.homeScreen @@ -131,7 +132,7 @@ class HistoryTest { clickUndoDeleteButton() verifyHistoryItemExists(true, firstWebPage.url.toString()) clickDeleteHistoryButton(firstWebPage.url.toString()) - verifyDeleteSnackbarText("Deleted") + verifySnackBarText(expectedText = "Deleted") verifyEmptyHistoryView() } } @@ -161,7 +162,7 @@ class HistoryTest { verifyDeleteConfirmationMessage() selectEverythingOption() confirmDeleteAllHistory() - verifyDeleteSnackbarText("Browsing data deleted") + verifySnackBarText(expectedText = "Browsing data deleted") verifyEmptyHistoryView() } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt index a725fd33d..394c449eb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/LoginsTest.kt @@ -28,6 +28,7 @@ import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.helpers.TestHelper.restartApp import org.mozilla.fenix.helpers.TestHelper.scrollToElementByText import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText +import org.mozilla.fenix.helpers.TestHelper.waitForAppWindowToBeUpdated import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clearTextFieldItem import org.mozilla.fenix.ui.robots.clickPageObject @@ -260,12 +261,16 @@ class LoginsTest { navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { setPageObjectText(itemWithResId("username"), firstUser) + waitForAppWindowToBeUpdated() setPageObjectText(itemWithResId("password"), firstPass) + waitForAppWindowToBeUpdated() clickPageObject(itemWithResId("submit")) verifySaveLoginPromptIsDisplayed() clickPageObject(itemWithText("Save")) setPageObjectText(itemWithResId("username"), secondUser) + waitForAppWindowToBeUpdated() setPageObjectText(itemWithResId("password"), secondPass) + waitForAppWindowToBeUpdated() clickPageObject(itemWithResId("submit")) verifySaveLoginPromptIsDisplayed() clickPageObject(itemWithText("Save")) @@ -505,9 +510,13 @@ class LoginsTest { navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { + waitForPageToLoad() setPageObjectText(itemWithResId("username"), "mozilla") + waitForAppWindowToBeUpdated() setPageObjectText(itemWithResId("password"), "firefox") + waitForAppWindowToBeUpdated() clickPageObject(itemWithResId("submit")) + waitForPageToLoad() verifySaveLoginPromptIsDisplayed() clickPageObject(itemWithText("Save")) }.openTabDrawer { @@ -516,6 +525,8 @@ class LoginsTest { navigationToolbar { }.enterURLAndEnterToBrowser(loginPage.toUri()) { + waitForPageToLoad() + clickPageObject(itemWithResId("togglePassword")) verifyPrefilledLoginCredentials("mozilla", "firefox", true) }.openTabDrawer { closeTab() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt index fa871f779..24a877737 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/MainMenuTest.kt @@ -175,21 +175,21 @@ class MainMenuTest { verifyFindInPagePrevButton() verifyFindInPageCloseButton() enterFindInPageQuery("a") - verifyFindNextInPageResult("1/3") + verifyFindInPageResult("1/3") clickFindInPageNextButton() - verifyFindNextInPageResult("2/3") + verifyFindInPageResult("2/3") clickFindInPageNextButton() - verifyFindNextInPageResult("3/3") + verifyFindInPageResult("3/3") clickFindInPagePrevButton() - verifyFindPrevInPageResult("2/3") + verifyFindInPageResult("2/3") clickFindInPagePrevButton() - verifyFindPrevInPageResult("1/3") + verifyFindInPageResult("1/3") }.closeFindInPageWithCloseButton { verifyFindInPageBar(false) }.openThreeDotMenu { }.openFindInPage { enterFindInPageQuery("3") - verifyFindNextInPageResult("1/1") + verifyFindInPageResult("1/1") }.closeFindInPageWithBackButton { verifyFindInPageBar(false) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt index 5ea9084c6..eba6aad2e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/MediaNotificationTest.kt @@ -20,6 +20,7 @@ import org.mozilla.fenix.helpers.HomeActivityTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemWithText import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/PDFViewerTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/PDFViewerTest.kt index 7b07993a2..340cbd08e 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/PDFViewerTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/PDFViewerTest.kt @@ -117,17 +117,17 @@ class PDFViewerTest { verifyFindInPagePrevButton() verifyFindInPageCloseButton() enterFindInPageQuery("l") - verifyFindNextInPageResult("1/2") + verifyFindInPageResult("1/2") clickFindInPageNextButton() - verifyFindNextInPageResult("2/2") + verifyFindInPageResult("2/2") clickFindInPagePrevButton() - verifyFindPrevInPageResult("1/2") + verifyFindInPageResult("1/2") }.closeFindInPageWithCloseButton { verifyFindInPageBar(false) }.openThreeDotMenu { }.openFindInPage { enterFindInPageQuery("p") - verifyFindNextInPageResult("1/1") + verifyFindInPageResult("1/1") }.closeFindInPageWithBackButton { verifyFindInPageBar(false) } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt index 0a5686c03..d1d0076cd 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SearchTest.kt @@ -44,6 +44,7 @@ import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton import org.mozilla.fenix.helpers.TestHelper.exitMenu import org.mozilla.fenix.helpers.TestHelper.longTapSelectItem import org.mozilla.fenix.helpers.TestHelper.mDevice +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.clickContextMenuItem import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen @@ -487,7 +488,7 @@ class SearchTest { }.openRecentlyVisitedSearchGroupHistoryList(queryString) { clickDeleteAllHistoryButton() confirmDeleteAllHistory() - verifyDeleteSnackbarText("Group deleted") + verifySnackBarText("Group deleted") verifyHistoryItemExists(shouldExist = false, firstPageUrl.toString()) }.goBack {} homeScreen { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt index f11f87783..86b0b1752 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsAdvancedTest.kt @@ -38,7 +38,6 @@ class SettingsAdvancedTest { private val youTubeFullLink = itemContainingText("Youtube full link") private val playStoreLink = itemContainingText("Playstore link") private val playStoreUrl = "play.google.com" - private val youTubePage = "vnd.youtube://".toUri() @get:Rule val activityIntentTestRule = HomeActivityIntentTestRule.withDefaultSettingsOverrides() @@ -159,11 +158,10 @@ class SettingsAdvancedTest { navigationToolbar { }.enterURLAndEnterToBrowser(externalLinksPage.url) { - clickPageObject(youTubeFullLink) + clickPageObject(youTubeSchemaLink) verifyOpenLinkInAnotherAppPrompt() clickPageObject(itemWithResIdAndText("android:id/button2", "CANCEL")) - waitForPageToLoad() - verifyUrl("youtube") + verifyUrl(externalLinksPage.url.toString()) } } @@ -226,14 +224,13 @@ class SettingsAdvancedTest { navigationToolbar { }.enterURLAndEnterToBrowser(externalLinksPage.url) { - clickPageObject(youTubeFullLink) + clickPageObject(youTubeSchemaLink) verifyPrivateBrowsingOpenLinkInAnotherAppPrompt( url = "youtube", - pageObject = youTubeFullLink, + pageObject = youTubeSchemaLink, ) clickPageObject(itemWithResIdAndText("android:id/button2", "CANCEL")) - waitForPageToLoad() - verifyUrl("youtube") + verifyUrl(externalLinksPage.url.toString()) } } @@ -311,7 +308,7 @@ class SettingsAdvancedTest { } navigationToolbar { - }.enterURLAndEnterToBrowser(youTubePage) { + }.enterURLAndEnterToBrowser("https://m.youtube.com/".toUri()) { waitForPageToLoad() verifyOpenLinksInAppsCFRExists(true) clickOpenLinksInAppsDismissCFRButton() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsHomepageTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsHomepageTest.kt index 4c525f096..bc4a78a9f 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsHomepageTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/SettingsHomepageTest.kt @@ -18,6 +18,7 @@ import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.restartApp +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen import org.mozilla.fenix.ui.robots.navigationToolbar diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt index d09ac4e0c..7072d6efa 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TabbedBrowsingTest.kt @@ -23,6 +23,7 @@ import org.mozilla.fenix.helpers.RetryTestRule import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestHelper.closeApp import org.mozilla.fenix.helpers.TestHelper.restartApp +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.clickPageObject import org.mozilla.fenix.ui.robots.homeScreen diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt index 7858a5224..a45320d36 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/TopSitesTest.kt @@ -20,6 +20,7 @@ import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.HomeActivityIntentTestRule import org.mozilla.fenix.helpers.TestAssetHelper.getGenericAsset import org.mozilla.fenix.helpers.TestHelper.clickSnackbarButton +import org.mozilla.fenix.helpers.TestHelper.verifySnackBarText import org.mozilla.fenix.helpers.TestHelper.waitUntilSnackbarGone import org.mozilla.fenix.ui.robots.browserScreen import org.mozilla.fenix.ui.robots.homeScreen @@ -61,8 +62,12 @@ class TopSitesTest { fun addAWebsiteAsATopSiteTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(shouldExist = true) @@ -79,8 +84,12 @@ class TopSitesTest { fun openTopSiteInANewTabTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(shouldExist = true) @@ -107,8 +116,12 @@ class TopSitesTest { fun openTopSiteInANewPrivateTabTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(shouldExist = true) @@ -130,6 +143,9 @@ class TopSitesTest { val defaultWebPage = getGenericAsset(mockWebServer, 1) val newPageTitle = generateRandomString(5) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { waitForPageToLoad() @@ -154,8 +170,12 @@ class TopSitesTest { fun removeTopSiteUsingMenuButtonTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(shouldExist = true) @@ -181,8 +201,12 @@ class TopSitesTest { fun removeTopSiteFromMainMenuTest() { val defaultWebPage = getGenericAsset(mockWebServer, 1) + homeScreen { + verifyExistingTopSitesList() + } navigationToolbar { }.enterURLAndEnterToBrowser(defaultWebPage.url) { + verifyPageContent(defaultWebPage.content) }.openThreeDotMenu { expandMenu() verifyAddToShortcutsButton(shouldExist = true) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt index 5d0c83e9a..f42941bbc 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/AddToHomeScreenRobot.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui.robots import android.os.Build +import android.util.Log import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.ComposeTestRule import androidx.compose.ui.test.onNodeWithTag @@ -13,6 +14,7 @@ import androidx.test.uiautomator.By import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId @@ -27,27 +29,47 @@ import java.util.regex.Pattern */ class AddToHomeScreenRobot { - fun verifyAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) = + fun verifyAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) { + Log.i(TAG, "verifyAddPrivateBrowsingShortcutButton: Trying to verify \"Add to Home screen\" private browsing shortcut dialog button is displayed") composeTestRule.onNodeWithTag("private.add").assertIsDisplayed() + Log.i(TAG, "verifyAddPrivateBrowsingShortcutButton: Verified \"Add to Home screen\" private browsing shortcut dialog button is displayed") + } - fun verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) = + fun verifyNoThanksPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) { + Log.i(TAG, "verifyNoThanksPrivateBrowsingShortcutButton: Trying to verify \"No thanks\" private browsing shortcut dialog button is displayed") composeTestRule.onNodeWithTag("private.cancel").assertIsDisplayed() + Log.i(TAG, "verifyNoThanksPrivateBrowsingShortcutButton: Verified \"No thanks\" private browsing shortcut dialog button is displayed") + } - fun clickAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) = + fun clickAddPrivateBrowsingShortcutButton(composeTestRule: ComposeTestRule) { + Log.i(TAG, "clickAddPrivateBrowsingShortcutButton: Trying to click \"Add to Home screen\" private browsing shortcut dialog button") composeTestRule.onNodeWithTag("private.add").performClick() + Log.i(TAG, "clickAddPrivateBrowsingShortcutButton: Clicked \"Add to Home screen\" private browsing shortcut dialog button") + } - fun addShortcutName(title: String) = shortcutTextField.setText(title) + fun addShortcutName(title: String) { + Log.i(TAG, "addShortcutName: Trying to set shortcut name to: $title") + shortcutTextField().setText(title) + Log.i(TAG, "addShortcutName: Set shortcut name to: $title") + } fun verifyShortcutTextFieldTitle(title: String) = assertUIObjectExists(shortcutTitle(title)) - fun clickAddShortcutButton() = - confirmAddToHomeScreenButton.clickAndWaitForNewWindow(waitingTime) + fun clickAddShortcutButton() { + Log.i(TAG, "clickAddShortcutButton: Trying to click \"Add\" button from \"Add to home screen\" dialog and wait for $waitingTime ms for a new window") + confirmAddToHomeScreenButton().clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickAddShortcutButton: Clicked \"Add\" button from \"Add to home screen\" dialog and waited for $waitingTime ms for a new window") + } - fun clickCancelShortcutButton() = - cancelAddToHomeScreenButton.click() + fun clickCancelShortcutButton() { + Log.i(TAG, "clickCancelShortcutButton: Trying to click \"Cancel\" button from \"Add to home screen\" dialog") + cancelAddToHomeScreenButton().click() + Log.i(TAG, "clickCancelShortcutButton: Clicked \"Cancel\" button from \"Add to home screen\" dialog") + } fun clickAddAutomaticallyButton() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Log.i(TAG, "clickAddAutomaticallyButton: Waiting for $waitingTime ms until finding \"Add automatically\" system dialog button") mDevice.wait( Until.findObject( By.text( @@ -56,7 +78,10 @@ class AddToHomeScreenRobot { ), waitingTime, ) + Log.i(TAG, "clickAddAutomaticallyButton: Waited for $waitingTime ms until \"Add automatically\" system dialog button was found") + Log.i(TAG, "clickAddAutomaticallyButton: Trying to click \"Add automatically\" system dialog button") addAutomaticallyButton().click() + Log.i(TAG, "clickAddAutomaticallyButton: Clicked \"Add automatically\" system dialog button") } } @@ -65,27 +90,37 @@ class AddToHomeScreenRobot { class Transition { fun openHomeScreenShortcut(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openHomeScreenShortcut: Waiting for $waitingTime ms until finding $title home screen shortcut") mDevice.wait( Until.findObject(By.text(title)), waitingTime, ) + Log.i(TAG, "openHomeScreenShortcut: Waited for $waitingTime ms until $title home screen shortcut was found") + Log.i(TAG, "openHomeScreenShortcut: Trying to click $title home screen shortcut and wait for $waitingTime ms for a new window") mDevice.findObject((UiSelector().text(title))).clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "openHomeScreenShortcut: Clicked $title home screen shortcut and waited for $waitingTime ms for a new window") BrowserRobot().interact() return BrowserRobot.Transition() } fun searchAndOpenHomeScreenShortcut(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Trying to press device home button") mDevice.pressHome() + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Pressed device home button") fun homeScreenView() = UiScrollable(UiSelector().scrollable(true)) + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Waiting for $waitingTime ms for home screen view to exist") homeScreenView().waitForExists(waitingTime) + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Waited for $waitingTime ms for home screen view to exist") fun shortcut() = homeScreenView() .setAsHorizontalList() .getChildByText(UiSelector().textContains(title), title, true) + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Trying to click home screen shortcut: $title and wait for a new window") shortcut().clickAndWaitForNewWindow() + Log.i(TAG, "searchAndOpenHomeScreenShortcut: Clicked home screen shortcut: $title and waited for a new window") BrowserRobot().interact() return BrowserRobot.Transition() @@ -101,11 +136,11 @@ fun addToHomeScreen(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenR private fun addAutomaticallyButton() = mDevice.findObject(UiSelector().textContains("add automatically")) -private val cancelAddToHomeScreenButton = +private fun cancelAddToHomeScreenButton() = itemWithResId("$packageName:id/cancel_button") -private val confirmAddToHomeScreenButton = +private fun confirmAddToHomeScreenButton() = itemWithResId("$packageName:id/add_button") -private val shortcutTextField = +private fun shortcutTextField() = itemWithResId("$packageName:id/shortcut_text") private fun shortcutTitle(title: String) = itemWithResIdAndText("$packageName:id/shortcut_text", title) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt index 7247f0075..48b73ced8 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BookmarksRobot.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.ui.robots import android.net.Uri +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.clearText import androidx.test.espresso.action.ViewActions.longClick @@ -32,6 +33,7 @@ import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.junit.Assert.assertEquals import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText @@ -40,7 +42,6 @@ import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdAndText import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText import org.mozilla.fenix.helpers.MatcherHelper.itemWithText -import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort import org.mozilla.fenix.helpers.TestHelper.mDevice @@ -54,51 +55,114 @@ import org.mozilla.fenix.helpers.ext.waitNotNull class BookmarksRobot { fun verifyBookmarksMenuView() { + Log.i(TAG, "verifyBookmarksMenuView: Waiting for $waitingTime ms for bookmarks view to exist") mDevice.findObject( UiSelector().text("Bookmarks"), ).waitForExists(waitingTime) - - assertBookmarksView() + Log.i(TAG, "verifyBookmarksMenuView: Waited for $waitingTime ms for bookmarks view to exist") + Log.i(TAG, "verifyBookmarksMenuView: Trying to verify bookmarks view is displayed") + onView( + allOf( + withText("Bookmarks"), + withParent(withId(R.id.navigationToolbar)), + ), + ).check(matches(isDisplayed())) + Log.i(TAG, "verifyBookmarksMenuView: Verified bookmarks view is displayed") } - fun verifyAddFolderButton() = assertAddFolderButton() - - fun verifyCloseButton() = assertCloseButton() + fun verifyAddFolderButton() { + Log.i(TAG, "verifyAddFolderButton: Trying to verify add bookmarks folder button is visible") + addFolderButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyAddFolderButton: Verified add bookmarks folder button is visible") + } - fun verifyDeleteMultipleBookmarksSnackBar() = assertSnackBarText("Bookmarks deleted") + fun verifyCloseButton() { + Log.i(TAG, "verifyCloseButton: Trying to verify close bookmarks section button is visible") + closeButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyCloseButton: Verified close bookmarks section button is visible") + } - fun verifyBookmarkFavicon(forUrl: Uri) = assertBookmarkFavicon(forUrl) + fun verifyBookmarkFavicon(forUrl: Uri) { + Log.i(TAG, "verifyBookmarkFavicon: Trying to verify bookmarks favicon for $forUrl is visible") + bookmarkFavicon(forUrl.toString()).check( + matches( + withEffectiveVisibility( + ViewMatchers.Visibility.VISIBLE, + ), + ), + ) + Log.i(TAG, "verifyBookmarkFavicon: Verified bookmarks favicon for $forUrl is visible") + } - fun verifyBookmarkedURL(url: String) = assertBookmarkURL(url) + fun verifyBookmarkedURL(url: String) { + Log.i(TAG, "verifyBookmarkedURL: Trying to verify bookmarks url: $url is displayed") + bookmarkURL(url).check(matches(isDisplayed())) + Log.i(TAG, "verifyBookmarkedURL: Verified bookmarks url: $url is displayed") + } fun verifyFolderTitle(title: String) { + Log.i(TAG, "verifyFolderTitle: Waiting for $waitingTime ms for bookmarks folder with title: $title to exist") mDevice.findObject(UiSelector().text(title)).waitForExists(waitingTime) - assertFolderTitle(title) + Log.i(TAG, "verifyFolderTitle: Waited for $waitingTime ms for bookmarks folder with title: $title to exist") + Log.i(TAG, "verifyFolderTitle: Trying to verify bookmarks folder with title: $title is displayed") + onView(withText(title)).check(matches(isDisplayed())) + Log.i(TAG, "verifyFolderTitle: Verified bookmarks folder with title: $title is displayed") } - fun verifyBookmarkFolderIsNotCreated(title: String) = assertBookmarkFolderIsNotCreated(title) + fun verifyBookmarkFolderIsNotCreated(title: String) { + Log.i(TAG, "verifyBookmarkFolderIsNotCreated: Waiting for $waitingTime ms for bookmarks folder with title: $title to exist") + mDevice.findObject( + UiSelector() + .resourceId("$packageName:id/bookmarks_wrapper"), + ).waitForExists(waitingTime) + Log.i(TAG, "verifyBookmarkFolderIsNotCreated: Waited for $waitingTime ms for bookmarks folder with title: $title to exist") + + assertUIObjectExists(itemContainingText(title), exists = false) + } fun verifyBookmarkTitle(title: String) { + Log.i(TAG, "verifyBookmarkTitle: Waiting for $waitingTime ms for bookmark with title: $title to exist") mDevice.findObject(UiSelector().text(title)).waitForExists(waitingTime) - assertBookmarkTitle(title) + Log.i(TAG, "verifyBookmarkTitle: Waited for $waitingTime ms for bookmark with title: $title to exist") + Log.i(TAG, "verifyBookmarkTitle: Trying to verify bookmark with title: $title is displayed") + onView(withText(title)).check(matches(isDisplayed())) + Log.i(TAG, "verifyBookmarkTitle: Verified bookmark with title: $title is displayed") } - fun verifyBookmarkIsDeleted(expectedTitle: String) = assertBookmarkIsDeleted(expectedTitle) - - fun verifyDeleteSnackBarText() = assertSnackBarText("Deleted") + fun verifyBookmarkIsDeleted(expectedTitle: String) { + Log.i(TAG, "verifyBookmarkIsDeleted: Waiting for $waitingTime ms for bookmarks view to exist") + mDevice.findObject( + UiSelector() + .resourceId("$packageName:id/bookmarks_wrapper"), + ).waitForExists(waitingTime) + Log.i(TAG, "verifyBookmarkIsDeleted: Waited for $waitingTime ms for bookmarks view to exist") + assertUIObjectExists( + itemWithResIdContainingText( + "$packageName:id/title", + expectedTitle, + ), + exists = false, + ) + } - fun verifyUndoDeleteSnackBarButton() = assertUndoDeleteSnackBarButton() + fun verifyUndoDeleteSnackBarButton() { + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Trying to verify bookmark deletion undo snack bar button") + snackBarUndoButton().check(matches(withText("UNDO"))) + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Verified bookmark deletion undo snack bar button") + } fun verifySnackBarHidden() { + Log.i(TAG, "verifySnackBarHidden: Waiting until undo snack bar button is gone") mDevice.waitNotNull( Until.gone(By.text("UNDO")), - TestAssetHelper.waitingTime, + waitingTime, ) + Log.i(TAG, "verifySnackBarHidden: Waited until undo snack bar button was gone") + Log.i(TAG, "verifySnackBarHidden: Trying to verify bookmark snack bar does not exist") onView(withId(R.id.snackbar_layout)).check(doesNotExist()) + Log.i(TAG, "verifySnackBarHidden: Verified bookmark snack bar does not exist") } - fun verifyCopySnackBarText() = assertSnackBarText("URL copied") - fun verifyEditBookmarksView() = assertUIObjectExists( itemWithDescription("Navigate up"), @@ -110,27 +174,50 @@ class BookmarksRobot { itemWithResId("$packageName:id/bookmarkParentFolderSelector"), ) - fun verifyKeyboardHidden() = assertKeyboardVisibility(isExpectedToBeVisible = false) - - fun verifyKeyboardVisible() = assertKeyboardVisibility(isExpectedToBeVisible = true) - - fun verifyShareOverlay() = assertShareOverlay() + fun verifyKeyboardHidden(isExpectedToBeVisible: Boolean) { + Log.i(TAG, "assertKeyboardVisibility: Trying to verify that the keyboard is visible: $isExpectedToBeVisible") + assertEquals( + isExpectedToBeVisible, + mDevice + .executeShellCommand("dumpsys input_method | grep mInputShown") + .contains("mInputShown=true"), + ) + Log.i(TAG, "assertKeyboardVisibility: Verified that the keyboard is visible: $isExpectedToBeVisible") + } - fun verifyShareBookmarkFavicon() = assertShareBookmarkFavicon() + fun verifyShareOverlay() { + Log.i(TAG, "verifyShareOverlay: Trying to verify bookmarks sharing overlay is displayed") + onView(withId(R.id.shareWrapper)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareOverlay: Verified bookmarks sharing overlay is displayed") + } - fun verifyShareBookmarkTitle() = assertShareBookmarkTitle() + fun verifyShareBookmarkFavicon() { + Log.i(TAG, "verifyShareBookmarkFavicon: Trying to verify shared bookmarks favicon is displayed") + onView(withId(R.id.share_tab_favicon)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareBookmarkFavicon: Verified shared bookmarks favicon is displayed") + } - fun verifyShareBookmarkUrl() = assertShareBookmarkUrl() + fun verifyShareBookmarkTitle() { + Log.i(TAG, "verifyShareBookmarkTitle: Trying to verify shared bookmarks title is displayed") + onView(withId(R.id.share_tab_title)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareBookmarkTitle: Verified shared bookmarks title is displayed") + } - fun verifySelectDefaultFolderSnackBarText() = assertSnackBarText("Can’t edit default folders") + fun verifyShareBookmarkUrl() { + Log.i(TAG, "verifyShareBookmarkUrl: Trying to verify shared bookmarks url is displayed") + onView(withId(R.id.share_tab_url)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareBookmarkUrl: Verified shared bookmarks url is displayed") + } fun verifyCurrentFolderTitle(title: String) { + Log.i(TAG, "verifyCurrentFolderTitle: Waiting for $waitingTime ms for bookmark with title: $title to exist") mDevice.findObject( UiSelector().resourceId("$packageName:id/navigationToolbar") .textContains(title), ) .waitForExists(waitingTime) - + Log.i(TAG, "verifyCurrentFolderTitle: Waited for $waitingTime ms for bookmark with title: $title to exist") + Log.i(TAG, "verifyCurrentFolderTitle: Trying to verify bookmark with title: $title is displayed") onView( allOf( withText(title), @@ -138,28 +225,34 @@ class BookmarksRobot { ), ) .check(matches(isDisplayed())) + Log.i(TAG, "verifyCurrentFolderTitle: Verified bookmark with title: $title is displayed") } fun waitForBookmarksFolderContentToExist(parentFolderName: String, childFolderName: String) { + Log.i(TAG, "waitForBookmarksFolderContentToExist: Waiting for $waitingTime ms for navigation toolbar containing bookmark folder with title: $parentFolderName to exist") mDevice.findObject( UiSelector().resourceId("$packageName:id/navigationToolbar") .textContains(parentFolderName), ) .waitForExists(waitingTime) + Log.i(TAG, "waitForBookmarksFolderContentToExist: Waited for $waitingTime ms for navigation toolbar containing bookmark folder with title: $parentFolderName to exist") mDevice.waitNotNull(Until.findObject(By.text(childFolderName)), waitingTime) } - fun verifySyncSignInButton() = + fun verifySyncSignInButton() { + Log.i(TAG, "verifySyncSignInButton: Trying to verify sign in to sync button is visible") syncSignInButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - - fun verifyDeleteFolderConfirmationMessage() = assertDeleteFolderConfirmationMessage() + Log.i(TAG, "verifySyncSignInButton: Verified sign in to sync button is visible") + } fun cancelFolderDeletion() { + Log.i(TAG, "cancelFolderDeletion: Trying to click \"Cancel\" bookmarks folder deletion dialog button") onView(withText("CANCEL")) .inRoot(RootMatchers.isDialog()) .check(matches(isDisplayed())) .click() + Log.i(TAG, "cancelFolderDeletion: Clicked \"Cancel\" bookmarks folder deletion dialog button") } fun createFolder(name: String, parent: String? = null) { @@ -180,90 +273,127 @@ class BookmarksRobot { fun clickAddFolderButton() { mDevice.waitNotNull( Until.findObject(By.desc("Add folder")), - TestAssetHelper.waitingTime, + waitingTime, ) + Log.i(TAG, "clickAddFolderButton: Trying to click add bookmarks folder button") addFolderButton().click() + Log.i(TAG, "clickAddFolderButton: Clicked add bookmarks folder button") } - fun clickAddNewFolderButtonFromSelectFolderView() = + fun clickAddNewFolderButtonFromSelectFolderView() { itemWithResId("$packageName:id/add_folder_button") .also { + Log.i(TAG, "clickAddNewFolderButtonFromSelectFolderView: Waiting for $waitingTime ms for add bookmarks folder button from folder selection view to exist") it.waitForExists(waitingTime) + Log.i(TAG, "clickAddNewFolderButtonFromSelectFolderView: Waited for $waitingTime ms for add bookmarks folder button from folder selection view to exist") + Log.i(TAG, "clickAddNewFolderButtonFromSelectFolderView: Trying to click add bookmarks folder button from folder selection view") it.click() + Log.i(TAG, "clickAddNewFolderButtonFromSelectFolderView: Clicked add bookmarks folder button from folder selection view") } + } fun addNewFolderName(name: String) { - addFolderTitleField() - .click() - .perform(replaceText(name)) + Log.i(TAG, "addNewFolderName: Trying to click add folder name field") + addFolderTitleField().click() + Log.i(TAG, "addNewFolderName: Clicked to click add folder name field") + Log.i(TAG, "addNewFolderName: Trying to set bookmarks folder name to: $name") + addFolderTitleField().perform(replaceText(name)) + Log.i(TAG, "addNewFolderName: Bookmarks folder name was set to: $name") } fun saveNewFolder() { + Log.i(TAG, "saveNewFolder: Trying to click save folder button") saveFolderButton().click() + Log.i(TAG, "saveNewFolder: Clicked save folder button") } fun navigateUp() { + Log.i(TAG, "navigateUp: Trying to click navigate up toolbar button") goBackButton().click() + Log.i(TAG, "navigateUp: Clicked navigate up toolbar button") } fun clickUndoDeleteButton() { + Log.i(TAG, "clickUndoDeleteButton: Trying to click undo snack bar button") snackBarUndoButton().click() + Log.i(TAG, "clickUndoDeleteButton: Clicked undo snack bar button") } fun changeBookmarkTitle(newTitle: String) { - bookmarkNameEditBox() - .perform(clearText()) - .perform(typeText(newTitle)) + Log.i(TAG, "changeBookmarkTitle: Trying to clear bookmark name text box") + bookmarkNameEditBox().perform(clearText()) + Log.i(TAG, "changeBookmarkTitle: Cleared bookmark name text box") + Log.i(TAG, "changeBookmarkTitle: Trying to set bookmark title to: $newTitle") + bookmarkNameEditBox().perform(typeText(newTitle)) + Log.i(TAG, "changeBookmarkTitle: Bookmark title was set to: $newTitle") } fun changeBookmarkUrl(newUrl: String) { - bookmarkURLEditBox() - .perform(clearText()) - .perform(typeText(newUrl)) + Log.i(TAG, "changeBookmarkUrl: Trying to clear bookmark url text box") + bookmarkURLEditBox().perform(clearText()) + Log.i(TAG, "changeBookmarkUrl: Cleared bookmark url text box") + Log.i(TAG, "changeBookmarkUrl: Trying to set bookmark url to: $newUrl") + bookmarkURLEditBox().perform(typeText(newUrl)) + Log.i(TAG, "changeBookmarkUrl: Bookmark url was set to: $newUrl") } fun saveEditBookmark() { + Log.i(TAG, "saveEditBookmark: Trying to click save bookmark button") saveBookmarkButton().click() + Log.i(TAG, "saveEditBookmark: Clicked save bookmark button") + Log.i(TAG, "saveEditBookmark: Waiting for $waitingTime ms for bookmarks list to exist") mDevice.findObject(UiSelector().resourceId("org.mozilla.fenix.debug:id/bookmark_list")).waitForExists(waitingTime) + Log.i(TAG, "saveEditBookmark: Waited for $waitingTime ms for bookmarks list to exist") } - fun clickParentFolderSelector() = bookmarkFolderSelector().click() + fun clickParentFolderSelector() { + Log.i(TAG, "clickParentFolderSelector: Trying to click folder selector") + bookmarkFolderSelector().click() + Log.i(TAG, "clickParentFolderSelector: Clicked folder selector") + } - fun selectFolder(title: String) = onView(withText(title)).click() + fun selectFolder(title: String) { + Log.i(TAG, "selectFolder: Trying to click folder with title: $title") + onView(withText(title)).click() + Log.i(TAG, "selectFolder: Clicked folder with title: $title") + } - fun longTapDesktopFolder(title: String) = onView(withText(title)).perform(longClick()) + fun longTapDesktopFolder(title: String) { + Log.i(TAG, "longTapDesktopFolder: Trying to long tap folder with title: $title") + onView(withText(title)).perform(longClick()) + Log.i(TAG, "longTapDesktopFolder: Long tapped folder with title: $title") + } fun cancelDeletion() { val cancelButton = mDevice.findObject(UiSelector().textContains("CANCEL")) + Log.i(TAG, "cancelDeletion: Waiting for $waitingTime ms for \"Cancel\" bookmarks deletion button to exist") cancelButton.waitForExists(waitingTime) + Log.i(TAG, "cancelDeletion: Waited for $waitingTime ms for \"Cancel\" bookmarks deletion button to exist") + Log.i(TAG, "cancelDeletion: Trying to click \"Cancel\" bookmarks deletion button") cancelButton.click() + Log.i(TAG, "cancelDeletion: Clicked \"Cancel\" bookmarks deletion button") } fun confirmDeletion() { + Log.i(TAG, "confirmDeletion: Trying to click \"Delete\" bookmarks deletion button") onView(withText(R.string.delete_browsing_data_prompt_allow)) .inRoot(RootMatchers.isDialog()) .check(matches(isDisplayed())) .click() + Log.i(TAG, "confirmDeletion: Clicked \"Delete\" bookmarks deletion button") } - fun clickDeleteInEditModeButton() = deleteInEditModeButton().click() - - fun searchBookmarkedItem(bookmarkedItem: String) { - itemWithResId("$packageName:id/mozac_browser_toolbar_edit_url_view").also { - it.waitForExists(waitingTime) - it.setText(bookmarkedItem) - } - mDevice.waitForWindowUpdate(packageName, waitingTimeShort) + fun clickDeleteInEditModeButton() { + Log.i(TAG, "clickDeleteInEditModeButton: Trying to click delete bookmarks button while in edit mode") + deleteInEditModeButton().click() + Log.i(TAG, "clickDeleteInEditModeButton: Clicked delete bookmarks button while in edit mode") } - fun verifySearchedBookmarkExists(bookmarkUrl: String, exists: Boolean = true) = - assertUIObjectExists(itemContainingText(bookmarkUrl), exists = exists) - - fun dismissBookmarksSearchBar() = mDevice.pressBack() - class Transition { fun closeMenu(interact: HomeScreenRobot.() -> Unit): Transition { + Log.i(TAG, "closeMenu: Trying to click close bookmarks section button") closeButton().click() + Log.i(TAG, "closeMenu: Clicked close bookmarks section button") HomeScreenRobot().interact() return Transition() @@ -271,35 +401,45 @@ class BookmarksRobot { fun openThreeDotMenu(bookmark: String, interact: ThreeDotMenuBookmarksRobot.() -> Unit): ThreeDotMenuBookmarksRobot.Transition { mDevice.waitNotNull(Until.findObject(res("$packageName:id/overflow_menu"))) + Log.i(TAG, "openThreeDotMenu: Trying to click three dot button for bookmark item: $bookmark") threeDotMenu(bookmark).click() + Log.i(TAG, "openThreeDotMenu: Clicked three dot button for bookmark item: $bookmark") ThreeDotMenuBookmarksRobot().interact() return ThreeDotMenuBookmarksRobot.Transition() } fun clickSingInToSyncButton(interact: SettingsTurnOnSyncRobot.() -> Unit): SettingsTurnOnSyncRobot.Transition { + Log.i(TAG, "clickSingInToSyncButton: Trying to click sign in to sync button") syncSignInButton().click() + Log.i(TAG, "clickSingInToSyncButton: Clicked sign in to sync button") SettingsTurnOnSyncRobot().interact() return SettingsTurnOnSyncRobot.Transition() } fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBack: Trying to click go back button") goBackButton().click() + Log.i(TAG, "goBack: Clicked go back button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun goBackToBrowserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "goBackToBrowserScreen: Trying to click go back button") goBackButton().click() + Log.i(TAG, "goBackToBrowserScreen: Clicked go back button") BrowserRobot().interact() return BrowserRobot.Transition() } fun closeEditBookmarkSection(interact: BookmarksRobot.() -> Unit): Transition { + Log.i(TAG, "goBackToBrowserScreen: Trying to click go back button") goBackButton().click() + Log.i(TAG, "goBackToBrowserScreen: Clicked go back button") BookmarksRobot().interact() return Transition() @@ -308,8 +448,12 @@ class BookmarksRobot { fun openBookmarkWithTitle(bookmarkTitle: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { itemWithResIdAndText("$packageName:id/title", bookmarkTitle) .also { + Log.i(TAG, "openBookmarkWithTitle: Waiting for $waitingTime ms for bookmark with title: $bookmarkTitle") it.waitForExists(waitingTime) + Log.i(TAG, "openBookmarkWithTitle: Waited for $waitingTime ms for bookmark with title: $bookmarkTitle") + Log.i(TAG, "openBookmarkWithTitle: Trying to click bookmark with title: $bookmarkTitle and wait for $waitingTimeShort ms for a new window") it.clickAndWaitForNewWindow(waitingTimeShort) + Log.i(TAG, "openBookmarkWithTitle: Clicked bookmark with title: $bookmarkTitle and waited for $waitingTimeShort ms for a new window") } BrowserRobot().interact() @@ -317,7 +461,9 @@ class BookmarksRobot { } fun clickSearchButton(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "clickSearchButton: Trying to click search bookmarks button") itemWithResId("$packageName:id/bookmark_search").click() + Log.i(TAG, "clickSearchButton: Clicked search bookmarks button") SearchRobot().interact() return SearchRobot.Transition() @@ -375,92 +521,3 @@ private fun saveBookmarkButton() = onView(withId(R.id.save_bookmark_button)) private fun deleteInEditModeButton() = onView(withId(R.id.delete_bookmark_button)) private fun syncSignInButton() = onView(withId(R.id.bookmark_folders_sign_in)) - -private fun assertBookmarksView() { - onView( - allOf( - withText("Bookmarks"), - withParent(withId(R.id.navigationToolbar)), - ), - ) - .check(matches(isDisplayed())) -} - -private fun assertAddFolderButton() = - addFolderButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - -private fun assertCloseButton() = closeButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - -private fun assertEmptyBookmarksList() = - onView(withId(R.id.bookmarks_empty_view)).check(matches(withText("No bookmarks here"))) - -private fun assertBookmarkFolderIsNotCreated(title: String) { - mDevice.findObject( - UiSelector() - .resourceId("$packageName:id/bookmarks_wrapper"), - ).waitForExists(waitingTime) - - assertUIObjectExists(itemContainingText(title), exists = false) -} - -private fun assertBookmarkFavicon(forUrl: Uri) = bookmarkFavicon(forUrl.toString()).check( - matches( - withEffectiveVisibility( - ViewMatchers.Visibility.VISIBLE, - ), - ), -) - -private fun assertBookmarkURL(expectedURL: String) = - bookmarkURL(expectedURL).check(matches(isDisplayed())) - -private fun assertFolderTitle(expectedTitle: String) = - onView(withText(expectedTitle)).check(matches(isDisplayed())) - -private fun assertBookmarkTitle(expectedTitle: String) = - onView(withText(expectedTitle)).check(matches(isDisplayed())) - -private fun assertBookmarkIsDeleted(expectedTitle: String) { - mDevice.findObject( - UiSelector() - .resourceId("$packageName:id/bookmarks_wrapper"), - ).waitForExists(waitingTime) - - assertUIObjectExists( - itemWithResIdContainingText( - "$packageName:id/title", - expectedTitle, - ), - exists = false, - ) -} -private fun assertUndoDeleteSnackBarButton() = - snackBarUndoButton().check(matches(withText("UNDO"))) - -private fun assertSnackBarText(text: String) = - snackBarText().check(matches(withText(containsString(text)))) - -private fun assertKeyboardVisibility(isExpectedToBeVisible: Boolean) = - assertEquals( - isExpectedToBeVisible, - mDevice - .executeShellCommand("dumpsys input_method | grep mInputShown") - .contains("mInputShown=true"), - ) - -private fun assertShareOverlay() = - onView(withId(R.id.shareWrapper)).check(matches(isDisplayed())) - -private fun assertShareBookmarkTitle() = - onView(withId(R.id.share_tab_title)).check(matches(isDisplayed())) - -private fun assertShareBookmarkFavicon() = - onView(withId(R.id.share_tab_favicon)).check(matches(isDisplayed())) - -private fun assertShareBookmarkUrl() = - onView(withId(R.id.share_tab_url)).check(matches(isDisplayed())) - -private fun assertDeleteFolderConfirmationMessage() = - onView(withText(R.string.bookmark_delete_folder_confirmation_dialog)) - .inRoot(RootMatchers.isDialog()) - .check(matches(isDisplayed())) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt index 7a0b7c479..d98e22a9c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/BrowserRobot.kt @@ -15,17 +15,14 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.ViewInteraction import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.longClick import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.PickerActions import androidx.test.espresso.matcher.RootMatchers.isDialog -import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.withContentDescription -import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.uiautomator.By import androidx.test.uiautomator.By.text @@ -74,7 +71,9 @@ class BrowserRobot { fun verifyCurrentPrivateSession(context: Context) { val selectedTab = context.components.core.store.state.selectedTab + Log.i(TAG, "verifyCurrentPrivateSession: Trying to verify that current browsing session is private") assertTrue("Current session is private", selectedTab?.content?.private ?: false) + Log.i(TAG, "verifyCurrentPrivateSession: Verified that current browsing session is private") } fun verifyUrl(url: String) { @@ -165,11 +164,6 @@ class BrowserRobot { ), ) - fun verifySnackBarText(expectedText: String) { - mDevice.waitForObjects(mDevice.findObject(UiSelector().textContains(expectedText))) - assertUIObjectExists(itemContainingText(expectedText)) - } - fun verifyContextMenuForLocalHostLinks(containsURL: Uri) { // If the link is directing to another local asset the "Download link" option is not available // If the link is not re-directing to an external app the "Open link in external app" option is not available @@ -234,11 +228,11 @@ class BrowserRobot { fun verifyNavURLBarHidden() = assertUIObjectIsGone(navURLBar()) - fun verifySecureConnectionLockIcon() = - onView(withId(R.id.mozac_browser_toolbar_security_indicator)) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - - fun verifyMenuButton() = threeDotButton().check(matches(isDisplayed())) + fun verifyMenuButton() { + Log.i(TAG, "verifyMenuButton: Trying to verify main menu button is displayed") + threeDotButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyMenuButton: Verified main menu button is displayed") + } fun verifyNoLinkImageContextMenuItems(containsURL: Uri) { mDevice.waitNotNull(Until.findObject(By.textContains(containsURL.toString()))) @@ -256,13 +250,10 @@ class BrowserRobot { fun verifyNotificationDotOnMainMenu() = assertUIObjectExists(itemWithResId("$packageName:id/notification_dot")) - fun verifyHomeScreenButton() = - homeScreenButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - - fun verifySearchBar() = assertUIObjectExists(searchBar()) - fun dismissContentContextMenu() { + Log.i(TAG, "dismissContentContextMenu: Trying to click device back button") mDevice.pressBack() + Log.i(TAG, "dismissContentContextMenu: Clicked device back button") assertUIObjectExists(itemWithResId("$packageName:id/engineView")) } @@ -292,7 +283,9 @@ class BrowserRobot { fun clickSubmitLoginButton() { clickPageObject(itemWithResId("submit")) assertUIObjectIsGone(itemWithResId("submit")) + Log.i(TAG, "clickSubmitLoginButton: Waiting for device to be idle for $waitingTimeLong ms") mDevice.waitForIdle(waitingTimeLong) + Log.i(TAG, "clickSubmitLoginButton: Waited for device to be idle for $waitingTimeLong ms") } fun enterPassword(password: String) { @@ -334,10 +327,16 @@ class BrowserRobot { fun swipeNavBarRight(tabUrl: String) { // failing to swipe on Firebase sometimes, so it tries again try { + Log.i(TAG, "swipeNavBarRight: Try block") + Log.i(TAG, "swipeNavBarRight: Trying to perform swipe right action on navigation toolbar") navURLBar().swipeRight(2) + Log.i(TAG, "swipeNavBarRight: Performed swipe right action on navigation toolbar") assertUIObjectIsGone(itemWithText(tabUrl)) } catch (e: AssertionError) { + Log.i(TAG, "swipeNavBarRight: AssertionError caught, executing fallback methods") + Log.i(TAG, "swipeNavBarRight: Trying to perform swipe right action on navigation toolbar") navURLBar().swipeRight(2) + Log.i(TAG, "swipeNavBarRight: Performed swipe right action on navigation toolbar") assertUIObjectIsGone(itemWithText(tabUrl)) } } @@ -345,10 +344,16 @@ class BrowserRobot { fun swipeNavBarLeft(tabUrl: String) { // failing to swipe on Firebase sometimes, so it tries again try { + Log.i(TAG, "swipeNavBarLeft: Try block") + Log.i(TAG, "swipeNavBarLeft: Trying to perform swipe left action on navigation toolbar") navURLBar().swipeLeft(2) + Log.i(TAG, "swipeNavBarLeft: Performed swipe left action on navigation toolbar") assertUIObjectIsGone(itemWithText(tabUrl)) } catch (e: AssertionError) { + Log.i(TAG, "swipeNavBarLeft: AssertionError caught, executing fallback methods") + Log.i(TAG, "swipeNavBarLeft: Trying to perform swipe left action on navigation toolbar") navURLBar().swipeLeft(2) + Log.i(TAG, "swipeNavBarLeft: Performed swipe left action on navigation toolbar") assertUIObjectIsGone(itemWithText(tabUrl)) } } @@ -356,11 +361,15 @@ class BrowserRobot { fun clickSuggestedLoginsButton() { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "clickSuggestedLoginsButton: Started try #$i") mDevice.waitForObjects(suggestedLogins()) + Log.i(TAG, "clickSuggestedLoginsButton: Trying to click suggested logins button") suggestedLogins().click() + Log.i(TAG, "clickSuggestedLoginsButton: Clicked suggested logins button") mDevice.waitForObjects(suggestedLogins()) break } catch (e: UiObjectNotFoundException) { + Log.i(TAG, "clickSuggestedLoginsButton: UiObjectNotFoundException caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -370,8 +379,11 @@ class BrowserRobot { } } - fun setTextForApartmentTextBox(apartment: String) = + fun setTextForApartmentTextBox(apartment: String) { + Log.i(TAG, "setTextForApartmentTextBox: Trying to set the text for the apartment text box to: $apartment") itemWithResId("apartment").setText(apartment) + Log.i(TAG, "setTextForApartmentTextBox: The text for the apartment text box was set to: $apartment") + } fun clearAddressForm() { clearTextFieldItem(itemWithResId("streetAddress")) @@ -385,11 +397,15 @@ class BrowserRobot { fun clickSelectAddressButton() { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "clickSelectAddressButton: Started try #$i") assertUIObjectExists(selectAddressButton()) + Log.i(TAG, "clickSelectAddressButton: Trying to click the select address button and wait for $waitingTime ms for a new window") selectAddressButton().clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickSelectAddressButton: Clicked the select address button and waited for $waitingTime ms for a new window") break } catch (e: AssertionError) { + Log.i(TAG, "clickSelectAddressButton: AssertionError caught, executing fallback methods") // Retrying to trigger the prompt, in case we hit https://bugzilla.mozilla.org/show_bug.cgi?id=1816869 // This should be removed when the bug is fixed. if (i == RETRY_COUNT) { @@ -404,28 +420,52 @@ class BrowserRobot { fun verifySelectAddressButtonExists(exists: Boolean) = assertUIObjectExists(selectAddressButton(), exists = exists) - fun changeCreditCardExpiryDate(expiryDate: String) = + fun changeCreditCardExpiryDate(expiryDate: String) { + Log.i(TAG, "changeCreditCardExpiryDate: Trying to set credit card expiry date to: $expiryDate") itemWithResId("expiryMonthAndYear").setText(expiryDate) + Log.i(TAG, "changeCreditCardExpiryDate: Credit card expiry date was set to: $expiryDate") + } fun clickCreditCardNumberTextBox() { + Log.i(TAG, "clickCreditCardNumberTextBox: Waiting for $waitingTime ms until finding the credit card number text box") mDevice.wait(Until.findObject(By.res("cardNumber")), waitingTime) + Log.i(TAG, "clickCreditCardNumberTextBox: Waited for $waitingTime ms until the credit card number text box was found") + Log.i(TAG, "clickCreditCardNumberTextBox: Trying to click the credit card number text box") mDevice.findObject(By.res("cardNumber")).click() + Log.i(TAG, "clickCreditCardNumberTextBox: Clicked the credit card number text box") + Log.i(TAG, "clickCreditCardNumberTextBox: Waiting for $waitingTimeShort ms for $appName window to be updated") mDevice.waitForWindowUpdate(appName, waitingTimeShort) + Log.i(TAG, "clickCreditCardNumberTextBox: Waited for $waitingTimeShort ms for $appName window to be updated") } - fun clickCreditCardFormSubmitButton() = + fun clickCreditCardFormSubmitButton() { + Log.i(TAG, "clickCreditCardFormSubmitButton: Trying to click the credit card form submit button and wait for $waitingTime ms for a new window") itemWithResId("submit").clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickCreditCardFormSubmitButton: Clicked the credit card form submit button and waited for $waitingTime ms for a new window") + } fun fillAndSaveCreditCard(cardNumber: String, cardName: String, expiryMonthAndYear: String) { + Log.i(TAG, "fillAndSaveCreditCard: Tying to set credit card number to: $cardNumber") itemWithResId("cardNumber").setText(cardNumber) + Log.i(TAG, "fillAndSaveCreditCard: Credit card number was set to: $cardNumber") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "fillAndSaveCreditCard: Trying to set credit card name to: $cardName") itemWithResId("nameOnCard").setText(cardName) + Log.i(TAG, "fillAndSaveCreditCard: Credit card name was set to: $cardName") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "fillAndSaveCreditCard: Trying to set credit card expiry month and year to: $expiryMonthAndYear") itemWithResId("expiryMonthAndYear").setText(expiryMonthAndYear) + Log.i(TAG, "fillAndSaveCreditCard: Credit card expiry month and year were set to: $expiryMonthAndYear") + Log.i(TAG, "fillAndSaveCreditCard: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "fillAndSaveCreditCard: Waited for device to be idle for $waitingTime ms") + Log.i(TAG, "fillAndSaveCreditCard: Trying to click the credit card form submit button and wait for $waitingTime ms for a new window") itemWithResId("submit").clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "fillAndSaveCreditCard: Clicked the credit card form submit button and waited for $waitingTime ms for a new window") waitForPageToLoad() + Log.i(TAG, "fillAndSaveCreditCard: Waiting for $waitingTime ms for $packageName window to be updated") mDevice.waitForWindowUpdate(packageName, waitingTime) + Log.i(TAG, "fillAndSaveCreditCard: Waited for $waitingTime ms for $packageName window to be updated") } fun verifyUpdateOrSaveCreditCardPromptExists(exists: Boolean) = @@ -449,10 +489,9 @@ class BrowserRobot { } fun verifySuggestedUserName(userName: String) { - mDevice.findObject( - UiSelector() - .resourceId("$packageName:id/mozac_feature_login_multiselect_expand"), - ).waitForExists(waitingTime) + Log.i(TAG, "verifySuggestedUserName: Waiting for $waitingTime ms for suggested logins fragment to exist") + itemWithResId("$packageName:id/mozac_feature_login_multiselect_expand").waitForExists(waitingTime) + Log.i(TAG, "verifySuggestedUserName: Waited for $waitingTime ms for suggested logins fragment to exist") assertUIObjectExists(itemContainingText(userName)) } @@ -460,6 +499,7 @@ class BrowserRobot { // Sometimes the assertion of the pre-filled logins fails so we are re-trying after refreshing the page for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifyPrefilledLoginCredentials: Started try #$i") mDevice.waitForObjects(itemWithResId("username")) assertItemTextEquals(itemWithResId("username"), expectedText = userName, isEqual = credentialsArePrefilled) mDevice.waitForObjects(itemWithResId("password")) @@ -467,6 +507,7 @@ class BrowserRobot { break } catch (e: AssertionError) { + Log.i(TAG, "verifyPrefilledLoginCredentials: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -499,23 +540,6 @@ class BrowserRobot { assertUIObjectExists(itemWithResIdAndText("cardNumber", creditCardNumber)) } - fun verifyPrefilledPWALoginCredentials(userName: String, shortcutTitle: String) { - mDevice.waitForIdle(waitingTime) - - var currentTries = 0 - while (currentTries++ < 3) { - try { - assertUIObjectExists(itemWithResId("submit")) - itemWithResId("submit").click() - assertItemTextEquals(itemWithResId("username"), expectedText = userName) - break - } catch (e: AssertionError) { - addToHomeScreen { - }.searchAndOpenHomeScreenShortcut(shortcutTitle) {} - } - } - } - fun verifySaveLoginPromptIsDisplayed() = assertUIObjectExists( itemWithResId("$packageName:id/feature_prompt_login_fragment"), @@ -530,14 +554,16 @@ class BrowserRobot { fun verifyTrackingProtectionWebContent(state: String) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifyTrackingProtectionWebContent: Started try #$i") assertUIObjectExists(itemContainingText(state)) break } catch (e: AssertionError) { + Log.i(TAG, "verifyTrackingProtectionWebContent: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { - Log.e("TestLog", "On try $i, trackers are not: $state") + Log.e(TAG, "On try $i, trackers are not: $state") navigationToolbar { }.openThreeDotMenu { @@ -550,38 +576,61 @@ class BrowserRobot { fun verifyCookiesProtectionHintIsDisplayed(composeTestRule: HomeActivityComposeTestRule, isDisplayed: Boolean) { if (isDisplayed) { + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection message is displayed") composeTestRule.onNodeWithTag("tcp_cfr.message").assertIsDisplayed() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified total cookie protection message is displayed") + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection learn more link is displayed") composeTestRule.onNodeWithTag("tcp_cfr.action").assertIsDisplayed() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified that the total cookie protection learn more link is displayed") + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection dismiss button is displayed") composeTestRule.onNodeWithTag("cfr.dismiss").assertIsDisplayed() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified total cookie protection dismiss button is displayed") } else { + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection message does not exist") composeTestRule.onNodeWithTag("tcp_cfr.message").assertDoesNotExist() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified that the total cookie protection message does not exist") + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection learn more link does not exist") composeTestRule.onNodeWithTag("tcp_cfr.action").assertDoesNotExist() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified total cookie protection learn more link does not exist") + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Trying to verify that the total cookie protection dismiss button does not exist") composeTestRule.onNodeWithTag("cfr.dismiss").assertDoesNotExist() + Log.i(TAG, "verifyCookiesProtectionHintIsDisplayed: Verified that the total cookie protection dismiss button does not exist") } } fun clickTCPCFRLearnMore(composeTestRule: HomeActivityComposeTestRule) { + Log.i(TAG, "clickTCPCFRLearnMore: Trying to click the total cookie protection learn more link") composeTestRule.onNodeWithTag("tcp_cfr.action").performClick() + Log.i(TAG, "clickTCPCFRLearnMore: Clicked total cookie protection learn more link") } fun dismissTCPCFRPopup(composeTestRule: HomeActivityComposeTestRule) { + Log.i(TAG, "dismissTCPCFRPopup: Trying to click the total cookie protection dismiss button") composeTestRule.onNodeWithTag("cfr.dismiss").performClick() + Log.i(TAG, "dismissTCPCFRPopup: Clicked total cookie protection dismiss button") } fun verifyShouldShowCFRTCP(shouldShow: Boolean, settings: Settings) { if (shouldShow) { + Log.i(TAG, "verifyShouldShowCFRTCP: Trying to verify that the TCP CFR should be shown") assertTrue(settings.shouldShowTotalCookieProtectionCFR) + Log.i(TAG, "verifyShouldShowCFRTCP: Verified that the TCP CFR should be shown") } else { + Log.i(TAG, "verifyShouldShowCFRTCP: Trying to verify that the TCP CFR should not be shown") assertFalse(settings.shouldShowTotalCookieProtectionCFR) + Log.i(TAG, "verifyShouldShowCFRTCP: Verified that the TCP CFR should not be shown") } } - fun selectTime(hour: Int, minute: Int): ViewInteraction = + fun selectTime(hour: Int, minute: Int) { + Log.i(TAG, "selectTime: Trying to select time picker hour: $hour and minute: $minute") onView( isAssignableFrom(TimePicker::class.java), ).inRoot( isDialog(), ).perform(PickerActions.setTime(hour, minute)) + Log.i(TAG, "selectTime: Selected time picker hour: $hour and minute: $minute") + } fun verifySelectedDate() { val currentDate = LocalDate.now() @@ -591,11 +640,13 @@ class BrowserRobot { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifySelectedDate: Started try #$i") assertUIObjectExists(itemContainingText("Selected date is: $currentDate")) break } catch (e: AssertionError) { - Log.e("TestLog", "Selected time isn't displayed ${e.localizedMessage}") + Log.i(TAG, "verifySelectedDate: AssertionError caught, executing fallback methods") + Log.e(TAG, "Selected time isn't displayed ${e.localizedMessage}") clickPageObject(itemWithResId("calendar")) clickPageObject(itemWithDescription("$currentDay $currentMonth $currentYear")) @@ -618,11 +669,13 @@ class BrowserRobot { fun verifySelectedTime(hour: Int, minute: Int) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifySelectedTime: Started try #$i") assertUIObjectExists(itemContainingText("Selected time is: $hour:$minute")) break } catch (e: AssertionError) { - Log.e("TestLog", "Selected time isn't displayed ${e.localizedMessage}") + Log.i(TAG, "verifySelectedTime: AssertionError caught, executing fallback methods") + Log.e(TAG, "Selected time isn't displayed ${e.localizedMessage}") clickPageObject(itemWithResId("clock")) clickPageObject(itemContainingText("CLEAR")) @@ -638,11 +691,13 @@ class BrowserRobot { fun verifySelectedColor(hexValue: String) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifySelectedColor: Started try #$i") assertUIObjectExists(itemContainingText("Selected color is: $hexValue")) break } catch (e: AssertionError) { - Log.e("TestLog", "Selected color isn't displayed ${e.localizedMessage}") + Log.i(TAG, "verifySelectedColor: AssertionError caught, executing fallback methods") + Log.e(TAG, "Selected color isn't displayed ${e.localizedMessage}") clickPageObject(itemWithResId("colorPicker")) clickPageObject(itemWithDescription(hexValue)) @@ -657,17 +712,20 @@ class BrowserRobot { fun verifySelectedDropDownOption(optionName: String) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifySelectedDropDownOption: Started try #$i") + Log.i(TAG, "verifySelectedDropDownOption: Waiting for $waitingTime ms for \"Submit drop down option\" form button to exist") mDevice.findObject( UiSelector() .textContains("Submit drop down option") .resourceId("submitOption"), ).waitForExists(waitingTime) - + Log.i(TAG, "verifySelectedDropDownOption: Waited for $waitingTime ms for \"Submit drop down option\" form button to exist") assertUIObjectExists(itemContainingText("Selected option is: $optionName")) break } catch (e: AssertionError) { - Log.e("TestLog", "Selected option isn't displayed ${e.localizedMessage}") + Log.i(TAG, "verifySelectedDropDownOption: AssertionError caught, executing fallback methods") + Log.e(TAG, "Selected option isn't displayed ${e.localizedMessage}") clickPageObject(itemWithResId("dropDown")) clickPageObject(itemContainingText(optionName)) @@ -686,16 +744,18 @@ class BrowserRobot { fun verifyCookieBannerExists(exists: Boolean) { for (i in 1..RETRY_COUNT) { - Log.i(TAG, "verifyCookieBannerExists: For loop: $i") + Log.i(TAG, "verifyCookieBannerExists: Started try #$i") try { // Wait for the blocker to kick-in and make the cookie banner disappear + Log.i(TAG, "verifyCookieBannerExists: Waiting for $waitingTime ms for cookie banner to be gone") itemWithResId("CybotCookiebotDialog").waitUntilGone(waitingTime) - Log.i(TAG, "verifyCookieBannerExists: Waiting for window update") + Log.i(TAG, "verifyCookieBannerExists: Waited for $waitingTime ms for cookie banner to be gone") // Assert that the blocker properly dismissed the cookie banner assertUIObjectExists(itemWithResId("CybotCookiebotDialog"), exists = exists) break } catch (e: AssertionError) { + Log.i(TAG, "verifyCookieBannerExists: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } @@ -724,6 +784,7 @@ class BrowserRobot { fun verifyPrivateBrowsingOpenLinkInAnotherAppPrompt(url: String, pageObject: UiObject) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifyPrivateBrowsingOpenLinkInAnotherAppPrompt: Started try #$i") assertUIObjectExists( itemContainingText( getStringResource(R.string.mozac_feature_applinks_confirm_dialog_title), @@ -733,6 +794,7 @@ class BrowserRobot { break } catch (e: AssertionError) { + Log.i(TAG, "verifyPrivateBrowsingOpenLinkInAnotherAppPrompt: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -774,6 +836,7 @@ class BrowserRobot { fun verifyOpenLinksInAppsCFRExists(exists: Boolean) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "verifyOpenLinksInAppsCFRExists: Started try #$i") assertUIObjectExists( itemWithResId("$packageName:id/banner_container"), itemWithResIdContainingText( @@ -791,6 +854,7 @@ class BrowserRobot { exists = exists, ) } catch (e: AssertionError) { + Log.i(TAG, "verifyOpenLinksInAppsCFRExists: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -817,11 +881,14 @@ class BrowserRobot { fun verifyHomeScreenSurveyCloseButton() = assertUIObjectExists(itemWithDescription("Close")) - fun clickOpenLinksInAppsDismissCFRButton() = + fun clickOpenLinksInAppsDismissCFRButton() { + Log.i(TAG, "clickOpenLinksInAppsDismissCFRButton: Trying to click the open links in apps banner \"Dismiss\" button") itemWithResIdContainingText( "$packageName:id/dismiss", getStringResource(R.string.open_in_app_cfr_negative_button_text), ).click() + Log.i(TAG, "clickOpenLinksInAppsDismissCFRButton: Clicked the open links in apps banner \"Dismiss\" button") + } fun clickTakeSurveyButton() { val button = mDevice.findObject( @@ -846,7 +913,11 @@ class BrowserRobot { button.click() } - fun longClickToolbar() = onView(withId(R.id.mozac_browser_toolbar_url_view)).perform(longClick()) + fun longClickToolbar() { + Log.i(TAG, "longClickToolbar: Trying to long click the toolbar") + onView(withId(R.id.mozac_browser_toolbar_url_view)).perform(longClick()) + Log.i(TAG, "longClickToolbar: Long clicked the toolbar") + } fun verifyDownloadPromptIsDismissed() = assertUIObjectExists( @@ -876,27 +947,31 @@ class BrowserRobot { } fun clickStayInPrivateBrowsingPromptButton() { + Log.i(TAG, "clickStayInPrivateBrowsingPromptButton: Trying to click the \"STAY IN PRIVATE BROWSING\" prompt button") itemWithResIdContainingText( "$packageName:id/deny_button", getStringResource(R.string.mozac_feature_downloads_cancel_active_private_downloads_deny), ).click() - Log.i(TAG, "clickStayInPrivateBrowsingPromptButton: Clicked \"STAY IN PRIVATE BROWSING\" prompt button") + Log.i(TAG, "clickStayInPrivateBrowsingPromptButton: Clicked the \"STAY IN PRIVATE BROWSING\" prompt button") } fun clickCancelPrivateDownloadsPromptButton() { + Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Trying to click the \"CANCEL DOWNLOADS\" prompt button") itemWithResIdContainingText( "$packageName:id/accept_button", getStringResource(R.string.mozac_feature_downloads_cancel_active_downloads_accept), ).click() - Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Clicked \"CANCEL DOWNLOADS\" prompt button") - + Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Clicked the \"CANCEL DOWNLOADS\" prompt button") + Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Waiting for $waitingTime ms for $packageName window to be updated") mDevice.waitForWindowUpdate(packageName, waitingTime) + Log.i(TAG, "clickCancelPrivateDownloadsPromptButton: Waited for $waitingTime ms for $packageName window to be updated") } fun fillPdfForm(name: String) { // Set PDF form text for the text box + Log.i(TAG, "fillPdfForm: Trying to set the text of the PDF form text box to: $name") itemWithResId("pdfjs_internal_id_10R").setText(name) - Log.i(TAG, "fillPdfForm: Set PDF form text box text to: $name") + Log.i(TAG, "fillPdfForm: PDF form text box text was set to: $name") mDevice.waitForWindowUpdate(packageName, waitingTime) if ( !itemWithResId("pdfjs_internal_id_11R").exists() && @@ -905,18 +980,22 @@ class BrowserRobot { .contains("mInputShown=true") ) { // Close the keyboard + Log.i(TAG, "fillPdfForm: Trying to close the keyboard using device back button") mDevice.pressBack() - Log.i(TAG, "fillPdfForm: Closing the keyboard using device back button") + Log.i(TAG, "fillPdfForm: Closed the keyboard using device back button") } // Click PDF form check box + Log.i(TAG, "fillPdfForm: Trying to click the PDF form check box") itemWithResId("pdfjs_internal_id_11R").click() Log.i(TAG, "fillPdfForm: Clicked PDF form check box") } class Transition { fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { + Log.i(TAG, "openThreeDotMenu: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) Log.i(TAG, "openThreeDotMenu: Device was idle for $waitingTime ms") + Log.i(TAG, "openThreeDotMenu: Trying to click the main menu button") threeDotButton().perform(click()) Log.i(TAG, "openThreeDotMenu: Clicked the main menu button") @@ -926,7 +1005,9 @@ class BrowserRobot { fun openNavigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition { clickPageObject(navURLBar()) + Log.i(TAG, "openNavigationToolbar: Waiting for $waitingTime ms for for search bar to exist") searchBar().waitForExists(waitingTime) + Log.i(TAG, "openNavigationToolbar: Waited for $waitingTime ms for for search bar to exist") NavigationToolbarRobot().interact() return NavigationToolbarRobot.Transition() @@ -935,6 +1016,7 @@ class BrowserRobot { fun openTabDrawer(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "openTabDrawer: Started try #$i") mDevice.waitForObjects( mDevice.findObject( UiSelector() @@ -942,16 +1024,20 @@ class BrowserRobot { ), waitingTime, ) - + Log.i(TAG, "openTabDrawer: Trying to click the tab counter button") tabsCounter().click() + Log.i(TAG, "openTabDrawer: Clicked the tab counter button") assertUIObjectExists(itemWithResId("$packageName:id/new_tab_button")) break } catch (e: AssertionError) { + Log.i(TAG, "openTabDrawer: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { + Log.i(TAG, "openTabDrawer: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "openTabDrawer: Waited for device to be idle") } } } @@ -965,6 +1051,7 @@ class BrowserRobot { fun openComposeTabDrawer(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "openComposeTabDrawer: Started try #$i") mDevice.waitForObjects( mDevice.findObject( UiSelector() @@ -972,30 +1059,37 @@ class BrowserRobot { ), waitingTime, ) - + Log.i(TAG, "openComposeTabDrawer: Trying to click the tab counter button") tabsCounter().click() - + Log.i(TAG, "openComposeTabDrawer: Clicked the tab counter button") + Log.i(TAG, "openComposeTabDrawer: Trying to verify the tabs tray exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.tabsTray).assertExists() + Log.i(TAG, "openComposeTabDrawer: Verified the tabs tray exists") break } catch (e: AssertionError) { + Log.i(TAG, "openComposeTabDrawer: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { + Log.i(TAG, "openComposeTabDrawer: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "openComposeTabDrawer: Waited for device to be idle") } } } - + Log.i(TAG, "openComposeTabDrawer: Trying to verify the tabs tray new tab FAB button exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.fab).assertExists() + Log.i(TAG, "openComposeTabDrawer: Verified the tabs tray new tab FAB button exists") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) } fun openNotificationShade(interact: NotificationRobot.() -> Unit): NotificationRobot.Transition { + Log.i(TAG, "openNotificationShade: Trying to open the notification tray") mDevice.openNotification() - Log.i(TAG, "openNotificationShade: Opened notification tray") + Log.i(TAG, "openNotificationShade: Opened the notification tray") NotificationRobot().interact() return NotificationRobot.Transition() @@ -1003,7 +1097,7 @@ class BrowserRobot { fun goToHomescreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { clickPageObject(itemWithDescription("Home screen")) - + Log.i(TAG, "goToHomescreen: Waiting for $waitingTime ms for for home screen layout or jump back in contextual hint to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/homeLayout")) .waitForExists(waitingTime) || mDevice.findObject( @@ -1011,6 +1105,7 @@ class BrowserRobot { getStringResource(R.string.onboarding_home_screen_jump_back_contextual_hint_2), ), ).waitForExists(waitingTime) + Log.i(TAG, "goToHomescreen: Waited for $waitingTime ms for for home screen layout or jump back in contextual hint to exist") HomeScreenRobot().interact() return HomeScreenRobot.Transition() @@ -1019,6 +1114,7 @@ class BrowserRobot { fun goToHomescreenWithComposeTopSites(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTopSitesRobot.() -> Unit): ComposeTopSitesRobot.Transition { clickPageObject(itemWithDescription("Home screen")) + Log.i(TAG, "goToHomescreenWithComposeTopSites: Waiting for $waitingTime ms for for home screen layout or jump back in contextual hint to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/homeLayout")) .waitForExists(waitingTime) || mDevice.findObject( @@ -1026,13 +1122,16 @@ class BrowserRobot { getStringResource(R.string.onboarding_home_screen_jump_back_contextual_hint_2), ), ).waitForExists(waitingTime) + Log.i(TAG, "goToHomescreenWithComposeTopSites: Waited for $waitingTime ms for for home screen layout or jump back in contextual hint to exist") ComposeTopSitesRobot(composeTestRule).interact() return ComposeTopSitesRobot.Transition(composeTestRule) } fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBack: Trying to click device back button") mDevice.pressBack() + Log.i(TAG, "goBack: Clicked device back button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() @@ -1040,7 +1139,9 @@ class BrowserRobot { fun clickTabCrashedCloseButton(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { clickPageObject(itemWithText("Close tab")) + Log.i(TAG, "clickTabCrashedCloseButton: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "clickTabCrashedCloseButton: Waited for device to be idle") HomeScreenRobot().interact() return HomeScreenRobot.Transition() @@ -1126,45 +1227,56 @@ class BrowserRobot { } fun openSiteSecuritySheet(interact: SiteSecurityRobot.() -> Unit): SiteSecurityRobot.Transition { + Log.i(TAG, "openSiteSecuritySheet: Waiting for $waitingTime ms for site security toolbar button to exist") siteSecurityToolbarButton().waitForExists(waitingTime) + Log.i(TAG, "openSiteSecuritySheet: Waited for $waitingTime ms for site security toolbar button to exist") + Log.i(TAG, "openSiteSecuritySheet: Trying to click the site security toolbar button and wait for $waitingTime ms for a new window") siteSecurityToolbarButton().clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "openSiteSecuritySheet: Clicked the site security toolbar button and waited for $waitingTime ms for a new window") SiteSecurityRobot().interact() return SiteSecurityRobot.Transition() } fun clickManageAddressButton(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition { + Log.i(TAG, "clickManageAddressButton: Trying to click the manage address button and wait for $waitingTime ms for a new window") itemWithResId("$packageName:id/manage_addresses") .clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickManageAddressButton: Clicked the manage address button and waited for $waitingTime ms for a new window") SettingsSubMenuAutofillRobot().interact() return SettingsSubMenuAutofillRobot.Transition() } fun clickManageCreditCardsButton(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition { + Log.i(TAG, "clickManageCreditCardsButton: Trying to click the manage credit cards button and wait for $waitingTime ms for a new window") itemWithResId("$packageName:id/manage_credit_cards") .clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickManageCreditCardsButton: Clicked the manage credit cards button and waited for $waitingTime ms for a new window") SettingsSubMenuAutofillRobot().interact() return SettingsSubMenuAutofillRobot.Transition() } fun clickOpenLinksInAppsGoToSettingsCFRButton(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + Log.i(TAG, "clickOpenLinksInAppsGoToSettingsCFRButton: Trying to click the \"Go to settings\" open links in apps CFR button and wait for $waitingTime ms for a new window") itemWithResIdContainingText( "$packageName:id/action", getStringResource(R.string.open_in_app_cfr_positive_button_text), ).clickAndWaitForNewWindow(waitingTime) - Log.i(TAG, "clickOpenLinksInAppsGoToSettingsCFRButton: Clicked \"Go to settings\" open links in apps CFR button") + Log.i(TAG, "clickOpenLinksInAppsGoToSettingsCFRButton: Clicked the \"Go to settings\" open links in apps CFR button and waited for $waitingTime ms for a new window") SettingsRobot().interact() return SettingsRobot.Transition() } fun clickDownloadPDFButton(interact: DownloadRobot.() -> Unit): DownloadRobot.Transition { + Log.i(TAG, "clickDownloadPDFButton: Trying to click the download PDF button") itemWithResIdContainingText( "download", "Download", ).click() + Log.i(TAG, "clickDownloadPDFButton: Clicked the download PDF button") DownloadRobot().interact() return DownloadRobot.Transition() @@ -1205,8 +1317,6 @@ private fun navURLBar() = itemWithResId("$packageName:id/toolbar") private fun searchBar() = itemWithResId("$packageName:id/mozac_browser_toolbar_url_view") -fun homeScreenButton() = onView(withContentDescription(R.string.browser_toolbar_home)) - private fun threeDotButton() = onView(withContentDescription("Menu")) private fun tabsCounter() = @@ -1224,26 +1334,25 @@ private fun siteSecurityToolbarButton() = fun clickPageObject(item: UiObject) { for (i in 1..RETRY_COUNT) { - Log.i(TAG, "clickPageObject: For loop i = $i") try { - Log.i(TAG, "clickPageObject: Try block") + Log.i(TAG, "clickPageObject: Started try #$i") + Log.i(TAG, "clickPageObject: Waiting for $waitingTime ms for ${item.selector} to exist") item.waitForExists(waitingTime) + Log.i(TAG, "clickPageObject: Waited for $waitingTime ms for ${item.selector} to exist") + Log.i(TAG, "clickPageObject: Trying to click ${item.selector}") item.click() Log.i(TAG, "clickPageObject: Clicked ${item.selector}") break } catch (e: UiObjectNotFoundException) { - Log.i(TAG, "clickPageObject: Catch block") + Log.i(TAG, "clickPageObject: UiObjectNotFoundException caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { browserScreen { - Log.i(TAG, "clickPageObject: Browser screen") }.openThreeDotMenu { - Log.i(TAG, "clickPageObject: Opened main menu") }.refreshPage { waitForPageToLoad() - Log.i(TAG, "clickPageObject: Page refreshed, progress bar is gone") } } } @@ -1253,11 +1362,17 @@ fun clickPageObject(item: UiObject) { fun longClickPageObject(item: UiObject) { for (i in 1..RETRY_COUNT) { try { + Log.i(TAG, "longClickPageObject: Started try #$i") + Log.i(TAG, "longClickPageObject: Waiting for $waitingTime ms for ${item.selector} to exist") item.waitForExists(waitingTime) + Log.i(TAG, "longClickPageObject: Waited for $waitingTime ms for ${item.selector} to exist") + Log.i(TAG, "longClickPageObject: Trying to long click ${item.selector}") item.longClick() + Log.i(TAG, "longClickPageObject: Long clicked ${item.selector}") break } catch (e: UiObjectNotFoundException) { + Log.i(TAG, "longClickPageObject: UiObjectNotFoundException caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -1276,20 +1391,30 @@ fun clickContextMenuItem(item: String) { Until.findObject(text(item)), waitingTime, ) + Log.i(TAG, "clickContextMenuItem: Trying to click context menu item: $item") mDevice.findObject(text(item)).click() + Log.i(TAG, "clickContextMenuItem: Clicked context menu item: $item") } fun setPageObjectText(webPageItem: UiObject, text: String) { for (i in 1..RETRY_COUNT) { + Log.i(TAG, "setPageObjectText: Started try #$i") try { webPageItem.also { + Log.i(TAG, "setPageObjectText: Waiting for $waitingTime ms for ${webPageItem.selector} to exist") it.waitForExists(waitingTime) + Log.i(TAG, "setPageObjectText: Waited for $waitingTime ms for ${webPageItem.selector} to exist") + Log.i(TAG, "setPageObjectText: Trying to clear ${webPageItem.selector} text field") it.clearTextField() + Log.i(TAG, "setPageObjectText: Cleared ${webPageItem.selector} text field") + Log.i(TAG, "setPageObjectText: Trying to set ${webPageItem.selector} text to $text") it.text = text + Log.i(TAG, "setPageObjectText: ${webPageItem.selector} text was set to $text") } break } catch (e: UiObjectNotFoundException) { + Log.i(TAG, "setPageObjectText: UiObjectNotFoundException caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -1304,8 +1429,12 @@ fun setPageObjectText(webPageItem: UiObject, text: String) { } fun clearTextFieldItem(item: UiObject) { + Log.i(TAG, "clearTextFieldItem: Waiting for $waitingTime ms for ${item.selector} to exist") item.waitForExists(waitingTime) + Log.i(TAG, "clearTextFieldItem: Waited for $waitingTime ms for ${item.selector} to exist") + Log.i(TAG, "clearTextFieldItem: Trying to clear ${item.selector} text field") item.clearTextField() + Log.i(TAG, "clearTextFieldItem: Cleared ${item.selector} text field") } // Context menu items diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CollectionRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CollectionRobot.kt index 1cbac1730..1dc74bb38 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CollectionRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CollectionRobot.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasContentDescription import androidx.compose.ui.test.hasText @@ -17,10 +18,10 @@ import androidx.test.espresso.action.ViewActions.pressImeActionButton import androidx.test.espresso.matcher.RootMatchers import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.uiautomator.By -import androidx.test.uiautomator.UiScrollable import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.MatcherHelper.assertItemTextEquals import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists @@ -46,29 +47,45 @@ class CollectionRobot { itemWithResId("$packageName:id/collections_list"), ) - fun clickAddNewCollection() = addNewCollectionButton().click() + fun clickAddNewCollection() { + Log.i(TAG, "clickAddNewCollection: Trying to click the add new collection button") + addNewCollectionButton().click() + Log.i(TAG, "clickAddNewCollection: Clicked the add new collection button") + } fun verifyCollectionNameTextField() = assertUIObjectExists(mainMenuEditCollectionNameField()) // names a collection saved from tab drawer fun typeCollectionNameAndSave(collectionName: String) { + Log.i(TAG, "typeCollectionNameAndSave: Trying to set collection name text field to: $collectionName") collectionNameTextField().text = collectionName - addCollectionButtonPanel.waitForExists(waitingTime) - addCollectionOkButton.click() + Log.i(TAG, "typeCollectionNameAndSave: Collection name text field set to: $collectionName") + Log.i(TAG, "typeCollectionNameAndSave: Waiting for $waitingTime ms for add collection button panel to exist") + addCollectionButtonPanel().waitForExists(waitingTime) + Log.i(TAG, "typeCollectionNameAndSave: Waited for $waitingTime ms for add collection button panel to exist") + Log.i(TAG, "typeCollectionNameAndSave: Trying to click \"OK\" panel button") + addCollectionOkButton().click() + Log.i(TAG, "typeCollectionNameAndSave: Clicked \"OK\" panel button") } fun verifyTabsSelectedCounterText(numOfTabs: Int) { + Log.i(TAG, "verifyTabsSelectedCounterText: Waiting for $waitingTime ms for \"Select tabs to save\" prompt to be gone") itemWithText("Select tabs to save").waitUntilGone(waitingTime) + Log.i(TAG, "verifyTabsSelectedCounterText: Waited for $waitingTime ms for \"Select tabs to save\" prompt to be gone") val tabsCounter = mDevice.findObject(UiSelector().resourceId("$packageName:id/bottom_bar_text")) + Log.i(TAG, "verifyTabsSelectedCounterText: Trying to assert that number of tabs selected is: $numOfTabs") when (numOfTabs) { 1 -> assertItemTextEquals(tabsCounter, expectedText = "$numOfTabs tab selected") 2 -> assertItemTextEquals(tabsCounter, expectedText = "$numOfTabs tabs selected") } + Log.i(TAG, "verifyTabsSelectedCounterText: Asserted number of tabs selected is: $numOfTabs") } fun saveTabsSelectedForCollection() { - mDevice.findObject(UiSelector().resourceId("$packageName:id/save_button")).click() + Log.i(TAG, "saveTabsSelectedForCollection: Trying to click \"Save\" button") + itemWithResId("$packageName:id/save_button").click() + Log.i(TAG, "saveTabsSelectedForCollection: Clicked \"Save\" button") } fun verifyTabSavedInCollection(title: String, visible: Boolean = true) { @@ -88,83 +105,114 @@ class CollectionRobot { fun verifyCollectionMenuIsVisible(visible: Boolean, rule: ComposeTestRule) { if (visible) { - collectionThreeDotButton(rule) - .assertExists() - .assertIsDisplayed() + Log.i(TAG, "verifyCollectionMenuIsVisible: Trying to verify collection three dot button exists") + collectionThreeDotButton(rule).assertExists() + Log.i(TAG, "verifyCollectionMenuIsVisible: Verified collection three dot button exists") + Log.i(TAG, "verifyCollectionMenuIsVisible: Trying to verify collection three dot button is displayed") + collectionThreeDotButton(rule).assertIsDisplayed() + Log.i(TAG, "verifyCollectionMenuIsVisible: Verified collection three dot button is displayed") } else { + Log.i(TAG, "verifyCollectionMenuIsVisible: Trying to verify collection three dot button does not exist") collectionThreeDotButton(rule) .assertDoesNotExist() + Log.i(TAG, "verifyCollectionMenuIsVisible: Verified collection three dot button does not exist") } } fun clickCollectionThreeDotButton(rule: ComposeTestRule) { - collectionThreeDotButton(rule) - .assertIsDisplayed() - .performClick() + Log.i(TAG, "clickCollectionThreeDotButton: Trying to verify three dot button is displayed") + collectionThreeDotButton(rule).assertIsDisplayed() + Log.i(TAG, "clickCollectionThreeDotButton: Verified three dot button is displayed") + Log.i(TAG, "clickCollectionThreeDotButton: Trying to click three dot button") + collectionThreeDotButton(rule).performClick() + Log.i(TAG, "clickCollectionThreeDotButton: Clicked three dot button") } fun selectOpenTabs(rule: ComposeTestRule) { - rule.onNode(hasText("Open tabs")) - .assertIsDisplayed() - .performClick() + Log.i(TAG, "selectOpenTabs: Trying to verify \"Open tabs\" menu option is displayed") + rule.onNode(hasText("Open tabs")).assertIsDisplayed() + Log.i(TAG, "selectOpenTabs: Verified \"Open tabs\" menu option is displayed") + Log.i(TAG, "selectOpenTabs: Trying to click \"Open tabs\" menu option") + rule.onNode(hasText("Open tabs")).performClick() + Log.i(TAG, "selectOpenTabs: Clicked \"Open tabs\" menu option") } fun selectRenameCollection(rule: ComposeTestRule) { - rule.onNode(hasText("Rename collection")) - .assertIsDisplayed() - .performClick() + Log.i(TAG, "selectRenameCollection: Trying to verify \"Rename collection\" menu option is displayed") + rule.onNode(hasText("Rename collection")).assertIsDisplayed() + Log.i(TAG, "selectRenameCollection: Verified \"Rename collection\" menu option is displayed") + Log.i(TAG, "selectRenameCollection: Trying to click \"Rename collection\" menu option") + rule.onNode(hasText("Rename collection")).performClick() + Log.i(TAG, "selectRenameCollection: Clicked \"Rename collection\" menu option") + Log.i(TAG, "selectRenameCollection: Waiting for $waitingTime ms for collection name text field to exist") mainMenuEditCollectionNameField().waitForExists(waitingTime) + Log.i(TAG, "selectRenameCollection: Waited for $waitingTime ms for collection name text field to exist") } fun selectAddTabToCollection(rule: ComposeTestRule) { - rule.onNode(hasText("Add tab")) - .assertIsDisplayed() - .performClick() + Log.i(TAG, "selectAddTabToCollection: Trying to verify \"Add tab\" menu option is displayed") + rule.onNode(hasText("Add tab")).assertIsDisplayed() + Log.i(TAG, "selectAddTabToCollection: Verified \"Add tab\" menu option is displayed") + Log.i(TAG, "selectAddTabToCollection: Trying to click \"Add tab\" menu option") + rule.onNode(hasText("Add tab")).performClick() + Log.i(TAG, "selectAddTabToCollection: Clicked \"Add tab\" menu option") mDevice.waitNotNull(Until.findObject(By.text("Select Tabs"))) } fun selectDeleteCollection(rule: ComposeTestRule) { - rule.onNode(hasText("Delete collection")) - .assertIsDisplayed() - .performClick() + Log.i(TAG, "selectDeleteCollection: Trying to verify \"Delete collection\" menu option is displayed") + rule.onNode(hasText("Delete collection")).assertIsDisplayed() + Log.i(TAG, "selectDeleteCollection: Verified \"Delete collection\" menu option is displayed") + Log.i(TAG, "selectDeleteCollection: Trying to click \"Delete collection\" menu option") + rule.onNode(hasText("Delete collection")).performClick() + Log.i(TAG, "selectDeleteCollection: Clicked \"Delete collection\" menu option") } fun verifyCollectionItemRemoveButtonIsVisible(title: String, visible: Boolean) = assertUIObjectExists(removeTabFromCollectionButton(title), exists = visible) - fun removeTabFromCollection(title: String) = removeTabFromCollectionButton(title).click() + fun removeTabFromCollection(title: String) { + Log.i(TAG, "removeTabFromCollection: Trying to click remove button for tab: $title") + removeTabFromCollectionButton(title).click() + Log.i(TAG, "removeTabFromCollection: Clicked remove button for tab: $title") + } fun swipeTabLeft(title: String, rule: ComposeTestRule) { + Log.i(TAG, "swipeTabLeft: Trying to remove tab: $title using swipe left action") rule.onNode(hasText(title), useUnmergedTree = true) .performTouchInput { swipeLeft() } + Log.i(TAG, "swipeTabLeft: Removed tab: $title using swipe left action") + Log.i(TAG, "swipeTabLeft: Waiting for rule to be idle") rule.waitForIdle() + Log.i(TAG, "swipeTabLeft: Waited for rule to be idle") } fun swipeTabRight(title: String, rule: ComposeTestRule) { + Log.i(TAG, "swipeTabRight: Trying to remove tab: $title using swipe right action") rule.onNode(hasText(title), useUnmergedTree = true) .performTouchInput { swipeRight() } + Log.i(TAG, "swipeTabRight: Removed tab: $title using swipe right action") + Log.i(TAG, "swipeTabRight: Waiting for rule to be idle") rule.waitForIdle() + Log.i(TAG, "swipeTabRight: Waited for rule to be idle") } - fun verifySnackBarText(expectedText: String) { - mDevice.findObject(UiSelector().text(expectedText)).waitForExists(waitingTime) + fun goBackInCollectionFlow() { + Log.i(TAG, "goBackInCollectionFlow: Trying to click collection creation flow back button") + backButton().click() + Log.i(TAG, "goBackInCollectionFlow: Clicked collection creation flow back button") } - fun goBackInCollectionFlow() = backButton().click() - - fun swipeToBottom() = - UiScrollable( - UiSelector().resourceId("$packageName:id/sessionControlRecyclerView"), - ).scrollToEnd(3) - class Transition { fun collapseCollection( title: String, interact: HomeScreenRobot.() -> Unit, ): HomeScreenRobot.Transition { assertUIObjectExists(itemContainingText(title)) + Log.i(TAG, "collapseCollection: Trying to click collection $title and wait for $waitingTimeShort ms for a new window") itemContainingText(title).clickAndWaitForNewWindow(waitingTimeShort) + Log.i(TAG, "collapseCollection: Clicked collection $title and waited for $waitingTimeShort ms for a new window") assertUIObjectExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection)), exists = false) HomeScreenRobot().interact() @@ -176,9 +224,15 @@ class CollectionRobot { name: String, interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { + Log.i(TAG, "typeCollectionNameAndSave: Waiting for $waitingTime ms for collection name text field to exist") mainMenuEditCollectionNameField().waitForExists(waitingTime) + Log.i(TAG, "typeCollectionNameAndSave: Waited for $waitingTime ms for collection name text field to exist") + Log.i(TAG, "typeCollectionNameAndSave: Trying to set collection name text field to: $name") mainMenuEditCollectionNameField().text = name + Log.i(TAG, "typeCollectionNameAndSave: Collection name text field set to: $name") + Log.i(TAG, "typeCollectionNameAndSave: Trying to press done action button") onView(withId(R.id.name_collection_edittext)).perform(pressImeActionButton()) + Log.i(TAG, "typeCollectionNameAndSave: Pressed done action button") // wait for the collection creation wrapper to be dismissed mDevice.waitNotNull(Until.gone(By.res("$packageName:id/createCollectionWrapper"))) @@ -191,16 +245,24 @@ class CollectionRobot { title: String, interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { + Log.i(TAG, "selectExistingCollection: Waiting for $waitingTime ms for collection with title: $title to exist") collectionTitle(title).waitForExists(waitingTime) + Log.i(TAG, "selectExistingCollection: Waited for $waitingTime ms for collection with title: $title to exist") + Log.i(TAG, "selectExistingCollection: Trying to click collection with title: $title") collectionTitle(title).click() + Log.i(TAG, "selectExistingCollection: Clicked collection with title: $title") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickShareCollectionButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition { + Log.i(TAG, "clickShareCollectionButton: Waiting for $waitingTime ms for share collection button to exist") shareCollectionButton().waitForExists(waitingTime) + Log.i(TAG, "clickShareCollectionButton: Waited for $waitingTime ms for share collection button to exist") + Log.i(TAG, "clickShareCollectionButton: Trying to click share collection button") shareCollectionButton().click() + Log.i(TAG, "clickShareCollectionButton: Clicked share collection button") ShareOverlayRobot().interact() return ShareOverlayRobot.Transition() @@ -213,21 +275,14 @@ fun collectionRobot(interact: CollectionRobot.() -> Unit): CollectionRobot.Trans return CollectionRobot.Transition() } -private fun collectionTitle(title: String) = - mDevice.findObject( - UiSelector() - .text(title), - ) +private fun collectionTitle(title: String) = itemWithText(title) private fun collectionThreeDotButton(rule: ComposeTestRule) = rule.onNode(hasContentDescription("Collection menu")) private fun collectionListItem(title: String) = mDevice.findObject(UiSelector().text(title)) -private fun shareCollectionButton() = - mDevice.findObject( - UiSelector().description("Share"), - ) +private fun shareCollectionButton() = itemWithDescription("Share") private fun removeTabFromCollectionButton(title: String) = mDevice.findObject( @@ -245,9 +300,7 @@ private fun collectionNameTextField() = // collection name text field, when saving from the main menu option private fun mainMenuEditCollectionNameField() = - mDevice.findObject( - UiSelector().resourceId("$packageName:id/name_collection_edittext"), - ) + itemWithResId("$packageName:id/name_collection_edittext") private fun addNewCollectionButton() = mDevice.findObject(UiSelector().text("Add new collection")) @@ -256,7 +309,7 @@ private fun backButton() = mDevice.findObject( UiSelector().resourceId("$packageName:id/back_button"), ) -private val addCollectionButtonPanel = +private fun addCollectionButtonPanel() = itemWithResId("$packageName:id/buttonPanel") -private val addCollectionOkButton = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog()) +private fun addCollectionOkButton() = onView(withId(android.R.id.button1)).inRoot(RootMatchers.isDialog()) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTabDrawerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTabDrawerRobot.kt index baa7271b0..d42fd8e4d 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTabDrawerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTabDrawerRobot.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import android.view.View import androidx.compose.ui.semantics.SemanticsActions import androidx.compose.ui.test.ExperimentalTestApi @@ -42,12 +43,13 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import org.hamcrest.Matcher import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.HomeActivityComposeTestRule import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText -import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime +import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.clickAtLocationInView import org.mozilla.fenix.helpers.idlingresource.BottomSheetBehaviorStateIdlingResource @@ -62,25 +64,37 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest fun verifyNormalBrowsingButtonIsSelected(isSelected: Boolean = true) { if (isSelected) { + Log.i(TAG, "verifyNormalBrowsingButtonIsSelected: Trying to verify that the normal browsing button is selected") composeTestRule.normalBrowsingButton().assertIsSelected() + Log.i(TAG, "verifyNormalBrowsingButtonIsSelected: Verified that the normal browsing button is selected") } else { + Log.i(TAG, "verifyNormalBrowsingButtonIsSelected: Trying to verify that the normal browsing button is not selected") composeTestRule.normalBrowsingButton().assertIsNotSelected() + Log.i(TAG, "verifyNormalBrowsingButtonIsSelected: Verified that the normal browsing button is not selected") } } fun verifyPrivateBrowsingButtonIsSelected(isSelected: Boolean = true) { if (isSelected) { + Log.i(TAG, "verifyPrivateBrowsingButtonIsSelected: Trying to verify that the private browsing button is selected") composeTestRule.privateBrowsingButton().assertIsSelected() + Log.i(TAG, "verifyPrivateBrowsingButtonIsSelected: Verified that the private browsing button is selected") } else { + Log.i(TAG, "verifyPrivateBrowsingButtonIsSelected: Trying to verify that the private browsing button is not selected") composeTestRule.privateBrowsingButton().assertIsNotSelected() + Log.i(TAG, "verifyPrivateBrowsingButtonIsSelected: Verified that the private browsing button is not selected") } } fun verifySyncedTabsButtonIsSelected(isSelected: Boolean = true) { if (isSelected) { + Log.i(TAG, "verifySyncedTabsButtonIsSelected: Trying to verify that the synced tabs button is selected") composeTestRule.syncedTabsButton().assertIsSelected() + Log.i(TAG, "verifySyncedTabsButtonIsSelected: Verified that the synced tabs button is selected") } else { + Log.i(TAG, "verifySyncedTabsButtonIsSelected: Trying to verify that the synced tabs button is not selected") composeTestRule.syncedTabsButton().assertIsNotSelected() + Log.i(TAG, "verifySyncedTabsButtonIsSelected: Verified that the synced tabs button is not selected") } } @@ -95,16 +109,23 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest fun verifyExistingOpenTabs(vararg titles: String) { titles.forEach { title -> + Log.i(TAG, "verifyExistingOpenTabs: Waiting for $waitingTime ms for tab with title: $title to exist") itemContainingText(title).waitForExists(waitingTime) + Log.i(TAG, "verifyExistingOpenTabs: Waited for $waitingTime ms for tab with title: $title to exist") + Log.i(TAG, "verifyExistingOpenTabs: Trying to verify that the open tab with title: $title exists") composeTestRule.tabItem(title).assertExists() + Log.i(TAG, "verifyExistingOpenTabs: Verified that the open tab with title: $title exists") } } - fun verifyOpenTabsOrder(title: String, position: Int) = + fun verifyOpenTabsOrder(title: String, position: Int) { + Log.i(TAG, "verifyOpenTabsOrder: Trying to verify that the open tab at position: $position has title: $title") composeTestRule.normalTabsList() .onChildAt(position - 1) .assert(hasTestTag(TabsTrayTestTag.tabItemRoot)) .assert(hasAnyChild(hasText(title))) + Log.i(TAG, "verifyOpenTabsOrder: Verified that the open tab at position: $position has title: $title") + } fun verifyNoExistingOpenTabs(vararg titles: String) { titles.forEach { title -> @@ -116,110 +137,163 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest } fun verifyNormalTabsList() { + Log.i(TAG, "verifyNormalTabsList: Trying to verify that the normal tabs list exists") composeTestRule.normalTabsList().assertExists() + Log.i(TAG, "verifyNormalTabsList: Verified that the normal tabs list exists") } fun verifyPrivateTabsList() { + Log.i(TAG, "verifyPrivateTabsList: Trying to verify that the private tabs list exists") composeTestRule.privateTabsList().assertExists() + Log.i(TAG, "verifyPrivateTabsList: Verified that the private tabs list exists") } fun verifySyncedTabsList() { + Log.i(TAG, "verifySyncedTabsList: Trying to verify that the synced tabs list exists") composeTestRule.syncedTabsList().assertExists() + Log.i(TAG, "verifySyncedTabsList: Verified that the synced tabs list exists") } fun verifyNoOpenTabsInNormalBrowsing() { + Log.i(TAG, "verifyNoOpenTabsInNormalBrowsing: Trying to verify that the empty normal tabs list exists") composeTestRule.emptyNormalTabsList().assertExists() + Log.i(TAG, "verifyNoOpenTabsInNormalBrowsing: Verified that the empty normal tabs list exists") } fun verifyNoOpenTabsInPrivateBrowsing() { + Log.i(TAG, "verifyNoOpenTabsInPrivateBrowsing: Trying to verify that the empty private tabs list exists") composeTestRule.emptyPrivateTabsList().assertExists() + Log.i(TAG, "verifyNoOpenTabsInPrivateBrowsing: Verified that the empty private tabs list exists") } fun verifyAccountSettingsButton() { + Log.i(TAG, "verifyAccountSettingsButton: Trying to verify that the \"Account settings\" menu button exists") composeTestRule.dropdownMenuItemAccountSettings().assertExists() + Log.i(TAG, "verifyAccountSettingsButton: Verified that the \"Account settings\" menu button exists") } fun verifyCloseAllTabsButton() { + Log.i(TAG, "verifyCloseAllTabsButton: Trying to verify that the \"Close all tabs\" menu button exists") composeTestRule.dropdownMenuItemCloseAllTabs().assertExists() + Log.i(TAG, "verifyCloseAllTabsButton: Verified that the \"Close all tabs\" menu button exists") } fun verifySelectTabsButton() { + Log.i(TAG, "verifySelectTabsButton: Trying to verify that the \"Select tabs\" menu button exists") composeTestRule.dropdownMenuItemSelectTabs().assertExists() + Log.i(TAG, "verifySelectTabsButton: Verified that the \"Select tabs\" menu button exists") } fun verifyShareAllTabsButton() { + Log.i(TAG, "verifyShareAllTabsButton: Trying to verify that the \"Share all tabs\" menu button exists") composeTestRule.dropdownMenuItemShareAllTabs().assertExists() + Log.i(TAG, "verifyShareAllTabsButton: Verified that the \"Share all tabs\" menu button exists") } fun verifyRecentlyClosedTabsButton() { + Log.i(TAG, "verifyRecentlyClosedTabsButton: Trying to verify that the \"Recently closed tabs\" menu button exists") composeTestRule.dropdownMenuItemRecentlyClosedTabs().assertExists() + Log.i(TAG, "verifyRecentlyClosedTabsButton: Verified that the \"Recently closed tabs\" menu button exists") } fun verifyTabSettingsButton() { + Log.i(TAG, "verifyTabSettingsButton: Trying to verify that the \"Tab settings\" menu button exists") composeTestRule.dropdownMenuItemTabSettings().assertExists() + Log.i(TAG, "verifyTabSettingsButton: Verified that the \"Tab settings\" menu button exists") } fun verifyThreeDotButton() { + Log.i(TAG, "verifyThreeDotButton: Trying to verify that the three dot button exists") composeTestRule.threeDotButton().assertExists() + Log.i(TAG, "verifyThreeDotButton: Verified that the three dot button exists") } fun verifyFab() { + Log.i(TAG, "verifyFab: Trying to verify that the new tab FAB button exists") composeTestRule.tabsTrayFab().assertExists() + Log.i(TAG, "verifyFab: Verified that the new tab FAB button exists") } fun verifyNormalTabCounter() { + Log.i(TAG, "verifyNormalTabCounter: Trying to verify that the normal tabs list counter exists") composeTestRule.normalTabsCounter().assertExists() + Log.i(TAG, "verifyNormalTabCounter: Verified that the normal tabs list counter exists") } /** * Verifies a tab's thumbnail when there is only one tab open. */ fun verifyTabThumbnail() { + Log.i(TAG, "verifyTabThumbnail: Trying to verify that the tab thumbnail exists") composeTestRule.tabThumbnail().assertExists() + Log.i(TAG, "verifyTabThumbnail: Verified that the tab thumbnail exists") } /** * Verifies a tab's close button when there is only one tab open. */ fun verifyTabCloseButton() { + Log.i(TAG, "verifyTabCloseButton: Trying to verify that the close tab button exists") composeTestRule.closeTabButton().assertExists() + Log.i(TAG, "verifyTabCloseButton: Verified that the close tab button exists") } fun verifyTabsTrayBehaviorState(expectedState: Int) { + Log.i(TAG, "verifyTabsTrayBehaviorState: Trying to verify that the tabs tray state matches: $expectedState") tabsTrayView().check(ViewAssertions.matches(BottomSheetBehaviorStateMatcher(expectedState))) + Log.i(TAG, "verifyTabsTrayBehaviorState: Verified that the tabs tray state matches: $expectedState") } fun verifyMinusculeHalfExpandedRatio() { + Log.i(TAG, "verifyMinusculeHalfExpandedRatio: Trying to verify the tabs tray half expanded ratio") tabsTrayView().check(ViewAssertions.matches(BottomSheetBehaviorHalfExpandedMaxRatioMatcher(0.001f))) + Log.i(TAG, "verifyMinusculeHalfExpandedRatio: Verified the tabs tray half expanded ratio") } fun verifyTabTrayIsOpen() { + Log.i(TAG, "verifyTabTrayIsOpen: Trying to verify that the tabs tray exists") composeTestRule.tabsTray().assertExists() + Log.i(TAG, "verifyTabTrayIsOpen: Verified that the tabs tray exists") } fun verifyTabTrayIsClosed() { + Log.i(TAG, "verifyTabTrayIsClosed: Trying to verify that the tabs tray does not exist") composeTestRule.tabsTray().assertDoesNotExist() + Log.i(TAG, "verifyTabTrayIsClosed: Verified that the tabs tray does not exist") } /** * Closes a tab when there is only one tab open. */ + @OptIn(ExperimentalTestApi::class) fun closeTab() { + Log.i(TAG, "closeTab: Waiting until the close tab button exists") + composeTestRule.waitUntilAtLeastOneExists(hasTestTag(TabsTrayTestTag.tabItemClose)) + Log.i(TAG, "closeTab: Waited until the close tab button exists") + Log.i(TAG, "closeTab: Trying to verify that the close tab button exists") + composeTestRule.closeTabButton().assertExists() + Log.i(TAG, "closeTab: Verified that the close tab button exists") + Log.i(TAG, "closeTab: Trying to click the close tab button") composeTestRule.closeTabButton().performClick() + Log.i(TAG, "closeTab: Clicked the close tab button") } /** * Swipes a tab with [title] left. */ fun swipeTabLeft(title: String) { + Log.i(TAG, "swipeTabLeft: Trying to perform swipe left action on tab: $title") composeTestRule.tabItem(title).performTouchInput { swipeLeft() } + Log.i(TAG, "swipeTabLeft: Performed swipe left action on tab: $title") } /** * Swipes a tab with [title] right. */ fun swipeTabRight(title: String) { + Log.i(TAG, "swipeTabRight: Trying to perform swipe right action on tab: $title") composeTestRule.tabItem(title).performTouchInput { swipeRight() } + Log.i(TAG, "swipeTabRight: Performed swipe right action on tab: $title") } /** @@ -230,8 +304,12 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest collectionName: String, firstCollection: Boolean = true, ) { + Log.i(TAG, "createCollection: Trying to click the three dot button") composeTestRule.threeDotButton().performClick() + Log.i(TAG, "createCollection: Clicked the three dot button") + Log.i(TAG, "createCollection: Trying to click the \"Select tabs\" menu button") composeTestRule.dropdownMenuItemSelectTabs().performClick() + Log.i(TAG, "createCollection: Clicked the \"Select tabs\" menu button") for (tab in tabTitles) { selectTab(tab) @@ -250,24 +328,32 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest */ @OptIn(ExperimentalTestApi::class) fun selectTab(title: String) { - composeTestRule.waitUntilExactlyOneExists(hasText(title), TestAssetHelper.waitingTime) + Log.i(TAG, "selectTab: Waiting for $waitingTime ms until the tab with title: $title exists") + composeTestRule.waitUntilExactlyOneExists(hasText(title), waitingTime) + Log.i(TAG, "selectTab: Waited for $waitingTime ms until the tab with title: $title exists") + Log.i(TAG, "selectTab: Trying to click tab with title: $title") composeTestRule.tabItem(title).performClick() + Log.i(TAG, "selectTab: Clicked tab with title: $title") } /** * Performs a long click on a tab with [title]. */ fun longClickTab(title: String) { + Log.i(TAG, "longClickTab: Trying to long click tab with title: $title") composeTestRule.tabItem(title) .performTouchInput { longClick(durationMillis = Constants.LONG_CLICK_DURATION) } + Log.i(TAG, "longClickTab: Long clicked tab with title: $title") } /** * Verifies the multi selection counter displays [numOfTabs]. */ fun verifyTabsMultiSelectionCounter(numOfTabs: Int) { + Log.i(TAG, "verifyTabsMultiSelectionCounter: Trying to verify that $numOfTabs tabs are selected") composeTestRule.multiSelectionCounter() .assert(hasText("$numOfTabs selected")) + Log.i(TAG, "verifyTabsMultiSelectionCounter: Verified that $numOfTabs tabs are selected") } /** @@ -275,9 +361,13 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest */ @OptIn(ExperimentalTestApi::class) fun verifyTabMediaControlButtonState(action: String) { + Log.i(TAG, "verifyTabMediaControlButtonStateTab: Waiting for $waitingTime ms until the media tab control button: $action exists") composeTestRule.waitUntilAtLeastOneExists(hasContentDescription(action), waitingTime) + Log.i(TAG, "verifyTabMediaControlButtonStateTab: Waited for $waitingTime ms until the media tab control button: $action exists") + Log.i(TAG, "verifyTabMediaControlButtonStateTab: Trying to verify that the tab media control button: $action exists") composeTestRule.tabMediaControlButton(action) .assertExists() + Log.i(TAG, "verifyTabMediaControlButtonStateTab: Verified tab media control button: $action exists") } /** @@ -285,90 +375,118 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest */ @OptIn(ExperimentalTestApi::class) fun clickTabMediaControlButton(action: String) { + Log.i(TAG, "clickTabMediaControlButton: Waiting for $waitingTime ms until the media tab control button: $action exists") composeTestRule.waitUntilAtLeastOneExists(hasContentDescription(action), waitingTime) + Log.i(TAG, "clickTabMediaControlButton: Waited for $waitingTime ms until the media tab control button: $action exists") + Log.i(TAG, "clickTabMediaControlButton: Trying to click the tab media control button: $action") composeTestRule.tabMediaControlButton(action) .performClick() + Log.i(TAG, "clickTabMediaControlButton: Clicked the tab media control button: $action") } /** * Closes a tab with a given [title]. */ fun closeTabWithTitle(title: String) { + Log.i(TAG, "closeTabWithTitle: Trying to click the close button for tab with title: $title") composeTestRule.onAllNodesWithTag(TabsTrayTestTag.tabItemClose) .filter(hasParent(hasText(title))) .onFirst() .performClick() + Log.i(TAG, "closeTabWithTitle: Clicked the close button for tab with title: $title") } class Transition(private val composeTestRule: HomeActivityComposeTestRule) { fun openNewTab(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "openNewTab: Waiting for device to be idle") mDevice.waitForIdle() - + Log.i(TAG, "openNewTab: Waited for device to be idle") + Log.i(TAG, "openNewTab: Trying to click the new tab FAB button") composeTestRule.tabsTrayFab().performClick() + Log.i(TAG, "openNewTab: Clicked the new tab FAB button") SearchRobot().interact() return SearchRobot.Transition() } fun toggleToNormalTabs(interact: ComposeTabDrawerRobot.() -> Unit): Transition { + Log.i(TAG, "toggleToNormalTabs: Trying to click the normal browsing button") composeTestRule.normalBrowsingButton().performClick() + Log.i(TAG, "toggleToNormalTabs: Clicked the normal browsing button") ComposeTabDrawerRobot(composeTestRule).interact() return Transition(composeTestRule) } fun toggleToPrivateTabs(interact: ComposeTabDrawerRobot.() -> Unit): Transition { + Log.i(TAG, "toggleToPrivateTabs: Trying to click the private browsing button") composeTestRule.privateBrowsingButton().performClick() + Log.i(TAG, "toggleToPrivateTabs: Clicked the private browsing button") ComposeTabDrawerRobot(composeTestRule).interact() return Transition(composeTestRule) } fun toggleToSyncedTabs(interact: ComposeTabDrawerRobot.() -> Unit): Transition { + Log.i(TAG, "toggleToSyncedTabs: Trying to click the synced tabs button") composeTestRule.syncedTabsButton().performClick() + Log.i(TAG, "toggleToSyncedTabs: Clicked the synced tabs button") ComposeTabDrawerRobot(composeTestRule).interact() return Transition(composeTestRule) } fun clickSignInToSyncButton(interact: SyncSignInRobot.() -> Unit): SyncSignInRobot.Transition { + Log.i(TAG, "clickSignInToSyncButton: Trying to click the sign in to sync button and wait for $waitingTimeShort ms for a new window") itemContainingText(getStringResource(R.string.sync_sign_in)) - .clickAndWaitForNewWindow(TestAssetHelper.waitingTimeShort) + .clickAndWaitForNewWindow(waitingTimeShort) + Log.i(TAG, "clickSignInToSyncButton: Clicked the sign in to sync button and waited for $waitingTimeShort ms for a new window") SyncSignInRobot().interact() return SyncSignInRobot.Transition() } fun openThreeDotMenu(interact: ComposeTabDrawerRobot.() -> Unit): Transition { + Log.i(TAG, "openThreeDotMenu: Trying to click the three dot button") composeTestRule.threeDotButton().performClick() + Log.i(TAG, "openThreeDotMenu: Clicked three dot button") ComposeTabDrawerRobot(composeTestRule).interact() return Transition(composeTestRule) } fun closeAllTabs(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "closeAllTabs: Trying to click the \"Close all tabs\" menu button") composeTestRule.dropdownMenuItemCloseAllTabs().performClick() + Log.i(TAG, "closeAllTabs: Clicked the \"Close all tabs\" menu button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun openTab(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - composeTestRule.tabItem(title) - .performScrollTo() - .performClick() + Log.i(TAG, "openTab: Trying to scroll to tab with title: $title") + composeTestRule.tabItem(title).performScrollTo() + Log.i(TAG, "openTab: Scrolled to tab with title: $title") + Log.i(TAG, "openTab: Trying to click tab with title: $title") + composeTestRule.tabItem(title).performClick() + Log.i(TAG, "openTab: Clicked tab with title: $title") BrowserRobot().interact() return BrowserRobot.Transition() } fun openPrivateTab(position: Int, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openPrivateTab: Trying to click private tab at position: ${position + 1}") composeTestRule.privateTabsList() .onChildren()[position] .performClick() + Log.i(TAG, "openPrivateTab: Clicked private tab at position: ${position + 1}") BrowserRobot().interact() return BrowserRobot.Transition() } fun openNormalTab(position: Int, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openNormalTab: Trying to click tab at position: ${position + 1}") composeTestRule.normalTabsList() .onChildren()[position] .performClick() + Log.i(TAG, "openNormalTab: Clicked tab at position: ${position + 1}") BrowserRobot().interact() return BrowserRobot.Transition() @@ -377,7 +495,9 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest fun clickTopBar(interact: ComposeTabDrawerRobot.() -> Unit): Transition { // The topBar contains other views. // Don't do the default click in the middle, rather click in some free space - top right. + Log.i(TAG, "clickTopBar: Trying to click the tabs tray top bar") Espresso.onView(ViewMatchers.withId(R.id.topBar)).clickAtLocationInView(GeneralLocation.TOP_RIGHT) + Log.i(TAG, "clickTopBar: Clicked the tabs tray top bar") ComposeTabDrawerRobot(composeTestRule).interact() return Transition(composeTestRule) } @@ -434,21 +554,27 @@ class ComposeTabDrawerRobot(private val composeTestRule: HomeActivityComposeTest } fun closeTabDrawer(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeTabDrawer: Trying to close the tabs tray by clicking the handle") composeTestRule.bannerHandle().performSemanticsAction(SemanticsActions.OnClick) + Log.i(TAG, "closeTabDrawer: Closed the tabs tray by clicking the handle") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickSaveCollection(interact: CollectionRobot.() -> Unit): CollectionRobot.Transition { + Log.i(TAG, "clickSaveCollection: Trying to click the collections button") composeTestRule.collectionsButton().performClick() + Log.i(TAG, "clickSaveCollection: Clicked collections button") CollectionRobot().interact() return CollectionRobot.Transition() } fun clickShareAllTabsButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition { + Log.i(TAG, "clickShareAllTabsButton: Trying to click the \"Share all tabs\" menu button button") composeTestRule.dropdownMenuItemShareAllTabs().performClick() + Log.i(TAG, "clickShareAllTabsButton: Clicked the \"Share all tabs\" menu button button") ShareOverlayRobot().interact() return ShareOverlayRobot.Transition() @@ -468,7 +594,9 @@ fun composeTabDrawer(composeTestRule: HomeActivityComposeTestRule, interact: Com * Clicks on the Collections button in the Tabs Tray banner and opens a transition in the [CollectionRobot]. */ private fun clickCollectionsButton(composeTestRule: HomeActivityComposeTestRule, interact: CollectionRobot.() -> Unit): CollectionRobot.Transition { + Log.i(TAG, "clickCollectionsButton: Trying to click the collections button") composeTestRule.collectionsButton().performClick() + Log.i(TAG, "clickCollectionsButton: Clicked the collections button") CollectionRobot().interact() return CollectionRobot.Transition() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTopSitesRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTopSitesRobot.kt index 0edba483d..53f1121bf 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTopSitesRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ComposeTopSitesRobot.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.filter import androidx.compose.ui.test.hasAnyChild @@ -16,14 +17,13 @@ import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTouchInput -import androidx.test.uiautomator.UiSelector +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.HomeActivityComposeTestRule import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort -import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.packageName import org.mozilla.fenix.home.topsites.TopSitesTestTag @@ -34,21 +34,31 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR @OptIn(ExperimentalTestApi::class) fun verifyExistingTopSitesList() { - composeTestRule.waitUntilExactlyOneExists(hasTestTag(TopSitesTestTag.topSites), timeoutMillis = waitingTime) + Log.i(TAG, "verifyExistingTopSitesList: Waiting for $waitingTime ms until the top sites list exists") + composeTestRule.waitUntilAtLeastOneExists(hasTestTag(TopSitesTestTag.topSites), timeoutMillis = waitingTime) + Log.i(TAG, "verifyExistingTopSitesList: Waited for $waitingTime ms until the top sites list to exists") } @OptIn(ExperimentalTestApi::class) fun verifyExistingTopSiteItem(vararg titles: String) { titles.forEach { title -> - mDevice.findObject(UiSelector().textContains(title)).waitForExists(waitingTimeShort) + Log.i(TAG, "verifyExistingTopSiteItem: Waiting for $waitingTime ms until the top site with title: $title exists") + composeTestRule.waitUntilAtLeastOneExists(hasText(title), timeoutMillis = waitingTime) + Log.i(TAG, "verifyExistingTopSiteItem: Waited for $waitingTime ms until the top site with title: $title exists") + Log.i(TAG, "verifyExistingTopSiteItem: Trying to verify that the top site with title: $title exists") composeTestRule.topSiteItem(title).assertExists() + Log.i(TAG, "verifyExistingTopSiteItem: Verified that the top site with title: $title exists") } } fun verifyNotExistingTopSiteItem(vararg titles: String) { titles.forEach { title -> + Log.i(TAG, "verifyNotExistingTopSiteItem: Waiting for $waitingTime ms for top site with title: $title to exist") itemContainingText(title).waitForExists(waitingTime) + Log.i(TAG, "verifyNotExistingTopSiteItem: Waited for $waitingTime ms for top site with title: $title to exist") + Log.i(TAG, "verifyNotExistingTopSiteItem: Trying to verify that top site with title: $title does not exist") composeTestRule.topSiteItem(title).assertDoesNotExist() + Log.i(TAG, "verifyNotExistingTopSiteItem: Verified that top site with title: $title does not exist") } } @@ -59,15 +69,21 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR } fun verifyTopSiteContextMenuOpenInPrivateTabButton() { + Log.i(TAG, "verifyTopSiteContextMenuOpenInPrivateTabButton: Trying to verify that the \"Open in private tab\" menu button exists") composeTestRule.contextMenuItemOpenInPrivateTab().assertExists() + Log.i(TAG, "verifyTopSiteContextMenuOpenInPrivateTabButton: Verified that the \"Open in private tab\" menu button exists") } fun verifyTopSiteContextMenuRenameButton() { + Log.i(TAG, "verifyTopSiteContextMenuRenameButton: Trying to verify that the \"Rename\" menu button exists") composeTestRule.contextMenuItemRename().assertExists() + Log.i(TAG, "verifyTopSiteContextMenuRenameButton: Verified that the \"Rename\" menu button exists") } fun verifyTopSiteContextMenuRemoveButton() { + Log.i(TAG, "verifyTopSiteContextMenuRemoveButton: Trying to verify that the \"Remove\" menu button exists") composeTestRule.contextMenuItemRemove().assertExists() + Log.i(TAG, "verifyTopSiteContextMenuRemoveButton: Verified that the \"Remove\" menu button exists") } class Transition(private val composeTestRule: HomeActivityComposeTestRule) { @@ -76,7 +92,12 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR title: String, interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { - composeTestRule.topSiteItem(title).performScrollTo().performClick() + Log.i(TAG, "openTopSiteTabWithTitle: Trying to scroll to top site with title: $title") + composeTestRule.topSiteItem(title).performScrollTo() + Log.i(TAG, "openTopSiteTabWithTitle: Scrolled to top site with title: $title") + Log.i(TAG, "openTopSiteTabWithTitle: Trying to click top site with title: $title") + composeTestRule.topSiteItem(title).performClick() + Log.i(TAG, "openTopSiteTabWithTitle: Clicked top site with title: $title") BrowserRobot().interact() return BrowserRobot.Transition() @@ -85,7 +106,9 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR fun openTopSiteInPrivate( interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { + Log.i(TAG, "openTopSiteInPrivate: Trying to click the \"Open in private tab\" menu button") composeTestRule.contextMenuItemOpenInPrivateTab().performClick() + Log.i(TAG, "openTopSiteInPrivate: Clicked the \"Open in private tab\" menu button") composeTestRule.waitForIdle() BrowserRobot().interact() @@ -96,9 +119,12 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR title: String, interact: ComposeTopSitesRobot.() -> Unit, ): Transition { - composeTestRule.topSiteItem(title).performScrollTo().performTouchInput { - longClick() - } + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Trying to scroll to top site with title: $title") + composeTestRule.topSiteItem(title).performScrollTo() + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Scrolled to top site with title: $title") + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Trying to long click top site with title: $title") + composeTestRule.topSiteItem(title).performTouchInput { longClick() } + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Long clicked top site with title: $title") ComposeTopSitesRobot(composeTestRule).interact() return Transition(composeTestRule) @@ -108,13 +134,21 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR title: String, interact: ComposeTopSitesRobot.() -> Unit, ): Transition { + Log.i(TAG, "renameTopSite: Trying to click the \"Rename\" menu button") composeTestRule.contextMenuItemRename().performClick() + Log.i(TAG, "renameTopSite: Clicked the \"Rename\" menu button") itemWithResId("$packageName:id/top_site_title") .also { + Log.i(TAG, "renameTopSite: Waiting for $waitingTimeShort ms for top site rename text box to exist") it.waitForExists(waitingTimeShort) + Log.i(TAG, "renameTopSite: Waited for $waitingTimeShort ms for top site rename text box to exist") + Log.i(TAG, "renameTopSite: Trying to set top site rename text box text to: $title") it.setText(title) + Log.i(TAG, "renameTopSite: Top site rename text box text was set to: $title") } + Log.i(TAG, "renameTopSite: Trying to click the \"Ok\" dialog button") itemWithResIdContainingText("android:id/button1", "OK").click() + Log.i(TAG, "renameTopSite: Clicked the \"Ok\" dialog button") ComposeTopSitesRobot(composeTestRule).interact() return Transition(composeTestRule) @@ -124,23 +158,16 @@ class ComposeTopSitesRobot(private val composeTestRule: HomeActivityComposeTestR fun removeTopSite( interact: ComposeTopSitesRobot.() -> Unit, ): Transition { + Log.i(TAG, "removeTopSite: Trying to click the \"Remove\" menu button") composeTestRule.contextMenuItemRemove().performClick() + Log.i(TAG, "removeTopSite: Clicked the \"Remove\" menu button") + Log.i(TAG, "removeTopSite: Waiting for $waitingTime ms until the \"Remove\" menu button does not exist") composeTestRule.waitUntilDoesNotExist(hasTestTag(TopSitesTestTag.remove), waitingTime) + Log.i(TAG, "removeTopSite: Waited for $waitingTime ms until the \"Remove\" menu button does not exist") ComposeTopSitesRobot(composeTestRule).interact() return Transition(composeTestRule) } - - @OptIn(ExperimentalTestApi::class) - fun deleteTopSiteFromHistory( - interact: BrowserRobot.() -> Unit, - ): BrowserRobot.Transition { - composeTestRule.contextMenuItemRemove().performClick() - composeTestRule.waitUntilDoesNotExist(hasTestTag(TopSitesTestTag.remove), waitingTime) - - BrowserRobot().interact() - return BrowserRobot.Transition() - } } } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt index fd76071c1..3c4d37710 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/CustomTabRobot.kt @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.assertion.ViewAssertions.matches @@ -14,6 +15,7 @@ import androidx.test.uiautomator.By import androidx.test.uiautomator.UiSelector import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.LONG_CLICK_DURATION +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText @@ -43,21 +45,27 @@ class CustomTabRobot { itemWithDescription(getStringResource(R.string.mozac_feature_customtabs_share_link)), ) - fun verifyMainMenuButton() = assertUIObjectExists(mainMenuButton) + fun verifyMainMenuButton() = assertUIObjectExists(mainMenuButton()) fun verifyDesktopSiteButtonExists() { + Log.i(TAG, "verifyDesktopSiteButtonExists: Trying to verify that the request desktop site button is displayed") desktopSiteButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyDesktopSiteButtonExists: Verified that the request desktop site button is displayed") } fun verifyFindInPageButtonExists() { + Log.i(TAG, "verifyFindInPageButtonExists: Trying to verify that the find in page button is displayed") findInPageButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyFindInPageButtonExists: Verified that the find in page button is displayed") } fun verifyPoweredByTextIsDisplayed() = assertUIObjectExists(itemContainingText("POWERED BY $appName")) fun verifyOpenInBrowserButtonExists() { + Log.i(TAG, "verifyOpenInBrowserButtonExists: Trying to verify that the \"Open in Firefox\" button is displayed") openInBrowserButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyOpenInBrowserButtonExists: Verified that the \"Open in Firefox\" button is displayed") } fun verifyBackButtonExists() = assertUIObjectExists(itemWithDescription("Back")) @@ -69,7 +77,9 @@ class CustomTabRobot { fun verifyCustomMenuItem(label: String) = assertUIObjectExists(itemContainingText(label)) fun verifyCustomTabCloseButton() { + Log.i(TAG, "verifyCustomTabCloseButton: Trying to verify that the close custom tab button is displayed") closeButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyCustomTabCloseButton: Verified that the close custom tab button is displayed") } fun verifyCustomTabToolbarTitle(title: String) { @@ -103,12 +113,16 @@ class CustomTabRobot { mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")), waitingTime, ) + Log.i(TAG, "longCLickAndCopyToolbarUrl: Trying to long click the custom tab toolbar") customTabToolbar().click(LONG_CLICK_DURATION) + Log.i(TAG, "longCLickAndCopyToolbarUrl: Long clicked the custom tab toolbar") clickContextMenuItem("Copy") } fun fillAndSubmitLoginCredentials(userName: String, password: String) { + Log.i(TAG, "fillAndSubmitLoginCredentials: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "fillAndSubmitLoginCredentials: Waited for device to be idle for $waitingTime ms") setPageObjectText(itemWithResId("username"), userName) setPageObjectText(itemWithResId("password"), password) clickPageObject(itemWithResId("submit")) @@ -118,9 +132,17 @@ class CustomTabRobot { ) } - fun waitForPageToLoad() = progressBar.waitUntilGone(waitingTime) + fun waitForPageToLoad() { + Log.i(TAG, "waitForPageToLoad: Waiting for $waitingTime ms until progress bar is gone") + progressBar().waitUntilGone(waitingTime) + Log.i(TAG, "waitForPageToLoad: Waited for $waitingTime ms until progress bar was gone") + } - fun clickCustomTabCloseButton() = closeButton().click() + fun clickCustomTabCloseButton() { + Log.i(TAG, "clickCustomTabCloseButton: Trying to click close custom tab button") + closeButton().click() + Log.i(TAG, "clickCustomTabCloseButton: Clicked close custom tab button") + } fun verifyCustomTabActionButton(customTabActionButtonDescription: String) = assertUIObjectExists(itemWithDescription(customTabActionButtonDescription)) @@ -133,9 +155,13 @@ class CustomTabRobot { class Transition { fun openMainMenu(interact: CustomTabRobot.() -> Unit): Transition { - mainMenuButton.also { + mainMenuButton().also { + Log.i(TAG, "openMainMenu: Waiting for $waitingTime ms for the main menu button to exist") it.waitForExists(waitingTime) + Log.i(TAG, "openMainMenu: Waited for $waitingTime ms for the main menu button to exist") + Log.i(TAG, "openMainMenu: Trying to click the main menu button") it.click() + Log.i(TAG, "openMainMenu: Clicked the main menu button") } CustomTabRobot().interact() @@ -143,14 +169,18 @@ class CustomTabRobot { } fun clickOpenInBrowserButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "clickOpenInBrowserButton: Trying to click the \"Open in Firefox\" button") openInBrowserButton().perform(click()) + Log.i(TAG, "clickOpenInBrowserButton: Clicked the \"Open in Firefox\" button") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickShareButton(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition { + Log.i(TAG, "clickShareButton: Trying to click the share button") itemWithDescription(getStringResource(R.string.mozac_feature_customtabs_share_link)).click() + Log.i(TAG, "clickShareButton: Clicked the share button") ShareOverlayRobot().interact() return ShareOverlayRobot.Transition() @@ -163,7 +193,7 @@ fun customTabScreen(interact: CustomTabRobot.() -> Unit): CustomTabRobot.Transit return CustomTabRobot.Transition() } -private val mainMenuButton = itemWithResId("$packageName:id/mozac_browser_toolbar_menu") +private fun mainMenuButton() = itemWithResId("$packageName:id/mozac_browser_toolbar_menu") private fun desktopSiteButton() = onView(withId(R.id.switch_widget)) @@ -175,7 +205,7 @@ private fun closeButton() = onView(withContentDescription("Return to previous ap private fun customTabToolbar() = mDevice.findObject(By.res("$packageName:id/toolbar")) -private val progressBar = +private fun progressBar() = mDevice.findObject( UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_progress"), ) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt index 975000dd2..eab72fffb 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/DownloadRobot.kt @@ -51,9 +51,8 @@ class DownloadRobot { fun verifyDownloadPrompt(fileName: String) { var currentTries = 0 while (currentTries++ < 3) { - Log.i(TAG, "verifyDownloadPrompt: While loop currentTries = $currentTries") + Log.i(TAG, "verifyDownloadPrompt: Started try #$currentTries") try { - Log.i(TAG, "verifyDownloadPrompt: Try block") assertUIObjectExists( itemWithResId("$packageName:id/download_button"), itemContainingText(fileName), @@ -61,7 +60,7 @@ class DownloadRobot { break } catch (e: AssertionError) { - Log.i(TAG, "verifyDownloadPrompt: Catch block") + Log.i(TAG, "verifyDownloadPrompt: AssertionError caught, executing fallback methods") Log.e("DOWNLOAD_ROBOT", "Failed to find locator: ${e.localizedMessage}") browserScreen { @@ -96,11 +95,12 @@ class DownloadRobot { ) fun clickTryAgainButton() { + Log.i(TAG, "clickTryAgainButton: Trying to click the \"TRY AGAIN\" in app prompt button") itemWithResIdAndText( "$packageName:id/download_dialog_action_button", "Try Again", ).click() - Log.i(TAG, "clickTryAgainButton: Clicked \"TRY AGAIN\" in app prompt button") + Log.i(TAG, "clickTryAgainButton: Clicked the \"TRY AGAIN\" in app prompt button") } fun verifyPhotosAppOpens() = assertExternalAppOpens(GOOGLE_APPS_PHOTOS) @@ -111,34 +111,40 @@ class DownloadRobot { fun verifyDownloadedFileIcon() = assertUIObjectExists(itemWithResId("$packageName:id/favicon")) fun verifyEmptyDownloadsList() { - Log.i(TAG, "verifyEmptyDownloadsList: Looking for empty download list") + Log.i(TAG, "verifyEmptyDownloadsList: Waiting for $waitingTime ms for for empty download list to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/download_empty_view")) .waitForExists(waitingTime) + Log.i(TAG, "verifyEmptyDownloadsList: Waited for $waitingTime ms for for empty download list to exist") + Log.i(TAG, "verifyEmptyDownloadsList: Trying to verify that the \"No downloaded files\" list message is displayed") onView(withText("No downloaded files")).check(matches(isDisplayed())) - Log.i(TAG, "verifyEmptyDownloadsList: Verified \"No downloaded files\" list message") + Log.i(TAG, "verifyEmptyDownloadsList: Verified that the \"No downloaded files\" list message is displayed") } fun waitForDownloadsListToExist() = assertUIObjectExists(itemWithResId("$packageName:id/download_list")) fun openDownloadedFile(fileName: String) { - downloadedFile(fileName) - .check(matches(isDisplayed())) - .click() + Log.i(TAG, "openDownloadedFile: Trying to verify that the downloaded file: $fileName is displayed") + downloadedFile(fileName).check(matches(isDisplayed())) + Log.i(TAG, "openDownloadedFile: Verified that the downloaded file: $fileName is displayed") + Log.i(TAG, "openDownloadedFile: Trying to click downloaded file: $fileName") + downloadedFile(fileName).click() Log.i(TAG, "openDownloadedFile: Clicked downloaded file: $fileName") } fun deleteDownloadedItem(fileName: String) { + Log.i(TAG, "deleteDownloadedItem: Trying to click the trash bin icon to delete downloaded file: $fileName") onView( allOf( withId(R.id.overflow_menu), hasSibling(withText(fileName)), ), ).click() - Log.i(TAG, "deleteDownloadedItem: Deleted downloaded file: $fileName using trash bin icon") + Log.i(TAG, "deleteDownloadedItem: Clicked the trash bin icon to delete downloaded file: $fileName") } fun longClickDownloadedItem(title: String) { + Log.i(TAG, "longClickDownloadedItem: Trying to long click downloaded file: $title") onView( allOf( withId(R.id.title), @@ -149,21 +155,24 @@ class DownloadRobot { } fun selectDownloadedItem(title: String) { + Log.i(TAG, "selectDownloadedItem: Trying click downloaded file: $title to select it") onView( allOf( withId(R.id.title), withText(title), ), ).perform(click()) - Log.i(TAG, "selectDownloadedItem: Selected downloaded file: $title") + Log.i(TAG, "selectDownloadedItem: Clicked downloaded file: $title to select it") } fun openMultiSelectMoreOptionsMenu() { + Log.i(TAG, "openMultiSelectMoreOptionsMenu: Trying to click multi-select more options button") itemWithDescription(getStringResource(R.string.content_description_menu)).click() Log.i(TAG, "openMultiSelectMoreOptionsMenu: Clicked multi-select more options button") } fun clickMultiSelectRemoveButton() { + Log.i(TAG, "clickMultiSelectRemoveButton: Trying to click multi-select remove button") itemWithResIdContainingText("$packageName:id/title", "Remove").click() Log.i(TAG, "clickMultiSelectRemoveButton: Clicked multi-select remove button") } @@ -180,27 +189,31 @@ class DownloadRobot { class Transition { fun clickDownload(interact: DownloadRobot.() -> Unit): Transition { + Log.i(TAG, "clickDownload: Trying to click the \"Download\" download prompt button") downloadButton().click() - Log.i(TAG, "clickDownload: Clicked \"DOWNLOAD\" button from prompt") + Log.i(TAG, "clickDownload: Clicked the \"Download\" download prompt button") DownloadRobot().interact() return Transition() } fun closeDownloadPrompt(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeDownloadPrompt: Trying to click the close download prompt button") itemWithResId("$packageName:id/download_dialog_close_button").click() - Log.i(TAG, "closeDownloadPrompt: Dismissed download prompt by clicking close prompt button") + Log.i(TAG, "closeDownloadPrompt: Clicked the close download prompt button") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickOpen(type: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - Log.i(TAG, "clickOpen: Looking for \"OPEN\" download prompt button") + Log.i(TAG, "clickOpen: Waiting for $waitingTime ms for the for \"OPEN\" download prompt button to exist") openDownloadButton().waitForExists(waitingTime) + Log.i(TAG, "clickOpen: Waited for $waitingTime ms for the for \"OPEN\" download prompt button to exist") + Log.i(TAG, "clickOpen: Trying to click the \"OPEN\" download prompt button") openDownloadButton().click() - Log.i(TAG, "clickOpen: Clicked \"OPEN\" download prompt button") - + Log.i(TAG, "clickOpen: Clicked the \"OPEN\" download prompt button") + Log.i(TAG, "clickOpen: Trying to verify that the open intent is matched with associated data type") // verify open intent is matched with associated data type Intents.intended( allOf( @@ -208,37 +221,38 @@ class DownloadRobot { IntentMatchers.hasType(type), ), ) - Log.i(TAG, "clickOpen: Verified that open intent is matched with associated data type") + Log.i(TAG, "clickOpen: Verified that the open intent is matched with associated data type") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickAllowPermission(interact: DownloadRobot.() -> Unit): Transition { - Log.i(TAG, "clickAllowPermission: Looking for \"ALLOW\" permission button") mDevice.waitNotNull( Until.findObject(By.res(getPermissionAllowID() + ":id/permission_allow_button")), waitingTime, ) - + Log.i(TAG, "clickAllowPermission: Trying to click the \"ALLOW\" permission button") mDevice.findObject(By.res(getPermissionAllowID() + ":id/permission_allow_button")).click() - Log.i(TAG, "clickAllowPermission: Clicked \"ALLOW\" permission button") + Log.i(TAG, "clickAllowPermission: Clicked the \"ALLOW\" permission button") DownloadRobot().interact() return Transition() } fun exitDownloadsManagerToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "exitDownloadsManagerToBrowser: Trying to click the navigate up toolbar button") onView(withContentDescription("Navigate up")).click() - Log.i(TAG, "exitDownloadsManagerToBrowser: Exited download manager to browser by clicking the navigate up toolbar button") + Log.i(TAG, "exitDownloadsManagerToBrowser: Clicked the navigate up toolbar button") BrowserRobot().interact() return BrowserRobot.Transition() } fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBack: Trying to click the navigate up toolbar button") goBackButton().click() - Log.i(TAG, "exitDownloadsManagerToBrowser: Exited download manager to home screen by clicking the navigate up toolbar button") + Log.i(TAG, "goBack: Clicked the navigate up toolbar button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/EnhancedTrackingProtectionRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/EnhancedTrackingProtectionRobot.kt index 6c7cdeff3..365b30c98 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/EnhancedTrackingProtectionRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/EnhancedTrackingProtectionRobot.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.RootMatchers @@ -21,6 +22,7 @@ import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.not import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId @@ -36,15 +38,40 @@ import org.mozilla.fenix.helpers.isChecked * Implementation of Robot Pattern for Enhanced Tracking Protection UI. */ class EnhancedTrackingProtectionRobot { - fun verifyEnhancedTrackingProtectionSheetStatus(status: String, state: Boolean) = - assertEnhancedTrackingProtectionSheetStatus(status, state) + fun verifyEnhancedTrackingProtectionSheetStatus(status: String, state: Boolean) { + mDevice.waitNotNull(Until.findObjects(By.text("Protections are $status for this site"))) + Log.i(TAG, "verifyEnhancedTrackingProtectionSheetStatus: Trying to check ETP toggle is checked: $state") + onView(ViewMatchers.withResourceName("switch_widget")).check( + matches( + isChecked( + state, + ), + ), + ) + Log.i(TAG, "verifyEnhancedTrackingProtectionSheetStatus: Verified ETP toggle is checked: $state") + } - fun verifyETPSwitchVisibility(visible: Boolean) = assertETPSwitchVisibility(visible) + fun verifyETPSwitchVisibility(visible: Boolean) { + if (visible) { + Log.i(TAG, "verifyETPSwitchVisibility: Trying to verify ETP toggle is displayed") + enhancedTrackingProtectionSwitch() + .check(matches(isDisplayed())) + Log.i(TAG, "verifyETPSwitchVisibility: Verified ETP toggle is displayed") + } else { + Log.i(TAG, "verifyETPSwitchVisibility: Trying to verify ETP toggle is not displayed") + enhancedTrackingProtectionSwitch() + .check(matches(not(isDisplayed()))) + Log.i(TAG, "verifyETPSwitchVisibility: Verified ETP toggle is not displayed") + } + } fun verifyCrossSiteCookiesBlocked(isBlocked: Boolean) { assertUIObjectExists(itemWithResId("$packageName:id/cross_site_tracking")) - crossSiteCookiesBlockListButton.click() + Log.i(TAG, "verifyCrossSiteCookiesBlocked: Trying to click cross site cookies block list button") + crossSiteCookiesBlockListButton().click() + Log.i(TAG, "verifyCrossSiteCookiesBlocked: Clicked cross site cookies block list button") // Verifies the trackers block/allow list + Log.i(TAG, "verifyCrossSiteCookiesBlocked: Trying to verify cross site cookies are blocked: $isBlocked") onView(withId(R.id.details_blocking_header)) .check( matches( @@ -57,12 +84,16 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "verifyCrossSiteCookiesBlocked: Verified cross site cookies are blocked: $isBlocked") } fun verifySocialMediaTrackersBlocked(isBlocked: Boolean) { assertUIObjectExists(itemWithResId("$packageName:id/social_media_trackers")) - socialTrackersBlockListButton.click() + Log.i(TAG, "verifySocialMediaTrackersBlocked: Trying to click social trackers block list button") + socialTrackersBlockListButton().click() + Log.i(TAG, "verifySocialMediaTrackersBlocked: Clicked social trackers block list button") // Verifies the trackers block/allow list + Log.i(TAG, "verifySocialMediaTrackersBlocked: Trying to verify social trackers are blocked: $isBlocked") onView(withId(R.id.details_blocking_header)) .check( matches( @@ -75,13 +106,19 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "verifySocialMediaTrackersBlocked: Verified social trackers are blocked: $isBlocked") + Log.i(TAG, "verifySocialMediaTrackersBlocked: Trying to verify blocked social trackers list is displayed") onView(withId(R.id.blocking_text_list)).check(matches(isDisplayed())) + Log.i(TAG, "verifySocialMediaTrackersBlocked: Verified blocked social trackers list is displayed") } fun verifyFingerprintersBlocked(isBlocked: Boolean) { assertUIObjectExists(itemWithResId("$packageName:id/fingerprinters")) - fingerprintersBlockListButton.click() + Log.i(TAG, "verifyFingerprintersBlocked: Trying to click fingerprinters block list button") + fingerprintersBlockListButton().click() + Log.i(TAG, "verifyFingerprintersBlocked: Clicked fingerprinters block list button") // Verifies the trackers block/allow list + Log.i(TAG, "verifyFingerprintersBlocked: Trying to verify fingerprinters are blocked: $isBlocked") onView(withId(R.id.details_blocking_header)) .check( matches( @@ -94,13 +131,19 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "verifyFingerprintersBlocked: Verified fingerprinters are blocked: $isBlocked") + Log.i(TAG, "verifyFingerprintersBlocked: Trying to verify blocked fingerprinter trackers list is displayed") onView(withId(R.id.blocking_text_list)).check(matches(isDisplayed())) + Log.i(TAG, "verifyFingerprintersBlocked: Verified blocked fingerprinter trackers list is displayed") } fun verifyCryptominersBlocked(isBlocked: Boolean) { assertUIObjectExists(itemWithResId("$packageName:id/cryptominers")) - cryptominersBlockListButton.click() + Log.i(TAG, "verifyCryptominersBlocked: Trying to click cryptominers block list button") + cryptominersBlockListButton().click() + Log.i(TAG, "verifyCryptominersBlocked: Clicked cryptominers block list button") // Verifies the trackers block/allow list + Log.i(TAG, "verifyCryptominersBlocked: Trying to verify cryptominers are blocked: $isBlocked") onView(withId(R.id.details_blocking_header)) .check( matches( @@ -113,13 +156,19 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "verifyCryptominersBlocked: Verified cryptominers are blocked: $isBlocked") + Log.i(TAG, "verifyCryptominersBlocked: Trying to verify blocked cryptominers trackers list is displayed") onView(withId(R.id.blocking_text_list)).check(matches(isDisplayed())) + Log.i(TAG, "verifyCryptominersBlocked: Verified blocked cryptominers trackers list is displayed") } fun verifyTrackingContentBlocked(isBlocked: Boolean) { assertUIObjectExists(itemWithText("Tracking Content")) - trackingContentBlockListButton.click() + Log.i(TAG, "verifyTrackingContentBlocked: Trying to click tracking content block list button") + trackingContentBlockListButton().click() + Log.i(TAG, "verifyTrackingContentBlocked: Clicked tracking content block list button") // Verifies the trackers block/allow list + Log.i(TAG, "verifyTrackingContentBlocked: Trying to verify tracking content is blocked: $isBlocked") onView(withId(R.id.details_blocking_header)) .check( matches( @@ -132,10 +181,14 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "verifyTrackingContentBlocked: Verified tracking content is blocked: $isBlocked") + Log.i(TAG, "verifyTrackingContentBlocked: Trying to verify blocked tracking content trackers list is displayed") onView(withId(R.id.blocking_text_list)).check(matches(isDisplayed())) + Log.i(TAG, "verifyTrackingContentBlocked: Verified blocked tracking content trackers list is displayed") } fun viewTrackingContentBlockList() { + Log.i(TAG, "viewTrackingContentBlockList: Trying to verify blocked tracking content trackers") onView(withId(R.id.blocking_text_list)) .check( matches( @@ -148,6 +201,7 @@ class EnhancedTrackingProtectionRobot { ), ), ) + Log.i(TAG, "viewTrackingContentBlockList: Verified blocked tracking content trackers") } fun verifyETPSectionIsDisplayedInQuickSettingsSheet(isDisplayed: Boolean) = @@ -157,14 +211,24 @@ class EnhancedTrackingProtectionRobot { ) fun navigateBackToDetails() { + Log.i(TAG, "navigateBackToDetails: Trying to click details list back button") onView(withId(R.id.details_back)).click() + Log.i(TAG, "navigateBackToDetails: Clicked details list back button") } class Transition { fun openEnhancedTrackingProtectionSheet(interact: EnhancedTrackingProtectionRobot.() -> Unit): Transition { + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Waiting for $waitingTime ms for site security button to exist") pageSecurityIndicator().waitForExists(waitingTime) + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Waited for $waitingTime ms for site security button to exist") + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Trying to click site security button") pageSecurityIndicator().click() - assertSecuritySheetIsCompletelyDisplayed() + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Clicked site security button") + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Waiting for $waitingTime ms for quick actions sheet to exits") + mDevice.findObject(UiSelector().description(getStringResource(R.string.quick_settings_sheet))) + .waitForExists(waitingTime) + Log.i(TAG, "openEnhancedTrackingProtectionSheet: Waited for $waitingTime ms for quick actions sheet to exits") + assertUIObjectExists(itemWithResId("$packageName:id/quick_action_sheet")) EnhancedTrackingProtectionRobot().interact() return Transition() @@ -172,31 +236,45 @@ class EnhancedTrackingProtectionRobot { fun closeEnhancedTrackingProtectionSheet(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { // Back out of the Enhanced Tracking Protection sheet + Log.i(TAG, "closeEnhancedTrackingProtectionSheet: Trying to click device back button") mDevice.pressBack() + Log.i(TAG, "closeEnhancedTrackingProtectionSheet: Clicked device back button") BrowserRobot().interact() return BrowserRobot.Transition() } fun toggleEnhancedTrackingProtectionFromSheet(interact: EnhancedTrackingProtectionRobot.() -> Unit): Transition { + Log.i(TAG, "toggleEnhancedTrackingProtectionFromSheet: Trying to click ETP switch") enhancedTrackingProtectionSwitch().click() + Log.i(TAG, "toggleEnhancedTrackingProtectionFromSheet: Clicked ETP switch") EnhancedTrackingProtectionRobot().interact() return Transition() } fun openProtectionSettings(interact: SettingsSubMenuEnhancedTrackingProtectionRobot.() -> Unit): SettingsSubMenuEnhancedTrackingProtectionRobot.Transition { + Log.i(TAG, "openProtectionSettings: Waiting for $waitingTime ms for ETP sheet \"Details\" button to exist") openEnhancedTrackingProtectionDetails().waitForExists(waitingTime) + Log.i(TAG, "openProtectionSettings: Waited for $waitingTime ms for ETP sheet \"Details\" button to exist") + Log.i(TAG, "openProtectionSettings: Trying to click ETP sheet \"Details\" button") openEnhancedTrackingProtectionDetails().click() + Log.i(TAG, "openProtectionSettings: Clicked ETP sheet \"Details\" button") + Log.i(TAG, "openProtectionSettings: Trying to click \"Protection Settings\" button") trackingProtectionSettingsButton().click() + Log.i(TAG, "openProtectionSettings: Clicked \"Protection Settings\" button") SettingsSubMenuEnhancedTrackingProtectionRobot().interact() return SettingsSubMenuEnhancedTrackingProtectionRobot.Transition() } fun openDetails(interact: EnhancedTrackingProtectionRobot.() -> Unit): Transition { + Log.i(TAG, "openDetails: Waiting for $waitingTime ms for ETP sheet \"Details\" button to exist") openEnhancedTrackingProtectionDetails().waitForExists(waitingTime) + Log.i(TAG, "openDetails: Waited for $waitingTime ms for ETP sheet \"Details\" button to exist") + Log.i(TAG, "openDetails: Trying to click ETP sheet \"Details\" button") openEnhancedTrackingProtectionDetails().click() + Log.i(TAG, "openDetails: Clicked ETP sheet \"Details\" button") EnhancedTrackingProtectionRobot().interact() return Transition() @@ -209,27 +287,6 @@ fun enhancedTrackingProtection(interact: EnhancedTrackingProtectionRobot.() -> U return EnhancedTrackingProtectionRobot.Transition() } -private fun assertETPSwitchVisibility(visible: Boolean) { - if (visible) { - enhancedTrackingProtectionSwitch() - .check(matches(isDisplayed())) - } else { - enhancedTrackingProtectionSwitch() - .check(matches(not(isDisplayed()))) - } -} - -private fun assertEnhancedTrackingProtectionSheetStatus(status: String, state: Boolean) { - mDevice.waitNotNull(Until.findObjects(By.text("Protections are $status for this site"))) - onView(ViewMatchers.withResourceName("switch_widget")).check( - matches( - isChecked( - state, - ), - ), - ) -} - private fun pageSecurityIndicator() = mDevice.findObject(UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_security_indicator")) @@ -246,7 +303,7 @@ private fun trackingProtectionSettingsButton() = private fun openEnhancedTrackingProtectionDetails() = mDevice.findObject(UiSelector().resourceId("$packageName:id/trackingProtectionDetails")) -private val trackingContentBlockListButton = +private fun trackingContentBlockListButton() = onView( allOf( withText("Tracking Content"), @@ -254,7 +311,7 @@ private val trackingContentBlockListButton = ), ) -private val socialTrackersBlockListButton = +private fun socialTrackersBlockListButton() = onView( allOf( withId(R.id.social_media_trackers), @@ -262,7 +319,7 @@ private val socialTrackersBlockListButton = ), ) -private val crossSiteCookiesBlockListButton = +private fun crossSiteCookiesBlockListButton() = onView( allOf( withId(R.id.cross_site_tracking), @@ -270,7 +327,7 @@ private val crossSiteCookiesBlockListButton = ), ) -private val cryptominersBlockListButton = +private fun cryptominersBlockListButton() = onView( allOf( withId(R.id.cryptominers), @@ -278,16 +335,10 @@ private val cryptominersBlockListButton = ), ) -private val fingerprintersBlockListButton = +private fun fingerprintersBlockListButton() = onView( allOf( withId(R.id.fingerprinters), withText("Fingerprinters"), ), ) - -private fun assertSecuritySheetIsCompletelyDisplayed() { - mDevice.findObject(UiSelector().description(getStringResource(R.string.quick_settings_sheet))) - .waitForExists(waitingTime) - assertUIObjectExists(itemWithResId("$packageName:id/quick_action_sheet")) -} diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/FindInPageRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/FindInPageRobot.kt index 277375597..7f0789c22 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/FindInPageRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/FindInPageRobot.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.clearText import androidx.test.espresso.action.ViewActions.typeText @@ -16,6 +17,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By import androidx.test.uiautomator.Until import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.click @@ -25,52 +27,78 @@ import org.mozilla.fenix.helpers.ext.waitNotNull * Implementation of Robot Pattern for the find in page UI. */ class FindInPageRobot { - fun verifyFindInPageQuery() = assertFindInPageQuery()!! - fun verifyFindInPageNextButton() = assertFindInPageNextButton()!! - fun verifyFindInPagePrevButton() = assertFindInPagePrevButton()!! - fun verifyFindInPageCloseButton() = assertFindInPageCloseButton()!! - fun clickFindInPageNextButton() = findInPageNextButton().click() - fun clickFindInPagePrevButton() = findInPagePrevButton().click() - - fun verifyFindInPageSearchBarItems() { - verifyFindInPageQuery() - verifyFindInPageNextButton() - verifyFindInPagePrevButton() - verifyFindInPageCloseButton() + fun verifyFindInPageNextButton() { + Log.i(TAG, "verifyFindInPageNextButton: Trying to verify find in page next result button is visible") + findInPageNextButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyFindInPageNextButton: Verified find in page next result button is visible") + } + fun verifyFindInPagePrevButton() { + Log.i(TAG, "verifyFindInPagePrevButton: Trying to verify find in page previous result button is visible") + findInPagePrevButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyFindInPagePrevButton: Verified find in page previous result button is visible") + } + fun verifyFindInPageCloseButton() { + Log.i(TAG, "verifyFindInPageCloseButton: Trying to verify find in page close button is visible") + findInPageCloseButton() + .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyFindInPageCloseButton: Verified find in page close button is visible") + } + fun clickFindInPageNextButton() { + Log.i(TAG, "clickFindInPageNextButton: Trying to click next result button") + findInPageNextButton().click() + Log.i(TAG, "clickFindInPageNextButton: Clicked next result button") + } + fun clickFindInPagePrevButton() { + Log.i(TAG, "clickFindInPagePrevButton: Trying to click previous result button") + findInPagePrevButton().click() + Log.i(TAG, "clickFindInPagePrevButton: Clicked previous result button") } fun enterFindInPageQuery(expectedText: String) { mDevice.waitNotNull(Until.findObject(By.res("org.mozilla.fenix.debug:id/find_in_page_query_text")), waitingTime) + Log.i(TAG, "enterFindInPageQuery: Trying to clear find in page bar text") findInPageQuery().perform(clearText()) + Log.i(TAG, "enterFindInPageQuery: Cleared find in page bar text") mDevice.waitNotNull(Until.gone(By.res("org.mozilla.fenix.debug:id/find_in_page_result_text")), waitingTime) + Log.i(TAG, "enterFindInPageQuery: Trying to type $expectedText in find in page bar") findInPageQuery().perform(typeText(expectedText)) + Log.i(TAG, "enterFindInPageQuery: Typed $expectedText in find page bar") mDevice.waitNotNull(Until.findObject(By.res("org.mozilla.fenix.debug:id/find_in_page_result_text")), waitingTime) } - fun verifyFindNextInPageResult(ratioCounter: String) { - mDevice.waitNotNull(Until.findObject(By.text(ratioCounter)), waitingTime) - findInPageResult().check(matches(withText((ratioCounter)))) - } - - fun verifyFindPrevInPageResult(ratioCounter: String) { + fun verifyFindInPageResult(ratioCounter: String) { mDevice.waitNotNull(Until.findObject(By.text(ratioCounter)), waitingTime) + Log.i(TAG, "verifyFindInPageResult: Trying to verify $ratioCounter results") findInPageResult().check(matches(withText((ratioCounter)))) + Log.i(TAG, "verifyFindInPageResult: Verified $ratioCounter results") } class Transition { fun closeFindInPageWithCloseButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeFindInPageWithCloseButton: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "closeFindInPageWithCloseButton: Device was idle") + Log.i(TAG, "closeFindInPageWithCloseButton: Trying to close find in page button") findInPageCloseButton().click() + Log.i(TAG, "closeFindInPageWithCloseButton: Clicked close find in page button") BrowserRobot().interact() return BrowserRobot.Transition() } fun closeFindInPageWithBackButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeFindInPageWithBackButton: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "closeFindInPageWithBackButton: Device was idle") // Will need to press back 2x, the first will only dismiss the keyboard + Log.i(TAG, "closeFindInPageWithBackButton: Trying to press 1x the device back button") mDevice.pressBack() + Log.i(TAG, "closeFindInPageWithBackButton: Pressed 1x the device back button") + Log.i(TAG, "closeFindInPageWithBackButton: Trying to press 2x the device back button") mDevice.pressBack() + Log.i(TAG, "closeFindInPageWithBackButton: Pressed 2x the device back button") BrowserRobot().interact() return BrowserRobot.Transition() @@ -83,15 +111,3 @@ private fun findInPageResult() = onView(withId(R.id.find_in_page_result_text)) private fun findInPageNextButton() = onView(withId(R.id.find_in_page_next_btn)) private fun findInPagePrevButton() = onView(withId(R.id.find_in_page_prev_btn)) private fun findInPageCloseButton() = onView(withId(R.id.find_in_page_close_btn)) - -private fun assertFindInPageQuery() = findInPageQuery() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - -private fun assertFindInPageNextButton() = findInPageNextButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - -private fun assertFindInPagePrevButton() = findInPagePrevButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - -private fun assertFindInPageCloseButton() = findInPageCloseButton() - .check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt index 768121d45..fc6ee4d1a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HistoryRobot.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui.robots import android.net.Uri +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.RootMatchers.isDialog @@ -19,9 +20,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until -import org.hamcrest.Matchers import org.hamcrest.Matchers.allOf import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.DataGenerationHelper.getStringResource import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText @@ -38,17 +39,32 @@ import org.mozilla.fenix.helpers.ext.waitNotNull */ class HistoryRobot { - fun verifyHistoryMenuView() = assertHistoryMenuView() + fun verifyHistoryMenuView() { + Log.i(TAG, "verifyHistoryMenuView: Trying to verify that history menu view is visible") + onView( + allOf(withText("History"), withParent(withId(R.id.navigationToolbar))), + ).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyHistoryMenuView: Verified that history menu view is visible") + } fun verifyEmptyHistoryView() { + Log.i(TAG, "verifyEmptyHistoryView: Waiting for $waitingTime ms for empty history list view to exist") mDevice.findObject( UiSelector().text("No history here"), ).waitForExists(waitingTime) + Log.i(TAG, "verifyEmptyHistoryView: Waited for $waitingTime ms for empty history list view to exist") - assertEmptyHistoryView() + Log.i(TAG, "verifyEmptyHistoryView: Trying to verify empty history list view") + onView( + allOf( + withId(R.id.history_empty_view), + withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), + ), + ).check(matches(withText("No history here"))) + Log.i(TAG, "verifyEmptyHistoryView: Verified empty history list view") } - fun verifyHistoryListExists() = assertHistoryListExists() + fun verifyHistoryListExists() = assertUIObjectExists(itemWithResId("$packageName:id/history_list")) fun verifyVisitedTimeTitle() { mDevice.waitNotNull( @@ -57,53 +73,87 @@ class HistoryRobot { ), waitingTime, ) - assertVisitedTimeTitle() + Log.i(TAG, "verifyVisitedTimeTitle: Trying to verify \"Today\" chronological timeline title") + onView(withId(R.id.header_title)).check(matches(withText("Today"))) + Log.i(TAG, "verifyVisitedTimeTitle: Verified \"Today\" chronological timeline title") } fun verifyHistoryItemExists(shouldExist: Boolean, item: String) = assertUIObjectExists(itemContainingText(item), exists = shouldExist) - fun verifyFirstTestPageTitle(title: String) = assertTestPageTitle(title) - - fun verifyTestPageUrl(expectedUrl: Uri) = pageUrl(expectedUrl.toString()).check(matches(isDisplayed())) - - fun verifyCopySnackBarText() = assertCopySnackBarText() + fun verifyFirstTestPageTitle(title: String) { + Log.i(TAG, "verifyFirstTestPageTitle: Trying to verify $title page title is visible") + testPageTitle() + .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + .check(matches(withText(title))) + Log.i(TAG, "verifyFirstTestPageTitle: Verified $title page title is visible") + } - fun verifyDeleteConfirmationMessage() = assertDeleteConfirmationMessage() + fun verifyTestPageUrl(expectedUrl: Uri) { + Log.i(TAG, "verifyTestPageUrl: Trying to verify page url: $expectedUrl is displayed") + pageUrl(expectedUrl.toString()).check(matches(isDisplayed())) + Log.i(TAG, "verifyTestPageUrl: Verified page url: $expectedUrl is displayed") + } - fun verifyHomeScreen() = HomeScreenRobot().verifyHomeScreen() + fun verifyDeleteConfirmationMessage() = + assertUIObjectExists( + itemWithResIdContainingText("$packageName:id/title", getStringResource(R.string.delete_history_prompt_title)), + itemWithResIdContainingText("$packageName:id/body", getStringResource(R.string.delete_history_prompt_body_2)), + ) fun clickDeleteHistoryButton(item: String) { + Log.i(TAG, "clickDeleteHistoryButton: Trying to click delete history button for item: $item") deleteButton(item).click() + Log.i(TAG, "clickDeleteHistoryButton: Clicked delete history button for item: $item") } - fun verifyDeleteHistoryItemButton(historyItemTitle: String) = + fun verifyDeleteHistoryItemButton(historyItemTitle: String) { + Log.i(TAG, "verifyDeleteHistoryItemButton: Trying to verify delete history button for item: $historyItemTitle is visible") deleteButton(historyItemTitle).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "verifyDeleteHistoryItemButton: Verified delete history button for item: $historyItemTitle is visible") + } - fun clickDeleteAllHistoryButton() = deleteButton().click() + fun clickDeleteAllHistoryButton() { + Log.i(TAG, "clickDeleteAllHistoryButton: Trying to click delete all history button") + deleteButton().click() + Log.i(TAG, "clickDeleteAllHistoryButton: Clicked delete all history button") + } - fun selectEverythingOption() = deleteHistoryEverythingOption().click() + fun selectEverythingOption() { + Log.i(TAG, "selectEverythingOption: Trying to click \"Everything\" dialog option") + deleteHistoryEverythingOption().click() + Log.i(TAG, "selectEverythingOption: Clicked \"Everything\" dialog option") + } fun confirmDeleteAllHistory() { + Log.i(TAG, "confirmDeleteAllHistory: Trying to click \"Delete\" dialog button") onView(withText("Delete")) .inRoot(isDialog()) .check(matches(isDisplayed())) .click() + Log.i(TAG, "confirmDeleteAllHistory: Clicked \"Delete\" dialog button") } - fun cancelDeleteHistory() = + fun cancelDeleteHistory() { + Log.i(TAG, "cancelDeleteHistory: Trying to click \"Cancel\" dialog button") mDevice .findObject( UiSelector() .textContains(getStringResource(R.string.delete_browsing_data_prompt_cancel)), ).click() + Log.i(TAG, "cancelDeleteHistory: Clicked \"Cancel\" dialog button") + } - fun verifyDeleteSnackbarText(text: String) = assertSnackBarText(text) - - fun verifyUndoDeleteSnackBarButton() = assertUndoDeleteSnackBarButton() + fun verifyUndoDeleteSnackBarButton() { + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Trying to verify \"Undo\" snackbar button") + snackBarUndoButton().check(matches(withText("UNDO"))) + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Verified \"Undo\" snackbar button") + } fun clickUndoDeleteButton() { + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Trying to click \"Undo\" snackbar button") snackBarUndoButton().click() + Log.i(TAG, "verifyUndoDeleteSnackBarButton: Clicked \"Undo\" snackbar button") } fun verifySearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) = @@ -117,36 +167,50 @@ class HistoryRobot { ) fun openSearchGroup(searchTerm: String) { + Log.i(TAG, "openSearchGroup: Waiting for $waitingTime ms for search group: $searchTerm to exist") mDevice.findObject(UiSelector().text(searchTerm)).waitForExists(waitingTime) + Log.i(TAG, "openSearchGroup: Waited for $waitingTime ms for search group: $searchTerm to exist") + Log.i(TAG, "openSearchGroup: Trying to click search group: $searchTerm") mDevice.findObject(UiSelector().text(searchTerm)).click() + Log.i(TAG, "openSearchGroup: Clicked search group: $searchTerm") } class Transition { fun goBack(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "goBack: Trying to click go back menu button") onView(withContentDescription("Navigate up")).click() + Log.i(TAG, "goBack: Clicked go back menu button") BrowserRobot().interact() return BrowserRobot.Transition() } fun openWebsite(url: Uri, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - assertHistoryListExists() + assertUIObjectExists(itemWithResId("$packageName:id/history_list")) + Log.i(TAG, "openWebsite: Trying to click history item with url: $url") onView(withText(url.toString())).click() + Log.i(TAG, "openWebsite: Clicked history item with url: $url") BrowserRobot().interact() return BrowserRobot.Transition() } fun openRecentlyClosedTabs(interact: RecentlyClosedTabsRobot.() -> Unit): RecentlyClosedTabsRobot.Transition { - recentlyClosedTabsListButton.waitForExists(waitingTime) - recentlyClosedTabsListButton.click() + Log.i(TAG, "openRecentlyClosedTabs: Waiting for $waitingTime ms for \"Recently closed tabs\" button to exist") + recentlyClosedTabsListButton().waitForExists(waitingTime) + Log.i(TAG, "openRecentlyClosedTabs: Waited for $waitingTime ms for \"Recently closed tabs\" button to exist") + Log.i(TAG, "openRecentlyClosedTabs: Trying to click \"Recently closed tabs\" button") + recentlyClosedTabsListButton().click() + Log.i(TAG, "openRecentlyClosedTabs: Clicked \"Recently closed tabs\" button") RecentlyClosedTabsRobot().interact() return RecentlyClosedTabsRobot.Transition() } fun clickSearchButton(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "clickSearchButton: Trying to click search history button") itemWithResId("$packageName:id/history_search").click() + Log.i(TAG, "clickSearchButton: Clicked search history button") SearchRobot().interact() return SearchRobot.Transition() @@ -168,50 +232,8 @@ private fun deleteButton(title: String) = private fun deleteButton() = onView(withId(R.id.history_delete)) -private fun snackBarText() = onView(withId(R.id.snackbar_text)) - -private fun assertHistoryMenuView() { - onView( - allOf(withText("History"), withParent(withId(R.id.navigationToolbar))), - ) - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) -} - -private fun assertEmptyHistoryView() = - onView( - allOf( - withId(R.id.history_empty_view), - withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE), - ), - ) - .check(matches(withText("No history here"))) - -private fun assertHistoryListExists() = - mDevice.findObject(UiSelector().resourceId("$packageName:id/history_list")).waitForExists(waitingTime) - -private fun assertVisitedTimeTitle() = - onView(withId(R.id.header_title)).check(matches(withText("Today"))) - -private fun assertTestPageTitle(title: String) = testPageTitle() - .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) - .check(matches(withText(title))) - -private fun assertDeleteConfirmationMessage() = - assertUIObjectExists( - itemWithResIdContainingText("$packageName:id/title", getStringResource(R.string.delete_history_prompt_title)), - itemWithResIdContainingText("$packageName:id/body", getStringResource(R.string.delete_history_prompt_body_2)), - ) - -private fun assertCopySnackBarText() = snackBarText().check(matches(withText("URL copied"))) - -private fun assertSnackBarText(text: String) = - snackBarText().check(matches(withText(Matchers.containsString(text)))) - private fun snackBarUndoButton() = onView(withId(R.id.snackbar_btn)) -private fun assertUndoDeleteSnackBarButton() = - snackBarUndoButton().check(matches(withText("UNDO"))) - private fun deleteHistoryEverythingOption() = mDevice .findObject( @@ -220,5 +242,5 @@ private fun deleteHistoryEverythingOption() = .resourceId("$packageName:id/everything_button"), ) -private val recentlyClosedTabsListButton = +private fun recentlyClosedTabsListButton() = mDevice.findObject(UiSelector().resourceId("$packageName:id/recently_closed_tabs_header")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt index d3e78c462..38d5a4f84 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/HomeScreenRobot.kt @@ -48,7 +48,6 @@ import org.hamcrest.CoreMatchers.allOf import org.hamcrest.CoreMatchers.containsString import org.hamcrest.CoreMatchers.instanceOf import org.hamcrest.Matchers -import org.junit.Assert import org.junit.Assert.assertTrue import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants.LISTS_MAXSWIPES @@ -80,41 +79,77 @@ import org.mozilla.fenix.tabstray.TabsTrayTestTag * Implementation of Robot Pattern for the home screen menu. */ class HomeScreenRobot { - val privateSessionMessage = - "$appName clears your search and browsing history from private tabs when you close them" + - " or quit the app. While this doesn’t make you anonymous to websites or your internet" + - " service provider, it makes it easier to keep what you do online private from anyone" + - " else who uses this device." - fun verifyNavigationToolbar() = assertUIObjectExists(navigationToolbar()) fun verifyHomeScreen() = assertUIObjectExists(homeScreen()) fun verifyPrivateBrowsingHomeScreenItems() { verifyHomeScreenAppBarItems() - assertUIObjectExists(itemContainingText(privateSessionMessage)) + assertUIObjectExists( + itemContainingText( + "$appName clears your search and browsing history from private tabs when you close them" + + " or quit the app. While this doesn’t make you anonymous to websites or your internet" + + " service provider, it makes it easier to keep what you do online private from anyone" + + " else who uses this device.", + ), + ) verifyCommonMythsLink() } fun verifyHomeScreenAppBarItems() = assertUIObjectExists(homeScreen(), privateBrowsingButton(), homepageWordmark()) - fun verifyNavigationToolbarItems(numberOfOpenTabs: String = "0") = - assertUIObjectExists(navigationToolbar(), menuButton, tabCounter(numberOfOpenTabs)) - fun verifyHomePrivateBrowsingButton() = assertUIObjectExists(privateBrowsingButton()) - fun verifyHomeMenuButton() = assertUIObjectExists(menuButton) - fun verifyTabButton() = assertTabButton() - fun verifyCollectionsHeader() = assertCollectionsHeader() - fun verifyNoCollectionsText() = assertNoCollectionsText() + fun verifyHomeMenuButton() = assertUIObjectExists(menuButton()) + fun verifyTabButton() { + Log.i(TAG, "verifyTabButton: Trying to verify tab counter button is visible") + onView(allOf(withId(R.id.tab_button), isDisplayed())).check( + matches( + withEffectiveVisibility( + Visibility.VISIBLE, + ), + ), + ) + Log.i(TAG, "verifyTabButton: Verified tab counter button is visible") + } + fun verifyCollectionsHeader() { + Log.i(TAG, "verifyCollectionsHeader: Trying to verify collections header is visible") + onView(allOf(withText("Collections"))).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyCollectionsHeader: Verified collections header is visible") + } + fun verifyNoCollectionsText() { + Log.i(TAG, "verifyNoCollectionsText: Trying to verify empty collections placeholder text is displayed") + onView( + withText( + containsString( + "Collect the things that matter to you.\n" + + "Group together similar searches, sites, and tabs for quick access later.", + ), + ), + ).check(matches(isDisplayed())) + Log.i(TAG, "verifyNoCollectionsText: Verified empty collections placeholder text is displayed") + } + fun verifyHomeWordmark() { + Log.i(TAG, "verifyHomeWordmark: Trying to scroll 3x to the beginning of the home screen") homeScreenList().scrollToBeginning(3) + Log.i(TAG, "verifyHomeWordmark: Scrolled 3x to the beginning of the home screen") assertUIObjectExists(homepageWordmark()) } - fun verifyHomeComponent() = assertHomeComponent() + fun verifyHomeComponent() { + Log.i(TAG, "verifyHomeComponent: Trying to verify home screen view is visible") + onView(ViewMatchers.withResourceName("sessionControlRecyclerView")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyHomeComponent: Verified home screen view is visible") + } fun verifyTabCounter(numberOfOpenTabs: String) = - assertUIObjectExists(tabCounter(numberOfOpenTabs)) + onView( + allOf( + withId(R.id.counter_text), + withText(numberOfOpenTabs), + ), + ).check(matches(isDisplayed())) fun verifyWallpaperImageApplied(isEnabled: Boolean) = assertUIObjectExists(itemWithResId("$packageName:id/wallpaperImageView"), exists = isEnabled) @@ -122,101 +157,149 @@ class HomeScreenRobot { // Upgrading users onboarding dialog fun verifyUpgradingUserOnboardingFirstScreen(testRule: ComposeTestRule) { testRule.also { + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Trying to verify that the upgrading user first onboarding screen title is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_welcome_title_2)) .assertIsDisplayed() - + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Verified that the upgrading user first onboarding screen title is displayed") + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Trying to verify that the upgrading user first onboarding screen description is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_welcome_description)) .assertIsDisplayed() - + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Verified that the upgrading user first onboarding screen description is displayed") + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Trying to verify that the upgrading user first onboarding \"Get started\" button is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_get_started_button)) .assertIsDisplayed() + Log.i(TAG, "verifyUpgradingUserOnboardingFirstScreen: Verified that the upgrading user first onboarding \"Get started\" button is displayed") } } fun verifyFirstOnboardingCard(composeTestRule: ComposeTestRule) { composeTestRule.also { + Log.i(TAG, "verifyFirstOnboardingCard: Trying to verify that the first onboarding screen title exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_title_nimbus_2), ).assertExists() - + Log.i(TAG, "verifyFirstOnboardingCard: Verified that the first onboarding screen title exists") + Log.i(TAG, "verifyFirstOnboardingCard: Trying to verify that the first onboarding screen description exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_description_nimbus_3), ).assertExists() - + Log.i(TAG, "verifyFirstOnboardingCard: Verified that the first onboarding screen description exists") + Log.i(TAG, "verifyFirstOnboardingCard: Trying to verify that the first onboarding \"Set as default browser\" button exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_positive_button), ).assertExists() - + Log.i(TAG, "verifyFirstOnboardingCard: Verified that the first onboarding \"Set as default browser\" button exists") + Log.i(TAG, "verifyFirstOnboardingCard: Trying to verify that the first onboarding \"Not now\" button exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_negative_button), ).assertExists() + Log.i(TAG, "verifyFirstOnboardingCard: Verified that the first onboarding \"Not now\" button exists") } } fun verifySecondOnboardingCard(composeTestRule: ComposeTestRule) { composeTestRule.also { + Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the second onboarding screen title exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_sign_in_title_2), ).assertExists() - + Log.i(TAG, "verifySecondOnboardingCard: Verified that the second onboarding screen title exists") + Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the second onboarding screen description exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_sign_in_description_2), ).assertExists() - + Log.i(TAG, "verifySecondOnboardingCard: Verified that the second onboarding screen description exists") + Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the first onboarding \"Sign in\" button exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_sign_in_positive_button), ).assertExists() - + Log.i(TAG, "verifySecondOnboardingCard: Verified that the first onboarding \"Sign in\" button exists") + Log.i(TAG, "verifySecondOnboardingCard: Trying to verify that the first onboarding \"Not now\" button exists") it.onNodeWithText( getStringResource(R.string.juno_onboarding_sign_in_negative_button), ).assertExists() + Log.i(TAG, "verifySecondOnboardingCard: Verified that the first onboarding \"Not now\" button exists") } } - fun clickNotNowOnboardingButton(composeTestRule: ComposeTestRule) = + fun clickNotNowOnboardingButton(composeTestRule: ComposeTestRule) { + Log.i(TAG, "clickNotNowOnboardingButton: Trying to click \"Not now\" onboarding button") composeTestRule.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_negative_button), ).performClick() + Log.i(TAG, "clickNotNowOnboardingButton: Clicked \"Not now\" onboarding button") + } - fun swipeSecondOnboardingCardToRight() = + fun swipeSecondOnboardingCardToRight() { + Log.i(TAG, "swipeSecondOnboardingCardToRight: Trying to perform swipe right action on second onboarding card") mDevice.findObject( UiSelector().textContains( getStringResource(R.string.juno_onboarding_sign_in_title_2), ), ).swipeRight(3) + Log.i(TAG, "swipeSecondOnboardingCardToRight: Performed swipe right action on second onboarding card") + } - fun clickGetStartedButton(testRule: ComposeTestRule) = - testRule.onNodeWithText(getStringResource(R.string.onboarding_home_get_started_button)).performClick() + fun clickGetStartedButton(testRule: ComposeTestRule) { + Log.i(TAG, "clickGetStartedButton: Trying to click \"Get started\" onboarding button") + testRule.onNodeWithText(getStringResource(R.string.onboarding_home_get_started_button)) + .performClick() + Log.i(TAG, "clickGetStartedButton: Clicked \"Get started\" onboarding button") + } - fun clickCloseButton(testRule: ComposeTestRule) = + fun clickCloseButton(testRule: ComposeTestRule) { + Log.i(TAG, "clickCloseButton: Trying to click close onboarding button") testRule.onNode(hasContentDescription("Close")).performClick() + Log.i(TAG, "clickCloseButton: Clicked close onboarding button") + } fun verifyUpgradingUserOnboardingSecondScreen(testRule: ComposeTestRule) { testRule.also { + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Trying to verify that the upgrading user second onboarding screen title is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_sync_title_3)) .assertIsDisplayed() - + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Verified that the upgrading user second onboarding screen title is displayed") + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Trying to verify that the upgrading user second onboarding screen description is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_sync_description)) .assertIsDisplayed() - + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Verified that the upgrading user second onboarding screen description is displayed") + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Trying to verify that the upgrading user second onboarding \"Sign in\" button is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_sign_in_button)) .assertIsDisplayed() - + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Verified that the upgrading user second onboarding \"Sign in\" button is displayed") + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Trying to that the verify upgrading user second onboarding \"Skip\" button is displayed") it.onNodeWithText(getStringResource(R.string.onboarding_home_skip_button)) .assertIsDisplayed() + Log.i(TAG, "verifyUpgradingUserOnboardingSecondScreen: Verified that the upgrading user second onboarding \"Skip\" button is displayed") } } - fun clickSkipButton(testRule: ComposeTestRule) = + fun clickSkipButton(testRule: ComposeTestRule) { + Log.i(TAG, "clickSkipButton: Trying to click \"Skip\" onboarding button") testRule .onNodeWithText(getStringResource(R.string.onboarding_home_skip_button)) .performClick() + Log.i(TAG, "clickSkipButton: Clicked \"Skip\" onboarding button") + } fun verifyCommonMythsLink() = assertUIObjectExists(itemContainingText(getStringResource(R.string.private_browsing_common_myths))) - fun verifyExistingTopSitesList() = assertExistingTopSitesList() - fun verifyNotExistingTopSitesList(title: String) = assertNotExistingTopSitesList(title) + fun verifyExistingTopSitesList() = + assertUIObjectExists(itemWithResId("$packageName:id/top_sites_list")) + + fun verifyNotExistingTopSitesList(title: String) { + Log.i(TAG, "verifyNotExistingTopSitesList: Waiting for $waitingTime ms for top site: $title to be gone") + mDevice.findObject(UiSelector().text(title)).waitUntilGone(waitingTime) + Log.i(TAG, "verifyNotExistingTopSitesList: Waited for $waitingTime ms for top site: $title to be gone") + assertUIObjectExists( + itemWithResIdContainingText( + "$packageName:id/top_site_title", + title, + ), + exists = false, + ) + } fun verifySponsoredShortcutDoesNotExist(sponsoredShortcutTitle: String, position: Int) = assertUIObjectExists( itemWithResIdAndIndex("$packageName:id/top_site_item", index = position - 1) @@ -226,17 +309,65 @@ class HomeScreenRobot { ), exists = false, ) - fun verifyNotExistingSponsoredTopSitesList() = assertSponsoredTopSitesNotDisplayed() + fun verifyNotExistingSponsoredTopSitesList() = + assertUIObjectExists( + itemWithResIdContainingText( + "$packageName:id/top_site_subtitle", + getStringResource(R.string.top_sites_sponsored_label), + ), + exists = false, + ) + fun verifyExistingTopSitesTabs(title: String) { + Log.i(TAG, "verifyExistingTopSitesTabs: Trying to scroll into view the top sites list") homeScreenList().scrollIntoView(itemWithResId("$packageName:id/top_sites_list")) - assertExistingTopSitesTabs(title) + Log.i(TAG, "verifyExistingTopSitesTabs: Scrolled into view the top sites list") + Log.i(TAG, "verifyExistingTopSitesTabs: Waiting for $waitingTime ms for top site: $title to exist") + mDevice.findObject( + UiSelector() + .resourceId("$packageName:id/top_site_title") + .textContains(title), + ).waitForExists(waitingTime) + Log.i(TAG, "verifyExistingTopSitesTabs: Waited for $waitingTime ms for top site: $title to exist") + Log.i(TAG, "verifyExistingTopSitesTabs: Trying to verify top site: $title is visible") + onView(allOf(withId(R.id.top_sites_list))) + .check(matches(hasDescendant(withText(title)))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyExistingTopSitesTabs: Verified top site: $title is visible") } fun verifySponsoredShortcutDetails(sponsoredShortcutTitle: String, position: Int) { - assertSponsoredShortcutLogoIsDisplayed(position) - assertSponsoredShortcutTitle(sponsoredShortcutTitle, position) - assertSponsoredSubtitleIsDisplayed(position) + assertUIObjectExists( + itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) + .getChild( + UiSelector() + .resourceId("$packageName:id/favicon_card"), + ), + ) + assertUIObjectExists( + itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) + .getChild( + UiSelector() + .textContains(sponsoredShortcutTitle), + ), + ) + assertUIObjectExists( + itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) + .getChild( + UiSelector() + .resourceId("$packageName:id/top_site_subtitle"), + ), + ) + } + fun verifyTopSiteContextMenuItems() { + mDevice.waitNotNull( + findObject(By.text("Open in private tab")), + waitingTime, + ) + mDevice.waitNotNull( + findObject(By.text("Remove")), + waitingTime, + ) } - fun verifyTopSiteContextMenuItems() = assertTopSiteContextMenuItems() fun verifyJumpBackInSectionIsDisplayed() { scrollToElementByText(getStringResource(R.string.recent_tabs_header)) @@ -244,14 +375,22 @@ class HomeScreenRobot { } fun verifyJumpBackInSectionIsNotDisplayed() = assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_header)), exists = false) - fun verifyJumpBackInItemTitle(testRule: ComposeTestRule, itemTitle: String) = - assertJumpBackInItemTitle(testRule, itemTitle) - fun verifyJumpBackInItemWithUrl(testRule: ComposeTestRule, itemUrl: String) = - assertJumpBackInItemWithUrl(testRule, itemUrl) - fun verifyJumpBackInShowAllButton() = assertJumpBackInShowAllButton() - fun verifyRecentlyVisitedSectionIsDisplayed(exists: Boolean) = assertRecentlyVisitedSectionIsDisplayed(exists) - fun verifyRecentBookmarksSectionIsDisplayed(exists: Boolean) = assertRecentBookmarksSectionIsDisplayed(exists) - fun verifyPocketSectionIsDisplayed(exists: Boolean) = assertPocketSectionIsDisplayed(exists) + fun verifyJumpBackInItemTitle(testRule: ComposeTestRule, itemTitle: String) { + Log.i(TAG, "verifyJumpBackInItemTitle: Trying to verify jump back in item with title: $itemTitle") + testRule.onNodeWithTag("recent.tab.title", useUnmergedTree = true) + .assert(hasText(itemTitle)) + Log.i(TAG, "verifyJumpBackInItemTitle: Verified jump back in item with title: $itemTitle") + } + fun verifyJumpBackInItemWithUrl(testRule: ComposeTestRule, itemUrl: String) { + Log.i(TAG, "verifyJumpBackInItemWithUrl: Trying to verify jump back in item with URL: $itemUrl") + testRule.onNodeWithTag("recent.tab.url", useUnmergedTree = true).assert(hasText(itemUrl)) + Log.i(TAG, "verifyJumpBackInItemWithUrl: Verified jump back in item with URL: $itemUrl") + } + fun verifyJumpBackInShowAllButton() = assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_show_all))) + fun verifyRecentlyVisitedSectionIsDisplayed(exists: Boolean) = + assertUIObjectExists(itemContainingText(getStringResource(R.string.history_metadata_header_2)), exists = exists) + fun verifyRecentBookmarksSectionIsDisplayed(exists: Boolean) = + assertUIObjectExists(itemContainingText(getStringResource(R.string.recently_saved_title)), exists = exists) fun verifyRecentlyVisitedSearchGroupDisplayed(shouldBeDisplayed: Boolean, searchTerm: String, groupSize: Int) { // checks if the search group exists in the Recently visited section @@ -279,41 +418,37 @@ class HomeScreenRobot { } fun togglePrivateBrowsingModeOnOff() { + Log.i(TAG, "togglePrivateBrowsingModeOnOff: Trying to click private browsing home screen button") onView(ViewMatchers.withResourceName("privateBrowsingButton")) .perform(click()) + Log.i(TAG, "togglePrivateBrowsingModeOnOff: Clicked private browsing home screen button") } - fun swipeToBottom() = onView(withId(R.id.homeLayout)).perform(ViewActions.swipeUp()) - - fun swipeToTop() = - onView(withId(R.id.sessionControlRecyclerView)).perform(ViewActions.swipeDown()) - - fun verifySnackBarText(expectedText: String) { - mDevice.waitNotNull(findObject(By.text(expectedText)), waitingTime) - } - - fun clickFirefoxLogo() = homepageWordmark().click() - fun verifyThoughtProvokingStories(enabled: Boolean) { if (enabled) { scrollToElementByText(getStringResource(R.string.pocket_stories_header_1)) assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1))) } else { + Log.i(TAG, "verifyThoughtProvokingStories: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") homeScreenList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "verifyThoughtProvokingStories: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1)), exists = false) } } fun scrollToPocketProvokingStories() { + Log.i(TAG, "scrollToPocketProvokingStories: Trying to scroll into view the featured pocket stories") homeScreenList().scrollIntoView( mDevice.findObject(UiSelector().resourceId("pocket.recommended.story").index(2)), ) + Log.i(TAG, "scrollToPocketProvokingStories: Scrolled into view the featured pocket stories") } fun verifyPocketRecommendedStoriesItems() { for (position in 0..8) { - pocketStoriesList - .scrollIntoView(UiSelector().index(position)) + Log.i(TAG, "verifyPocketRecommendedStoriesItems: Trying to scroll into view the featured pocket story from position: $position") + pocketStoriesList().scrollIntoView(UiSelector().index(position)) + Log.i(TAG, "verifyPocketRecommendedStoriesItems: Scrolled into view the featured pocket story from position: $position") assertUIObjectExists(itemWithIndex(position)) } } @@ -334,8 +469,9 @@ class HomeScreenRobot { // } fun verifyDiscoverMoreStoriesButton() { - pocketStoriesList - .scrollIntoView(UiSelector().text("Discover more")) + Log.i(TAG, "verifyDiscoverMoreStoriesButton: Trying to scroll into view the Pocket \"Discover more\" button") + pocketStoriesList().scrollIntoView(UiSelector().text("Discover more")) + Log.i(TAG, "verifyDiscoverMoreStoriesButton: Scrolled into view the Pocket \"Discover more\" button") assertUIObjectExists(itemWithText("Discover more")) } @@ -344,33 +480,54 @@ class HomeScreenRobot { scrollToElementByText(getStringResource(R.string.pocket_stories_categories_header)) assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_categories_header))) } else { + Log.i(TAG, "verifyStoriesByTopic: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") homeScreenList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "verifyStoriesByTopic: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_categories_header)), exists = false) } } fun verifyStoriesByTopicItems() { + Log.i(TAG, "verifyStoriesByTopicItems: Trying to scroll into view the stories by topic home screen section") homeScreenList().scrollIntoView(UiSelector().resourceId("pocket.categories")) + Log.i(TAG, "verifyStoriesByTopicItems: Scrolled into view the stories by topic home screen section") + Log.i(TAG, "verifyStoriesByTopicItems: Trying to verify that there are more than 1 \"Stories by topic\" categories") assertTrue(mDevice.findObject(UiSelector().resourceId("pocket.categories")).childCount > 1) + Log.i(TAG, "verifyStoriesByTopicItems: Verified that there are more than 1 \"Stories by topic\" categories") } fun verifyStoriesByTopicItemState(composeTestRule: ComposeTestRule, isSelected: Boolean, position: Int) { + Log.i(TAG, "verifyStoriesByTopicItemState: Trying to scroll into view \"Powered By Pocket\" home screen section") homeScreenList().scrollIntoView(mDevice.findObject(UiSelector().resourceId("pocket.header"))) + Log.i(TAG, "verifyStoriesByTopicItemState: Scrolled into view \"Powered By Pocket\" home screen section") if (isSelected) { + Log.i(TAG, "verifyStoriesByTopicItemState: Trying verify that the stories by topic home screen section is displayed") composeTestRule.onNodeWithTag("pocket.categories").assertIsDisplayed() + Log.i(TAG, "verifyStoriesByTopicItemState: Verified that the stories by topic home screen section is displayed") + Log.i(TAG, "verifyStoriesByTopicItemState: Trying verify that the stories by topic item at position: $position is selected") storyByTopicItem(composeTestRule, position).assertIsSelected() + Log.i(TAG, "verifyStoriesByTopicItemState: Verified that the stories by topic item at position: $position is selected") } else { + Log.i(TAG, "verifyStoriesByTopicItemState: Trying verify that the stories by topic home screen section is displayed") composeTestRule.onNodeWithTag("pocket.categories").assertIsDisplayed() + Log.i(TAG, "verifyStoriesByTopicItemState: Verified that the stories by topic home screen section is displayed") + Log.i(TAG, "verifyStoriesByTopicItemState: Trying to verify that the stories by topic item at position: $position is not selected") storyByTopicItem(composeTestRule, position).assertIsNotSelected() + Log.i(TAG, "verifyStoriesByTopicItemState: Verified that the stories by topic item at position: $position is not selected") } } - fun clickStoriesByTopicItem(composeTestRule: ComposeTestRule, position: Int) = + fun clickStoriesByTopicItem(composeTestRule: ComposeTestRule, position: Int) { + Log.i(TAG, "clickStoriesByTopicItem: Trying to click stories by topic item from position: $position") storyByTopicItem(composeTestRule, position).performClick() + Log.i(TAG, "clickStoriesByTopicItem: Clicked stories by topic item from position: $position") + } fun verifyPoweredByPocket() { + Log.i(TAG, "verifyPoweredByPocket: Trying to scroll into view \"Powered By Pocket\" home screen section") homeScreenList().scrollIntoView(mDevice.findObject(UiSelector().resourceId("pocket.header"))) + Log.i(TAG, "verifyPoweredByPocket: Scrolled into view \"Powered By Pocket\" home screen section") assertUIObjectExists(itemWithResId("pocket.header.title")) } @@ -379,16 +536,21 @@ class HomeScreenRobot { scrollToElementByText(getStringResource(R.string.browser_menu_customize_home_1)) assertUIObjectExists(itemContainingText("Customize homepage")) } else { + Log.i(TAG, "verifyCustomizeHomepageButton: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") homeScreenList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "verifyCustomizeHomepageButton: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") assertUIObjectExists(itemContainingText("Customize homepage"), exists = false) } } - fun verifyJumpBackInMessage(composeTestRule: ComposeTestRule) = + fun verifyJumpBackInMessage(composeTestRule: ComposeTestRule) { + Log.i(TAG, "verifyJumpBackInMessage: Trying to verify jump back in contextual message") composeTestRule .onNodeWithText( getStringResource(R.string.onboarding_home_screen_jump_back_contextual_hint_2), ).assertExists() + Log.i(TAG, "verifyJumpBackInMessage: Verified jump back in contextual message") + } fun getProvokingStoryPublisher(position: Int): String { val publisher = mDevice.findObject( @@ -405,6 +567,7 @@ class HomeScreenRobot { } fun verifyToolbarPosition(defaultPosition: Boolean) { + Log.i(TAG, "verifyToolbarPosition: Trying to verify toolbar is set to top: $defaultPosition") onView(withId(R.id.toolbarLayout)) .check( if (defaultPosition) { @@ -413,6 +576,7 @@ class HomeScreenRobot { isCompletelyAbove(withId(R.id.homeAppBar)) }, ) + Log.i(TAG, "verifyToolbarPosition: Verified toolbar position is set to top: $defaultPosition") } fun verifyNimbusMessageCard(title: String, text: String, action: String) { val textView = UiSelector() @@ -431,17 +595,22 @@ class HomeScreenRobot { } fun verifyIfInPrivateOrNormalMode(privateBrowsingEnabled: Boolean) { + Log.i(TAG, "verifyIfInPrivateOrNormalMode: Trying to verify private browsing mode is enabled") assert(isPrivateModeEnabled() == privateBrowsingEnabled) + Log.i(TAG, "verifyIfInPrivateOrNormalMode: Verified private browsing mode is enabled: $privateBrowsingEnabled") } class Transition { fun openTabDrawer(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { + Log.i(TAG, "openTabDrawer: Waiting for $waitingTime ms for tab counter button to exist") mDevice.findObject( UiSelector().descriptionContains("open tab. Tap to switch tabs."), ).waitForExists(waitingTime) - + Log.i(TAG, "openTabDrawer: Waited for $waitingTime ms for tab counter button to exist") + Log.i(TAG, "openTabDrawer: Trying to click tab counter button") tabsCounter().click() + Log.i(TAG, "openTabDrawer: Clicked tab counter button") mDevice.waitNotNull(Until.findObject(By.res("$packageName:id/tab_layout"))) TabDrawerRobot().interact() @@ -449,9 +618,15 @@ class HomeScreenRobot { } fun openComposeTabDrawer(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { + Log.i(TAG, "openComposeTabDrawer: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "openComposeTabDrawer: Device was idle for $waitingTime ms") + Log.i(TAG, "openComposeTabDrawer: Trying to click tab counter button") onView(withId(R.id.tab_button)).click() + Log.i(TAG, "openComposeTabDrawer: Clicked tab counter button") + Log.i(TAG, "openComposeTabDrawer: Trying to verify the tabs tray exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.tabsTray).assertExists() + Log.i(TAG, "openComposeTabDrawer: Verified the tabs tray exists") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) @@ -461,17 +636,18 @@ class HomeScreenRobot { // Issue: https://github.com/mozilla-mobile/fenix/issues/21578 try { Log.i(TAG, "openThreeDotMenu: Try block") - Log.i(TAG, "openThreeDotMenu: Looking for main menu button") mDevice.waitNotNull( Until.findObject(By.res("$packageName:id/menuButton")), waitingTime, ) } catch (e: AssertionError) { Log.i(TAG, "openThreeDotMenu: Catch block") + Log.i(TAG, "openThreeDotMenu: Trying to click device back button") mDevice.pressBack() - Log.i(TAG, "openThreeDotMenu: Pressed device back button") + Log.i(TAG, "openThreeDotMenu: Clicked device back button") } finally { Log.i(TAG, "openThreeDotMenu: Finally block") + Log.i(TAG, "openThreeDotMenu: Trying to click main menu button") threeDotButton().perform(click()) Log.i(TAG, "openThreeDotMenu: Clicked main menu button") } @@ -481,9 +657,15 @@ class HomeScreenRobot { } fun openSearch(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "openSearch: Waiting for $waitingTime ms for the navigation toolbar to exist") navigationToolbar().waitForExists(waitingTime) + Log.i(TAG, "openSearch: Waited for $waitingTime ms for the navigation toolbar to exist") + Log.i(TAG, "openSearch: Trying to click navigation toolbar") navigationToolbar().click() + Log.i(TAG, "openSearch: Clicked navigation toolbar") + Log.i(TAG, "openSearch: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "openSearch: Device was idle") SearchRobot().interact() return SearchRobot.Transition() @@ -493,7 +675,9 @@ class HomeScreenRobot { testRule: ComposeTestRule, interact: SyncSignInRobot.() -> Unit, ): SyncSignInRobot.Transition { + Log.i(TAG, "clickUpgradingUserOnboardingSignInButton: Trying to click the upgrading user onboarding \"Sign in\" button") testRule.onNodeWithText("Sign in").performClick() + Log.i(TAG, "clickUpgradingUserOnboardingSignInButton: Clicked the upgrading user onboarding \"Sign in\" button") SyncSignInRobot().interact() return SyncSignInRobot.Transition() @@ -502,26 +686,38 @@ class HomeScreenRobot { fun togglePrivateBrowsingMode(switchPBModeOn: Boolean = true) { // Switch to private browsing homescreen if (switchPBModeOn && !isPrivateModeEnabled()) { + Log.i(TAG, "togglePrivateBrowsingMode: Waiting for $waitingTime ms for private browsing button to exist") privateBrowsingButton().waitForExists(waitingTime) + Log.i(TAG, "togglePrivateBrowsingMode: Waited for $waitingTime ms for private browsing button to exist") + Log.i(TAG, "togglePrivateBrowsingMode: Trying to click private browsing button") privateBrowsingButton().click() + Log.i(TAG, "togglePrivateBrowsingMode: Clicked private browsing button") } // Switch to normal browsing homescreen if (!switchPBModeOn && isPrivateModeEnabled()) { + Log.i(TAG, "togglePrivateBrowsingMode: Waiting for $waitingTime ms for private browsing button to exist") privateBrowsingButton().waitForExists(waitingTime) + Log.i(TAG, "togglePrivateBrowsingMode: Waited for $waitingTime ms for private browsing button to exist") + Log.i(TAG, "togglePrivateBrowsingMode: Trying to click private browsing button") + privateBrowsingButton().click() privateBrowsingButton().click() + Log.i(TAG, "togglePrivateBrowsingMode: Clicked private browsing button") } } fun triggerPrivateBrowsingShortcutPrompt(interact: AddToHomeScreenRobot.() -> Unit): AddToHomeScreenRobot.Transition { // Loop to press the PB icon for 5 times to display the Add the Private Browsing Shortcut CFR for (i in 1..5) { + Log.i(TAG, "triggerPrivateBrowsingShortcutPrompt: Waiting for $waitingTime ms for private browsing button to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/privateBrowsingButton")) .waitForExists( waitingTime, ) - + Log.i(TAG, "triggerPrivateBrowsingShortcutPrompt: Waited for $waitingTime ms for private browsing button to exist") + Log.i(TAG, "triggerPrivateBrowsingShortcutPrompt: Trying to click private browsing button") privateBrowsingButton().click() + Log.i(TAG, "triggerPrivateBrowsingShortcutPrompt: Clicked private browsing button") } AddToHomeScreenRobot().interact() @@ -529,13 +725,19 @@ class HomeScreenRobot { } fun pressBack() { + Log.i(TAG, "pressBack: Trying to click device back button") onView(ViewMatchers.isRoot()).perform(ViewActions.pressBack()) + Log.i(TAG, "pressBack: Clicked device back button") } fun openNavigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationToolbarRobot.Transition { + Log.i(TAG, "openNavigationToolbar: Waiting for $waitingTime ms for navigation the toolbar to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) .waitForExists(waitingTime) + Log.i(TAG, "openNavigationToolbar: Waited for $waitingTime ms for the navigation toolbar to exist") + Log.i(TAG, "openNavigationToolbar: Trying to click the navigation toolbar") navigationToolbar().click() + Log.i(TAG, "openNavigationToolbar: Clicked the navigation toolbar") NavigationToolbarRobot().interact() return NavigationToolbarRobot.Transition() @@ -545,20 +747,23 @@ class HomeScreenRobot { title: String, interact: HomeScreenRobot.() -> Unit, ): Transition { + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Trying to long click top site with title: $title") onView(withId(R.id.top_sites_list)).perform( actionOnItem( hasDescendant(withText(title)), ViewActions.longClick(), ), ) + Log.i(TAG, "openContextMenuOnTopSitesWithTitle: Long clicked top site with title: $title") HomeScreenRobot().interact() return Transition() } fun openContextMenuOnSponsoredShortcut(sponsoredShortcutTitle: String, interact: HomeScreenRobot.() -> Unit): Transition { + Log.i(TAG, "openContextMenuOnSponsoredShortcut: Trying to long click: $sponsoredShortcutTitle sponsored shortcut") sponsoredShortcut(sponsoredShortcutTitle).perform(longClick()) - Log.i(TAG, "openContextMenuOnSponsoredShortcut: Long clicked to open context menu for $sponsoredShortcutTitle sponsored shortcut") + Log.i(TAG, "openContextMenuOnSponsoredShortcut: Long clicked: $sponsoredShortcutTitle sponsored shortcut") HomeScreenRobot().interact() return Transition() @@ -568,86 +773,112 @@ class HomeScreenRobot { title: String, interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { + Log.i(TAG, "openTopSiteTabWithTitle: Trying to click top site with title $title") onView(withId(R.id.top_sites_list)).perform( actionOnItem(hasDescendant(withText(title)), click()), ) + Log.i(TAG, "openTopSiteTabWithTitle:Clicked top site with title $title") BrowserRobot().interact() return BrowserRobot.Transition() } fun openSponsoredShortcut(sponsoredShortcutTitle: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openSponsoredShortcut: Trying to click sponsored top site with title: $sponsoredShortcutTitle") sponsoredShortcut(sponsoredShortcutTitle).click() + Log.i(TAG, "openSponsoredShortcut: Clicked sponsored top site with title: $sponsoredShortcutTitle") BrowserRobot().interact() return BrowserRobot.Transition() } fun renameTopSite(title: String, interact: HomeScreenRobot.() -> Unit): Transition { + Log.i(TAG, "renameTopSite: Trying to click context menu \"Rename\" button") onView(withText("Rename")) .check((matches(withEffectiveVisibility(Visibility.VISIBLE)))) .perform(click()) + Log.i(TAG, "renameTopSite: Clicked context menu \"Rename\" button") + Log.i(TAG, "renameTopSite: Trying to set top site title to: $title") onView(Matchers.allOf(withId(R.id.top_site_title), instanceOf(EditText::class.java))) .perform(ViewActions.replaceText(title)) + Log.i(TAG, "renameTopSite: Set top site title to: $title") + Log.i(TAG, "renameTopSite: Trying to click \"Ok\" rename top site dialog button") onView(withId(android.R.id.button1)).perform((click())) + Log.i(TAG, "renameTopSite: Clicked \"Ok\" rename top site dialog button") HomeScreenRobot().interact() return Transition() } fun removeTopSite(interact: HomeScreenRobot.() -> Unit): Transition { + Log.i(TAG, "removeTopSite: Trying to click context menu \"Remove\" button") onView(withText("Remove")) .check((matches(withEffectiveVisibility(Visibility.VISIBLE)))) .perform(click()) + Log.i(TAG, "removeTopSite: Clicked context menu \"Remove\" button") HomeScreenRobot().interact() return Transition() } fun deleteTopSiteFromHistory(interact: HomeScreenRobot.() -> Unit): Transition { + Log.i(TAG, "deleteTopSiteFromHistory: Waiting for $waitingTime ms for context menu \"Remove from history\" button to exist") mDevice.findObject( UiSelector().resourceId("$packageName:id/simple_text"), ).waitForExists(waitingTime) - deleteFromHistory.click() + Log.i(TAG, "deleteTopSiteFromHistory: Waited for $waitingTime ms for context menu \"Remove from history\" button to exist") + Log.i(TAG, "deleteTopSiteFromHistory: Trying to click context menu \"Remove from history\" button") + deleteFromHistory().click() + Log.i(TAG, "deleteTopSiteFromHistory: Clicked context menu \"Remove from history\" button") HomeScreenRobot().interact() return Transition() } fun openTopSiteInPrivateTab(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openTopSiteInPrivateTab: Trying to click context menu \"Open in private tab\" button") onView(withText("Open in private tab")) .check((matches(withEffectiveVisibility(Visibility.VISIBLE)))) .perform(click()) + Log.i(TAG, "openTopSiteInPrivateTab: Clicked context menu \"Open in private tab\" button") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickSponsorsAndPrivacyButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - sponsorsAndPrivacyButton.waitForExists(waitingTime) - sponsorsAndPrivacyButton.clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickSponsorsAndPrivacyButton: Waiting for $waitingTime ms for context menu \"Our sponsors & your privacy\" button to exist") + sponsorsAndPrivacyButton().waitForExists(waitingTime) + Log.i(TAG, "clickSponsorsAndPrivacyButton: Waited for $waitingTime ms for context menu \"Our sponsors & your privacy\" button to exist") + Log.i(TAG, "clickSponsorsAndPrivacyButton: Trying to click \"Our sponsors & your privacy\" context menu button and wait for $waitingTime ms for a new window") + sponsorsAndPrivacyButton().clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickSponsorsAndPrivacyButton: Clicked \"Our sponsors & your privacy\" context menu button and waited for $waitingTime ms for a new window") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickSponsoredShortcutsSettingsButton(interact: SettingsSubMenuHomepageRobot.() -> Unit): SettingsSubMenuHomepageRobot.Transition { - Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Looking for: ${sponsoredShortcutsSettingsButton.selector}") - sponsoredShortcutsSettingsButton.waitForExists(waitingTime) - sponsoredShortcutsSettingsButton.clickAndWaitForNewWindow(waitingTime) - Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Clicked ${sponsoredShortcutsSettingsButton.selector} and waiting for $waitingTime for a new window") + Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Waiting for $waitingTime ms for context menu \"Settings\" button to exist") + sponsoredShortcutsSettingsButton().waitForExists(waitingTime) + Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Waited for $waitingTime ms for context menu \"Settings\" button to exist") + Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Trying to click \"Settings\" context menu button and wait for $waitingTime for a new window") + sponsoredShortcutsSettingsButton().clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickSponsoredShortcutsSettingsButton: Clicked \"Settings\" context menu button and waited for $waitingTime for a new window") SettingsSubMenuHomepageRobot().interact() return SettingsSubMenuHomepageRobot.Transition() } fun openCommonMythsLink(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "openCommonMythsLink: Trying to click private browsing home screen common myths link") mDevice.findObject( UiSelector() .textContains( getStringResource(R.string.private_browsing_common_myths), ), ).also { it.click() } + Log.i(TAG, "openCommonMythsLink: Clicked private browsing home screen common myths link") BrowserRobot().interact() return BrowserRobot.Transition() @@ -655,7 +886,9 @@ class HomeScreenRobot { fun clickSaveTabsToCollectionButton(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { scrollToElementByText(getStringResource(R.string.no_collections_description2)) + Log.i(TAG, "clickSaveTabsToCollectionButton: Trying to click save tabs to collection button") saveTabsToCollectionButton().click() + Log.i(TAG, "clickSaveTabsToCollectionButton: Clicked save tabs to collection button") TabDrawerRobot().interact() return TabDrawerRobot.Transition() @@ -663,15 +896,18 @@ class HomeScreenRobot { fun clickSaveTabsToCollectionButton(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { scrollToElementByText(getStringResource(R.string.no_collections_description2)) + Log.i(TAG, "clickSaveTabsToCollectionButton: Trying to click save tabs to collection button") saveTabsToCollectionButton().click() - + Log.i(TAG, "clickSaveTabsToCollectionButton: Clicked save tabs to collection button") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) } fun expandCollection(title: String, interact: CollectionRobot.() -> Unit): CollectionRobot.Transition { assertUIObjectExists(itemContainingText(title)) + Log.i(TAG, "expandCollection: Trying to click collection with title: $title and wait for $waitingTimeShort ms for a new window") itemContainingText(title).clickAndWaitForNewWindow(waitingTimeShort) + Log.i(TAG, "expandCollection: Clicked collection with title: $title and waited for $waitingTimeShort ms for a new window") assertUIObjectExists(itemWithDescription(getStringResource(R.string.remove_tab_from_collection))) CollectionRobot().interact() @@ -681,61 +917,62 @@ class HomeScreenRobot { fun openRecentlyVisitedSearchGroupHistoryList(title: String, interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { scrollToElementByText("Recently visited") val searchGroup = mDevice.findObject(UiSelector().text(title)) + Log.i(TAG, "openRecentlyVisitedSearchGroupHistoryList: Waiting for $waitingTimeShort ms for recently visited search group with title: $title to exist") searchGroup.waitForExists(waitingTimeShort) + Log.i(TAG, "openRecentlyVisitedSearchGroupHistoryList: Waited for $waitingTimeShort ms for recently visited search group with title: $title to exist") + Log.i(TAG, "openRecentlyVisitedSearchGroupHistoryList: Trying to click recently visited search group with title: $title") searchGroup.click() + Log.i(TAG, "openRecentlyVisitedSearchGroupHistoryList: Clicked recently visited search group with title: $title") HistoryRobot().interact() return HistoryRobot.Transition() } fun openCustomizeHomepage(interact: SettingsSubMenuHomepageRobot.() -> Unit): SettingsSubMenuHomepageRobot.Transition { + Log.i(TAG, "openCustomizeHomepage: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") homeScreenList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "openCustomizeHomepage: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the home screen") + Log.i(TAG, "openCustomizeHomepage: Trying to click \"Customize homepage\" button and wait for $waitingTime ms for a new window") mDevice.findObject( UiSelector() .textContains( "Customize homepage", ), ).clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "openCustomizeHomepage: Clicked \"Customize homepage\" button and wait for $waitingTime ms for a new window") SettingsSubMenuHomepageRobot().interact() return SettingsSubMenuHomepageRobot.Transition() } fun clickJumpBackInShowAllButton(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { + Log.i(TAG, "clickJumpBackInShowAllButton: Trying to click \"Show all\" button and wait for $waitingTime ms for a new window") mDevice .findObject( UiSelector() .textContains(getStringResource(R.string.recent_tabs_show_all)), ).clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickJumpBackInShowAllButton: Clicked \"Show all\" button and wait for $waitingTime ms for a new window") TabDrawerRobot().interact() return TabDrawerRobot.Transition() } fun clickJumpBackInShowAllButton(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { + Log.i(TAG, "clickJumpBackInShowAllButton: Trying to click \"Show all\" button and wait for $waitingTime ms for a new window") mDevice .findObject( UiSelector() .textContains(getStringResource(R.string.recent_tabs_show_all)), ).clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickJumpBackInShowAllButton: Clicked \"Show all\" button and wait for $waitingTime ms for a new window") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) } - fun clickJumpBackInItemWithTitle(itemTitle: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - mDevice - .findObject( - UiSelector() - .resourceId("recent.tab.title") - .textContains(itemTitle), - ).clickAndWaitForNewWindow(waitingTime) - - BrowserRobot().interact() - return BrowserRobot.Transition() - } - fun clickPocketStoryItem(publisher: String, position: Int, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "clickPocketStoryItem: Trying to click pocket story item published by: $publisher at position: $position and wait for $waitingTime ms for a new window") mDevice.findObject( UiSelector() .className("android.view.View") @@ -746,18 +983,25 @@ class HomeScreenRobot { .index(1) .textContains(publisher), ).clickAndWaitForNewWindow(waitingTime) + Log.i(TAG, "clickPocketStoryItem: Clicked pocket story item published by: $publisher at position: $position and wait for $waitingTime ms for a new window") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickPocketDiscoverMoreButton(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - pocketStoriesList + Log.i(TAG, "clickPocketDiscoverMoreButton: Trying to scroll into view the \"Discover more\" button") + pocketStoriesList() .scrollIntoView(UiSelector().text("Discover more")) + Log.i(TAG, "clickPocketDiscoverMoreButton: Scrolled into view the \"Discover more\" button") mDevice.findObject(UiSelector().text("Discover more")).also { + Log.i(TAG, "clickPocketDiscoverMoreButton: Waiting for $waitingTime ms for \"Discover more\" button to exist") it.waitForExists(waitingTimeShort) + Log.i(TAG, "clickPocketDiscoverMoreButton: Waited for $waitingTime ms for \"Discover more\" button to exist") + Log.i(TAG, "clickPocketDiscoverMoreButton: Trying to click \"Discover more\" button") it.click() + Log.i(TAG, "clickPocketDiscoverMoreButton: Clicked \"Discover more\" button") } BrowserRobot().interact() @@ -765,7 +1009,9 @@ class HomeScreenRobot { } fun clickPocketLearnMoreLink(composeTestRule: ComposeTestRule, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "clickPocketLearnMoreLink: Trying to click pocket \"Learn more\" link") composeTestRule.onNodeWithTag("pocket.header.subtitle", true).performClick() + Log.i(TAG, "clickPocketLearnMoreLink: Clicked pocket \"Learn more\" link") BrowserRobot().interact() return BrowserRobot.Transition() @@ -775,9 +1021,11 @@ class HomeScreenRobot { composeTestRule: ComposeTestRule, interact: SettingsRobot.() -> Unit, ): SettingsRobot.Transition { + Log.i(TAG, "clickSetAsDefaultBrowserOnboardingButton: Trying to click \"Set as default browser\" onboarding button") composeTestRule.onNodeWithText( getStringResource(R.string.juno_onboarding_default_browser_positive_button), ).performClick() + Log.i(TAG, "clickSetAsDefaultBrowserOnboardingButton: Clicked \"Set as default browser\" onboarding button") SettingsRobot().interact() return SettingsRobot.Transition() @@ -787,9 +1035,11 @@ class HomeScreenRobot { composeTestRule: ComposeTestRule, interact: SyncSignInRobot.() -> Unit, ): SyncSignInRobot.Transition { + Log.i(TAG, "clickSignInOnboardingButton: Trying to click \"Sign in\" onboarding button") composeTestRule.onNodeWithText( getStringResource(R.string.juno_onboarding_sign_in_positive_button), ).performClick() + Log.i(TAG, "clickSignInOnboardingButton: Clicked \"Sign in\" onboarding button") SyncSignInRobot().interact() return SyncSignInRobot.Transition() @@ -814,129 +1064,8 @@ private fun homeScreenList() = .scrollable(true), ).setAsVerticalList() -private fun assertKeyboardVisibility(isExpectedToBeVisible: Boolean) = - Assert.assertEquals( - isExpectedToBeVisible, - mDevice - .executeShellCommand("dumpsys input_method | grep mInputShown") - .contains("mInputShown=true"), - ) - -private fun assertTabButton() = - onView(allOf(withId(R.id.tab_button), isDisplayed())) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertCollectionsHeader() = - onView(allOf(withText("Collections"))) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertNoCollectionsText() = - onView( - withText( - containsString( - "Collect the things that matter to you.\n" + - "Group together similar searches, sites, and tabs for quick access later.", - ), - ), - ).check(matches(isDisplayed())) - -private fun assertHomeComponent() = - onView(ViewMatchers.withResourceName("sessionControlRecyclerView")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - private fun threeDotButton() = onView(allOf(withId(R.id.menuButton))) -private fun assertExistingTopSitesList() = - assertUIObjectExists(itemWithResId("$packageName:id/top_sites_list")) - -private fun assertExistingTopSitesTabs(title: String) { - mDevice.findObject( - UiSelector() - .resourceId("$packageName:id/top_site_title") - .textContains(title), - ).waitForExists(waitingTime) - - onView(allOf(withId(R.id.top_sites_list))) - .check(matches(hasDescendant(withText(title)))) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertSponsoredShortcutLogoIsDisplayed(position: Int) = - assertUIObjectExists( - itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) - .getChild( - UiSelector() - .resourceId("$packageName:id/favicon_card"), - ), - ) - -private fun assertSponsoredSubtitleIsDisplayed(position: Int) = - assertUIObjectExists( - itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) - .getChild( - UiSelector() - .resourceId("$packageName:id/top_site_subtitle"), - ), - ) - -private fun assertSponsoredShortcutTitle(sponsoredShortcutTitle: String, position: Int) = - assertUIObjectExists( - itemWithResIdAndIndex(resourceId = "$packageName:id/top_site_item", index = position - 1) - .getChild( - UiSelector() - .textContains(sponsoredShortcutTitle), - ), - ) - -private fun assertNotExistingTopSitesList(title: String) { - mDevice.findObject(UiSelector().text(title)).waitUntilGone(waitingTime) - assertUIObjectExists( - itemWithResIdContainingText( - "$packageName:id/top_site_title", - title, - ), - exists = false, - ) -} - -private fun assertSponsoredTopSitesNotDisplayed() = - assertUIObjectExists( - itemWithResIdContainingText( - "$packageName:id/top_site_subtitle", - getStringResource(R.string.top_sites_sponsored_label), - ), - exists = false, - ) - -private fun assertTopSiteContextMenuItems() { - mDevice.waitNotNull( - findObject(By.text("Open in private tab")), - waitingTime, - ) - mDevice.waitNotNull( - findObject(By.text("Remove")), - waitingTime, - ) -} - -private fun assertJumpBackInItemTitle(testRule: ComposeTestRule, itemTitle: String) = - testRule.onNodeWithTag("recent.tab.title", useUnmergedTree = true).assert(hasText(itemTitle)) - -private fun assertJumpBackInItemWithUrl(testRule: ComposeTestRule, itemUrl: String) = - testRule.onNodeWithTag("recent.tab.url", useUnmergedTree = true).assert(hasText(itemUrl)) - -private fun assertJumpBackInShowAllButton() = - assertUIObjectExists(itemContainingText(getStringResource(R.string.recent_tabs_show_all))) - -private fun assertRecentlyVisitedSectionIsDisplayed(exists: Boolean) = - assertUIObjectExists(itemContainingText(getStringResource(R.string.history_metadata_header_2)), exists = exists) - -private fun assertRecentBookmarksSectionIsDisplayed(exists: Boolean) = - assertUIObjectExists(itemContainingText(getStringResource(R.string.recently_saved_title)), exists = exists) - -private fun assertPocketSectionIsDisplayed(exists: Boolean) = - assertUIObjectExists(itemContainingText(getStringResource(R.string.pocket_stories_header_1)), exists = exists) - private fun saveTabsToCollectionButton() = onView(withId(R.id.add_tabs_to_collections_button)) private fun tabsCounter() = onView(withId(R.id.tab_button)) @@ -968,12 +1097,12 @@ private fun homepageWordmark() = private fun navigationToolbar() = itemWithResId("$packageName:id/toolbar") -private val menuButton = +private fun menuButton() = itemWithResId("$packageName:id/menuButton") private fun tabCounter(numberOfOpenTabs: String) = itemWithResIdAndText("$packageName:id/counter_text", numberOfOpenTabs) -val deleteFromHistory = +fun deleteFromHistory() = onView( allOf( withId(R.id.simple_text), @@ -981,13 +1110,7 @@ val deleteFromHistory = ), ).inRoot(RootMatchers.isPlatformPopup()) -private val recentlyVisitedList = - UiScrollable( - UiSelector() - .className("android.widget.HorizontalScrollView"), - ).setAsHorizontalList() - -private val sponsoredShortcutsSettingsButton = +private fun sponsoredShortcutsSettingsButton() = mDevice .findObject( UiSelector() @@ -995,7 +1118,7 @@ private val sponsoredShortcutsSettingsButton = .resourceId("$packageName:id/simple_text"), ) -private val sponsorsAndPrivacyButton = +private fun sponsorsAndPrivacyButton() = mDevice .findObject( UiSelector() @@ -1003,5 +1126,5 @@ private val sponsorsAndPrivacyButton = .resourceId("$packageName:id/simple_text"), ) -private val pocketStoriesList = +private fun pocketStoriesList() = UiScrollable(UiSelector().resourceId("pocket.stories")).setAsHorizontalList() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/LibrarySubMenusMultipleSelectionToolbarRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/LibrarySubMenusMultipleSelectionToolbarRobot.kt index a86f8802e..b3b3d395c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/LibrarySubMenusMultipleSelectionToolbarRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/LibrarySubMenusMultipleSelectionToolbarRobot.kt @@ -5,7 +5,7 @@ package org.mozilla.fenix.ui.robots import android.net.Uri -import android.widget.TextView +import android.util.Log import androidx.compose.ui.test.onNodeWithTag import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches @@ -16,12 +16,12 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withParent import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.uiautomator.By -import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.Matchers.allOf import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.HomeActivityComposeTestRule -import org.mozilla.fenix.helpers.TestAssetHelper import org.mozilla.fenix.helpers.TestAssetHelper.waitingTime import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.packageName @@ -34,30 +34,90 @@ import org.mozilla.fenix.tabstray.TabsTrayTestTag */ class LibrarySubMenusMultipleSelectionToolbarRobot { - fun verifyMultiSelectionCheckmark() = assertMultiSelectionCheckmark() - - fun verifyMultiSelectionCheckmark(url: Uri) = assertMultiSelectionCheckmark(url) + fun verifyMultiSelectionCheckmark() { + Log.i(TAG, "verifyMultiSelectionCheckmark: Trying to verify that the multi-selection checkmark is displayed") + onView(withId(R.id.checkmark)).check(matches(isDisplayed())) + Log.i(TAG, "verifyMultiSelectionCheckmark: Verified that the multi-selection checkmark is displayed") + } - fun verifyMultiSelectionCounter() = assertMultiSelectionCounter() + fun verifyMultiSelectionCheckmark(url: Uri) { + Log.i(TAG, "verifyMultiSelectionCheckmark: Trying to verify that the multi-selection checkmark for item with url: $url is displayed") + onView( + allOf( + withId(R.id.checkmark), + withParent( + withParent( + withChild( + allOf( + withId(R.id.url), + withText(url.toString()), + ), + ), + ), + ), + + // This is used as part of the `multiSelectionToolbarItemsTest` test. Somehow, in the view hierarchy, + // the match above is finding two checkmark views - one visible, one hidden, which is throwing off + // the matcher. This 'isDisplayed' check is a hacky workaround for this, we're explicitly ignoring + // the hidden one. Why are there two to begin with, though? + isDisplayed(), + ), + ).check(matches(isDisplayed())) + Log.i(Constants.TAG, "verifyMultiSelectionCheckmark: Verified that the multi-selection checkmark for item with url: $url is displayed") + } - fun verifyShareHistoryButton() = assertShareHistoryButton() + fun verifyMultiSelectionCounter() { + Log.i(TAG, "verifyMultiSelectionCounter: Trying to verify that the multi-selection toolbar containing: \"1 selected\" is displayed") + onView(withText("1 selected")).check(matches(isDisplayed())) + Log.i(TAG, "verifyMultiSelectionCounter: Verified that the multi-selection toolbar containing: \"1 selected\" is displayed") + } - fun verifyShareBookmarksButton() = assertShareBookmarksButton() + fun verifyShareHistoryButton() { + Log.i(TAG, "verifyShareHistoryButton: Trying to verify that the multi-selection share history button is displayed") + shareHistoryButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyShareHistoryButton: Verified that the multi-selection share history button is displayed") + } - fun verifyShareOverlay() = assertShareOverlay() + fun verifyShareBookmarksButton() { + Log.i(TAG, "verifyShareBookmarksButton: Trying to verify that the multi-selection share bookmarks button is displayed") + shareBookmarksButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyShareBookmarksButton: Verified that the multi-selection share bookmarks button is displayed") + } - fun verifyShareAppsLayout() = assertShareAppsLayout() + fun verifyShareOverlay() { + Log.i(TAG, "verifyShareOverlay: Trying to verify that the share overlay is displayed") + onView(withId(R.id.shareWrapper)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareOverlay: Verified that the share overlay is displayed") + } - fun verifyShareTabFavicon() = assertShareTabFavicon() + fun verifyShareTabFavicon() { + Log.i(TAG, "verifyShareTabFavicon: Trying to verify that the shared tab favicon is displayed") + onView(withId(R.id.share_tab_favicon)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareTabFavicon: Verified that the shared tab favicon is displayed") + } - fun verifyShareTabTitle() = assertShareTabTitle() + fun verifyShareTabTitle() { + Log.i(TAG, "verifyShareTabTitle: Trying to verify that the shared tab title is displayed") + onView(withId(R.id.share_tab_title)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareTabTitle: Verified that the shared tab title is displayed") + } - fun verifyShareTabUrl() = assertShareTabUrl() + fun verifyShareTabUrl() { + Log.i(TAG, "verifyShareTabUrl: Trying to verify that the shared tab url is displayed") + onView(withId(R.id.share_tab_url)).check(matches(isDisplayed())) + Log.i(TAG, "verifyShareTabUrl: Verified that the shared tab url is displayed") + } - fun verifyCloseToolbarButton() = assertCloseToolbarButton() + fun verifyCloseToolbarButton() { + Log.i(TAG, "verifyCloseToolbarButton: Trying to verify that the navigate up toolbar button is displayed") + closeToolbarButton().check(matches(isDisplayed())) + Log.i(TAG, "verifyCloseToolbarButton: Verified that the navigate up toolbar button is displayed") + } fun clickShareHistoryButton() { + Log.i(TAG, "clickShareHistoryButton: Trying to click the multi-selection share history button") shareHistoryButton().click() + Log.i(TAG, "clickShareHistoryButton: Clicked the multi-selection share history button") mDevice.waitNotNull( Until.findObject( @@ -68,7 +128,9 @@ class LibrarySubMenusMultipleSelectionToolbarRobot { } fun clickShareBookmarksButton() { + Log.i(TAG, "clickShareBookmarksButton: Trying to click the multi-selection share bookmarks button") shareBookmarksButton().click() + Log.i(TAG, "clickShareBookmarksButton: Clicked the multi-selection share bookmarks button") mDevice.waitNotNull( Until.findObject( @@ -79,31 +141,35 @@ class LibrarySubMenusMultipleSelectionToolbarRobot { } fun clickMultiSelectionDelete() { + Log.i(TAG, "clickMultiSelectionDelete: Trying to click the multi-selection delete button") deleteButton().click() + Log.i(TAG, "clickMultiSelectionDelete: Clicked the multi-selection delete button") } class Transition { - fun closeShareDialogReturnToPage(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { - BrowserRobot().interact() - return BrowserRobot.Transition() - } - fun closeToolbarReturnToHistory(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { + Log.i(TAG, "closeToolbarReturnToHistory: Trying to click the navigate up toolbar button") closeToolbarButton().click() + Log.i(TAG, "closeToolbarReturnToHistory: Clicked the navigate up toolbar button") HistoryRobot().interact() return HistoryRobot.Transition() } fun closeToolbarReturnToBookmarks(interact: BookmarksRobot.() -> Unit): BookmarksRobot.Transition { + Log.i(TAG, "closeToolbarReturnToBookmarks: Trying to click the navigate up toolbar button") closeToolbarButton().click() + Log.i(TAG, "closeToolbarReturnToBookmarks: Clicked the navigate up toolbar button") BookmarksRobot().interact() return BookmarksRobot.Transition() } fun clickOpenNewTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { + Log.i(TAG, "clickOpenNewTab: Trying to click the multi-select \"Open in a new tab\" context menu button") openInNewTabButton().click() + Log.i(TAG, "clickOpenNewTab: Clicked the multi-select \"Open in a new tab\" context menu button") + mDevice.waitNotNull( Until.findObject(By.res("$packageName:id/tab_layout")), waitingTime, @@ -114,15 +180,21 @@ class LibrarySubMenusMultipleSelectionToolbarRobot { } fun clickOpenNewTab(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { + Log.i(TAG, "clickOpenNewTab: Trying to click the multi-select \"Open in a new tab\" context menu button") openInNewTabButton().click() + Log.i(TAG, "clickOpenNewTab: Clicked the multi-select \"Open in a new tab\" context menu button") + Log.i(TAG, "clickOpenNewTab: Trying to verify that the tabs tray exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.tabsTray).assertExists() + Log.i(TAG, "clickOpenNewTab: Verified that the tabs tray exists") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) } fun clickOpenPrivateTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { + Log.i(TAG, "clickOpenPrivateTab: Trying to click the multi-select \"Open in a private tab\" context menu button") openInPrivateTabButton().click() + Log.i(TAG, "clickOpenPrivateTab: Clicked the multi-select \"Open in a private tab\" context menu button") mDevice.waitNotNull( Until.findObject(By.res("$packageName:id/tab_layout")), waitingTime, @@ -133,7 +205,9 @@ class LibrarySubMenusMultipleSelectionToolbarRobot { } fun clickOpenPrivateTab(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { + Log.i(TAG, "clickOpenPrivateTab: Trying to click the multi-select \"Open in a private tab\" context menu button") openInPrivateTabButton().click() + Log.i(TAG, "clickOpenPrivateTab: Clicked the multi-select \"Open in a private tab\" context menu button") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) @@ -157,53 +231,3 @@ private fun openInNewTabButton() = onView(withText("Open in new tab")) private fun openInPrivateTabButton() = onView(withText("Open in private tab")) private fun deleteButton() = onView(withText("Delete")) - -private fun assertMultiSelectionCheckmark() = - onView(withId(R.id.checkmark)) - .check(matches(isDisplayed())) - -private fun assertMultiSelectionCheckmark(url: Uri) = - onView( - allOf( - withId(R.id.checkmark), - withParent(withParent(withChild(allOf(withId(R.id.url), withText(url.toString()))))), - - // This is used as part of the `multiSelectionToolbarItemsTest` test. Somehow, in the view hierarchy, - // the match above is finding two checkmark views - one visible, one hidden, which is throwing off - // the matcher. This 'isDisplayed' check is a hacky workaround for this, we're explicitly ignoring - // the hidden one. Why are there two to begin with, though? - isDisplayed(), - ), - ) - .check(matches(isDisplayed())) - -private fun assertMultiSelectionCounter() = - onView(withText("1 selected")).check(matches(isDisplayed())) - -private fun assertShareHistoryButton() = - shareHistoryButton().check(matches(isDisplayed())) - -private fun assertShareBookmarksButton() = - shareBookmarksButton().check(matches(isDisplayed())) - -private fun assertShareOverlay() = - onView(withId(R.id.shareWrapper)).check(matches(isDisplayed())) - -private fun assertShareAppsLayout() = { - val sendToDeviceTitle = mDevice.findObject( - UiSelector() - .instance(0) - .className(TextView::class.java), - ) - sendToDeviceTitle.waitForExists(TestAssetHelper.waitingTime) -} - -private fun assertShareTabTitle() = - onView(withId(R.id.share_tab_title)).check(matches(isDisplayed())) - -private fun assertShareTabFavicon() = - onView(withId(R.id.share_tab_favicon)).check(matches(isDisplayed())) - -private fun assertShareTabUrl() = onView(withId(R.id.share_tab_url)) - -private fun assertCloseToolbarButton() = closeToolbarButton().check(matches(isDisplayed())) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt index 2cb540324..cb6a84956 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NavigationToolbarRobot.kt @@ -31,7 +31,6 @@ import androidx.test.uiautomator.By.textContains import androidx.test.uiautomator.UiSelector import androidx.test.uiautomator.Until import org.hamcrest.CoreMatchers.allOf -import org.hamcrest.CoreMatchers.not import org.junit.Assert.assertTrue import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants @@ -58,27 +57,55 @@ import org.mozilla.fenix.tabstray.TabsTrayTestTag * Implementation of Robot Pattern for the URL toolbar. */ class NavigationToolbarRobot { - fun verifyUrl(url: String) = + fun verifyUrl(url: String) { + Log.i(TAG, "verifyUrl: Trying to verify toolbar text matches $url") onView(withId(R.id.mozac_browser_toolbar_url_view)).check(matches(withText(url))) + Log.i(TAG, "verifyUrl: Verified toolbar text matches $url") + } - fun verifyNoHistoryBookmarks() = assertNoHistoryBookmarks() - - fun verifyTabButtonShortcutMenuItems() = assertTabButtonShortcutMenuItems() - - fun verifyReaderViewDetected(visible: Boolean = false) = - assertReaderViewDetected(visible) + fun verifyTabButtonShortcutMenuItems() { + Log.i(TAG, "verifyTabButtonShortcutMenuItems: Trying to verify tab counter shortcut options") + onView(withId(R.id.mozac_browser_menu_recyclerView)) + .check(matches(hasDescendant(withText("Close tab")))) + .check(matches(hasDescendant(withText("New private tab")))) + .check(matches(hasDescendant(withText("New tab")))) + Log.i(TAG, "verifyTabButtonShortcutMenuItems: Verified tab counter shortcut options") + } - fun verifyCloseReaderViewDetected(visible: Boolean = false) = - assertCloseReaderViewDetected(visible) + fun verifyReaderViewDetected(visible: Boolean = false) { + Log.i(TAG, "verifyReaderViewDetected: Waiting for $waitingTime ms for reader view button to exist") + mDevice.findObject( + UiSelector() + .description("Reader view"), + ).waitForExists(waitingTime) + Log.i(TAG, "verifyReaderViewDetected: Waited for $waitingTime ms for reader view button to exist") + Log.i(TAG, "verifyReaderViewDetected: Trying to verify that the reader view button is visible") + onView( + allOf( + withParent(withId(R.id.mozac_browser_toolbar_page_actions)), + withContentDescription("Reader view"), + ), + ).check( + if (visible) { + matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)) + } else { + ViewAssertions.doesNotExist() + }, + ) + Log.i(TAG, "verifyReaderViewDetected: Verified that the reader view button is visible") + } fun toggleReaderView() { + Log.i(TAG, "toggleReaderView: Waiting for $waitingTime ms for reader view button to exist") mDevice.findObject( UiSelector() .resourceId("$packageName:id/mozac_browser_toolbar_page_actions"), ) .waitForExists(waitingTime) - + Log.i(TAG, "toggleReaderView: Waited for $waitingTime ms for reader view button to exist") + Log.i(TAG, "toggleReaderView: Trying to click the reader view button") readerViewToggle().click() + Log.i(TAG, "toggleReaderView: Clicked the reader view button") } fun verifyClipboardSuggestionsAreDisplayed(link: String = "", shouldBeDisplayed: Boolean) = @@ -91,35 +118,49 @@ class NavigationToolbarRobot { exists = shouldBeDisplayed, ) - fun longClickEditModeToolbar() = - mDevice.findObject(By.res("$packageName:id/mozac_browser_toolbar_edit_url_view")).click(LONG_CLICK_DURATION) + fun longClickEditModeToolbar() { + Log.i(TAG, "longClickEditModeToolbar: Trying to long click the edit mode toolbar") + mDevice.findObject(By.res("$packageName:id/mozac_browser_toolbar_edit_url_view")) + .click(LONG_CLICK_DURATION) + Log.i(TAG, "longClickEditModeToolbar: Long clicked the edit mode toolbar") + } fun clickContextMenuItem(item: String) { mDevice.waitNotNull( Until.findObject(By.text(item)), waitingTime, ) + Log.i(TAG, "clickContextMenuItem: Trying click context menu item: $item") mDevice.findObject(By.text(item)).click() + Log.i(TAG, "clickContextMenuItem: Clicked context menu item: $item") } - fun clickClearToolbarButton() = clearAddressBarButton().click() + fun clickClearToolbarButton() { + Log.i(TAG, "clickClearToolbarButton: Trying click the clear address button") + clearAddressBarButton().click() + Log.i(TAG, "clickClearToolbarButton: Clicked the clear address button") + } fun verifyToolbarIsEmpty() = - itemWithResIdContainingText( - "$packageName:id/mozac_browser_toolbar_edit_url_view", - getStringResource(R.string.search_hint), + assertUIObjectExists( + itemWithResIdContainingText( + "$packageName:id/mozac_browser_toolbar_edit_url_view", + getStringResource(R.string.search_hint), + ), ) // New unified search UI selector fun verifySearchBarPlaceholder(text: String) { + Log.i(TAG, "verifySearchBarPlaceholder: Waiting for $waitingTime ms for the toolbar to exist") urlBar().waitForExists(waitingTime) + Log.i(TAG, "verifySearchBarPlaceholder: Waited for $waitingTime ms for the toolbar to exist") assertItemTextEquals(urlBar(), expectedText = text) } // New unified search UI selector fun verifyDefaultSearchEngine(engineName: String) = assertUIObjectExists( - searchSelectorButton.getChild(UiSelector().description(engineName)), + searchSelectorButton().getChild(UiSelector().description(engineName)), ) fun verifyTextSelectionOptions(vararg textSelectionOptions: String) { @@ -138,19 +179,21 @@ class NavigationToolbarRobot { sessionLoadedIdlingResource = SessionLoadedIdlingResource() openEditURLView() - Log.i(TAG, "enterURLAndEnterToBrowser: Opened edit mode URL view") - + Log.i(TAG, "enterURLAndEnterToBrowser: Trying to set toolbar text to: $url") awesomeBar().setText(url.toString()) - Log.i(TAG, "enterURLAndEnterToBrowser: Set toolbar text to: $url") + Log.i(TAG, "enterURLAndEnterToBrowser: Toolbar text was set to: $url") + Log.i(TAG, "enterURLAndEnterToBrowser: Trying to press device enter button") mDevice.pressEnter() - Log.i(TAG, "enterURLAndEnterToBrowser: Clicked enter on keyboard, submitted query") + Log.i(TAG, "enterURLAndEnterToBrowser: Pressed device enter button") runWithIdleRes(sessionLoadedIdlingResource) { + Log.i(TAG, "enterURLAndEnterToBrowser: Trying to assert that home screen layout or download button or the total cookie protection contextual hint exist") assertTrue( itemWithResId("$packageName:id/browserLayout").waitForExists(waitingTime) || itemWithResId("$packageName:id/download_button").waitForExists(waitingTime) || itemWithResId("cfr.dismiss").waitForExists(waitingTime), ) + Log.i(TAG, "enterURLAndEnterToBrowser: Asserted that home screen layout or download button or the total cookie protection contextual hint exist") } BrowserRobot().interact() @@ -162,9 +205,12 @@ class NavigationToolbarRobot { interact: BrowserRobot.() -> Unit, ): BrowserRobot.Transition { openEditURLView() - + Log.i(TAG, "enterURLAndEnterToBrowserForTCPCFR: Trying to set toolbar text to: $url") awesomeBar().setText(url.toString()) + Log.i(TAG, "enterURLAndEnterToBrowserForTCPCFR: Toolbar text was set to: $url") + Log.i(TAG, "enterURLAndEnterToBrowserForTCPCFR: Trying to press device enter button") mDevice.pressEnter() + Log.i(TAG, "enterURLAndEnterToBrowserForTCPCFR: Pressed device enter button") BrowserRobot().interact() return BrowserRobot.Transition() @@ -176,12 +222,17 @@ class NavigationToolbarRobot { sessionLoadedIdlingResource = SessionLoadedIdlingResource() openEditURLView() - + Log.i(TAG, "openTabCrashReporter: Trying to set toolbar text to: $crashUrl") awesomeBar().setText(crashUrl) + Log.i(TAG, "openTabCrashReporter: Toolbar text was set to: $crashUrl") + Log.i(TAG, "openTabCrashReporter: Trying to press device enter button") mDevice.pressEnter() + Log.i(TAG, "openTabCrashReporter: Pressed device enter button") runWithIdleRes(sessionLoadedIdlingResource) { + Log.i(TAG, "openTabCrashReporter: Trying to find the tab crasher image") mDevice.findObject(UiSelector().resourceId("$packageName:id/crash_tab_image")) + Log.i(TAG, "openTabCrashReporter: Found the tab crasher image") } BrowserRobot().interact() @@ -190,15 +241,21 @@ class NavigationToolbarRobot { fun openThreeDotMenu(interact: ThreeDotMenuMainRobot.() -> Unit): ThreeDotMenuMainRobot.Transition { mDevice.waitNotNull(Until.findObject(By.res("$packageName:id/mozac_browser_toolbar_menu")), waitingTime) + Log.i(TAG, "openThreeDotMenu: Trying to click the main menu button") threeDotButton().click() + Log.i(TAG, "openThreeDotMenu: Clicked the main menu button") ThreeDotMenuMainRobot().interact() return ThreeDotMenuMainRobot.Transition() } fun openTabTray(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition { + Log.i(TAG, "openTabTray: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) + Log.i(TAG, "openTabTray: Waited for device to be idle for $waitingTime ms") + Log.i(TAG, "openTabTray: Trying to click the tabs tray button") tabTrayButton().click() + Log.i(TAG, "openTabTray: Clicked the tabs tray button") mDevice.waitNotNull( Until.findObject(By.res("$packageName:id/tab_layout")), waitingTime, @@ -211,6 +268,7 @@ class NavigationToolbarRobot { fun openComposeTabDrawer(composeTestRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { for (i in 1..Constants.RETRY_COUNT) { try { + Log.i(TAG, "openComposeTabDrawer: Started try #$i") mDevice.waitForObjects( mDevice.findObject( UiSelector() @@ -218,30 +276,40 @@ class NavigationToolbarRobot { ), waitingTime, ) - + Log.i(TAG, "openComposeTabDrawer: Trying to click the tabs tray button") tabTrayButton().click() - + Log.i(TAG, "openComposeTabDrawer: Clicked the tabs tray button") + Log.i(TAG, "openComposeTabDrawer: Trying to verify that the tabs tray exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.tabsTray).assertExists() + Log.i(TAG, "openComposeTabDrawer: Verified that the tabs tray exists") break } catch (e: AssertionError) { + Log.i(TAG, "openComposeTabDrawer: AssertionError caught, executing fallback methods") if (i == Constants.RETRY_COUNT) { throw e } else { + Log.i(TAG, "openComposeTabDrawer: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "openComposeTabDrawer: Waited for device to be idle") } } } - + Log.i(TAG, "openComposeTabDrawer: Trying to verify the tabs tray new tab FAB button exists") composeTestRule.onNodeWithTag(TabsTrayTestTag.fab).assertExists() + Log.i(TAG, "openComposeTabDrawer: Verified the tabs tray new tab FAB button exists") ComposeTabDrawerRobot(composeTestRule).interact() return ComposeTabDrawerRobot.Transition(composeTestRule) } fun visitLinkFromClipboard(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "visitLinkFromClipboard: Waiting for $waitingTimeShort ms for clear address button to exist") if (clearAddressBarButton().waitForExists(waitingTimeShort)) { + Log.i(TAG, "visitLinkFromClipboard: Waited for $waitingTimeShort ms for clear address button to exist") + Log.i(TAG, "visitLinkFromClipboard: Trying to click the clear address button") clearAddressBarButton().click() + Log.i(TAG, "visitLinkFromClipboard: Clicked the clear address button") } mDevice.waitNotNull( @@ -257,26 +325,33 @@ class NavigationToolbarRobot { waitingTime, ) } - + Log.i(TAG, "visitLinkFromClipboard: Trying to click the fill link from clipboard button") fillLinkButton().click() + Log.i(TAG, "visitLinkFromClipboard: Clicked the fill link from clipboard button") BrowserRobot().interact() return BrowserRobot.Transition() } fun goBackToHomeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBackToHomeScreen: Trying to click the device back button") mDevice.pressBack() + Log.i(TAG, "goBackToHomeScreen: Clicked the device back button") + Log.i(TAG, "goBackToHomeScreen: Waiting for $waitingTimeShort ms for $packageName window to be updated") mDevice.waitForWindowUpdate(packageName, waitingTimeShort) + Log.i(TAG, "goBackToHomeScreen: Waited for $waitingTimeShort ms for $packageName window to be updated") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun goBackToBrowserScreen(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "goBackToBrowserScreen: Trying to click the device back button") mDevice.pressBack() - Log.i(TAG, "goBackToBrowserScreen: Dismiss awesome bar using device back button") + Log.i(TAG, "goBackToBrowserScreen: Clicked the device back button") + Log.i(TAG, "goBackToBrowserScreen: Waiting for $waitingTimeShort ms for $packageName window to be updated") mDevice.waitForWindowUpdate(packageName, waitingTimeShort) - Log.i(TAG, "goBackToBrowserScreen: Waited $waitingTimeShort for window update") + Log.i(TAG, "goBackToBrowserScreen: Waited for $waitingTimeShort ms for $packageName window to be updated") BrowserRobot().interact() return BrowserRobot.Transition() @@ -284,16 +359,19 @@ class NavigationToolbarRobot { fun openTabButtonShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): Transition { mDevice.waitNotNull(Until.findObject(By.res("$packageName:id/counter_root"))) + Log.i(TAG, "openTabButtonShortcutsMenu: Trying to long click the tab counter button") tabsCounter().perform(longClick()) - Log.i(TAG, "Tabs counter long-click successful.") + Log.i(TAG, "openTabButtonShortcutsMenu: Long clicked the tab counter button") NavigationToolbarRobot().interact() return Transition() } fun closeTabFromShortcutsMenu(interact: NavigationToolbarRobot.() -> Unit): Transition { + Log.i(TAG, "closeTabFromShortcutsMenu: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) - + Log.i(TAG, "closeTabFromShortcutsMenu: Waited for device to be idle for $waitingTime ms") + Log.i(TAG, "closeTabFromShortcutsMenu: Trying to click the \"Close tab\" button") onView(withId(R.id.mozac_browser_menu_recyclerView)) .perform( RecyclerViewActions.actionOnItem( @@ -303,15 +381,17 @@ class NavigationToolbarRobot { ViewActions.click(), ), ) - Log.i(TAG, "Clicked the tab shortcut Close tab button.") + Log.i(TAG, "closeTabFromShortcutsMenu: Clicked the \"Close tab\" button") NavigationToolbarRobot().interact() return Transition() } fun openNewTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "openNewTabFromShortcutsMenu: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) - Log.i(TAG, "Looking for tab shortcut New tab button.") + Log.i(TAG, "openNewTabFromShortcutsMenu: Waited for device to be idle for $waitingTime ms") + Log.i(TAG, "openNewTabFromShortcutsMenu: Trying to click the \"New tab\" button") onView(withId(R.id.mozac_browser_menu_recyclerView)) .perform( RecyclerViewActions.actionOnItem( @@ -321,15 +401,17 @@ class NavigationToolbarRobot { ViewActions.click(), ), ) - Log.i(TAG, "Clicked the tab shortcut New tab button.") + Log.i(TAG, "openNewTabFromShortcutsMenu: Clicked the \"New tab\" button") SearchRobot().interact() return SearchRobot.Transition() } fun openNewPrivateTabFromShortcutsMenu(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "openNewPrivateTabFromShortcutsMenu: Waiting for device to be idle for $waitingTime ms") mDevice.waitForIdle(waitingTime) - Log.i(TAG, "Looking for tab shortcut New private tab button.") + Log.i(TAG, "openNewPrivateTabFromShortcutsMenu: Waited for device to be idle for $waitingTime ms") + Log.i(TAG, "openNewPrivateTabFromShortcutsMenu: Trying to click the \"New private tab\" button") onView(withId(R.id.mozac_browser_menu_recyclerView)) .perform( RecyclerViewActions.actionOnItem( @@ -339,26 +421,33 @@ class NavigationToolbarRobot { ViewActions.click(), ), ) - Log.i(TAG, "Clicked the tab shortcut New private tab button.") + Log.i(TAG, "openNewPrivateTabFromShortcutsMenu: Clicked the \"New private tab\" button") SearchRobot().interact() return SearchRobot.Transition() } fun clickUrlbar(interact: SearchRobot.() -> Unit): SearchRobot.Transition { + Log.i(TAG, "clickUrlbar: Trying to click the toolbar") urlBar().click() - + Log.i(TAG, "clickUrlbar: Clicked the toolbar") + Log.i(TAG, "clickUrlbar: Waiting for $waitingTime ms for the edit mode toolbar to exist") mDevice.findObject( UiSelector().resourceId("$packageName:id/mozac_browser_toolbar_edit_url_view"), ).waitForExists(waitingTime) + Log.i(TAG, "clickUrlbar: Waited for $waitingTime ms for the edit mode toolbar to exist") SearchRobot().interact() return SearchRobot.Transition() } fun clickSearchSelectorButton(interact: SearchRobot.() -> Unit): SearchRobot.Transition { - searchSelectorButton.waitForExists(waitingTime) - searchSelectorButton.click() + Log.i(TAG, "clickSearchSelectorButton: Waiting for $waitingTime ms for the search selector button to exist") + searchSelectorButton().waitForExists(waitingTime) + Log.i(TAG, "clickSearchSelectorButton: Waited for $waitingTime ms for the search selector button to exist") + Log.i(TAG, "clickSearchSelectorButton: Trying to click the search selector button") + searchSelectorButton().click() + Log.i(TAG, "clickSearchSelectorButton: Clicked the search selector button") SearchRobot().interact() return SearchRobot.Transition() @@ -372,25 +461,15 @@ fun navigationToolbar(interact: NavigationToolbarRobot.() -> Unit): NavigationTo } fun openEditURLView() { + Log.i(TAG, "openEditURLView: Waiting for $waitingTime ms for the toolbar to exist") urlBar().waitForExists(waitingTime) + Log.i(TAG, "openEditURLView: Waited for $waitingTime ms for the toolbar to exist") + Log.i(TAG, "openEditURLView: Trying to click the toolbar") urlBar().click() - Log.i(TAG, "openEditURLView: URL bar clicked.") + Log.i(TAG, "openEditURLView: Clicked the toolbar") + Log.i(TAG, "openEditURLView: Waiting for $waitingTime ms for the edit mode toolbar to exist") itemWithResId("$packageName:id/mozac_browser_toolbar_edit_url_view").waitForExists(waitingTime) - Log.i(TAG, "openEditURLView: Edit URL bar displayed.") -} - -private fun assertNoHistoryBookmarks() { - onView(withId(R.id.container)) - .check(matches(not(hasDescendant(withText("Test_Page_1"))))) - .check(matches(not(hasDescendant(withText("Test_Page_2"))))) - .check(matches(not(hasDescendant(withText("Test_Page_3"))))) -} - -private fun assertTabButtonShortcutMenuItems() { - onView(withId(R.id.mozac_browser_menu_recyclerView)) - .check(matches(hasDescendant(withText("Close tab")))) - .check(matches(hasDescendant(withText("New private tab")))) - .check(matches(hasDescendant(withText("New tab")))) + Log.i(TAG, "openEditURLView: Waited for $waitingTime ms for the edit mode toolbar to exist") } private fun urlBar() = mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) @@ -404,49 +483,7 @@ private fun clearAddressBarButton() = itemWithResId("$packageName:id/mozac_brows private fun readerViewToggle() = onView(withParent(withId(R.id.mozac_browser_toolbar_page_actions))) -private fun assertReaderViewDetected(visible: Boolean) { - mDevice.findObject( - UiSelector() - .description("Reader view"), - ) - .waitForExists(waitingTime) - - onView( - allOf( - withParent(withId(R.id.mozac_browser_toolbar_page_actions)), - withContentDescription("Reader view"), - ), - ).check( - if (visible) { - matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)) - } else { - ViewAssertions.doesNotExist() - }, - ) -} - -private fun assertCloseReaderViewDetected(visible: Boolean) { - mDevice.findObject( - UiSelector() - .description("Close reader view"), - ) - .waitForExists(waitingTime) - - onView( - allOf( - withParent(withId(R.id.mozac_browser_toolbar_page_actions)), - withContentDescription("Close reader view"), - ), - ).check( - if (visible) { - matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)) - } else { - ViewAssertions.doesNotExist() - }, - ) -} - -private val searchSelectorButton = +private fun searchSelectorButton() = mDevice.findObject(UiSelector().resourceId("$packageName:id/search_selector")) inline fun runWithIdleRes(ir: IdlingResource?, pendingCheck: () -> Unit) { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt index 7398746e9..99cbbf9a6 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/NotificationRobot.kt @@ -29,44 +29,48 @@ class NotificationRobot { var notificationFound = mDevice.findObject(notification).waitForExists(waitingTime) while (!notificationFound) { + Log.i(TAG, "verifySystemNotificationExists: Waiting for $waitingTime ms for notification: $notification to exist") scrollToEnd() - Log.i(TAG, "verifySystemNotificationExists: Scrolling to the end of the notification tray") - Log.i(TAG, "verifySystemNotificationExists: Looking for $notificationMessage notification") notificationFound = mDevice.findObject(notification).waitForExists(waitingTime) + Log.i(TAG, "verifySystemNotificationExists: Waited for $waitingTime ms for notification: $notification to exist") } assertUIObjectExists(itemWithText(notificationMessage)) } fun clearNotifications() { - if (clearButton.exists()) { - Log.i(TAG, "clearNotifications: Verified that clear notifications button exists") - clearButton.click() - Log.i(TAG, "clearNotifications: Clicked clear notifications button") + if (clearButton().exists()) { + Log.i(TAG, "clearNotifications:The clear notifications button exists") + Log.i(TAG, "clearNotifications: Trying to click the clear notifications button") + clearButton().click() + Log.i(TAG, "clearNotifications: Clicked the clear notifications button") } else { scrollToEnd() - Log.i(TAG, "clearNotifications: Scrolled to end of notifications tray") - if (clearButton.exists()) { - Log.i(TAG, "clearNotifications: Verified that clear notifications button exists") - clearButton.click() - Log.i(TAG, "clearNotifications: Clicked clear notifications button") + if (clearButton().exists()) { + Log.i(TAG, "clearNotifications:The clear notifications button exists") + Log.i(TAG, "clearNotifications: Trying to click the clear notifications button") + clearButton().click() + Log.i(TAG, "clearNotifications: Clicked the clear notifications button") } else if (notificationTray().exists()) { + Log.i(TAG, "clearNotifications: The notifications tray is still displayed") + Log.i(TAG, "clearNotifications: Trying to click device back button") mDevice.pressBack() - Log.i(TAG, "clearNotifications: Dismiss notifications tray by clicking device back button") + Log.i(TAG, "clearNotifications: Clicked device back button") } } } fun cancelAllShownNotifications() { + Log.i(TAG, "cancelAllShownNotifications: Trying to cancel all system notifications") cancelAll() Log.i(TAG, "cancelAllShownNotifications: Canceled all system notifications") } fun verifySystemNotificationDoesNotExist(notificationMessage: String) { - Log.i(TAG, "verifySystemNotificationDoesNotExist: Waiting for $notificationMessage notification to be gone") + Log.i(TAG, "verifySystemNotificationDoesNotExist: Waiting for $waitingTime ms for notification: $notificationMessage to be gone") mDevice.findObject(UiSelector().textContains(notificationMessage)).waitUntilGone(waitingTime) + Log.i(TAG, "verifySystemNotificationDoesNotExist: Waited for $waitingTime ms for notification: $notificationMessage to be gone") assertUIObjectExists(itemContainingText(notificationMessage), exists = false) - Log.i(TAG, "verifySystemNotificationDoesNotExist: Verified that $notificationMessage notification does not exist") } fun verifyPrivateTabsNotification() { @@ -75,17 +79,22 @@ class NotificationRobot { } fun clickMediaNotificationControlButton(action: String) { + Log.i(TAG, "clickMediaNotificationControlButton: Waiting for $waitingTime ms for the system media control button: $action to exist") mediaSystemNotificationButton(action).waitForExists(waitingTime) + Log.i(TAG, "clickMediaNotificationControlButton: Waited for $waitingTime ms for the system media control button: $action to exist") + Log.i(TAG, "clickMediaNotificationControlButton: Trying to click the system media control button: $action") mediaSystemNotificationButton(action).click() + Log.i(TAG, "clickMediaNotificationControlButton: Clicked the system media control button: $action") } fun clickDownloadNotificationControlButton(action: String) { for (i in 1..RETRY_COUNT) { - Log.i(TAG, "clickPageObject: For loop i = $i") + Log.i(TAG, "clickDownloadNotificationControlButton: Started try #$i") try { assertUIObjectExists(downloadSystemNotificationButton(action)) + Log.i(TAG, "clickDownloadNotificationControlButton: Trying to click the download system notification: $action button and wait for $waitingTimeShort ms for a new window") downloadSystemNotificationButton(action).clickAndWaitForNewWindow(waitingTimeShort) - Log.i(TAG, "clickDownloadNotificationControlButton: Clicked app notification $action button and waits for a new window for $waitingTimeShort ms") + Log.i(TAG, "clickDownloadNotificationControlButton: Clicked the download system notification: $action button and waited for $waitingTimeShort ms for a new window") assertUIObjectExists( downloadSystemNotificationButton(action), exists = false, @@ -93,12 +102,13 @@ class NotificationRobot { break } catch (e: AssertionError) { - Log.i(TAG, "clickDownloadNotificationControlButton: Catch block") + Log.i(TAG, "clickDownloadNotificationControlButton: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } + Log.i(TAG, "clickDownloadNotificationControlButton: Waiting for $waitingTimeShort ms for $packageName window to be updated") mDevice.waitForWindowUpdate(packageName, waitingTimeShort) - Log.i(TAG, "clickDownloadNotificationControlButton: Waited $waitingTimeShort ms for window update") + Log.i(TAG, "clickDownloadNotificationControlButton: Waited for $waitingTimeShort ms for $packageName window to be updated") } } } @@ -107,15 +117,17 @@ class NotificationRobot { assertUIObjectExists(mediaSystemNotificationButton(action)) fun expandNotificationMessage() { - while (!notificationHeader.exists()) { + while (!notificationHeader().exists()) { + Log.i(TAG, "expandNotificationMessage: Waiting for $appName notification to exist") scrollToEnd() - Log.i(TAG, "expandNotificationMessage: Scrolled to end of notification tray") } - if (notificationHeader.exists()) { + if (notificationHeader().exists()) { + Log.i(TAG, "expandNotificationMessage: $appName notification exists") // expand the notification - notificationHeader.click() - Log.i(TAG, "expandNotificationMessage: Clicked the app notification") + Log.i(TAG, "expandNotificationMessage: Trying to click $appName notification") + notificationHeader().click() + Log.i(TAG, "expandNotificationMessage: Clicked $appName notification") // double check if notification actions are viewable by checking for action existence; otherwise scroll again while (!mDevice.findObject(UiSelector().resourceId("android:id/action0")).exists() && @@ -123,7 +135,6 @@ class NotificationRobot { ) { Log.i(TAG, "expandNotificationMessage: App notification action buttons do not exist") scrollToEnd() - Log.i(TAG, "expandNotificationMessage: Scrolled to end of notification tray") } } } @@ -136,41 +147,46 @@ class NotificationRobot { ) { // In case it fails, retry max 3x the swipe action on download system notifications for (i in 1..RETRY_COUNT) { - Log.i(TAG, "swipeDownloadNotification: For loop i = $i") + Log.i(TAG, "swipeDownloadNotification: Started try #$i") try { - Log.i(TAG, "swipeDownloadNotification: Try block") var retries = 0 while (itemContainingText(appName).exists() && retries++ < 3) { - Log.i(TAG, "swipeDownloadNotification: While loop retries = $retries") // Swipe left the download system notification if (direction == "Left") { itemContainingText(appName) .also { + Log.i(TAG, "swipeDownloadNotification: Waiting for $waitingTime ms for $appName notification to exist") it.waitForExists(waitingTime) + Log.i(TAG, "swipeDownloadNotification: Waited for $waitingTime ms for $appName notification to exist") + Log.i(TAG, "swipeDownloadNotification: Trying to perform swipe left action on $appName notification") it.swipeLeft(3) + Log.i(TAG, "swipeDownloadNotification: Performed swipe left action on $appName notification") } - Log.i(TAG, "swipeDownloadNotification: Swiped left download notification") } else { // Swipe right the download system notification itemContainingText(appName) .also { + Log.i(TAG, "swipeDownloadNotification: Waiting for $waitingTime ms for $appName notification to exist") it.waitForExists(waitingTime) + Log.i(TAG, "swipeDownloadNotification: Waited for $waitingTime ms for $appName notification to exist") + Log.i(TAG, "swipeDownloadNotification: Trying to perform swipe right action on $appName notification") it.swipeRight(3) + Log.i(TAG, "swipeDownloadNotification: Performed swipe right action on $appName notification") } - Log.i(TAG, "swipeDownloadNotification: Swiped right download notification") } } // Not all download related system notifications can be dismissed if (shouldDismissNotification) { + Log.i(TAG, "swipeDownloadNotification: $appName notification can't be dismissed: $shouldDismissNotification") assertUIObjectExists(itemContainingText(appName), exists = false) } else { + Log.i(TAG, "swipeDownloadNotification: $appName notification can be dismissed: $shouldDismissNotification") assertUIObjectExists(itemContainingText(appName)) - Log.i(TAG, "swipeDownloadNotification: Verified that $appName notification exist") } break } catch (e: AssertionError) { - Log.i(TAG, "swipeDownloadNotification: Catch block") + Log.i(TAG, "swipeDownloadNotification: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { @@ -179,11 +195,12 @@ class NotificationRobot { }.openNotificationShade { // The download complete system notification can't be expanded if (canExpandNotification) { + Log.i(TAG, "swipeDownloadNotification: $appName notification can be expanded: $canExpandNotification") // In all cases the download system notification title will be the app name verifySystemNotificationExists(appName) - Log.i(TAG, "swipeDownloadNotification: Verified that $appName notification exist") expandNotificationMessage() } else { + Log.i(TAG, "swipeDownloadNotification: $appName notification can't be expanded: $canExpandNotification") // Using the download completed system notification summary to bring in to view an properly verify it verifySystemNotificationExists("Download completed") } @@ -194,10 +211,12 @@ class NotificationRobot { } fun clickNotification(notificationMessage: String) { - Log.i(TAG, "clickNotification: Looking for $notificationMessage notification") + Log.i(TAG, "clickNotification: Waiting for $waitingTime ms for $notificationMessage notification to exist") mDevice.findObject(UiSelector().text(notificationMessage)).waitForExists(waitingTime) + Log.i(TAG, "clickNotification: Waited for $waitingTime ms for $notificationMessage notification to exist") + Log.i(TAG, "clickNotification: Trying to click the $notificationMessage notification and wait for $waitingTimeShort ms for a new window") mDevice.findObject(UiSelector().text(notificationMessage)).clickAndWaitForNewWindow(waitingTimeShort) - Log.i(TAG, "clickNotification: Clicked $notificationMessage notification and waiting for $waitingTimeShort ms for a new window") + Log.i(TAG, "clickNotification: Clicked the $notificationMessage notification and waited for $waitingTimeShort ms for a new window") } class Transition { @@ -206,18 +225,22 @@ class NotificationRobot { try { assertUIObjectExists(closePrivateTabsNotification()) } catch (e: AssertionError) { + Log.i(TAG, "clickClosePrivateTabsNotification: Trying to perform fling action to the end of the notification tray") notificationTray().flingToEnd(1) + Log.i(TAG, "clickClosePrivateTabsNotification: Performed fling action to the end of the notification tray") } - + Log.i(TAG, "clickClosePrivateTabsNotification: Trying to click the close private tabs notification") closePrivateTabsNotification().click() + Log.i(TAG, "clickClosePrivateTabsNotification: Clicked the close private tabs notification") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun closeNotificationTray(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeNotificationTray: Trying to click device back button") mDevice.pressBack() - Log.i(TAG, "closeNotificationTray: Closed notification tray using device back button") + Log.i(TAG, "closeNotificationTray: Clicked device back button") BrowserRobot().interact() return BrowserRobot.Transition() @@ -251,7 +274,7 @@ private fun notificationTray() = UiScrollable( UiSelector().resourceId("com.android.systemui:id/notification_stack_scroller"), ).setAsVerticalList() -private val notificationHeader = +private fun notificationHeader() = mDevice.findObject( UiSelector() .resourceId("android:id/app_name_text") @@ -259,10 +282,12 @@ private val notificationHeader = ) private fun scrollToEnd() { + Log.i(TAG, "scrollToEnd: Trying to perform scroll to the end of the notification tray action") notificationTray().scrollToEnd(1) + Log.i(TAG, "scrollToEnd: Performed scroll to the end of the notification tray action") } -private val clearButton = mDevice.findObject(UiSelector().resourceId("com.android.systemui:id/dismiss_text")) +private fun clearButton() = mDevice.findObject(UiSelector().resourceId("com.android.systemui:id/dismiss_text")) private fun cancelAll() { val notificationManager: NotificationManager = diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/PwaRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/PwaRobot.kt index f9e050526..cd31c2fc8 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/PwaRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/PwaRobot.kt @@ -4,24 +4,30 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import androidx.test.uiautomator.UiSelector import org.junit.Assert.assertTrue import org.mozilla.fenix.helpers.AppAndSystemHelper.isExternalAppBrowserActivityInCurrentTask +import org.mozilla.fenix.helpers.Constants +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists +import org.mozilla.fenix.helpers.MatcherHelper.itemWithResId import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.TestHelper.packageName class PwaRobot { - fun verifyCustomTabToolbarIsNotDisplayed() = assertUIObjectExists(customTabToolbar(), exists = false) - fun verifyPwaActivityInCurrentTask() = assertTrue(isExternalAppBrowserActivityInCurrentTask()) + fun verifyCustomTabToolbarIsNotDisplayed() = assertUIObjectExists(itemWithResId("$packageName:id/toolbar"), exists = false) + fun verifyPwaActivityInCurrentTask() { + assertTrue("$TAG: The latest activity of the application is not used for custom tabs or PWAs", isExternalAppBrowserActivityInCurrentTask()) + } class Transition } fun pwaScreen(interact: PwaRobot.() -> Unit): PwaRobot.Transition { + Log.i(TAG, "pwaScreen: Trying to find the engine view") mDevice.findObject(UiSelector().resourceId("$packageName:id/engineView")) + Log.i(Constants.TAG, "pwaScreen: Found the engine view") PwaRobot().interact() return PwaRobot.Transition() } - -private fun customTabToolbar() = mDevice.findObject(UiSelector().resourceId("$packageName:id/toolbar")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ReaderViewRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ReaderViewRobot.kt index 89bd934fb..30d87d72c 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ReaderViewRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/ReaderViewRobot.kt @@ -7,8 +7,8 @@ package org.mozilla.fenix.ui.robots import android.content.Context +import android.util.Log import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.ViewInteraction import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility @@ -16,6 +16,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.platform.app.InstrumentationRegistry import org.junit.Assert.assertEquals import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.click @@ -24,34 +25,98 @@ import org.mozilla.fenix.helpers.click */ class ReaderViewRobot { - fun verifyAppearanceFontGroup(visible: Boolean = false): ViewInteraction = - assertAppearanceFontGroup(visible) + fun verifyAppearanceFontGroup(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceFontGroup: Trying to verify that the font group buttons are visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_font_group), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceFontGroup: Verified that the font group buttons are visible: $visible") + } - fun verifyAppearanceFontSansSerif(visible: Boolean = false): ViewInteraction = - assertAppearanceFontSansSerif(visible) + fun verifyAppearanceFontSansSerif(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceFontSansSerif: Trying to verify that the sans serif font button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_font_sans_serif), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceFontSansSerif: Verified that the sans serif font button is visible: $visible") + } - fun verifyAppearanceFontSerif(visible: Boolean = false): ViewInteraction = - assertAppearanceFontSerif(visible) + fun verifyAppearanceFontSerif(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceFontSerif: Trying to verify that the serif font button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_font_serif), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceFontSerif: Verified that the serif font button is visible: $visible") + } - fun verifyAppearanceFontDecrease(visible: Boolean = false): ViewInteraction = - assertAppearanceFontDecrease(visible) + fun verifyAppearanceFontDecrease(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceFontDecrease: Trying to verify that the decrease font button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_font_size_decrease), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceFontDecrease: Verified that the decrease font button is visible: $visible") + } - fun verifyAppearanceFontIncrease(visible: Boolean = false): ViewInteraction = - assertAppearanceFontIncrease(visible) + fun verifyAppearanceFontIncrease(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceFontIncrease: Trying to verify that the increase font button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_font_size_increase), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceFontIncrease: Verified that the increase font button is visible: $visible") + } - fun verifyAppearanceColorGroup(visible: Boolean = false): ViewInteraction = - assertAppearanceColorGroup(visible) + fun verifyAppearanceColorGroup(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceColorGroup: Trying to verify that the color group buttons are visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_color_scheme_group), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceColorGroup: Verified that the color group buttons are visible: $visible") + } - fun verifyAppearanceColorSepia(visible: Boolean = false): ViewInteraction = - assertAppearanceColorSepia(visible) + fun verifyAppearanceColorSepia(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceColorSepia: Trying to verify that the sepia color button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_color_sepia), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceColorSepia: Verified that the sepia color button is visible: $visible") + } - fun verifyAppearanceColorDark(visible: Boolean = false): ViewInteraction = - assertAppearanceColorDark(visible) + fun verifyAppearanceColorDark(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceColorDark: Trying to verify that the dark color button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_color_dark), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceColorDark: Verified that the dark color button is visible: $visible") + } - fun verifyAppearanceColorLight(visible: Boolean = false): ViewInteraction = - assertAppearanceColorLight(visible) + fun verifyAppearanceColorLight(visible: Boolean = false) { + Log.i(TAG, "verifyAppearanceColorLight: Trying to verify that the light color button is visible: $visible") + onView( + withId(R.id.mozac_feature_readerview_color_light), + ).check( + matches(withEffectiveVisibility(visibleOrGone(visible))), + ) + Log.i(TAG, "verifyAppearanceColorLight: Verified that the light color button is visible: $visible") + } fun verifyAppearanceFontIsActive(fontType: String) { + Log.i(TAG, "verifyAppearanceFontIsActive: Trying to verify that the font type is: $fontType") val fontTypeKey: String = "mozac-readerview-fonttype" val prefs = InstrumentationRegistry.getInstrumentation() @@ -61,9 +126,11 @@ class ReaderViewRobot { ) assertEquals(fontType, prefs.getString(fontTypeKey, "")) + Log.i(TAG, "verifyAppearanceFontIsActive: Verified that the font type is: $fontType") } fun verifyAppearanceFontSize(expectedFontSize: Int) { + Log.i(TAG, "verifyAppearanceFontSize: Trying to verify that the font size is: $expectedFontSize") val fontSizeKey: String = "mozac-readerview-fontsize" val prefs = InstrumentationRegistry.getInstrumentation() @@ -75,9 +142,11 @@ class ReaderViewRobot { val fontSizeKeyValue = prefs.getInt(fontSizeKey, 3) assertEquals(expectedFontSize, fontSizeKeyValue) + Log.i(TAG, "verifyAppearanceFontSize: Verified that the font size is: $expectedFontSize") } fun verifyAppearanceColorSchemeChange(expectedColorScheme: String) { + Log.i(TAG, "verifyAppearanceColorSchemeChange: Trying to verify that the color scheme is: $expectedColorScheme") val colorSchemeKey: String = "mozac-readerview-colorscheme" val prefs = InstrumentationRegistry.getInstrumentation() @@ -87,12 +156,15 @@ class ReaderViewRobot { ) assertEquals(expectedColorScheme, prefs.getString(colorSchemeKey, "")) + Log.i(TAG, "verifyAppearanceColorSchemeChange: Verified that the color scheme is: $expectedColorScheme") } class Transition { fun closeAppearanceMenu(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "closeAppearanceMenu: Trying to click device back button") mDevice.pressBack() + Log.i(TAG, "closeAppearanceMenu: Clicked device back button") BrowserRobot().interact() return BrowserRobot.Transition() @@ -103,8 +175,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_font_sans_serif), ) - + Log.i(TAG, "toggleSansSerif: Trying to click sans serif button") sansSerifButton().click() + Log.i(TAG, "toggleSansSerif: Clicked sans serif button") ReaderViewRobot().interact() return Transition() @@ -115,8 +188,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_font_serif), ) - + Log.i(TAG, "toggleSerif: Trying to click serif button") serifButton().click() + Log.i(TAG, "toggleSerif: Clicked serif button") ReaderViewRobot().interact() return Transition() @@ -127,8 +201,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_font_size_decrease), ) - + Log.i(TAG, "toggleFontSizeDecrease: Trying to click the decrease font button") fontSizeDecrease().click() + Log.i(TAG, "toggleFontSizeDecrease: Clicked the decrease font button") ReaderViewRobot().interact() return Transition() @@ -139,8 +214,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_font_size_increase), ) - + Log.i(TAG, "toggleFontSizeIncrease: Trying to click the increase font button") fontSizeIncrease().click() + Log.i(TAG, "toggleFontSizeIncrease: Clicked the increase font button") ReaderViewRobot().interact() return Transition() @@ -151,8 +227,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_color_light), ) - + Log.i(TAG, "toggleColorSchemeChangeLight: Trying to click the light color button") toggleLightColorSchemeButton().click() + Log.i(TAG, "toggleColorSchemeChangeLight: Clicked the light color button") ReaderViewRobot().interact() return Transition() @@ -163,8 +240,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_color_dark), ) - + Log.i(TAG, "toggleColorSchemeChangeDark: Trying to click the dark color button") toggleDarkColorSchemeButton().click() + Log.i(TAG, "toggleColorSchemeChangeDark: Clicked the dark color button") ReaderViewRobot().interact() return Transition() @@ -175,8 +253,9 @@ class ReaderViewRobot { onView( withId(R.id.mozac_feature_readerview_color_sepia), ) - + Log.i(TAG, "toggleColorSchemeChangeSepia: Trying to click the sepia color button") toggleSepiaColorSchemeButton().click() + Log.i(TAG, "toggleColorSchemeChangeSepia: Clicked the sepia color button") ReaderViewRobot().interact() return Transition() @@ -184,73 +263,5 @@ class ReaderViewRobot { } } -fun readerViewRobot(interact: ReaderViewRobot.() -> Unit): ReaderViewRobot.Transition { - ReaderViewRobot().interact() - return ReaderViewRobot.Transition() -} - -private fun assertAppearanceFontGroup(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_font_group), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceFontSansSerif(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_font_sans_serif), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceFontSerif(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_font_serif), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceFontDecrease(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_font_size_decrease), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceFontIncrease(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_font_size_increase), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceColorDark(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_color_dark), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceColorLight(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_color_light), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceColorSepia(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_color_sepia), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - -private fun assertAppearanceColorGroup(visible: Boolean) = - onView( - withId(R.id.mozac_feature_readerview_color_scheme_group), - ).check( - matches(withEffectiveVisibility(visibleOrGone(visible))), - ) - private fun visibleOrGone(visibility: Boolean) = if (visibility) ViewMatchers.Visibility.VISIBLE else ViewMatchers.Visibility.GONE diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt index d77962cfb..8034e4674 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/RecentlyClosedTabsRobot.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui.robots import android.net.Uri +import android.util.Log import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers.Visibility @@ -17,6 +18,7 @@ import androidx.test.uiautomator.UiSelector import org.hamcrest.Matchers import org.hamcrest.Matchers.allOf import org.mozilla.fenix.R +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.HomeActivityComposeTestRule import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists import org.mozilla.fenix.helpers.MatcherHelper.itemWithResIdContainingText @@ -32,28 +34,36 @@ import org.mozilla.fenix.helpers.click class RecentlyClosedTabsRobot { - fun waitForListToExist() = + fun waitForListToExist() { + Log.i(TAG, "waitForListToExist: Waiting for $waitingTime ms for recently closed tabs list to exist") mDevice.findObject(UiSelector().resourceId("$packageName:id/recently_closed_list")) .waitForExists(waitingTime) + Log.i(TAG, "waitForListToExist: Waited for $waitingTime ms for recently closed tabs list to exist") + } fun verifyRecentlyClosedTabsMenuView() { + Log.i(TAG, "verifyRecentlyClosedTabsMenuView: Trying to verify that the recently closed tabs menu view is visible") onView( allOf( withText("Recently closed tabs"), withParent(withId(R.id.navigationToolbar)), ), ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyRecentlyClosedTabsMenuView: Verified that the recently closed tabs menu view is visible") } fun verifyEmptyRecentlyClosedTabsList() { + Log.i(TAG, "verifyEmptyRecentlyClosedTabsList: Waiting for device to be idle") mDevice.waitForIdle() - + Log.i(TAG, "verifyEmptyRecentlyClosedTabsList: Waited for device to be idle") + Log.i(TAG, "verifyEmptyRecentlyClosedTabsList: Trying to verify that the empty recently closed tabs list is visible") onView( allOf( withId(R.id.recently_closed_empty_view), withText(R.string.recently_closed_empty_message), ), ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyEmptyRecentlyClosedTabsList: Verified that the empty recently closed tabs list is visible") } fun verifyRecentlyClosedTabsPageTitle(title: String) = @@ -62,6 +72,7 @@ class RecentlyClosedTabsRobot { ) fun verifyRecentlyClosedTabsUrl(expectedUrl: Uri) { + Log.i(TAG, "verifyRecentlyClosedTabsUrl: Trying to verify that the recently closed tab with url: $expectedUrl is visible") onView( allOf( withId(R.id.url), @@ -70,45 +81,64 @@ class RecentlyClosedTabsRobot { ), ), ).check(matches(withText(Matchers.containsString(expectedUrl.toString())))) + Log.i(TAG, "verifyRecentlyClosedTabsUrl: Verified that the recently closed tab with url: $expectedUrl is visible") } - fun clickDeleteRecentlyClosedTabs() = recentlyClosedTabDeleteButton().click() + fun clickDeleteRecentlyClosedTabs() { + Log.i(TAG, "clickDeleteRecentlyClosedTabs: Trying to click the recently closed tab item delete button") + recentlyClosedTabDeleteButton().click() + Log.i(TAG, "clickDeleteRecentlyClosedTabs: Clicked the recently closed tab item delete button") + } class Transition { fun clickRecentlyClosedItem(title: String, interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { recentlyClosedTabsPageTitle(title).also { + Log.i(TAG, "clickRecentlyClosedItem: Waiting for $waitingTimeShort ms for recently closed tab with title: $title to exist") it.waitForExists(waitingTimeShort) + Log.i(TAG, "clickRecentlyClosedItem: Waited for $waitingTimeShort ms for recently closed tab with title: $title to exist") + Log.i(TAG, "clickRecentlyClosedItem: Trying to click the recently closed tab with title: $title") it.click() + Log.i(TAG, "clickRecentlyClosedItem: Clicked the recently closed tab with title: $title") } + Log.i(TAG, "clickRecentlyClosedItem: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "clickRecentlyClosedItem: Waited for device to be idle") BrowserRobot().interact() return BrowserRobot.Transition() } fun clickOpenInNewTab(testRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { - openInNewTabOption.click() + Log.i(TAG, "clickOpenInNewTab: Trying to click the multi-select \"Open in a new tab\" context menu button") + openInNewTabOption().click() + Log.i(TAG, "clickOpenInNewTab: Clicked the multi-select \"Open in a new tab\" context menu button") ComposeTabDrawerRobot(testRule).interact() return ComposeTabDrawerRobot.Transition(testRule) } fun clickOpenInPrivateTab(testRule: HomeActivityComposeTestRule, interact: ComposeTabDrawerRobot.() -> Unit): ComposeTabDrawerRobot.Transition { - openInPrivateTabOption.click() + Log.i(TAG, "clickOpenInPrivateTab: Trying to click the multi-select \"Open in a private tab\" context menu button") + openInPrivateTabOption().click() + Log.i(TAG, "clickOpenInPrivateTab: Clicked the multi-select \"Open in a private tab\" context menu button") ComposeTabDrawerRobot(testRule).interact() return ComposeTabDrawerRobot.Transition(testRule) } fun clickShare(interact: ShareOverlayRobot.() -> Unit): ShareOverlayRobot.Transition { - multipleSelectionShareButton.click() + Log.i(TAG, "clickShare: Trying to click the share recently closed tabs button") + multipleSelectionShareButton().click() + Log.i(TAG, "clickShare: Clicked the share recently closed tabs button") ShareOverlayRobot().interact() return ShareOverlayRobot.Transition() } fun goBackToHistoryMenu(interact: HistoryRobot.() -> Unit): HistoryRobot.Transition { + Log.i(TAG, "goBackToHistoryMenu: Trying to click navigate up toolbar button") onView(withContentDescription("Navigate up")).click() + Log.i(TAG, "goBackToHistoryMenu: Clicked navigate up toolbar button") HistoryRobot().interact() return HistoryRobot.Transition() @@ -132,8 +162,8 @@ private fun recentlyClosedTabDeleteButton() = ), ) -private val openInNewTabOption = onView(withText("Open in new tab")) +private fun openInNewTabOption() = onView(withText("Open in new tab")) -private val openInPrivateTabOption = onView(withText("Open in private tab")) +private fun openInPrivateTabOption() = onView(withText("Open in private tab")) -private val multipleSelectionShareButton = onView(withId(R.id.share_history_multi_select)) +private fun multipleSelectionShareButton() = onView(withId(R.id.share_history_multi_select)) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt index 84da4f5d1..8e6a98de4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsRobot.kt @@ -11,15 +11,12 @@ import android.net.Uri import android.util.Log import androidx.recyclerview.widget.RecyclerView import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.ViewInteraction import androidx.test.espresso.action.ViewActions import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.contrib.RecyclerViewActions import androidx.test.espresso.intent.Intents.intended -import androidx.test.espresso.intent.matcher.IntentMatchers import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction import androidx.test.espresso.intent.matcher.IntentMatchers.hasData -import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.Visibility import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.hasSibling @@ -28,6 +25,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isNotChecked import androidx.test.espresso.matcher.ViewMatchers.withClassName +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText @@ -69,20 +67,64 @@ import org.mozilla.fenix.ui.robots.SettingsRobot.Companion.DEFAULT_APPS_SETTINGS class SettingsRobot { // BASICS SECTION - fun verifyGeneralHeading() = assertGeneralHeading() + fun verifyGeneralHeading() { + scrollToElementByText("General") + Log.i(TAG, "verifyGeneralHeading: Trying to verify that the \"General\" heading is visible") + onView(withText("General")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyGeneralHeading: Verified that the \"General\" heading is visible") + } + + fun verifySearchButton() { + Log.i(TAG, "verifySearchButton: Waiting for $waitingTime ms until finding the \"Search\" button") + mDevice.wait(Until.findObject(By.text("Search")), waitingTime) + Log.i(TAG, "verifySearchButton: Waited for $waitingTime ms until the \"Search\" button was found") + Log.i(TAG, "verifySearchButton: Trying to verify that the \"Search\" button is visible") + onView(withText(R.string.preferences_search)) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySearchButton: Verified that the \"Search\" button is visible") + } + fun verifyCustomizeButton() { + Log.i(TAG, "verifyCustomizeButton: Trying to verify that the \"Customize\" button is visible") + onView(withText("Customize")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyCustomizeButton: Verified that the \"Customize\" button is visible") + } - fun verifySearchButton() = assertSearchButton() - fun verifyCustomizeButton() = assertCustomizeButton() - fun verifyThemeSelected() = assertThemeSelected() - fun verifyAccessibilityButton() = assertAccessibilityButton() - fun verifySetAsDefaultBrowserButton() = assertSetAsDefaultBrowserButton() + fun verifyAccessibilityButton() { + Log.i(TAG, "verifyAccessibilityButton: Trying to verify that the \"Accessibility\" button is visible") + onView(withText("Accessibility")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAccessibilityButton: Verified that the \"Accessibility\" button is visible") + } + fun verifySetAsDefaultBrowserButton() { + scrollToElementByText("Set as default browser") + Log.i(TAG, "verifySetAsDefaultBrowserButton: Trying to verify that the \"Set as default browser\" button is visible") + onView(withText("Set as default browser")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySetAsDefaultBrowserButton: Verified that the \"Set as default browser\" button is visible") + } fun verifyTabsButton() = assertUIObjectExists(itemContainingText(getStringResource(R.string.preferences_tabs))) - fun verifyHomepageButton() = assertHomepageButton() - fun verifyAutofillButton() = assertAutofillButton() - fun verifyLanguageButton() = assertLanguageButton() + fun verifyHomepageButton() { + Log.i(TAG, "verifyHomepageButton: Trying to verify that the \"Homepage\" button is visible") + onView(withText(R.string.preferences_home_2)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyHomepageButton: Verified that the \"Homepage\" button is visible") + } + fun verifyAutofillButton() { + Log.i(TAG, "verifyAutofillButton: Trying to verify that the \"Autofill\" button is visible") + onView(withText(R.string.preferences_autofill)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAutofillButton: Verified that the \"Autofill\" button is visible") + } + fun verifyLanguageButton() { + scrollToElementByText(getStringResource(R.string.preferences_language)) + Log.i(TAG, "verifyLanguageButton: Trying to verify that the \"Language\" button is visible") + onView(withText(R.string.preferences_language)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyLanguageButton: Verified that the \"Language\" button is visible") + } fun verifyDefaultBrowserToggle(isEnabled: Boolean) { scrollToElementByText(getStringResource(R.string.preferences_set_as_default_browser)) + Log.i(TAG, "verifyDefaultBrowserToggle: Trying to verify that the \"Set as default browser\" toggle is enabled: $isEnabled") onView(withText(R.string.preferences_set_as_default_browser)) .check( matches( @@ -98,18 +140,36 @@ class SettingsRobot { ), ), ) + Log.i(TAG, "verifyDefaultBrowserToggle: Verified that the \"Set as default browser\" toggle is enabled: $isEnabled") } fun clickDefaultBrowserSwitch() = toggleDefaultBrowserSwitch() - fun verifyAndroidDefaultAppsMenuAppears() = assertAndroidDefaultAppsMenuAppears() + fun verifyAndroidDefaultAppsMenuAppears() { + Log.i(TAG, "verifyAndroidDefaultAppsMenuAppears: Trying to verify that default browser apps dialog appears") + intended(hasAction(DEFAULT_APPS_SETTINGS_ACTION)) + Log.i(TAG, "verifyAndroidDefaultAppsMenuAppears: Verified that the default browser apps dialog appears") + } // PRIVACY SECTION - fun verifyPrivacyHeading() = assertPrivacyHeading() - - fun verifyHTTPSOnlyModeButton() = assertHTTPSOnlyModeButton() + fun verifyPrivacyHeading() { + scrollToElementByText("Privacy and security") + Log.i(TAG, "verifyPrivacyHeading: Trying to verify that the \"Privacy and security\" heading is visible") + onView(withText("Privacy and security")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyPrivacyHeading: Verified that the \"Privacy and security\" heading is visible") + } + fun verifyHTTPSOnlyModeButton() { + scrollToElementByText(getStringResource(R.string.preferences_https_only_title)) + Log.i(TAG, "verifyHTTPSOnlyModeButton: Trying to verify that the \"HTTPS-Only Mode\" button is visible") + onView( + withText(R.string.preferences_https_only_title), + ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyHTTPSOnlyModeButton: Verified that the \"HTTPS-Only Mode\" button is visible") + } fun verifyCookieBannerBlockerButton(enabled: Boolean) { scrollToElementByText(getStringResource(R.string.preferences_cookie_banner_reduction_private_mode)) + Log.i(TAG, "verifyCookieBannerBlockerButton: Trying to verify that the \"Cookie Banner Blocker in private browsing\" toggle is enabled: $enabled") onView(withText(R.string.preferences_cookie_banner_reduction_private_mode)) .check( matches( @@ -125,31 +185,167 @@ class SettingsRobot { ), ), ) - Log.i(TAG, "verifyCookieBannerBlockerButton: Verified if cookie banner blocker toggle is enabled: $enabled") + Log.i(TAG, "verifyCookieBannerBlockerButton: Verified that the \"Cookie Banner Blocker in private browsing\" toggle is enabled: $enabled") } - fun verifyEnhancedTrackingProtectionButton() = assertEnhancedTrackingProtectionButton() - fun verifyLoginsAndPasswordsButton() = assertLoginsAndPasswordsButton() - fun verifyPrivateBrowsingButton() = assertPrivateBrowsingButton() - fun verifySitePermissionsButton() = assertSitePermissionsButton() - fun verifyDeleteBrowsingDataButton() = assertDeleteBrowsingDataButton() - fun verifyDeleteBrowsingDataOnQuitButton() = assertDeleteBrowsingDataOnQuitButton() - fun verifyNotificationsButton() = assertNotificationsButton() - fun verifyDataCollectionButton() = assertDataCollectionButton() - fun verifyOpenLinksInAppsButton() = assertOpenLinksInAppsButton() - fun verifySettingsView() = assertSettingsView() - fun verifySettingsToolbar() = assertSettingsToolbar() + fun verifyEnhancedTrackingProtectionButton() { + Log.i(TAG, "verifyEnhancedTrackingProtectionButton: Waiting for $waitingTime ms until finding the \"Privacy and Security\" heading") + mDevice.wait(Until.findObject(By.text("Privacy and Security")), waitingTime) + Log.i(TAG, "verifyEnhancedTrackingProtectionButton: Waited for $waitingTime ms until the \"Privacy and Security\" heading was found") + Log.i(TAG, "verifyEnhancedTrackingProtectionButton: Trying to verify that the \"Enhanced Tracking Protection\" button is visible") + onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Enhanced Tracking Protection")), + ), + ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyEnhancedTrackingProtectionButton: Verified that the \"Enhanced Tracking Protection\" button is visible") + } + fun verifyLoginsAndPasswordsButton() { + scrollToElementByText("Logins and passwords") + Log.i(TAG, "verifyLoginsAndPasswordsButton: Trying to verify that the \"Logins and passwords\" button is visible") + onView(withText(R.string.preferences_passwords_logins_and_passwords)) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyLoginsAndPasswordsButton: Verified that the \"Logins and passwords\" button is visible") + } + fun verifyPrivateBrowsingButton() { + scrollToElementByText("Private browsing") + Log.i(TAG, "verifyPrivateBrowsingButton: Waiting for $waitingTime ms until finding the \"Private browsing\" button") + mDevice.wait(Until.findObject(By.text("Private browsing")), waitingTime) + Log.i(TAG, "verifyPrivateBrowsingButton: Waited for $waitingTime ms until the \"Private browsing\" button was found") + Log.i(TAG, "verifyPrivateBrowsingButton: Trying to verify that the \"Private browsing\" button is visible") + onView(withText("Private browsing")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyPrivateBrowsingButton: Verified that the \"Private browsing\" button is visible") + } + fun verifySitePermissionsButton() { + scrollToElementByText("Site permissions") + Log.i(TAG, "verifySitePermissionsButton: Trying to verify that the \"Site permissions\" button is visible") + onView(withText("Site permissions")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySitePermissionsButton: Verified that the \"Site permissions\" button is visible") + } + fun verifyDeleteBrowsingDataButton() { + scrollToElementByText("Delete browsing data") + Log.i(TAG, "verifyDeleteBrowsingDataButton: Trying to verify that the \"Delete browsing data\" button is visible") + onView(withText("Delete browsing data")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyDeleteBrowsingDataButton: Verified that the \"Delete browsing data\" button is visible") + } + fun verifyDeleteBrowsingDataOnQuitButton() { + scrollToElementByText("Delete browsing data on quit") + Log.i(TAG, "verifyDeleteBrowsingDataOnQuitButton: Trying to verify that the \"Delete browsing data on quit\" button is visible") + onView(withText("Delete browsing data on quit")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyDeleteBrowsingDataOnQuitButton: Verified that the \"Delete browsing data on quit\" button is visible") + } + fun verifyNotificationsButton() { + scrollToElementByText("Notifications") + Log.i(TAG, "verifyNotificationsButton: Trying to verify that the \"Notifications\" button is visible") + onView(withText("Notifications")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyNotificationsButton: Verified that the \"Notifications\" button is visible") + } + fun verifyDataCollectionButton() { + scrollToElementByText("Data collection") + Log.i(TAG, "verifyDataCollectionButton: Trying to verify that the \"Data collection\" button is visible") + onView(withText("Data collection")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyDataCollectionButton: Verified that the \"Data collection\" button is visible") + } + fun verifyOpenLinksInAppsButton() { + scrollToElementByText("Open links in apps") + Log.i(TAG, "verifyOpenLinksInAppsButton: Trying to verify that the \"Open links in apps\" button is visible") + openLinksInAppsButton() + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyOpenLinksInAppsButton: Verified that the \"Open links in apps\" button is visible") + } + fun verifySettingsView() { + scrollToElementByText("General") + Log.i(TAG, "verifySettingsView: Trying to verify that the \"General\" heading is visible") + onView(withText("General")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsView: Verified that the \"General\" heading is visible") + scrollToElementByText("Privacy and security") + Log.i(TAG, "verifySettingsView: Trying to verify that the \"Privacy and security\" heading is visible") + onView(withText("Privacy and security")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsView: Verified that the \"Privacy and security\" heading is visible") + Log.i(TAG, "verifySettingsView: Trying to perform scroll to the \"Add-ons\" button") + onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Add-ons")), + ), + ) + Log.i(TAG, "verifySettingsView: Performed scroll to the \"Add-ons\" button") + Log.i(TAG, "verifySettingsView: Trying to verify that the \"Add-ons\" button is completely displayed") + onView(withText("Add-ons")) + .check(matches(isCompletelyDisplayed())) + Log.i(TAG, "verifySettingsView: Verified that the \"Add-ons\" button is completely displayed") + Log.i(TAG, "verifySettingsView: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the settings list") + settingsList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "verifySettingsView: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the settings list") + Log.i(TAG, "verifySettingsView: Trying to verify that the \"About\" heading is visible") + onView(withText("About")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsView: Verified that the \"About\" heading is visible") + } + fun verifySettingsToolbar() { + Log.i(TAG, "verifySettingsToolbar: Trying to verify that the navigate up button is visible") + onView( + allOf( + withId(R.id.navigationToolbar), + hasDescendant(withContentDescription(R.string.action_bar_up_description)), + ), + ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsToolbar: Verified that the navigate up button is visible") + Log.i(TAG, "verifySettingsToolbar: Trying to verify that the \"Settings\" toolbar title is visible") + onView( + allOf( + withId(R.id.navigationToolbar), + hasDescendant(withText(R.string.settings)), + ), + ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsToolbar: Verified that the \"Settings\" toolbar title is visible") + } // ADVANCED SECTION - fun verifyAdvancedHeading() = assertAdvancedHeading() - fun verifyAddons() = assertAddonsButton() + fun verifyAdvancedHeading() { + Log.i(TAG, "verifyAdvancedHeading: Trying to perform scroll to the \"Add-ons\" button") + onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Add-ons")), + ), + ) + Log.i(TAG, "verifyAdvancedHeading: Performed scroll to the \"Add-ons\" button") + Log.i(TAG, "verifyAdvancedHeading: Trying to verify that the \"Add-ons\" button is completely displayed") + onView(withText("Add-ons")) + .check(matches(isCompletelyDisplayed())) + Log.i(TAG, "verifyAdvancedHeading: Verified that the \"Add-ons\" button is completely displayed") + } + fun verifyAddons() { + Log.i(TAG, "verifyAddons: Trying to perform scroll to the \"Add-ons\" button") + onView(withId(R.id.recycler_view)).perform( + RecyclerViewActions.scrollTo( + hasDescendant(withText("Add-ons")), + ), + ) + Log.i(TAG, "verifyAddons: Performed scroll to the \"Add-ons\" button") + Log.i(TAG, "verifyAddons: Trying to verify that the \"Add-ons\" button is completely displayed") + addonsManagerButton() + .check(matches(isCompletelyDisplayed())) + Log.i(TAG, "verifyAddons: Verified that the \"Add-ons\" button is completely displayed") + } - fun verifyExternalDownloadManagerButton() = + fun verifyExternalDownloadManagerButton() { + Log.i(TAG, "verifyExternalDownloadManagerButton: Trying to verify that the \"External download manager\" button is visible") onView( withText(R.string.preferences_external_download_manager), ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyExternalDownloadManagerButton: Verified that the \"External download manager\" button is visible") + } - fun verifyExternalDownloadManagerToggle(enabled: Boolean) = + fun verifyExternalDownloadManagerToggle(enabled: Boolean) { + Log.i(TAG, "verifyExternalDownloadManagerToggle: Trying to verify that the \"External download manager\" toggle is enabled: $enabled") onView(withText(R.string.preferences_external_download_manager)) .check( matches( @@ -165,8 +361,11 @@ class SettingsRobot { ), ), ) + Log.i(TAG, "verifyExternalDownloadManagerToggle: Verified that the \"External download manager\" toggle is enabled: $enabled") + } - fun verifyLeakCanaryToggle(enabled: Boolean) = + fun verifyLeakCanaryToggle(enabled: Boolean) { + Log.i(TAG, "verifyLeakCanaryToggle: Trying to verify that the \"LeakCanary\" toggle is enabled: $enabled") onView(withText(R.string.preference_leakcanary)) .check( matches( @@ -182,8 +381,11 @@ class SettingsRobot { ), ), ) + Log.i(TAG, "verifyLeakCanaryToggle: Verified that the \"LeakCanary\" toggle is enabled: $enabled") + } - fun verifyRemoteDebuggingToggle(enabled: Boolean) = + fun verifyRemoteDebuggingToggle(enabled: Boolean) { + Log.i(TAG, "verifyRemoteDebuggingToggle: Trying to verify that the \"Remote debugging via USB\" toggle is enabled: $enabled") onView(withText(R.string.preferences_remote_debugging)) .check( matches( @@ -199,53 +401,106 @@ class SettingsRobot { ), ), ) + Log.i(TAG, "verifyRemoteDebuggingToggle: Verified that the \"Remote debugging via USB\" toggle is enabled: $enabled") + } // DEVELOPER TOOLS SECTION - fun verifyRemoteDebuggingButton() = assertRemoteDebuggingButton() - fun verifyLeakCanaryButton() = assertLeakCanaryButton() + fun verifyRemoteDebuggingButton() { + scrollToElementByText("Remote debugging via USB") + Log.i(TAG, "verifyRemoteDebuggingButton: Trying to verify that the \"Remote debugging via USB\" button is visible") + onView(withText("Remote debugging via USB")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyRemoteDebuggingButton: Verified that the \"Remote debugging via USB\" button is visible") + } + fun verifyLeakCanaryButton() { + scrollToElementByText("LeakCanary") + Log.i(TAG, "verifyLeakCanaryButton: Trying to verify that the \"LeakCanary\" button is visible") + onView(withText("LeakCanary")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyLeakCanaryButton: Verified that the \"LeakCanary\" button is visible") + } // ABOUT SECTION - fun verifyAboutHeading() = assertAboutHeading() + fun verifyAboutHeading() { + Log.i(TAG, "verifyAboutHeading: Trying to perform ${LISTS_MAXSWIPES}x a scroll action to the end of the settings list") + settingsList().scrollToEnd(LISTS_MAXSWIPES) + Log.i(TAG, "verifyAboutHeading: Performed ${LISTS_MAXSWIPES}x a scroll action to the end of the settings list") + Log.i(TAG, "verifyAboutHeading: Trying to verify that the \"About\" heading is visible") + onView(withText("About")) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAboutHeading: Verified that the \"About\" heading is visible") + } fun verifyRateOnGooglePlay() = assertUIObjectExists(rateOnGooglePlayHeading()) fun verifyAboutFirefoxPreview() = assertUIObjectExists(aboutFirefoxHeading()) - fun verifyGooglePlayRedirect() = assertGooglePlayRedirect() + fun verifyGooglePlayRedirect() { + if (isPackageInstalled(GOOGLE_PLAY_SERVICES)) { + Log.i(TAG, "verifyGooglePlayRedirect: $GOOGLE_PLAY_SERVICES is installed") + try { + Log.i(TAG, "verifyGooglePlayRedirect: Trying to verify intent to: $GOOGLE_PLAY_SERVICES") + intended( + allOf( + hasAction(Intent.ACTION_VIEW), + hasData(Uri.parse(SupportUtils.RATE_APP_URL)), + ), + ) + Log.i(TAG, "verifyGooglePlayRedirect: Verified intent to: $GOOGLE_PLAY_SERVICES") + } catch (e: AssertionFailedError) { + Log.i(TAG, "verifyGooglePlayRedirect: AssertionFailedError caught, executing fallback methods") + BrowserRobot().verifyRateOnGooglePlayURL() + } + } else { + BrowserRobot().verifyRateOnGooglePlayURL() + } + } fun verifySettingsOptionSummary(setting: String, summary: String) { scrollToElementByText(setting) + Log.i(TAG, "verifySettingsOptionSummary: Trying to verify that setting: $setting with summary:$summary is visible") onView( allOf( withText(setting), hasSibling(withText(summary)), ), ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifySettingsOptionSummary: Verified that setting: $setting with summary:$summary is visible") } class Transition { fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBack: Trying to click the navigate up button") goBackButton().click() + Log.i(TAG, "goBack: Clicked the navigate up button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun goBackToOnboardingScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { + Log.i(TAG, "goBackToOnboardingScreen: Trying to click device back button") mDevice.pressBack() + Log.i(TAG, "goBackToOnboardingScreen: Clicked device back button") + Log.i(TAG, "goBackToOnboardingScreen: Waiting for device to be idle for $waitingTimeShort ms") mDevice.waitForIdle(waitingTimeShort) + Log.i(TAG, "goBackToOnboardingScreen: Device was idle for $waitingTimeShort ms") HomeScreenRobot().interact() return HomeScreenRobot.Transition() } fun goBackToBrowser(interact: BrowserRobot.() -> Unit): BrowserRobot.Transition { + Log.i(TAG, "goBackToBrowser: Trying to click the navigate up button") goBackButton().click() + Log.i(TAG, "goBackToBrowser: Clicked the navigate up button") BrowserRobot().interact() return BrowserRobot.Transition() } fun openAboutFirefoxPreview(interact: SettingsSubMenuAboutRobot.() -> Unit): SettingsSubMenuAboutRobot.Transition { + Log.i(TAG, "openAboutFirefoxPreview: Trying to click the \"About Firefox\" button") aboutFirefoxHeading().click() + Log.i(TAG, "openAboutFirefoxPreview: Clicked the \"About Firefox\" button") SettingsSubMenuAboutRobot().interact() return SettingsSubMenuAboutRobot.Transition() } @@ -253,8 +508,12 @@ class SettingsRobot { fun openSearchSubMenu(interact: SettingsSubMenuSearchRobot.() -> Unit): SettingsSubMenuSearchRobot.Transition { itemWithText(getStringResource(R.string.preferences_search)) .also { + Log.i(TAG, "openSearchSubMenu: Waiting for $waitingTimeShort ms for the \"Search\" button to exist") it.waitForExists(waitingTimeShort) + Log.i(TAG, "openSearchSubMenu: Waited for $waitingTimeShort ms for the \"Search\" button to exist") + Log.i(TAG, "openSearchSubMenu: Trying to click the \"Search\" button") it.click() + Log.i(TAG, "openSearchSubMenu: Clicked the \"Search\" button") } SettingsSubMenuSearchRobot().interact() @@ -262,8 +521,9 @@ class SettingsRobot { } fun openCustomizeSubMenu(interact: SettingsSubMenuCustomizeRobot.() -> Unit): SettingsSubMenuCustomizeRobot.Transition { - fun customizeButton() = onView(withText("Customize")) - customizeButton().click() + Log.i(TAG, "openCustomizeSubMenu: Trying to click the \"Customize\" button") + onView(withText("Customize")).click() + Log.i(TAG, "openCustomizeSubMenu: Clicked the \"Customize\" button") SettingsSubMenuCustomizeRobot().interact() return SettingsSubMenuCustomizeRobot.Transition() @@ -272,8 +532,12 @@ class SettingsRobot { fun openTabsSubMenu(interact: SettingsSubMenuTabsRobot.() -> Unit): SettingsSubMenuTabsRobot.Transition { itemWithText(getStringResource(R.string.preferences_tabs)) .also { + Log.i(TAG, "openTabsSubMenu: Waiting for $waitingTime ms for the \"Tabs\" button to exist") it.waitForExists(waitingTime) + Log.i(TAG, "openTabsSubMenu: Waited for $waitingTime ms for the \"Tabs\" button to exist") + Log.i(TAG, "openTabsSubMenu: Trying to click the \"Tabs\" button and wait for $waitingTimeShort ms for a new window") it.clickAndWaitForNewWindow(waitingTimeShort) + Log.i(TAG, "openTabsSubMenu: Clicked the \"Tabs\" button and wait for $waitingTimeShort ms for a new window") } SettingsSubMenuTabsRobot().interact() @@ -281,8 +545,12 @@ class SettingsRobot { } fun openHomepageSubMenu(interact: SettingsSubMenuHomepageRobot.() -> Unit): SettingsSubMenuHomepageRobot.Transition { + Log.i(TAG, "openHomepageSubMenu: Waiting for $waitingTime ms for the \"Homepage\" button to exist") mDevice.findObject(UiSelector().textContains("Homepage")).waitForExists(waitingTime) + Log.i(TAG, "openHomepageSubMenu: Waited for $waitingTime ms for the \"Homepage\" button to exist") + Log.i(TAG, "openHomepageSubMenu: Trying to click the \"Homepage\" button") onView(withText(R.string.preferences_home_2)).click() + Log.i(TAG, "openHomepageSubMenu: Clicked the \"Homepage\" button") SettingsSubMenuHomepageRobot().interact() return SettingsSubMenuHomepageRobot.Transition() @@ -291,10 +559,12 @@ class SettingsRobot { fun openAutofillSubMenu(interact: SettingsSubMenuAutofillRobot.() -> Unit): SettingsSubMenuAutofillRobot.Transition { mDevice.findObject(UiSelector().textContains(getStringResource(R.string.preferences_autofill))) .also { - Log.i(TAG, "openAutofillSubMenu: Looking for \"Autofill\" settings button") + Log.i(TAG, "openAutofillSubMenu: Waiting for $waitingTime ms for the \"Autofill\" button to exist") it.waitForExists(waitingTime) + Log.i(TAG, "openAutofillSubMenu: Waited for $waitingTime ms for the \"Autofill\" button to exist") + Log.i(TAG, "openAutofillSubMenu: Trying to click the \"Autofill\" button") it.click() - Log.i(TAG, "openAutofillSubMenu: Clicked \"Autofill\" settings button") + Log.i(TAG, "openAutofillSubMenu: Clicked the \"Autofill\" button") } SettingsSubMenuAutofillRobot().interact() @@ -303,11 +573,12 @@ class SettingsRobot { fun openAccessibilitySubMenu(interact: SettingsSubMenuAccessibilityRobot.() -> Unit): SettingsSubMenuAccessibilityRobot.Transition { scrollToElementByText("Accessibility") - - fun accessibilityButton() = onView(withText("Accessibility")) - accessibilityButton() - .check(matches(isDisplayed())) - .click() + Log.i(TAG, "openAccessibilitySubMenu: Trying to verify that the \"Accessibility\" button is displayed") + onView(withText("Accessibility")).check(matches(isDisplayed())) + Log.i(TAG, "openAccessibilitySubMenu: Verified that the \"Accessibility\" button is displayed") + Log.i(TAG, "openAccessibilitySubMenu: Trying to click the \"Accessibility\" button") + onView(withText("Accessibility")).click() + Log.i(TAG, "openAccessibilitySubMenu: Clicked the \"Accessibility\" button") SettingsSubMenuAccessibilityRobot().interact() return SettingsSubMenuAccessibilityRobot.Transition() @@ -317,6 +588,7 @@ class SettingsRobot { localizedText: String = getStringResource(R.string.preferences_language), interact: SettingsSubMenuLanguageRobot.() -> Unit, ): SettingsSubMenuLanguageRobot.Transition { + Log.i(TAG, "openLanguageSubMenu: Trying to click the $localizedText button") onView(withId(R.id.recycler_view)) .perform( RecyclerViewActions.actionOnItem( @@ -326,6 +598,7 @@ class SettingsRobot { ViewActions.click(), ), ) + Log.i(TAG, "openLanguageSubMenu: Clicked the $localizedText button") SettingsSubMenuLanguageRobot().interact() return SettingsSubMenuLanguageRobot.Transition() @@ -333,8 +606,9 @@ class SettingsRobot { fun openSetDefaultBrowserSubMenu(interact: SettingsSubMenuSetDefaultBrowserRobot.() -> Unit): SettingsSubMenuSetDefaultBrowserRobot.Transition { scrollToElementByText("Set as default browser") - fun setDefaultBrowserButton() = onView(withText("Set as default browser")) - setDefaultBrowserButton().click() + Log.i(TAG, "openSetDefaultBrowserSubMenu: Trying to click the \"Set as default browser\" button") + onView(withText("Set as default browser")).click() + Log.i(TAG, "openSetDefaultBrowserSubMenu: Clicked the \"Set as default browser\" button") SettingsSubMenuSetDefaultBrowserRobot().interact() return SettingsSubMenuSetDefaultBrowserRobot.Transition() @@ -342,9 +616,9 @@ class SettingsRobot { fun openEnhancedTrackingProtectionSubMenu(interact: SettingsSubMenuEnhancedTrackingProtectionRobot.() -> Unit): SettingsSubMenuEnhancedTrackingProtectionRobot.Transition { scrollToElementByText("Enhanced Tracking Protection") - fun enhancedTrackingProtectionButton() = - onView(withText("Enhanced Tracking Protection")) - enhancedTrackingProtectionButton().click() + Log.i(TAG, "openEnhancedTrackingProtectionSubMenu: Trying to click the \"Enhanced Tracking Protection\" button") + onView(withText("Enhanced Tracking Protection")).click() + Log.i(TAG, "openEnhancedTrackingProtectionSubMenu: Clicked the \"Enhanced Tracking Protection\" button") SettingsSubMenuEnhancedTrackingProtectionRobot().interact() return SettingsSubMenuEnhancedTrackingProtectionRobot.Transition() @@ -352,16 +626,18 @@ class SettingsRobot { fun openLoginsAndPasswordSubMenu(interact: SettingsSubMenuLoginsAndPasswordRobot.() -> Unit): SettingsSubMenuLoginsAndPasswordRobot.Transition { scrollToElementByText("Logins and passwords") - fun loginsAndPasswordsButton() = onView(withText("Logins and passwords")) - loginsAndPasswordsButton().click() + Log.i(TAG, "openLoginsAndPasswordSubMenu: Trying to click the \"Logins and passwords\" button") + onView(withText("Logins and passwords")).click() + Log.i(TAG, "openLoginsAndPasswordSubMenu: Clicked the \"Logins and passwords\" button") SettingsSubMenuLoginsAndPasswordRobot().interact() return SettingsSubMenuLoginsAndPasswordRobot.Transition() } fun openTurnOnSyncMenu(interact: SettingsTurnOnSyncRobot.() -> Unit): SettingsTurnOnSyncRobot.Transition { - fun turnOnSyncButton() = onView(withText("Sync and save your data")) - turnOnSyncButton().click() + Log.i(TAG, "openTurnOnSyncMenu: Trying to click the \"Sync and save your data\" button") + onView(withText("Sync and save your data")).click() + Log.i(TAG, "openTurnOnSyncMenu: Clicked the \"Sync and save your data\" button") SettingsTurnOnSyncRobot().interact() return SettingsTurnOnSyncRobot.Transition() @@ -369,8 +645,9 @@ class SettingsRobot { fun openPrivateBrowsingSubMenu(interact: SettingsSubMenuPrivateBrowsingRobot.() -> Unit): SettingsSubMenuPrivateBrowsingRobot.Transition { scrollToElementByText("Private browsing") - fun privateBrowsingButton() = mDevice.findObject(textContains("Private browsing")) - privateBrowsingButton().click() + Log.i(TAG, "openPrivateBrowsingSubMenu: Trying to click the \"Private browsing\" button") + mDevice.findObject(textContains("Private browsing")).click() + Log.i(TAG, "openPrivateBrowsingSubMenu: Clicked the \"Private browsing\" button") SettingsSubMenuPrivateBrowsingRobot().interact() return SettingsSubMenuPrivateBrowsingRobot.Transition() @@ -378,8 +655,9 @@ class SettingsRobot { fun openSettingsSubMenuSitePermissions(interact: SettingsSubMenuSitePermissionsRobot.() -> Unit): SettingsSubMenuSitePermissionsRobot.Transition { scrollToElementByText("Site permissions") - fun sitePermissionButton() = mDevice.findObject(textContains("Site permissions")) - sitePermissionButton().click() + Log.i(TAG, "openSettingsSubMenuSitePermissions: Trying to click the \"Site permissions\" button") + mDevice.findObject(textContains("Site permissions")).click() + Log.i(TAG, "openSettingsSubMenuSitePermissions: Clicked the \"Site permissions\" button") SettingsSubMenuSitePermissionsRobot().interact() return SettingsSubMenuSitePermissionsRobot.Transition() @@ -387,8 +665,9 @@ class SettingsRobot { fun openSettingsSubMenuDeleteBrowsingData(interact: SettingsSubMenuDeleteBrowsingDataRobot.() -> Unit): SettingsSubMenuDeleteBrowsingDataRobot.Transition { scrollToElementByText("Delete browsing data") - fun deleteBrowsingDataButton() = mDevice.findObject(textContains("Delete browsing data")) - deleteBrowsingDataButton().click() + Log.i(TAG, "openSettingsSubMenuDeleteBrowsingData: Trying to click the \"Delete browsing data\" button") + mDevice.findObject(textContains("Delete browsing data")).click() + Log.i(TAG, "openSettingsSubMenuDeleteBrowsingData: Clicked the \"Delete browsing data\" button") SettingsSubMenuDeleteBrowsingDataRobot().interact() return SettingsSubMenuDeleteBrowsingDataRobot.Transition() @@ -396,8 +675,9 @@ class SettingsRobot { fun openSettingsSubMenuDeleteBrowsingDataOnQuit(interact: SettingsSubMenuDeleteBrowsingDataOnQuitRobot.() -> Unit): SettingsSubMenuDeleteBrowsingDataOnQuitRobot.Transition { scrollToElementByText("Delete browsing data on quit") - fun deleteBrowsingDataOnQuitButton() = mDevice.findObject(textContains("Delete browsing data on quit")) - deleteBrowsingDataOnQuitButton().click() + Log.i(TAG, "openSettingsSubMenuDeleteBrowsingDataOnQuit: Trying to click the \"Delete browsing data on quit\" button") + mDevice.findObject(textContains("Delete browsing data on quit")).click() + Log.i(TAG, "openSettingsSubMenuDeleteBrowsingDataOnQuit: Clicked the \"Delete browsing data on quit\" button") SettingsSubMenuDeleteBrowsingDataOnQuitRobot().interact() return SettingsSubMenuDeleteBrowsingDataOnQuitRobot.Transition() @@ -405,8 +685,9 @@ class SettingsRobot { fun openSettingsSubMenuNotifications(interact: SystemSettingsRobot.() -> Unit): SystemSettingsRobot.Transition { scrollToElementByText("Notifications") - fun notificationsButton() = mDevice.findObject(textContains("Notifications")) - notificationsButton().click() + Log.i(TAG, "openSettingsSubMenuNotifications: Trying to click the \"Notifications\" button") + mDevice.findObject(textContains("Notifications")).click() + Log.i(TAG, "openSettingsSubMenuNotifications: Clicked the \"Notifications\" button") SystemSettingsRobot().interact() return SystemSettingsRobot.Transition() @@ -414,22 +695,27 @@ class SettingsRobot { fun openSettingsSubMenuDataCollection(interact: SettingsSubMenuDataCollectionRobot.() -> Unit): SettingsSubMenuDataCollectionRobot.Transition { scrollToElementByText("Data collection") - fun dataCollectionButton() = mDevice.findObject(textContains("Data collection")) - dataCollectionButton().click() + Log.i(TAG, "openSettingsSubMenuDataCollection: Trying to click the \"Data collection\" button") + mDevice.findObject(textContains("Data collection")).click() + Log.i(TAG, "openSettingsSubMenuDataCollection: Clicked the \"Data collection\" button") SettingsSubMenuDataCollectionRobot().interact() return SettingsSubMenuDataCollectionRobot.Transition() } fun openAddonsManagerMenu(interact: SettingsSubMenuAddonsManagerRobot.() -> Unit): SettingsSubMenuAddonsManagerRobot.Transition { + Log.i(TAG, "openAddonsManagerMenu: Trying to click the \"Add-ons\" button") addonsManagerButton().click() + Log.i(TAG, "openAddonsManagerMenu: Clicked the \"Add-ons\" button") SettingsSubMenuAddonsManagerRobot().interact() return SettingsSubMenuAddonsManagerRobot.Transition() } fun openOpenLinksInAppsMenu(interact: SettingsSubMenuOpenLinksInAppsRobot.() -> Unit): SettingsSubMenuOpenLinksInAppsRobot.Transition { + Log.i(TAG, "openOpenLinksInAppsMenu: Trying to click the \"Open links in apps\" button") openLinksInAppsButton().click() + Log.i(TAG, "openOpenLinksInAppsMenu: Clicked the \"Open links in apps\" button") SettingsSubMenuOpenLinksInAppsRobot().interact() return SettingsSubMenuOpenLinksInAppsRobot.Transition() @@ -437,7 +723,9 @@ class SettingsRobot { fun openHttpsOnlyModeMenu(interact: SettingsSubMenuHttpsOnlyModeRobot.() -> Unit): SettingsSubMenuHttpsOnlyModeRobot.Transition { scrollToElementByText("HTTPS-Only Mode") + Log.i(TAG, "openHttpsOnlyModeMenu: Trying to click the \"HTTPS-Only Mode\" button") onView(withText(getStringResource(R.string.preferences_https_only_title))).click() + Log.i(TAG, "openHttpsOnlyModeMenu: Clicked the \"HTTPS-Only Mode\" button") mDevice.waitNotNull( Until.findObjects(By.res("$packageName:id/https_only_switch")), waitingTime, @@ -466,189 +754,15 @@ fun settingsScreen(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition return SettingsRobot.Transition() } -private fun assertSettingsView() { - // verify that we are in the correct library view - assertGeneralHeading() - assertPrivacyHeading() - assertAdvancedHeading() - assertAboutHeading() -} - -// GENERAL SECTION - -private fun assertSettingsToolbar() = - onView( - CoreMatchers.allOf( - withId(R.id.navigationToolbar), - hasDescendant(ViewMatchers.withContentDescription(R.string.action_bar_up_description)), - hasDescendant(withText(R.string.settings)), - ), - ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertGeneralHeading() { - scrollToElementByText("General") - onView(withText("General")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertSearchButton() { - mDevice.wait(Until.findObject(By.text("Search")), waitingTime) - onView(withText(R.string.preferences_search)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertHomepageButton() = - onView(withText(R.string.preferences_home_2)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertAutofillButton() = - onView(withText(R.string.preferences_autofill)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertLanguageButton() { - scrollToElementByText(getStringResource(R.string.preferences_language)) - onView(withText(R.string.preferences_language)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertCustomizeButton() = onView(withText("Customize")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertThemeSelected() = onView(withText("Light")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertAccessibilityButton() = onView(withText("Accessibility")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - -private fun assertSetAsDefaultBrowserButton() { - scrollToElementByText("Set as default browser") - onView(withText("Set as default browser")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - private fun toggleDefaultBrowserSwitch() { scrollToElementByText("Privacy and security") + Log.i(TAG, "toggleDefaultBrowserSwitch: Trying to click the \"Set as default browser\" button") onView(withText("Set as default browser")).perform(ViewActions.click()) -} - -private fun assertAndroidDefaultAppsMenuAppears() { - intended(IntentMatchers.hasAction(DEFAULT_APPS_SETTINGS_ACTION)) -} - -// PRIVACY SECTION -private fun assertPrivacyHeading() { - scrollToElementByText("Privacy and security") - onView(withText("Privacy and security")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertHTTPSOnlyModeButton() { - scrollToElementByText(getStringResource(R.string.preferences_https_only_title)) - onView( - withText(R.string.preferences_https_only_title), - ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertEnhancedTrackingProtectionButton() { - mDevice.wait(Until.findObject(By.text("Privacy and Security")), waitingTime) - onView(withId(R.id.recycler_view)).perform( - RecyclerViewActions.scrollTo( - hasDescendant(withText("Enhanced Tracking Protection")), - ), - ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertLoginsAndPasswordsButton() { - scrollToElementByText("Logins and passwords") - onView(withText(R.string.preferences_passwords_logins_and_passwords)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertPrivateBrowsingButton() { - scrollToElementByText("Private browsing") - mDevice.wait(Until.findObject(By.text("Private browsing")), waitingTime) - onView(withText("Private browsing")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertSitePermissionsButton() { - scrollToElementByText("Site permissions") - onView(withText("Site permissions")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertDeleteBrowsingDataButton() { - scrollToElementByText("Delete browsing data") - onView(withText("Delete browsing data")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertDeleteBrowsingDataOnQuitButton() { - scrollToElementByText("Delete browsing data on quit") - onView(withText("Delete browsing data on quit")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertNotificationsButton() { - scrollToElementByText("Notifications") - onView(withText("Notifications")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertDataCollectionButton() { - scrollToElementByText("Data collection") - onView(withText("Data collection")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "toggleDefaultBrowserSwitch: Clicked the \"Set as default browser\" button") } private fun openLinksInAppsButton() = onView(withText(R.string.preferences_open_links_in_apps)) -private fun assertOpenLinksInAppsButton() { - scrollToElementByText("Open links in apps") - openLinksInAppsButton() - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - Log.i(TAG, "clickOpenLinksInAppsGoToSettingsCFRButton: Verified \"Open links in apps\" setting option") -} - -// ADVANCED SECTION -private fun assertAdvancedHeading() { - onView(withId(R.id.recycler_view)).perform( - RecyclerViewActions.scrollTo( - hasDescendant(withText("Add-ons")), - ), - ) - - onView(withText("Add-ons")) - .check(matches(isCompletelyDisplayed())) -} - -private fun assertAddonsButton() { - onView(withId(R.id.recycler_view)).perform( - RecyclerViewActions.scrollTo( - hasDescendant(withText("Add-ons")), - ), - ) - - addonsManagerButton() - .check(matches(isCompletelyDisplayed())) -} - -private fun assertRemoteDebuggingButton() { - scrollToElementByText("Remote debugging via USB") - onView(withText("Remote debugging via USB")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -private fun assertLeakCanaryButton() { - scrollToElementByText("LeakCanary") - onView(withText("LeakCanary")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - -// ABOUT SECTION -private fun assertAboutHeading(): ViewInteraction { - settingsList().scrollToEnd(LISTS_MAXSWIPES) - return onView(withText("About")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - private fun rateOnGooglePlayHeading(): UiObject { val rateOnGooglePlay = mDevice.findObject(UiSelector().text("Rate on Google Play")) settingsList().scrollToEnd(LISTS_MAXSWIPES) @@ -679,27 +793,10 @@ fun clickRateButtonGooglePlay() { rateOnGooglePlayHeading().click() } -private fun assertGooglePlayRedirect() { - if (isPackageInstalled(GOOGLE_PLAY_SERVICES)) { - try { - intended( - allOf( - hasAction(Intent.ACTION_VIEW), - hasData(Uri.parse(SupportUtils.RATE_APP_URL)), - ), - ) - } catch (e: AssertionFailedError) { - BrowserRobot().verifyRateOnGooglePlayURL() - } - } else { - BrowserRobot().verifyRateOnGooglePlayURL() - } -} - private fun addonsManagerButton() = onView(withText(R.string.preferences_addons)) private fun goBackButton() = - onView(CoreMatchers.allOf(ViewMatchers.withContentDescription("Navigate up"))) + onView(CoreMatchers.allOf(withContentDescription("Navigate up"))) private fun settingsList() = UiScrollable(UiSelector().resourceId("$packageName:id/recycler_view")) diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt index 26655f2da..77c5650ab 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAccessibilityRobot.kt @@ -6,6 +6,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import android.view.KeyEvent import android.view.KeyEvent.ACTION_DOWN import android.view.KeyEvent.KEYCODE_DPAD_LEFT @@ -28,7 +29,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.platform.app.InstrumentationRegistry import org.hamcrest.CoreMatchers.allOf import org.hamcrest.Matcher +import org.junit.Assert.assertTrue import org.mozilla.fenix.components.Components +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.TestHelper.mDevice import org.mozilla.fenix.helpers.assertIsEnabled import org.mozilla.fenix.helpers.isEnabled @@ -50,22 +53,68 @@ class SettingsSubMenuAccessibilityRobot { const val TEXT_SIZE = 16f } - fun verifyAutomaticFontSizingMenuItems() = assertAutomaticFontSizingMenuItems() - fun clickFontSizingSwitch() = toggleFontSizingSwitch() - fun verifyEnabledMenuItems() = assertEnabledMenuItems() + fun verifyEnabledMenuItems() { + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the \"Font Size\" title is visible") + onView(withText("Font Size")).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the \"Font Size\" title is visible") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the \"Font Size\" title is enabled") + onView(withText("Font Size")).check(matches(isEnabled(true))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the \"Font Size\" title is enabled") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the \"Make text on websites larger or smaller\" summary is visible") + onView(withText("Make text on websites larger or smaller")).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the \"Make text on websites larger or smaller\" summary is visible") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the \"Make text on websites larger or smaller\" summary is enabled") + onView(withText("Make text on websites larger or smaller")).check(matches(isEnabled(true))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the \"Make text on websites larger or smaller\" summary is enabled") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify the \"This is sample text. It is here to show how text will appear\" sample text") + onView(withId(org.mozilla.fenix.R.id.sampleText)) + .check(matches(withText("This is sample text. It is here to show how text will appear when you increase or decrease the size with this setting."))) + Log.i(TAG, "verifyEnabledMenuItems: Verified the \"This is sample text. It is here to show how text will appear\" sample text") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the seek bar value is set to 100%") + onView(withId(org.mozilla.fenix.R.id.seekbar_value)).check(matches(withText("100%"))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the seek bar value is set to 100%") + Log.i(TAG, "verifyEnabledMenuItems: Trying to verify that the seek bar is visible") + onView(withId(org.mozilla.fenix.R.id.seekbar)).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyEnabledMenuItems: Verified that the seek bar is visible") + } - fun verifyMenuItemsAreDisabled() = assertMenuItemsAreDisabled() + fun verifyMenuItemsAreDisabled() { + Log.i(TAG, "verifyMenuItemsAreDisabled: Trying to verify that the \"Font Size\" title is not enabled") + onView(withText("Font Size")).assertIsEnabled(false) + Log.i(TAG, "verifyMenuItemsAreDisabled: Verified that the \"Font Size\" title is not enabled") + Log.i(TAG, "verifyMenuItemsAreDisabled: Trying to verify that the \"Make text on websites larger or smaller\" summary is not enabled") + onView(withText("Make text on websites larger or smaller")).assertIsEnabled(false) + Log.i(TAG, "verifyMenuItemsAreDisabled: Verified that the \"Make text on websites larger or smaller\" summary is not enabled") + Log.i(TAG, "verifyMenuItemsAreDisabled: Trying to verify that the \"This is sample text. It is here to show how text will appear\" sample text is not enabled") + onView(withId(org.mozilla.fenix.R.id.sampleText)).assertIsEnabled(false) + Log.i(TAG, "verifyMenuItemsAreDisabled: Verified that the \"This is sample text. It is here to show how text will appear\" sample text is not enabled") + Log.i(TAG, "verifyMenuItemsAreDisabled: Trying to verify that the seek bar value is not enabled") + onView(withId(org.mozilla.fenix.R.id.seekbar_value)).assertIsEnabled(false) + Log.i(TAG, "verifyMenuItemsAreDisabled: Verified that the seek bar value is not enabled") + Log.i(TAG, "verifyMenuItemsAreDisabled: Trying to verify that the seek bar is not enabled") + onView(withId(org.mozilla.fenix.R.id.seekbar)).assertIsEnabled(false) + Log.i(TAG, "verifyMenuItemsAreDisabled: Verified that the seek bar is not enabled") + } fun changeTextSizeSlider(seekBarPercentage: Int) = adjustTextSizeSlider(seekBarPercentage) - fun verifyTextSizePercentage(textSize: Int) = assertTextSizePercentage(textSize) + fun verifyTextSizePercentage(textSize: Int) { + Log.i(TAG, "verifyTextSizePercentage: Trying to verify that the text size percentage is set to: $textSize") + onView(withId(org.mozilla.fenix.R.id.sampleText)) + .check(textSizePercentageEquals(textSize)) + Log.i(TAG, "verifyTextSizePercentage: Verified that the text size percentage is set to: $textSize") + } class Transition { fun goBack(interact: SettingsRobot.() -> Unit): SettingsRobot.Transition { + Log.i(TAG, "goBack: Waiting for device to be idle") mDevice.waitForIdle() + Log.i(TAG, "goBack: Waited for device to be idle") + Log.i(TAG, "goBack: Trying to click the navigate up toolbar button") goBackButton().perform(click()) + Log.i(TAG, "goBack: Clicked the navigate up toolbar button") SettingsRobot().interact() return SettingsRobot.Transition() @@ -73,69 +122,20 @@ class SettingsSubMenuAccessibilityRobot { } } -private fun assertAutomaticFontSizingMenuItems() { - onView(withText("Automatic font sizing")) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - val strFont = "Font size will match your Android settings. Disable to manage font size here." - onView(withText(strFont)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) -} - private fun toggleFontSizingSwitch() { + Log.i(TAG, "toggleFontSizingSwitch: Trying to click the \"Automatic font sizing\" toggle") // Toggle font size to off onView(withText("Automatic font sizing")) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) .perform(click()) -} - -private fun assertEnabledMenuItems() { - assertFontSize() - assertSliderBar() -} - -private fun assertFontSize() { - val view = onView(withText("Font Size")) - view.check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - .check(matches(isEnabled(true))) - val strFont = "Make text on websites larger or smaller" - onView(withText(strFont)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - .check(matches(isEnabled(true))) -} - -private fun assertSliderBar() { - onView(withId(org.mozilla.fenix.R.id.sampleText)) - .check(matches(withText("This is sample text. It is here to show how text will appear when you increase or decrease the size with this setting."))) - - onView(withId(org.mozilla.fenix.R.id.seekbar_value)) - .check(matches(withText("100%"))) - - onView(withId(org.mozilla.fenix.R.id.seekbar)) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "toggleFontSizingSwitch: Clicked the \"Automatic font sizing\" toggle") } private fun adjustTextSizeSlider(seekBarPercentage: Int) { + Log.i(TAG, "adjustTextSizeSlider: Trying to set the seek bar value to: $seekBarPercentage") onView(withId(org.mozilla.fenix.R.id.seekbar)) .perform(SeekBarChangeProgressViewAction(seekBarPercentage)) -} - -private fun assertTextSizePercentage(textSize: Int) { - onView(withId(org.mozilla.fenix.R.id.sampleText)) - .check(textSizePercentageEquals(textSize)) -} - -private fun assertMenuItemsAreDisabled() { - onView(withText("Font Size")).assertIsEnabled(false) - - val strFont = "Make text on websites larger or smaller" - - onView(withText(strFont)).assertIsEnabled(false) - - onView(withId(org.mozilla.fenix.R.id.sampleText)).assertIsEnabled(false) - - onView(withId(org.mozilla.fenix.R.id.seekbar_value)).assertIsEnabled(false) - - onView(withId(org.mozilla.fenix.R.id.seekbar)).assertIsEnabled(false) + Log.i(TAG, "adjustTextSizeSlider: Seek bar value was set to: $seekBarPercentage") } private fun goBackButton() = @@ -189,9 +189,11 @@ fun calculateStepSizeFromPercentage(textSizePercentage: Int): Int { return ((textSizePercentage - MIN_VALUE) / STEP_SIZE) } -fun checkTextSizeOnWebsite(textSizePercentage: Int, components: Components): Boolean { +fun checkTextSizeOnWebsite(textSizePercentage: Int, components: Components) { + Log.i(TAG, "checkTextSizeOnWebsite: Trying to verify that text size on website is: $textSizePercentage") // Checks the Gecko engine settings for the font size val textSize = calculateStepSizeFromPercentage(textSizePercentage) val newTextScale = ((textSize * STEP_SIZE) + MIN_VALUE).toFloat() / DECIMAL_CONVERSION - return components.core.engine.settings.fontSizeFactor == newTextScale + assertTrue("$TAG: text size on website was not set to: $textSizePercentage", components.core.engine.settings.fontSizeFactor == newTextScale) + Log.i(TAG, "checkTextSizeOnWebsite: Verified that text size on website is: $textSizePercentage") } diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.kt index 799f3a991..43aceae29 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.ui.robots +import android.util.Log import android.view.View import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches @@ -17,6 +18,7 @@ import org.hamcrest.CoreMatchers.allOf import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.helpers.AppAndSystemHelper.registerAndCleanupIdlingResources +import org.mozilla.fenix.helpers.Constants.TAG import org.mozilla.fenix.helpers.ViewVisibilityIdlingResource import org.mozilla.fenix.helpers.click @@ -28,8 +30,9 @@ class SettingsSubMenuAddonsManagerAddonDetailedMenuRobot { class Transition { fun goBack(interact: SettingsSubMenuAddonsManagerRobot.() -> Unit): SettingsSubMenuAddonsManagerRobot.Transition { - fun goBackButton() = onView(allOf(withContentDescription("Navigate up"))) - goBackButton().click() + Log.i(TAG, "goBack: Trying to click the navigate up button") + onView(allOf(withContentDescription("Navigate up"))).click() + Log.i(TAG, "goBack: Clicked the navigate up button") SettingsSubMenuAddonsManagerRobot().interact() return SettingsSubMenuAddonsManagerRobot.Transition() @@ -42,8 +45,12 @@ class SettingsSubMenuAddonsManagerAddonDetailedMenuRobot { View.VISIBLE, ), ) { + Log.i(TAG, "removeAddon: Trying to verify that the remove add-on button is visible") removeAddonButton().check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE))) + Log.i(TAG, "removeAddon: Verified that the remove add-on button is visible") + Log.i(TAG, "removeAddon: Trying to click the remove add-on button") removeAddonButton().click() + Log.i(TAG, "removeAddon: Clicked the remove add-on button") } SettingsSubMenuAddonsManagerRobot().interact() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt index 3c73bc82a..95ea5f4c4 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAddonsManagerRobot.kt @@ -55,12 +55,15 @@ class SettingsSubMenuAddonsManagerRobot { fun verifyAddonsListIsDisplayed(shouldBeDisplayed: Boolean) = assertUIObjectExists(addonsList(), exists = shouldBeDisplayed) - fun verifyAddonDownloadOverlay() = + fun verifyAddonDownloadOverlay() { + Log.i(TAG, "verifyAddonDownloadOverlay: Trying to verify that the \"Downloading and verifying add-on\" prompt is displayed") onView(withText(R.string.mozac_add_on_install_progress_caption)).check(matches(isDisplayed())) + Log.i(TAG, "verifyAddonDownloadOverlay: Verified that the \"Downloading and verifying add-on\" prompt is displayed") + } fun verifyAddonPermissionPrompt(addonName: String) { mDevice.waitNotNull(Until.findObject(By.text("Add $addonName?")), waitingTime) - + Log.i(TAG, "verifyAddonPermissionPrompt: Trying to verify that the add-ons permission prompt items are displayed") onView( allOf( withText("Add $addonName?"), @@ -71,11 +74,14 @@ class SettingsSubMenuAddonsManagerRobot { ) .inRoot(isDialog()) .check(matches(isDisplayed())) + Log.i(TAG, "verifyAddonPermissionPrompt: Verified that the add-ons permission prompt items are displayed") } fun clickInstallAddon(addonName: String) { - Log.i(TAG, "clickInstallAddon: Looking for $addonName install button") + Log.i(TAG, "clickInstallAddon: Waiting for $waitingTime ms for add-ons list to exist") addonsList().waitForExists(waitingTime) + Log.i(TAG, "clickInstallAddon: Waited for $waitingTime ms for add-ons list to exist") + Log.i(TAG, "clickInstallAddon: Trying to scroll into view the install $addonName button") addonsList().scrollIntoView( mDevice.findObject( UiSelector() @@ -83,6 +89,8 @@ class SettingsSubMenuAddonsManagerRobot { .childSelector(UiSelector().text(addonName)), ), ) + Log.i(TAG, "clickInstallAddon: Scrolled into view the install $addonName button") + Log.i(TAG, "clickInstallAddon: Trying to ensure the full visibility of the the install $addonName button") addonsList().ensureFullyVisible( mDevice.findObject( UiSelector() @@ -90,22 +98,24 @@ class SettingsSubMenuAddonsManagerRobot { .childSelector(UiSelector().text(addonName)), ), ) - Log.i(TAG, "clickInstallAddon: Found $addonName install button") + Log.i(TAG, "clickInstallAddon: Ensured the full visibility of the the install $addonName button") + Log.i(TAG, "clickInstallAddon: Trying to click the install $addonName button") installButtonForAddon(addonName).click() - Log.i(TAG, "clickInstallAddon: Clicked Install $addonName button") + Log.i(TAG, "clickInstallAddon: Clicked the install $addonName button") } fun verifyAddonInstallCompleted(addonName: String, activityTestRule: HomeActivityIntentTestRule) { for (i in 1..RETRY_COUNT) { + Log.i(TAG, "verifyAddonInstallCompleted: Started try #$i") try { - assertUIObjectExists(itemWithText("Okay, Got it"), waitingTime = waitingTimeLong) + assertUIObjectExists(itemWithText("OK"), waitingTime = waitingTimeLong) break } catch (e: AssertionError) { + Log.i(TAG, "verifyAddonInstallCompleted: AssertionError caught, executing fallback methods") if (i == RETRY_COUNT) { throw e } else { - Log.i(TAG, "verifyAddonInstallCompleted: $addonName failed to install on try #$i") restartApp(activityTestRule) homeScreen { }.openThreeDotMenu { @@ -121,40 +131,98 @@ class SettingsSubMenuAddonsManagerRobot { } fun verifyAddonInstallCompletedPrompt(addonName: String) { + Log.i(TAG, "verifyAddonInstallCompletedPrompt: Trying to verify that completed add-on install prompt items are visible") onView( allOf( - withText("Okay, Got it"), + withText("OK"), withParent(instanceOf(RelativeLayout::class.java)), hasSibling(withText("$addonName has been added to $appName")), - hasSibling(withText("Open it in the menu")), + hasSibling(withText("Access $addonName from the $appName menu.")), hasSibling(withText("Allow in private browsing")), ), ) .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAddonInstallCompletedPrompt: Verified that completed add-on install prompt items are visible") } fun closeAddonInstallCompletePrompt() { - onView(withText("Okay, Got it")).click() + Log.i(TAG, "closeAddonInstallCompletePrompt: Trying to click the \"OK\" button from the completed add-on install prompt") + onView(withText("OK")).click() + Log.i(TAG, "closeAddonInstallCompletePrompt: Clicked the \"OK\" button from the completed add-on install prompt") } fun verifyAddonIsInstalled(addonName: String) { scrollToElementByText(addonName) - assertAddonIsInstalled(addonName) + Log.i(TAG, "verifyAddonIsInstalled: Trying to verify that the $addonName add-on was installed") + onView( + allOf( + withId(R.id.add_button), + isDescendantOfA(withId(R.id.add_on_item)), + hasSibling(hasDescendant(withText(addonName))), + ), + ).check(matches(withEffectiveVisibility(Visibility.INVISIBLE))) + Log.i(TAG, "verifyAddonIsInstalled: Verified that the $addonName add-on was installed") } fun verifyEnabledTitleDisplayed() { + Log.i(TAG, "verifyEnabledTitleDisplayed: Trying to verify that the \"Enabled\" heading is displayed") onView(withText("Enabled")) .check(matches(isCompletelyDisplayed())) + Log.i(TAG, "verifyEnabledTitleDisplayed: Verified that the \"Enabled\" heading is displayed") } fun cancelInstallAddon() = cancelInstall() fun acceptPermissionToInstallAddon() = allowPermissionToInstall() - fun verifyAddonsItems() = assertAddonsItems() - fun verifyAddonCanBeInstalled(addonName: String) = assertAddonCanBeInstalled(addonName) + fun verifyAddonsItems() { + Log.i(TAG, "verifyAddonsItems: Trying to verify that the \"Recommended\" heading is visible") + onView(allOf(withId(R.id.title), withText("Recommended"))) + .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAddonsItems: Verified that the \"Recommended\" heading is visible") + Log.i(TAG, "verifyAddonsItems: Trying to verify that all uBlock Origin items are completely displayed") + onView( + allOf( + isAssignableFrom(RelativeLayout::class.java), + withId(R.id.add_on_item), + hasDescendant(allOf(withId(R.id.add_on_icon), isCompletelyDisplayed())), + hasDescendant( + allOf( + withId(R.id.details_container), + hasDescendant(withText("uBlock Origin")), + hasDescendant(withText("Finally, an efficient wide-spectrum content blocker. Easy on CPU and memory.")), + hasDescendant(withId(R.id.rating)), + hasDescendant(withId(R.id.review_count)), + ), + ), + hasDescendant(withId(R.id.add_button)), + ), + ).check(matches(isCompletelyDisplayed())) + Log.i(TAG, "verifyAddonsItems: Verified that all uBlock Origin items are completely displayed") + } + fun verifyAddonCanBeInstalled(addonName: String) { + scrollToElementByText(addonName) + mDevice.waitNotNull(Until.findObject(By.text(addonName)), waitingTime) + Log.i(TAG, "verifyAddonCanBeInstalled: Trying to verify that the install $addonName button is visible") + onView( + allOf( + withId(R.id.add_button), + hasSibling( + hasDescendant( + allOf( + withId(R.id.add_on_name), + withText(addonName), + ), + ), + ), + ), + ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "verifyAddonCanBeInstalled: Verified that the install $addonName button is visible") + } fun selectAllowInPrivateBrowsing() { assertUIObjectExists(itemWithText("Allow in private browsing"), waitingTime = waitingTimeLong) + Log.i(TAG, "selectAllowInPrivateBrowsing: Trying to click the \"Allow in private browsing\" check box") onView(withId(R.id.allow_in_private_browsing)).click() + Log.i(TAG, "selectAllowInPrivateBrowsing: Clicked the \"Allow in private browsing\" check box") } fun installAddon(addonName: String, activityTestRule: HomeActivityIntentTestRule) { @@ -170,8 +238,9 @@ class SettingsSubMenuAddonsManagerRobot { class Transition { fun goBack(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition { - fun goBackButton() = onView(allOf(withContentDescription("Navigate up"))) - goBackButton().click() + Log.i(TAG, "goBack: Trying to click navigate up toolbar button") + onView(allOf(withContentDescription("Navigate up"))).click() + Log.i(TAG, "goBack: Clicked the navigate up toolbar button") HomeScreenRobot().interact() return HomeScreenRobot.Transition() @@ -182,19 +251,12 @@ class SettingsSubMenuAddonsManagerRobot { interact: SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.() -> Unit, ): SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.Transition { scrollToElementByText(addonName) - - onView( - allOf( - withId(R.id.add_on_item), - hasDescendant( - allOf( - withId(R.id.add_on_name), - withText(addonName), - ), - ), - ), - ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - .perform(click()) + Log.i(TAG, "openDetailedMenuForAddon: Trying to verify that the $addonName add-on is visible") + addonItem(addonName).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "openDetailedMenuForAddon: Verified that the $addonName add-on is visible") + Log.i(TAG, "openDetailedMenuForAddon: Trying to click the $addonName add-on") + addonItem(addonName).perform(click()) + Log.i(TAG, "openDetailedMenuForAddon: Clicked the $addonName add-on") SettingsSubMenuAddonsManagerAddonDetailedMenuRobot().interact() return SettingsSubMenuAddonsManagerAddonDetailedMenuRobot.Transition() @@ -204,87 +266,29 @@ class SettingsSubMenuAddonsManagerRobot { private fun installButtonForAddon(addonName: String) = onView( allOf( - withContentDescription(R.string.mozac_feature_addons_install_addon_content_description), + withContentDescription("Install $addonName"), isDescendantOfA(withId(R.id.add_on_item)), hasSibling(hasDescendant(withText(addonName))), ), ) - private fun assertAddonIsInstalled(addonName: String) { - onView( - allOf( - withId(R.id.add_button), - isDescendantOfA(withId(R.id.add_on_item)), - hasSibling(hasDescendant(withText(addonName))), - ), - ).check(matches(withEffectiveVisibility(Visibility.INVISIBLE))) - } - private fun cancelInstall() { - onView(allOf(withId(R.id.deny_button), withText("Cancel"))) - .check(matches(isCompletelyDisplayed())) - .perform(click()) + Log.i(TAG, "cancelInstall: Trying to verify that the \"Cancel\" button is completely displayed") + onView(allOf(withId(R.id.deny_button), withText("Cancel"))).check(matches(isCompletelyDisplayed())) + Log.i(TAG, "cancelInstall: Verified that the \"Cancel\" button is completely displayed") + Log.i(TAG, "cancelInstall: Trying to click the \"Cancel\" button") + onView(allOf(withId(R.id.deny_button), withText("Cancel"))).perform(click()) + Log.i(TAG, "cancelInstall: Clicked the \"Cancel\" button") } private fun allowPermissionToInstall() { mDevice.waitNotNull(Until.findObject(By.text("Add")), waitingTime) - - onView(allOf(withId(R.id.allow_button), withText("Add"))) - .check(matches(isCompletelyDisplayed())) - .perform(click()) - } - - private fun assertAddonsItems() { - assertRecommendedTitleDisplayed() - assertAddons() - } - - private fun assertRecommendedTitleDisplayed() { - onView(allOf(withId(R.id.title), withText("Recommended"))) - .check(matches(withEffectiveVisibility(Visibility.VISIBLE))) - } - - private fun assertAddons() { - assertAddonUblock() - } - - private fun assertAddonUblock() { - onView( - allOf( - isAssignableFrom(RelativeLayout::class.java), - withId(R.id.add_on_item), - hasDescendant(allOf(withId(R.id.add_on_icon), isCompletelyDisplayed())), - hasDescendant( - allOf( - withId(R.id.details_container), - hasDescendant(withText("uBlock Origin")), - hasDescendant(withText("Finally, an efficient wide-spectrum content blocker. Easy on CPU and memory.")), - hasDescendant(withId(R.id.rating)), - hasDescendant(withId(R.id.review_count)), - ), - ), - hasDescendant(withId(R.id.add_button)), - ), - ).check(matches(isCompletelyDisplayed())) - } - - private fun assertAddonCanBeInstalled(addonName: String) { - scrollToElementByText(addonName) - mDevice.waitNotNull(Until.findObject(By.text(addonName)), waitingTime) - - onView( - allOf( - withId(R.id.add_button), - hasSibling( - hasDescendant( - allOf( - withId(R.id.add_on_name), - withText(addonName), - ), - ), - ), - ), - ).check(matches(withEffectiveVisibility(Visibility.VISIBLE))) + Log.i(TAG, "allowPermissionToInstall: Trying to verify that the \"Add\" button is completely displayed") + onView(allOf(withId(R.id.allow_button), withText("Add"))).check(matches(isCompletelyDisplayed())) + Log.i(TAG, "allowPermissionToInstall: Verified that the \"Add\" button is completely displayed") + Log.i(TAG, "allowPermissionToInstall: Trying to click the \"Add\" button") + onView(allOf(withId(R.id.allow_button), withText("Add"))).perform(click()) + Log.i(TAG, "allowPermissionToInstall: Clicked the \"Add\" button") } } @@ -293,5 +297,18 @@ fun addonsMenu(interact: SettingsSubMenuAddonsManagerRobot.() -> Unit): Settings return SettingsSubMenuAddonsManagerRobot.Transition() } +private fun addonItem(addonName: String) = + onView( + allOf( + withId(R.id.add_on_item), + hasDescendant( + allOf( + withId(R.id.add_on_name), + withText(addonName), + ), + ), + ), + ) + private fun addonsList() = UiScrollable(UiSelector().resourceId("$packageName:id/add_ons_list")).setAsVerticalList() diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAutofillRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAutofillRobot.kt index 67b82b283..349451b69 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAutofillRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuAutofillRobot.kt @@ -9,7 +9,9 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.RootMatchers import androidx.test.espresso.matcher.ViewMatchers.isChecked +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isNotChecked +import androidx.test.espresso.matcher.ViewMatchers.withChild import androidx.test.espresso.matcher.ViewMatchers.withClassName import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText @@ -38,8 +40,16 @@ class SettingsSubMenuAutofillRobot { Log.i(TAG, "verifyAutofillToolbarTitle: Verified \"Autofill\" toolbar title exists") } fun verifyManageAddressesToolbarTitle() { - assertUIObjectExists(manageAddressesToolbarTitle) - Log.i(TAG, "verifyManageAddressesToolbarTitle: Verified \"Manage addresses\" toolbar title exists") + Log.i(TAG, "verifyManageAddressesToolbarTitle: Trying to verify the \"Manage addresses\" toolbar title is displayed") + onView( + allOf( + withId(R.id.navigationToolbar), + withChild( + withText(R.string.preferences_addresses_manage_addresses), + ), + ), + ).check(matches(isDisplayed())) + Log.i(TAG, "verifyManageAddressesToolbarTitle: Verified the \"Manage addresses\" toolbar title is displayed") } fun verifyAddressAutofillSection(isAddressAutofillEnabled: Boolean, userHasSavedAddress: Boolean) { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuHomepageRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuHomepageRobot.kt index b6c9f1c7c..6585616f2 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuHomepageRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/SettingsSubMenuHomepageRobot.kt @@ -23,8 +23,6 @@ import org.hamcrest.CoreMatchers.allOf import org.hamcrest.Matchers import org.mozilla.fenix.R import org.mozilla.fenix.helpers.Constants -import org.mozilla.fenix.helpers.MatcherHelper.assertUIObjectExists -import org.mozilla.fenix.helpers.MatcherHelper.itemContainingText import org.mozilla.fenix.helpers.TestAssetHelper.waitingTimeShort import org.mozilla.fenix.helpers.TestHelper import org.mozilla.fenix.helpers.TestHelper.mDevice @@ -101,11 +99,6 @@ class SettingsSubMenuHomepageRobot { fun selectWallpaper(wallpaperName: String) = mDevice.findObject(UiSelector().description(wallpaperName)).click() - fun verifySnackBarText(expectedText: String) = - assertUIObjectExists( - itemContainingText(expectedText), - ) - fun verifySponsoredShortcutsCheckBox(checked: Boolean) = assertSponsoredShortcutsCheckBox(checked) class Transition { diff --git a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt index c7b833dc8..419d2799a 100644 --- a/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt +++ b/app/src/androidTest/java/org/mozilla/fenix/ui/robots/TabDrawerRobot.kt @@ -206,9 +206,6 @@ class TabDrawerRobot { } } - fun verifySnackBarText(expectedText: String) = - assertUIObjectExists(itemContainingText(expectedText)) - fun snackBarButtonClick(expectedText: String) { val snackBarButton = mDevice.findObject( diff --git a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt index 805ff6625..7a71ecdd5 100644 --- a/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt +++ b/app/src/main/java/org/mozilla/fenix/FeatureFlags.kt @@ -67,7 +67,7 @@ object FeatureFlags { * Allows users to enable translations. * Preference to fully enable translations is pref_key_enable_translations. */ - val translations = Config.channel.isDebug + val translations = Config.channel.isNightlyOrDebug /** * Allows users to enable Firefox Suggest. diff --git a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt index 6ba76f2c5..9a4084415 100644 --- a/app/src/main/java/org/mozilla/fenix/FenixApplication.kt +++ b/app/src/main/java/org/mozilla/fenix/FenixApplication.kt @@ -381,6 +381,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider { components.fxSuggest.ingestionScheduler.stopPeriodicIngestion() } } + components.core.fileUploadsDirCleaner.cleanUploadsDirectory() } // Account manager initialization needs to happen on the main thread. GlobalScope.launch(Dispatchers.Main) { diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 5d3cb4fc5..2ec05881f 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -14,7 +14,6 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.os.StrictMode -import android.os.SystemClock import android.text.TextUtils import android.text.format.DateUtils import android.util.AttributeSet @@ -31,7 +30,6 @@ import androidx.annotation.RequiresApi import androidx.annotation.VisibleForTesting import androidx.appcompat.app.ActionBar import androidx.appcompat.widget.Toolbar -import androidx.core.app.NotificationManagerCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController @@ -63,7 +61,6 @@ import mozilla.components.feature.media.ext.findActiveMediaTab import mozilla.components.feature.privatemode.notification.PrivateNotificationFeature import mozilla.components.feature.search.BrowserStoreSearchAdapter import mozilla.components.service.fxa.sync.SyncReason -import mozilla.components.support.base.ext.areNotificationsEnabledSafe import mozilla.components.support.base.feature.ActivityResultHandler import mozilla.components.support.base.feature.UserInteractionHandler import mozilla.components.support.base.log.logger.Logger @@ -128,7 +125,6 @@ import org.mozilla.fenix.messaging.FenixNimbusMessagingController import org.mozilla.fenix.messaging.MessageNotificationWorker import org.mozilla.fenix.nimbus.FxNimbus import org.mozilla.fenix.onboarding.ReEngagementNotificationWorker -import org.mozilla.fenix.onboarding.ensureMarketingChannelExists import org.mozilla.fenix.perf.MarkersActivityLifecycleCallbacks import org.mozilla.fenix.perf.MarkersFragmentLifecycleCallbacks import org.mozilla.fenix.perf.Performance @@ -155,12 +151,6 @@ import java.util.Locale */ @SuppressWarnings("TooManyFunctions", "LargeClass", "LongMethod") open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { - // DO NOT MOVE ANYTHING ABOVE THIS, GETTING INIT TIME IS CRITICAL - // we need to store startup timestamp for warm startup. we cant directly store - // inside AppStartupTelemetry since that class lives inside components and - // components requires context to access. - protected val homeActivityInitTimeStampNanoSeconds = SystemClock.elapsedRealtimeNanos() - private lateinit var binding: ActivityHomeBinding lateinit var themeManager: ThemeManager lateinit var browsingModeManager: BrowsingModeManager @@ -243,8 +233,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { // There is disk read violations on some devices such as samsung and pixel for android 9/10 components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) { - // Theme setup should always be called before super.onCreate - setupThemeAndBrowsingMode(getModeFromIntentOrLastKnown(intent)) + // Browsing mode & theme setup should always be called before super.onCreate. + setupBrowsingMode(getModeFromIntentOrLastKnown(intent)) + setupTheme() + super.onCreate(savedInstanceState) } @@ -269,34 +261,32 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { binding = ActivityHomeBinding.inflate(layoutInflater) - if (Config.channel.isNightlyOrDebug) { - lifecycleScope.launch { - val debugSettingsRepository = DefaultDebugSettingsRepository( - context = this@HomeActivity, - writeScope = this, - ) + lifecycleScope.launch { + val debugSettingsRepository = DefaultDebugSettingsRepository( + context = this@HomeActivity, + writeScope = this, + ) - debugSettingsRepository.debugDrawerEnabled - .distinctUntilChanged() - .collect { enabled -> - with(binding.debugOverlay) { - if (enabled) { - visibility = View.VISIBLE - - setContent { - FenixOverlay( - browserStore = components.core.store, - inactiveTabsEnabled = settings().inactiveTabsAreEnabled, - ) - } - } else { - setContent {} - - visibility = View.GONE + debugSettingsRepository.debugDrawerEnabled + .distinctUntilChanged() + .collect { enabled -> + with(binding.debugOverlay) { + if (enabled) { + visibility = View.VISIBLE + + setContent { + FenixOverlay( + browserStore = components.core.store, + inactiveTabsEnabled = settings().inactiveTabsAreEnabled, + ) } + } else { + setContent {} + + visibility = View.GONE } } - } + } } setContentView(binding.root) @@ -345,8 +335,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { if (settings().showHomeOnboardingDialog && components.fenixOnboarding.userHasBeenOnboarded()) { navHost.navController.navigate(NavGraphDirections.actionGlobalHomeOnboardingDialog()) } - - showNotificationPermissionPromptIfRequired() } Performance.processIntentIfPerformanceTest(intent, this) @@ -443,30 +431,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { StartupTimeline.onActivityCreateEndHome(this) // DO NOT MOVE ANYTHING BELOW HERE. } - /** - * On Android 13 or above, prompt the user for notification permission at the start. - * Show the pre permission dialog to the user once if the notification are not enabled. - */ - private fun showNotificationPermissionPromptIfRequired() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && - !NotificationManagerCompat.from(applicationContext).areNotificationsEnabledSafe() && - settings().numberOfAppLaunches <= 1 - ) { - // Recording the exposure event here to capture all users who met all criteria to receive - // the pre permission notification prompt - FxNimbus.features.prePermissionNotificationPrompt.recordExposure() - - if (settings().notificationPrePermissionPromptEnabled) { - if (!settings().isNotificationPrePermissionShown) { - navHost.navController.navigate(NavGraphDirections.actionGlobalHomeNotificationPermissionDialog()) - } - } else { - // This will trigger the notification permission system dialog as app targets sdk 32. - ensureMarketingChannelExists(applicationContext) - } - } - } - private fun maybeShowSplashScreen() { if (components.settings.isFirstSplashScreenShown) { return @@ -555,7 +519,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { components.core.store.dispatch(SearchAction.RefreshSearchEnginesAction) } - override fun onStart() { + final override fun onStart() { // DO NOT MOVE ANYTHING ABOVE THIS getProfilerTime CALL. val startProfilerTime = components.core.engine.profiler?.getProfilerTime() @@ -575,7 +539,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { ) // DO NOT MOVE ANYTHING BELOW THIS addMarker CALL. } - override fun onStop() { + final override fun onStop() { super.onStop() // Diagnostic breadcrumb for "Display already aquired" crash: @@ -631,6 +595,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { outContent?.webUri = currentTabUrl?.let { Uri.parse(it) } } + @CallSuper override fun onDestroy() { super.onDestroy() @@ -649,12 +614,13 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { privateNotificationObserver?.stop() components.notificationsDelegate.unBindActivity(this) - if (this !is ExternalAppBrowserActivity) { + val activityStartedWithLink = startupPathProvider.startupPathForActivity == StartupPathProvider.StartupPath.VIEW + if (this !is ExternalAppBrowserActivity && !activityStartedWithLink) { stopMediaSession() } } - override fun onConfigurationChanged(newConfig: Configuration) { + final override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) // Diagnostic breadcrumb for "Display already aquired" crash: @@ -664,7 +630,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { ) } - override fun recreate() { + final override fun recreate() { // Diagnostic breadcrumb for "Display already aquired" crash: // https://github.com/mozilla-mobile/android-components/issues/7960 breadcrumb( @@ -749,12 +715,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { else -> super.onCreateView(parent, name, context, attrs) } - override fun onActionModeStarted(mode: ActionMode?) { + final override fun onActionModeStarted(mode: ActionMode?) { actionMode = mode super.onActionModeStarted(mode) } - override fun onActionModeFinished(mode: ActionMode?) { + final override fun onActionModeFinished(mode: ActionMode?) { actionMode = null super.onActionModeFinished(mode) } @@ -821,7 +787,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { return false } - override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { + final override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { ProfilerMarkers.addForDispatchTouchEvent(components.core.engine.profiler, ev) return super.dispatchTouchEvent(ev) } @@ -882,6 +848,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { * private mode directly before the content view is created. Returns the mode set by the intent * otherwise falls back to the last known mode. */ + @VisibleForTesting internal fun getModeFromIntentOrLastKnown(intent: Intent?): BrowsingMode { intent?.toSafeIntent()?.let { if (it.hasExtra(PRIVATE_BROWSING_MODE)) { @@ -905,12 +872,18 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { return false } - private fun setupThemeAndBrowsingMode(mode: BrowsingMode) { + private fun setupBrowsingMode(mode: BrowsingMode) { settings().lastKnownMode = mode browsingModeManager = createBrowsingModeManager(mode) + } + + private fun setupTheme() { themeManager = createThemeManager() - themeManager.setActivityTheme(this) - themeManager.applyStatusBarTheme(this) + // ExternalAppBrowserActivity exclusively handles it's own theming unless in private mode. + if (this !is ExternalAppBrowserActivity || browsingModeManager.mode.isPrivate) { + themeManager.setActivityTheme(this) + themeManager.applyStatusBarTheme(this) + } } // Stop active media when activity is destroyed. @@ -934,7 +907,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { * Returns the [supportActionBar], inflating it if necessary. * Everyone should call this instead of supportActionBar. */ - override fun getSupportActionBarAndInflateIfNecessary(): ActionBar { + final override fun getSupportActionBarAndInflateIfNecessary(): ActionBar { if (!isToolbarInflated) { navigationToolbar = binding.navigationToolbarStub.inflate() as Toolbar @@ -949,7 +922,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } @Suppress("SpreadOperator") - fun setupNavigationToolbar(vararg topLevelDestinationIds: Int) { + private fun setupNavigationToolbar(vararg topLevelDestinationIds: Int) { NavigationUI.setupWithNavController( navigationToolbar, navHost.navController, @@ -1132,13 +1105,13 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { navController.navigate(NavGraphDirections.actionStartupHome()) } - override fun attachBaseContext(base: Context) { + final override fun attachBaseContext(base: Context) { base.components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) { super.attachBaseContext(base) } } - override fun getSystemService(name: String): Any? { + final override fun getSystemService(name: String): Any? { // Issue #17759 had a crash with the PerformanceInflater.kt on Android 5.0 and 5.1 // when using the TimePicker. Since the inflater was created for performance monitoring // purposes and that we test on new android versions, this means that any difference in @@ -1152,7 +1125,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { return super.getSystemService(name) } - protected open fun createBrowsingModeManager(initialMode: BrowsingMode): BrowsingModeManager { + private fun createBrowsingModeManager(initialMode: BrowsingMode): BrowsingModeManager { return DefaultBrowsingModeManager(initialMode, components.settings) { newMode -> updateSecureWindowFlags(newMode) themeManager.currentTheme = newMode @@ -1169,7 +1142,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } } - protected open fun createThemeManager(): ThemeManager { + private fun createThemeManager(): ThemeManager { return DefaultThemeManager(browsingModeManager.mode, this) } @@ -1220,7 +1193,8 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { * Indicates if the user should be redirected to the [BrowserFragment] or to the [HomeFragment], * links from an external apps should always opened in the [BrowserFragment]. */ - fun shouldStartOnHome(intent: Intent? = this.intent): Boolean { + @VisibleForTesting + internal fun shouldStartOnHome(intent: Intent? = this.intent): Boolean { return components.strictMode.resetAfter(StrictMode.allowThreadDiskReads()) { // We only want to open on home when users tap the app, // we want to ignore other cases when the app gets open by users clicking on links. @@ -1300,6 +1274,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { // PWA must have been used within last 30 days to be considered "recently used" for the // telemetry purposes. - const val PWA_RECENTLY_USED_THRESHOLD = DateUtils.DAY_IN_MILLIS * 30L + private const val PWA_RECENTLY_USED_THRESHOLD = DateUtils.DAY_IN_MILLIS * 30L } } diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt index 8ad012fe8..3cfcc9575 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegate.kt @@ -10,6 +10,8 @@ import android.text.method.LinkMovementMethod import android.text.style.ClickableSpan import android.text.style.URLSpan import android.view.View +import android.widget.TextView +import androidx.annotation.VisibleForTesting import androidx.core.net.toUri import androidx.core.text.HtmlCompat import androidx.core.text.getSpans @@ -20,6 +22,7 @@ import mozilla.components.feature.addons.ui.updatedAtDate import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.R import org.mozilla.fenix.databinding.FragmentAddOnDetailsBinding +import org.mozilla.fenix.ext.addUnderline import java.text.DateFormat import java.text.NumberFormat import java.util.Locale @@ -61,14 +64,18 @@ class AddonDetailsBindingDelegate( private fun bindRating(addon: Addon) { addon.rating?.let { rating -> val resources = binding.root.resources - val ratingContentDescription = resources.getString(R.string.mozac_feature_addons_rating_content_description) - binding.ratingView.contentDescription = String.format(ratingContentDescription, rating.average) + val ratingContentDescription = + resources.getString(R.string.mozac_feature_addons_rating_content_description_2) + binding.ratingLabel.contentDescription = String.format(ratingContentDescription, rating.average) binding.ratingView.rating = rating.average + val reviewCount = resources.getString(R.string.mozac_feature_addons_user_rating_count_2) + binding.reviewCount.contentDescription = String.format(reviewCount, numberFormatter.format(rating.reviews)) binding.reviewCount.text = numberFormatter.format(rating.reviews) if (addon.ratingUrl.isNotBlank()) { binding.reviewCount.setTextColor(binding.root.context.getColorFromAttr(R.attr.textAccent)) + binding.reviewCount.addUnderline() binding.reviewCount.setOnClickListener { interactor.openWebsite(addon.ratingUrl.toUri()) } @@ -83,6 +90,7 @@ class AddonDetailsBindingDelegate( return } + binding.homePageLabel.addUnderline() binding.homePageLabel.setOnClickListener { interactor.openWebsite(addon.homepageUrl.toUri()) } @@ -96,7 +104,9 @@ class AddonDetailsBindingDelegate( return } - binding.lastUpdatedText.text = dateFormatter.format(addon.updatedAtDate) + val formattedDate = dateFormatter.format(addon.updatedAtDate) + binding.lastUpdatedText.text = formattedDate + binding.lastUpdatedLabel.joinContentDescriptions(formattedDate) } private fun bindVersion(addon: Addon) { @@ -114,6 +124,7 @@ class AddonDetailsBindingDelegate( } else { binding.versionText.setOnLongClickListener(null) } + binding.versionLabel.joinContentDescriptions(version) } private fun bindAuthor(addon: Addon) { @@ -129,10 +140,12 @@ class AddonDetailsBindingDelegate( if (author.url.isNotBlank()) { binding.authorText.setTextColor(binding.root.context.getColorFromAttr(R.attr.textAccent)) + binding.authorText.addUnderline() binding.authorText.setOnClickListener { interactor.openWebsite(author.url.toUri()) } } + binding.authorLabel.joinContentDescriptions(author.name) } private fun bindDetails(addon: Addon) { @@ -175,8 +188,14 @@ class AddonDetailsBindingDelegate( return } + binding.detailUrl.addUnderline() binding.detailUrl.setOnClickListener { interactor.openWebsite(addon.detailUrl.toUri()) } } + + @VisibleForTesting + internal fun TextView.joinContentDescriptions(text: String) { + this.contentDescription = "${this.text} $text" + } } diff --git a/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt index 168ab2fe9..b1c54ee1f 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/AddonPopupBaseFragment.kt @@ -43,6 +43,7 @@ abstract class AddonPopupBaseFragment : Fragment(), EngineSession.Observer, User store = requireComponents.core.store, customTabId = it.id, fragmentManager = parentFragmentManager, + fileUploadsDirCleaner = requireComponents.core.fileUploadsDirCleaner, onNeedToRequestPermissions = { permissions -> requestPermissions(permissions, REQUEST_CODE_PROMPT_PERMISSIONS) }, diff --git a/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt b/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt index 3da061c25..f5a873c36 100644 --- a/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragment.kt @@ -162,9 +162,10 @@ class InstalledAddonDetailsFragment : Fragment() { runIfFragmentIsAttached { this.addon = it switch.isClickable = true - privateBrowsingSwitch.isVisible = it.isEnabled() - privateBrowsingSwitch.isChecked = it.isAllowedInPrivateBrowsing() switch.setText(R.string.mozac_feature_addons_enabled) + privateBrowsingSwitch.isVisible = it.isEnabled() + privateBrowsingSwitch.isChecked = + it.incognito != Addon.Incognito.NOT_ALLOWED && it.isAllowedInPrivateBrowsing() binding.settings.isVisible = shouldSettingsBeVisible() enableButtons() context?.let { @@ -203,8 +204,8 @@ class InstalledAddonDetailsFragment : Fragment() { runIfFragmentIsAttached { this.addon = it switch.isClickable = true - privateBrowsingSwitch.isVisible = it.isEnabled() switch.setText(R.string.mozac_feature_addons_disabled) + privateBrowsingSwitch.isVisible = it.isEnabled() enableButtons() context?.let { showSnackBar( @@ -220,9 +221,8 @@ class InstalledAddonDetailsFragment : Fragment() { onError = { runIfFragmentIsAttached { switch.isClickable = true - privateBrowsingSwitch.isClickable = true - enableButtons() switch.setState(addon.isEnabled()) + enableButtons() context?.let { showSnackBar( binding.root, @@ -261,6 +261,45 @@ class InstalledAddonDetailsFragment : Fragment() { } } + @VisibleForTesting + internal fun bindAllowInPrivateBrowsingSwitch() { + val switch = providePrivateBrowsingSwitch() + switch.isVisible = addon.isEnabled() + + if (addon.incognito == Addon.Incognito.NOT_ALLOWED) { + switch.isChecked = false + switch.isEnabled = false + switch.text = requireContext().getString(R.string.mozac_feature_addons_not_allowed_in_private_browsing) + return + } + + switch.isChecked = addon.isAllowedInPrivateBrowsing() + + switch.setOnCheckedChangeListener { v, isChecked -> + val addonManager = v.context.components.addonManager + switch.isClickable = false + disableButtons() + addonManager.setAddonAllowedInPrivateBrowsing( + addon, + isChecked, + onSuccess = { + runIfFragmentIsAttached { + this.addon = it + switch.isClickable = true + enableButtons() + } + }, + onError = { + runIfFragmentIsAttached { + switch.isChecked = addon.isAllowedInPrivateBrowsing() + switch.isClickable = true + enableButtons() + } + }, + ) + } + } + private fun bindReportButton() { binding.reportAddOn.setOnClickListener { val shouldCreatePrivateSession = (activity as HomeActivity).browsingModeManager.mode.isPrivate @@ -325,35 +364,6 @@ class InstalledAddonDetailsFragment : Fragment() { } } - private fun bindAllowInPrivateBrowsingSwitch() { - val switch = binding.allowInPrivateBrowsingSwitch - switch.isChecked = addon.isAllowedInPrivateBrowsing() - switch.isVisible = addon.isEnabled() - switch.setOnCheckedChangeListener { v, isChecked -> - val addonManager = v.context.components.addonManager - switch.isClickable = false - disableButtons() - addonManager.setAddonAllowedInPrivateBrowsing( - addon, - isChecked, - onSuccess = { - runIfFragmentIsAttached { - this.addon = it - switch.isClickable = true - enableButtons() - } - }, - onError = { - runIfFragmentIsAttached { - switch.isChecked = addon.isAllowedInPrivateBrowsing() - switch.isClickable = true - enableButtons() - } - }, - ) - } - } - private fun bindRemoveButton() { binding.removeAddOn.setOnClickListener { setAllInteractiveViewsClickable(binding, false) diff --git a/app/src/main/java/org/mozilla/fenix/bindings/BrowserStoreBinding.kt b/app/src/main/java/org/mozilla/fenix/bindings/BrowserStoreBinding.kt new file mode 100644 index 000000000..85242e93c --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/bindings/BrowserStoreBinding.kt @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.bindings + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.distinctUntilChangedBy +import mozilla.components.browser.state.selector.selectedTab +import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.lib.state.helpers.AbstractBinding +import org.mozilla.fenix.components.AppStore +import org.mozilla.fenix.components.appstate.AppAction + +/** + * Binding to update the [AppStore] based on changes to [BrowserState]. + */ +class BrowserStoreBinding( + browserStore: BrowserStore, + private val appStore: AppStore, +) : AbstractBinding(browserStore) { + override suspend fun onState(flow: Flow) { + // Update the AppStore with the latest selected tab + flow.distinctUntilChangedBy { it.selectedTabId } + .collectLatest { state -> + state.selectedTab?.let { tab -> + // Ignore re-observations due to lifecycle events, or other pieces of state like + // [mode] may get overwritten + if (appStore.state.selectedTabId != tab.id) { + appStore.dispatch(AppAction.SelectedTabChanged(tab)) + } + } + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt index 5ecc95688..f09dff9f6 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BaseBrowserFragment.kt @@ -92,7 +92,6 @@ import mozilla.components.feature.session.PictureInPictureFeature import mozilla.components.feature.session.ScreenOrientationFeature import mozilla.components.feature.session.SessionFeature import mozilla.components.feature.session.SwipeRefreshFeature -import mozilla.components.feature.session.behavior.EngineViewBrowserToolbarBehavior import mozilla.components.feature.sitepermissions.SitePermissionsFeature import mozilla.components.feature.webauthn.WebAuthnFeature import mozilla.components.lib.state.ext.consumeFlow @@ -112,6 +111,7 @@ import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.kotlin.getOrigin import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifAnyChanged import mozilla.components.support.locale.ActivityContextWrapper +import mozilla.components.ui.widgets.behavior.EngineViewClippingBehavior import mozilla.components.ui.widgets.withCenterAlignedButtons import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.FeatureFlags @@ -138,6 +138,7 @@ import org.mozilla.fenix.components.toolbar.ToolbarIntegration import org.mozilla.fenix.components.toolbar.interactor.BrowserToolbarInteractor import org.mozilla.fenix.components.toolbar.interactor.DefaultBrowserToolbarInteractor import org.mozilla.fenix.crashes.CrashContentIntegration +import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity import org.mozilla.fenix.databinding.FragmentBrowserBinding import org.mozilla.fenix.downloads.DownloadService import org.mozilla.fenix.downloads.DynamicDownloadDialog @@ -169,7 +170,7 @@ import org.mozilla.fenix.utils.allowUndo import org.mozilla.fenix.wifi.SitePermissionsWifiIntegration import java.lang.ref.WeakReference import kotlin.coroutines.cancellation.CancellationException -import mozilla.components.feature.session.behavior.ToolbarPosition as MozacToolbarPosition +import mozilla.components.ui.widgets.behavior.ToolbarPosition as MozacToolbarPosition /** * Base fragment extended by [BrowserFragment]. @@ -267,7 +268,11 @@ abstract class BaseBrowserFragment : _binding = FragmentBrowserBinding.inflate(inflater, container, false) val activity = activity as HomeActivity - activity.themeManager.applyStatusBarTheme(activity) + // ExternalAppBrowserActivity exclusively handles it's own theming unless in private mode. + if (activity !is ExternalAppBrowserActivity || activity.browsingModeManager.mode.isPrivate) { + activity.themeManager.applyStatusBarTheme(activity) + } + val originalContext = ActivityContextWrapper.getOriginalContext(activity) binding.engineView.setActivityContext(originalContext) @@ -696,6 +701,7 @@ abstract class BaseBrowserFragment : fragmentManager = parentFragmentManager, identityCredentialColorsProvider = colorsProvider, tabsUseCases = requireComponents.useCases.tabsUseCases, + fileUploadsDirCleaner = requireComponents.core.fileUploadsDirCleaner, creditCardValidationDelegate = DefaultCreditCardValidationDelegate( context.components.core.lazyAutofillStorage, ), @@ -1130,7 +1136,7 @@ abstract class BaseBrowserFragment : MozacToolbarPosition.TOP } (getSwipeRefreshLayout().layoutParams as CoordinatorLayout.LayoutParams).behavior = - EngineViewBrowserToolbarBehavior( + EngineViewClippingBehavior( context, null, getSwipeRefreshLayout(), @@ -1543,7 +1549,10 @@ abstract class BaseBrowserFragment : activity?.exitImmersiveMode() (view as? SwipeGestureLayout)?.isSwipeEnabled = true (activity as? HomeActivity)?.let { activity -> - activity.themeManager.applyStatusBarTheme(activity) + // ExternalAppBrowserActivity exclusively handles it's own theming unless in private mode. + if (activity !is ExternalAppBrowserActivity || activity.browsingModeManager.mode.isPrivate) { + activity.themeManager.applyStatusBarTheme(activity) + } } if (webAppToolbarShouldBeVisible) { browserToolbarView.view.isVisible = true diff --git a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt index f93d8c455..5248f0773 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/BrowserFragment.kt @@ -230,7 +230,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler { context, R.drawable.mozac_ic_translate_24, )!!, - contentDescription = "", + contentDescription = context.getString(R.string.browser_toolbar_translate), contentDescriptionSelected = "", visible = { translationsAvailable || context.settings().enableTranslations diff --git a/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt b/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt index b49478793..facb796e5 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/TabPreview.kt @@ -22,7 +22,7 @@ import org.mozilla.fenix.databinding.TabPreviewBinding import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings import org.mozilla.fenix.theme.ThemeManager -import kotlin.math.max +import kotlin.math.min class TabPreview @JvmOverloads constructor( context: Context, @@ -72,7 +72,7 @@ class TabPreview @JvmOverloads constructor( fun loadPreviewThumbnail(thumbnailId: String, isPrivate: Boolean) { doOnNextLayout { val previewThumbnail = binding.previewThumbnail - val thumbnailSize = max(previewThumbnail.height, previewThumbnail.width) + val thumbnailSize = min(previewThumbnail.height, previewThumbnail.width) thumbnailLoader.loadIntoView( previewThumbnail, ImageLoadRequest(thumbnailId, thumbnailSize, isPrivate), diff --git a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt index 250a380ca..078cbcaab 100644 --- a/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt +++ b/app/src/main/java/org/mozilla/fenix/components/BackgroundServices.kt @@ -43,6 +43,7 @@ import org.mozilla.fenix.FeatureFlags import org.mozilla.fenix.GleanMetrics.SyncAuth import org.mozilla.fenix.R import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.maxActiveTime import org.mozilla.fenix.ext.settings import org.mozilla.fenix.perf.StrictModeManager import org.mozilla.fenix.perf.lazyMonitored @@ -143,7 +144,7 @@ class BackgroundServices( } val syncedTabsStorage by lazyMonitored { - SyncedTabsStorage(accountManager, context.components.core.store, remoteTabsStorage.value) + SyncedTabsStorage(accountManager, context.components.core.store, remoteTabsStorage.value, maxActiveTime) } val syncedTabsAutocompleteProvider by lazyMonitored { SyncedTabsAutocompleteProvider(syncedTabsStorage) diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 2f455ec4c..b9d3a50d0 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -207,7 +207,7 @@ class Components(private val context: Context) { ) } - val fxSuggest by lazyMonitored { FxSuggest(context, analytics.crashReporter) } + val fxSuggest by lazyMonitored { FxSuggest(context) } } /** diff --git a/app/src/main/java/org/mozilla/fenix/components/Core.kt b/app/src/main/java/org/mozilla/fenix/components/Core.kt index e1978453a..65778d279 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Core.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Core.kt @@ -12,6 +12,10 @@ import androidx.appcompat.content.res.AppCompatResources.getDrawable import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.toBitmap import androidx.datastore.preferences.preferencesDataStore +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import mozilla.components.browser.domains.autocomplete.BaseDomainAutocompleteProvider import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider import mozilla.components.browser.engine.gecko.GeckoEngine @@ -46,6 +50,8 @@ import mozilla.components.feature.media.MediaSessionFeature import mozilla.components.feature.media.middleware.LastMediaAccessMiddleware import mozilla.components.feature.media.middleware.RecordingDevicesMiddleware import mozilla.components.feature.prompts.PromptMiddleware +import mozilla.components.feature.prompts.file.FileUploadsDirCleaner +import mozilla.components.feature.prompts.file.FileUploadsDirCleanerMiddleware import mozilla.components.feature.pwa.ManifestStorage import mozilla.components.feature.pwa.WebAppShortcutManager import mozilla.components.feature.readerview.ReaderViewMiddleware @@ -56,6 +62,7 @@ import mozilla.components.feature.search.middleware.AdsTelemetryMiddleware import mozilla.components.feature.search.middleware.SearchExtraParams import mozilla.components.feature.search.middleware.SearchMiddleware import mozilla.components.feature.search.region.RegionMiddleware +import mozilla.components.feature.search.telemetry.SerpTelemetryRepository import mozilla.components.feature.search.telemetry.ads.AdsTelemetry import mozilla.components.feature.search.telemetry.incontent.InContentTelemetry import mozilla.components.feature.session.HistoryDelegate @@ -82,6 +89,7 @@ import mozilla.components.service.pocket.Profile import mozilla.components.service.sync.autofill.AutofillCreditCardsAddressesStorage import mozilla.components.service.sync.logins.SyncableLoginsStorage import mozilla.components.support.base.worker.Frequency +import mozilla.components.support.ktx.android.content.res.readJSONObject import mozilla.components.support.locale.LocaleManager import org.mozilla.fenix.AppRequestInterceptor import org.mozilla.fenix.BuildConfig @@ -189,6 +197,10 @@ class Core( ) } + val fileUploadsDirCleaner: FileUploadsDirCleaner by lazyMonitored { + FileUploadsDirCleaner { context.cacheDir } + } + val geckoRuntime: GeckoRuntime by lazyMonitored { GeckoProvider.getOrCreateRuntime( context, @@ -286,6 +298,7 @@ class Core( SessionPrioritizationMiddleware(), SaveToPDFMiddleware(context), FxSuggestFactsMiddleware(), + FileUploadsDirCleanerMiddleware(fileUploadsDirCleaner), ) BrowserStore( @@ -309,11 +322,25 @@ class Core( // Install the "icons" WebExtension to automatically load icons for every visited website. icons.install(engine, this) - // Install the "ads" WebExtension to get the links in an partner page. - adsTelemetry.install(engine, this) - - // Install the "cookies" WebExtension and tracks user interaction with SERPs. - searchTelemetry.install(engine, this) + CoroutineScope(Dispatchers.Main).launch { + val readJson = { context.assets.readJSONObject("search/search_telemetry_v2.json") } + val providerList = withContext(Dispatchers.IO) { + SerpTelemetryRepository( + rootStorageDirectory = context.filesDir, + readJson = readJson, + collectionName = COLLECTION_NAME, + serverUrl = if (context.settings().useProductionRemoteSettingsServer) { + REMOTE_PROD_ENDPOINT_URL + } else { + REMOTE_STAGE_ENDPOINT_URL + }, + ).updateProviderList() + } + // Install the "ads" WebExtension to get the links in an partner page. + adsTelemetry.install(engine, this@apply, providerList) + // Install the "cookies" WebExtension and tracks user interaction with SERPs. + searchTelemetry.install(engine, this@apply, providerList) + } WebNotificationFeature( context, @@ -598,5 +625,10 @@ class Core( // Maximum number of suggestions returned from shortcut search engine. const val METADATA_SHORTCUT_SUGGESTION_LIMIT = 20 + + // collection name to fetch from server for SERP telemetry + const val COLLECTION_NAME = "search-telemetry-v2" + internal const val REMOTE_PROD_ENDPOINT_URL = "https://firefox.settings.services.mozilla.com" + internal const val REMOTE_STAGE_ENDPOINT_URL = "https://firefox.settings.services.allizom.org" } } diff --git a/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt b/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt index 9bbc4d0b6..3909a52c0 100644 --- a/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt +++ b/app/src/main/java/org/mozilla/fenix/components/FenixSnackbar.kt @@ -121,7 +121,7 @@ class FenixSnackbar private constructor( * Suppressing ComplexCondition. Yes it's unfortunately complex but that's the nature * of the snackbar handling by Android. It will be simpler once dynamic toolbar is always on. */ - @Suppress("ComplexCondition") + @Suppress("ComplexCondition", "RestrictedApi") fun make( view: View, duration: Int = LENGTH_LONG, diff --git a/app/src/main/java/org/mozilla/fenix/components/FxSuggest.kt b/app/src/main/java/org/mozilla/fenix/components/FxSuggest.kt index 22a444442..05593c97f 100644 --- a/app/src/main/java/org/mozilla/fenix/components/FxSuggest.kt +++ b/app/src/main/java/org/mozilla/fenix/components/FxSuggest.kt @@ -5,7 +5,6 @@ package org.mozilla.fenix.components import android.content.Context -import mozilla.components.concept.base.crash.CrashReporting import mozilla.components.feature.fxsuggest.FxSuggestIngestionScheduler import mozilla.components.feature.fxsuggest.FxSuggestStorage import org.mozilla.fenix.perf.lazyMonitored @@ -14,12 +13,10 @@ import org.mozilla.fenix.perf.lazyMonitored * Component group for Firefox Suggest. * * @param context The Android application context. - * @param crashReporter An optional [CrashReporting] instance for reporting unexpected caught - * exceptions. */ -class FxSuggest(context: Context, crashReporter: CrashReporting? = null) { +class FxSuggest(context: Context) { val storage by lazyMonitored { - FxSuggestStorage(context, crashReporter) + FxSuggestStorage(context) } val ingestionScheduler by lazyMonitored { diff --git a/app/src/main/java/org/mozilla/fenix/components/UrlRequestInterceptor.kt b/app/src/main/java/org/mozilla/fenix/components/UrlRequestInterceptor.kt index d267a6043..675b4c6af 100644 --- a/app/src/main/java/org/mozilla/fenix/components/UrlRequestInterceptor.kt +++ b/app/src/main/java/org/mozilla/fenix/components/UrlRequestInterceptor.kt @@ -8,8 +8,11 @@ import androidx.annotation.VisibleForTesting import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.LoadUrlFlags import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.ALLOW_ADDITIONAL_HEADERS +import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.BYPASS_CACHE import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE import mozilla.components.concept.engine.request.RequestInterceptor +import java.net.MalformedURLException +import java.net.URL /** * [RequestInterceptor] implementation for intercepting URL load requests to allow custom @@ -19,9 +22,10 @@ import mozilla.components.concept.engine.request.RequestInterceptor */ class UrlRequestInterceptor(private val isDeviceRamAboveThreshold: Boolean) : RequestInterceptor { - private val isGoogleSearchRequest by lazy { - Regex("^https://www\\.google\\.(?:.+)/search") + private val isGoogleRequest by lazy { + Regex("^https://www\\.google\\..+") } + private val googleRequestPaths = setOf("/search", "/webhp", "/preferences") @VisibleForTesting internal fun getAdditionalHeaders(isDeviceRamAboveThreshold: Boolean): Map { @@ -41,7 +45,15 @@ class UrlRequestInterceptor(private val isDeviceRamAboveThreshold: Boolean) : Re uri: String, isSubframeRequest: Boolean, ): Boolean { - return !isSubframeRequest && isGoogleSearchRequest.containsMatchIn(uri) + if (isSubframeRequest || !isGoogleRequest.containsMatchIn(uri)) { + return false + } + + return try { + googleRequestPaths.contains(URL(uri).path) + } catch (e: MalformedURLException) { + false + } } override fun onLoadRequest( @@ -58,12 +70,24 @@ class UrlRequestInterceptor(private val isDeviceRamAboveThreshold: Boolean) : Re return null } - return RequestInterceptor.InterceptionResponse.Url( - url = uri, - flags = LoadUrlFlags.select( + // This is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1875668 + // Remove this by implementing https://bugzilla.mozilla.org/show_bug.cgi?id=1883496 + val loadUrlFlags = if (uri.endsWith("#ip=1", true)) { + LoadUrlFlags.select( + LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE, + ALLOW_ADDITIONAL_HEADERS, + BYPASS_CACHE, + ) + } else { + LoadUrlFlags.select( LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE, ALLOW_ADDITIONAL_HEADERS, - ), + ) + } + + return RequestInterceptor.InterceptionResponse.Url( + url = uri, + flags = loadUrlFlags, additionalHeaders = getAdditionalHeaders(isDeviceRamAboveThreshold), ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt index eae237c46..07eb907e7 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt @@ -4,6 +4,7 @@ package org.mozilla.fenix.components.appstate +import mozilla.components.browser.state.state.TabSessionState import mozilla.components.feature.tab.collections.TabCollection import mozilla.components.feature.top.sites.TopSite import mozilla.components.lib.crash.Crash.NativeCodeCrash @@ -128,6 +129,13 @@ sealed class AppAction : Action { */ data class RemoveRecentSyncedTab(val syncedTab: RecentSyncedTab) : AppAction() + /** + * Action indicating that the selected tab has been changed. + * + * @property tab The tab that has been selected. + */ + data class SelectedTabChanged(val tab: TabSessionState) : AppAction() + /** * [Action]s related to interactions with the Messaging Framework. */ diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt index 77edd2d01..a056a00e7 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt @@ -38,6 +38,7 @@ import org.mozilla.fenix.wallpapers.WallpaperState * @property expandedCollections A set containing the ids of the [TabCollection] that are expanded * in the [HomeFragment]. * @property mode Whether the app is in private browsing mode. + * @property selectedTabId The currently selected tab ID. This should be bound to [BrowserStore]. * @property topSites The list of [TopSite] in the [HomeFragment]. * @property showCollectionPlaceholder If true, shows a placeholder when there are no collections. * @property recentTabs The list of recent [RecentTab] in the [HomeFragment]. @@ -64,6 +65,7 @@ data class AppState( val collections: List = emptyList(), val expandedCollections: Set = emptySet(), val mode: BrowsingMode = BrowsingMode.Normal, + val selectedTabId: String? = null, val topSites: List = emptyList(), val showCollectionPlaceholder: Boolean = false, val recentTabs: List = emptyList(), diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt index e17530153..bf0ab3245 100644 --- a/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt @@ -8,6 +8,7 @@ import androidx.annotation.VisibleForTesting import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory import mozilla.components.service.pocket.PocketStory.PocketSponsoredStory import mozilla.components.service.pocket.ext.recordNewImpression +import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.appstate.shopping.ShoppingStateReducer import org.mozilla.fenix.ext.filterOutTab @@ -100,6 +101,10 @@ internal object AppStoreReducer { else -> state.recentSyncedTabState }, ) + is AppAction.SelectedTabChanged -> state.copy( + selectedTabId = action.tab.id, + mode = BrowsingMode.fromBoolean(action.tab.content.private), + ) is AppAction.DisbandSearchGroupAction -> state.copy( recentHistory = state.recentHistory.filterNot { it is RecentHistoryGroup && it.title.equals(action.searchTerm, true) diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/FirstSessionPing.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/FirstSessionPing.kt index 9474ff079..0666ab06e 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/FirstSessionPing.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/FirstSessionPing.kt @@ -10,8 +10,10 @@ import androidx.annotation.VisibleForTesting import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import mozilla.components.service.glean.private.NoExtras import mozilla.components.support.base.log.logger.Logger import org.mozilla.fenix.Config +import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.FirstSession import org.mozilla.fenix.GleanMetrics.Pings import org.mozilla.fenix.ext.settings @@ -74,6 +76,8 @@ class FirstSessionPing(private val context: Context) { Pings.firstSession.submit() markAsTriggered() } + } else { + Events.firstSessionPingCancelled.record(NoExtras()) } } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 2ecf9005a..52eb6c4ba 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -66,7 +66,6 @@ class GleanMetricsService( private var initialized = false private val activationPing = ActivationPing(context) - private val installationPing = FirstSessionPing(context) override fun start() { logger.debug("Enabling Glean.") @@ -87,7 +86,6 @@ class GleanMetricsService( Glean.registerPings(Pings) activationPing.checkAndSend() - installationPing.checkAndSend() } } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt index 453ff4750..6e43803f4 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/MetricController.kt @@ -339,7 +339,6 @@ internal class ReleaseMetricController( Awesomebar.sponsoredSuggestionImpressed.record( Awesomebar.SponsoredSuggestionImpressedExtra( provider = "amp", - engagementAbandoned = engagementAbandoned, ), ) } @@ -347,7 +346,6 @@ internal class ReleaseMetricController( Awesomebar.nonSponsoredSuggestionImpressed.record( Awesomebar.NonSponsoredSuggestionImpressedExtra( provider = "wikipedia", - engagementAbandoned = engagementAbandoned, ), ) } diff --git a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt index b3c24456c..64c19ea3b 100644 --- a/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt +++ b/app/src/main/java/org/mozilla/fenix/components/toolbar/BrowserToolbarView.kt @@ -19,9 +19,9 @@ import mozilla.components.browser.state.selector.selectedTab import mozilla.components.browser.state.state.CustomTabSessionState import mozilla.components.browser.state.state.ExternalAppType import mozilla.components.browser.toolbar.BrowserToolbar -import mozilla.components.browser.toolbar.behavior.BrowserToolbarBehavior import mozilla.components.browser.toolbar.display.DisplayToolbar import mozilla.components.support.ktx.util.URLStringUtils +import mozilla.components.ui.widgets.behavior.EngineViewScrollingBehavior import org.mozilla.fenix.R import org.mozilla.fenix.components.toolbar.interactor.BrowserToolbarInteractor import org.mozilla.fenix.customtabs.CustomTabToolbarIntegration @@ -32,7 +32,7 @@ import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.ToolbarPopupWindow import java.lang.ref.WeakReference -import mozilla.components.browser.toolbar.behavior.ToolbarPosition as MozacToolbarPosition +import mozilla.components.ui.widgets.behavior.ViewPosition as MozacToolbarPosition @SuppressWarnings("LargeClass") class BrowserToolbarView( @@ -53,8 +53,7 @@ class BrowserToolbarView( private val layout = LayoutInflater.from(context) .inflate(toolbarLayout, container, true) - @VisibleForTesting - internal var view: BrowserToolbar = layout + var view: BrowserToolbar = layout .findViewById(R.id.toolbar) val toolbarIntegration: ToolbarIntegration @@ -202,7 +201,7 @@ class BrowserToolbarView( } (view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply { - (behavior as? BrowserToolbarBehavior)?.forceExpand(view) + (behavior as? EngineViewScrollingBehavior)?.forceExpand(view) } } @@ -213,7 +212,7 @@ class BrowserToolbarView( } (view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply { - (behavior as? BrowserToolbarBehavior)?.forceCollapse(view) + (behavior as? EngineViewScrollingBehavior)?.forceCollapse(view) } } @@ -266,7 +265,7 @@ class BrowserToolbarView( @VisibleForTesting internal fun setDynamicToolbarBehavior(toolbarPosition: MozacToolbarPosition) { (view.layoutParams as? CoordinatorLayout.LayoutParams)?.apply { - behavior = BrowserToolbarBehavior(view.context, null, toolbarPosition) + behavior = EngineViewScrollingBehavior(view.context, null, toolbarPosition) } } diff --git a/app/src/main/java/org/mozilla/fenix/compose/Menu.kt b/app/src/main/java/org/mozilla/fenix/compose/Menu.kt index 68acd450b..2d1d5cbe1 100644 --- a/app/src/main/java/org/mozilla/fenix/compose/Menu.kt +++ b/app/src/main/java/org/mozilla/fenix/compose/Menu.kt @@ -6,11 +6,15 @@ package org.mozilla.fenix.compose import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.DropdownMenu import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -24,8 +28,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp +import org.mozilla.fenix.R import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.button.PrimaryButton import org.mozilla.fenix.theme.FirefoxTheme @@ -62,14 +69,51 @@ private fun Menu( .background(color = FirefoxTheme.colors.layer2) .then(modifier), ) { + val hasCheckedItems = menuItems.any { it.isChecked } + for (item in menuItems) { + val checkmarkModifier = if (hasCheckedItems) { + Modifier.selectable( + selected = item.isChecked, + role = Role.Button, + onClick = { + onDismissRequest() + item.onClick() + }, + ) + } else { + Modifier + } + DropdownMenuItem( - modifier = Modifier.testTag(item.testTag), + modifier = Modifier + .testTag(item.testTag) + .align(alignment = Alignment.CenterHorizontally) + .then(checkmarkModifier), onClick = { onDismissRequest() item.onClick() }, ) { + if (hasCheckedItems) { + if (item.isChecked) { + Icon( + painter = painterResource(id = R.drawable.mozac_ic_checkmark_24), + modifier = Modifier + .size(24.dp), + contentDescription = null, + tint = FirefoxTheme.colors.iconPrimary, + ) + } else { + Spacer( + modifier = Modifier + .size(24.dp), + ) + } + + Spacer(modifier = Modifier.width(12.dp)) + } + Text( text = item.title, color = item.color ?: FirefoxTheme.colors.textPrimary, @@ -117,12 +161,14 @@ fun ContextualMenu( * * @property title Text the item should display. * @property color Color used to display the text. + * @property isChecked Whether a checkmark should appear next to the text. * @property testTag Tag used to identify the item in automated tests. * @property onClick Callback to be called when the item is clicked. */ data class MenuItem( val title: String, val color: Color? = null, + val isChecked: Boolean = false, val testTag: String = "", val onClick: () -> Unit, ) diff --git a/app/src/main/java/org/mozilla/fenix/compose/MessageCard.kt b/app/src/main/java/org/mozilla/fenix/compose/MessageCard.kt index d5a6cc1d8..d3669470c 100644 --- a/app/src/main/java/org/mozilla/fenix/compose/MessageCard.kt +++ b/app/src/main/java/org/mozilla/fenix/compose/MessageCard.kt @@ -208,7 +208,7 @@ private fun MessageCardPreview() { ) { MessageCard( messageText = stringResource(id = R.string.default_browser_experiment_card_text), - titleText = stringResource(id = R.string.bookmark_empty_title_error), + titleText = stringResource(id = R.string.default_browser_experiment_card_title), onClick = {}, onCloseButtonClick = {}, ) @@ -245,7 +245,7 @@ private fun MessageCardWithButtonLabelPreview() { ) { MessageCard( messageText = stringResource(id = R.string.default_browser_experiment_card_text), - titleText = stringResource(id = R.string.bookmark_empty_title_error), + titleText = stringResource(id = R.string.default_browser_experiment_card_title), buttonText = stringResource(id = R.string.preferences_set_as_default_browser), onClick = {}, onCloseButtonClick = {}, diff --git a/app/src/main/java/org/mozilla/fenix/compose/TabCounter.kt b/app/src/main/java/org/mozilla/fenix/compose/TabCounter.kt new file mode 100644 index 000000000..b35235f2f --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/compose/TabCounter.kt @@ -0,0 +1,136 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.compose + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Icon +import androidx.compose.material.LocalContentAlpha +import androidx.compose.material.LocalContentColor +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.mozilla.fenix.R +import org.mozilla.fenix.compose.annotation.LightDarkPreview +import org.mozilla.fenix.compose.ext.toLocaleString +import org.mozilla.fenix.tabstray.TabsTrayTestTag +import org.mozilla.fenix.theme.FirefoxTheme + +private const val MAX_VISIBLE_TABS = 99 +private const val SO_MANY_TABS_OPEN = "∞" +private val NORMAL_TABS_BOTTOM_PADDING = 0.5.dp +private const val ONE_DIGIT_SIZE_RATIO = 0.5f +private const val TWO_DIGITS_SIZE_RATIO = 0.4f +private const val MIN_SINGLE_DIGIT = 0 +private const val MAX_SINGLE_DIGIT = 9 +private const val TWO_DIGIT_THRESHOLD = 10 +private const val TAB_TEXT_BOTTOM_PADDING_RATIO = 4 + +/** + * UI for displaying the number of opened tabs. +* +* This composable uses LocalContentColor, provided by CompositionLocalProvider, +* to set the color of its icons and text. +* +* @param tabCount the number to be displayed inside the counter. +*/ + +@Composable +fun TabCounter(tabCount: Int) { + val formattedTabCount = tabCount.toLocaleString() + val normalTabCountText: String + val tabCountTextRatio: Float + val needsBottomPaddingForInfiniteTabs: Boolean + + when (tabCount) { + in MIN_SINGLE_DIGIT..MAX_SINGLE_DIGIT -> { + normalTabCountText = formattedTabCount + tabCountTextRatio = ONE_DIGIT_SIZE_RATIO + needsBottomPaddingForInfiniteTabs = false + } + + in TWO_DIGIT_THRESHOLD..MAX_VISIBLE_TABS -> { + normalTabCountText = formattedTabCount + tabCountTextRatio = TWO_DIGITS_SIZE_RATIO + needsBottomPaddingForInfiniteTabs = false + } + + else -> { + normalTabCountText = SO_MANY_TABS_OPEN + tabCountTextRatio = ONE_DIGIT_SIZE_RATIO + needsBottomPaddingForInfiniteTabs = true + } + } + + val normalTabsContentDescription = if (tabCount == 1) { + stringResource(id = R.string.mozac_tab_counter_open_tab_tray_single) + } else { + stringResource( + id = R.string.mozac_tab_counter_open_tab_tray_plural, + formattedTabCount, + ) + } + + val counterBoxWidthDp = + dimensionResource(id = mozilla.components.ui.tabcounter.R.dimen.mozac_tab_counter_box_width_height) + val counterBoxWidthPx = LocalDensity.current.run { counterBoxWidthDp.roundToPx() } + val counterTabsTextSize = (tabCountTextRatio * counterBoxWidthPx).toInt() + + val normalTabsTextModifier = if (needsBottomPaddingForInfiniteTabs) { + val bottomPadding = with(LocalDensity.current) { counterTabsTextSize.toDp() / TAB_TEXT_BOTTOM_PADDING_RATIO } + Modifier.padding(bottom = bottomPadding) + } else { + Modifier.padding(bottom = NORMAL_TABS_BOTTOM_PADDING) + } + + Box( + modifier = Modifier + .semantics(mergeDescendants = true) { + testTag = TabsTrayTestTag.normalTabsCounter + }, + contentAlignment = Alignment.Center, + ) { + Icon( + painter = painterResource( + id = mozilla.components.ui.tabcounter.R.drawable.mozac_ui_tabcounter_box, + ), + contentDescription = normalTabsContentDescription, + ) + + Text( + text = normalTabCountText, + modifier = normalTabsTextModifier, + color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current), + fontSize = with(LocalDensity.current) { counterTabsTextSize.toDp().toSp() }, + fontWeight = FontWeight.W700, + textAlign = TextAlign.Center, + ) + } +} + +@LightDarkPreview +@Preview(locale = "ar") +@Composable +private fun TabCounterPreview() { + FirefoxTheme { + Box( + modifier = Modifier.background(color = FirefoxTheme.colors.layer1), + ) { + TabCounter(tabCount = 55) + } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/compose/button/FloatingActionButton.kt b/app/src/main/java/org/mozilla/fenix/compose/button/FloatingActionButton.kt index 29ed7f83f..954e40a61 100644 --- a/app/src/main/java/org/mozilla/fenix/compose/button/FloatingActionButton.kt +++ b/app/src/main/java/org/mozilla/fenix/compose/button/FloatingActionButton.kt @@ -47,7 +47,10 @@ fun FloatingActionButton( modifier: Modifier = Modifier, contentDescription: String? = null, label: String? = null, - elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(defaultElevation = 5.dp), + elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation( + defaultElevation = 5.dp, + pressedElevation = 5.dp, + ), onClick: () -> Unit, ) { FloatingActionButton( diff --git a/app/src/main/java/org/mozilla/fenix/compose/ext/Int.kt b/app/src/main/java/org/mozilla/fenix/compose/ext/Int.kt new file mode 100644 index 000000000..7d09419cc --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/compose/ext/Int.kt @@ -0,0 +1,15 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.compose.ext + +import androidx.compose.ui.text.intl.Locale +import java.text.NumberFormat +import java.util.Locale as JavaLocale + +/** + * Returns a localized string representation of the value. + */ +fun Int.toLocaleString(): String = + NumberFormat.getNumberInstance(JavaLocale(Locale.current.language)).format(this) diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt index be147c039..c2df28f24 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -5,7 +5,6 @@ package org.mozilla.fenix.customtabs import android.content.Context -import android.content.Intent import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.view.isVisible @@ -28,7 +27,6 @@ import mozilla.components.feature.pwa.feature.WebAppHideToolbarFeature import mozilla.components.feature.pwa.feature.WebAppSiteControlsFeature import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.ktx.android.arch.lifecycle.addObservers -import org.mozilla.fenix.BuildConfig import org.mozilla.fenix.R import org.mozilla.fenix.browser.BaseBrowserFragment import org.mozilla.fenix.browser.CustomTabContextMenuCandidate @@ -80,21 +78,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment() { ) windowFeature.set( - feature = CustomTabWindowFeature( - activity, - components.core.store, - customTabSessionId, - ) { uri -> - val intent = - Intent.parseUri("${BuildConfig.DEEP_LINK_SCHEME}://open?url=$uri", 0) - if (intent.action == Intent.ACTION_VIEW) { - intent.addCategory(Intent.CATEGORY_BROWSABLE) - intent.component = null - intent.selector = null - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - } - activity.startActivity(intent) - }, + feature = CustomTabWindowFeature(activity, components.core.store, customTabSessionId), owner = this, view = view, ) diff --git a/app/src/main/java/org/mozilla/fenix/debugsettings/tabs/TabTools.kt b/app/src/main/java/org/mozilla/fenix/debugsettings/tabs/TabTools.kt index c6daa5d80..5fa97b7c0 100644 --- a/app/src/main/java/org/mozilla/fenix/debugsettings/tabs/TabTools.kt +++ b/app/src/main/java/org/mozilla/fenix/debugsettings/tabs/TabTools.kt @@ -43,6 +43,7 @@ import org.mozilla.fenix.R import org.mozilla.fenix.compose.Divider import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.button.PrimaryButton +import org.mozilla.fenix.compose.ext.toLocaleString import org.mozilla.fenix.debugsettings.ui.DebugDrawer import org.mozilla.fenix.ext.maxActiveTime import org.mozilla.fenix.tabstray.ext.isNormalTabInactive @@ -152,19 +153,19 @@ private fun TabCounter( TabCountRow( tabType = stringResource(R.string.debug_drawer_tab_tools_tab_count_normal), - count = activeTabCount.toString(), + count = activeTabCount, ) if (inactiveTabsEnabled) { TabCountRow( tabType = stringResource(R.string.debug_drawer_tab_tools_tab_count_inactive), - count = inactiveTabCount.toString(), + count = inactiveTabCount, ) } TabCountRow( tabType = stringResource(R.string.debug_drawer_tab_tools_tab_count_private), - count = privateTabCount.toString(), + count = privateTabCount, ) Spacer(modifier = Modifier.height(8.dp)) @@ -175,7 +176,7 @@ private fun TabCounter( TabCountRow( tabType = stringResource(R.string.debug_drawer_tab_tools_tab_count_total), - count = totalTabCount.toString(), + count = totalTabCount, ) } } @@ -183,7 +184,7 @@ private fun TabCounter( @Composable private fun TabCountRow( tabType: String, - count: String, + count: Int, ) { Row( modifier = Modifier @@ -198,14 +199,14 @@ private fun TabCountRow( ) Text( - text = count, + text = count.toLocaleString(), color = FirefoxTheme.colors.textSecondary, style = FirefoxTheme.typography.headline6, ) } } -private const val DEFAULT_TABS_TO_ADD = "1" +private const val DEFAULT_TABS_TO_ADD = 1 @OptIn(ExperimentalComposeUiApi::class) @Composable @@ -213,7 +214,7 @@ private fun TabCreationTool( inactiveTabsEnabled: Boolean, onCreateTabsClick: ((quantity: Int, isInactive: Boolean, isPrivate: Boolean) -> Unit), ) { - var tabQuantityToCreate by rememberSaveable { mutableStateOf(DEFAULT_TABS_TO_ADD) } + var tabQuantityToCreate by rememberSaveable { mutableStateOf(DEFAULT_TABS_TO_ADD.toLocaleString()) } var hasError by rememberSaveable { mutableStateOf(false) } val keyboardController = LocalSoftwareKeyboardController.current diff --git a/app/src/main/java/org/mozilla/fenix/ext/Client.kt b/app/src/main/java/org/mozilla/fenix/ext/Client.kt index 99d3e79e2..513aca10d 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Client.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Client.kt @@ -21,7 +21,7 @@ suspend fun Client.bitmapForUrl(url: String): Bitmap? = withContext(Dispatchers. // Code below will cache it in Gecko's cache, which ensures that as long as we've fetched it once, // we will be able to display this avatar as long as the cache isn't purged (e.g. via 'clear user data'). val body = try { - fetch(Request(url, useCaches = true)).body + fetch(Request(url, useCaches = true, conservative = true)).body } catch (e: IOException) { return@withContext null } diff --git a/app/src/main/java/org/mozilla/fenix/ext/NavController.kt b/app/src/main/java/org/mozilla/fenix/ext/NavController.kt index 07e9713b9..e768d72f2 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/NavController.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/NavController.kt @@ -68,7 +68,7 @@ fun NavController.navigateWithBreadcrumb( */ @SuppressLint("RestrictedApi") fun NavController.hasTopDestination(fragmentClassName: String): Boolean { - return this.backQueue.lastOrNull()?.destination?.displayName?.contains( + return this.currentBackStackEntry?.destination?.displayName?.contains( fragmentClassName, true, ) == true diff --git a/app/src/main/java/org/mozilla/fenix/ext/Toolbar.kt b/app/src/main/java/org/mozilla/fenix/ext/Toolbar.kt index b7e9b953b..c7b6325db 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/Toolbar.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/Toolbar.kt @@ -33,6 +33,7 @@ fun Toolbar.setToolbarColors(@ColorInt foreground: Int, @ColorInt background: In } } +@Suppress("RestrictedApi") private fun themeActionMenuView(item: ActionMenuView, colorFilter: ColorFilter?) { item.forEach { innerChild -> if (innerChild is ActionMenuItemView) { diff --git a/app/src/main/java/org/mozilla/fenix/ext/View.kt b/app/src/main/java/org/mozilla/fenix/ext/View.kt index 83a02b7c1..3c5976e42 100644 --- a/app/src/main/java/org/mozilla/fenix/ext/View.kt +++ b/app/src/main/java/org/mozilla/fenix/ext/View.kt @@ -30,6 +30,23 @@ fun View.increaseTapArea(@Dimension(unit = DP) extraDps: Int) { } } +/** + * Increase tap area only vertically. + * + * @param extraDps the extra dps that's wanted to be added on top and bottom of the view + */ +fun View.increaseTapAreaVertically(@Dimension(unit = DP) extraDps: Int) { + val dips = extraDps.dpToPx(resources.displayMetrics) + val parent = this.parent as View + parent.post { + val touchArea = Rect() + getHitRect(touchArea) + touchArea.top -= dips + touchArea.bottom += dips + parent.touchDelegate = TouchDelegate(touchArea, this) + } +} + fun View.removeTouchDelegate() { val parent = this.parent as View parent.post { diff --git a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt index 6ed9c9620..6918058d2 100644 --- a/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt @@ -248,7 +248,11 @@ class HomeFragment : Fragment() { val components = requireComponents val currentWallpaperName = requireContext().settings().currentWallpaperName - applyWallpaper(wallpaperName = currentWallpaperName, orientationChange = false) + applyWallpaper( + wallpaperName = currentWallpaperName, + orientationChange = false, + orientation = requireContext().resources.configuration.orientation, + ) components.appStore.dispatch(AppAction.ModeChange(browsingModeManager.mode)) @@ -454,7 +458,11 @@ class HomeFragment : Fragment() { homeMenuView?.dismissMenu() val currentWallpaperName = requireContext().settings().currentWallpaperName - applyWallpaper(wallpaperName = currentWallpaperName, orientationChange = true) + applyWallpaper( + wallpaperName = currentWallpaperName, + orientationChange = true, + orientation = newConfig.orientation, + ) } /** @@ -1000,7 +1008,7 @@ class HomeFragment : Fragment() { internal fun shouldEnableWallpaper() = (activity as? HomeActivity)?.themeManager?.currentTheme?.isPrivate?.not() ?: false - private fun applyWallpaper(wallpaperName: String, orientationChange: Boolean) { + private fun applyWallpaper(wallpaperName: String, orientationChange: Boolean, orientation: Int) { when { !shouldEnableWallpaper() || (wallpaperName == lastAppliedWallpaperName && !orientationChange) -> return @@ -1013,8 +1021,7 @@ class HomeFragment : Fragment() { // loadBitmap does file lookups based on name, so we don't need a fully // qualified type to load the image val wallpaper = Wallpaper.Default.copy(name = wallpaperName) - val wallpaperImage = - context?.let { requireComponents.useCases.wallpaperUseCases.loadBitmap(it, wallpaper) } + val wallpaperImage = requireComponents.useCases.wallpaperUseCases.loadBitmap(wallpaper, orientation) wallpaperImage?.let { it.scaleToBottomOfView(binding.wallpaperImageView) binding.wallpaperImageView.isVisible = true @@ -1060,7 +1067,11 @@ class HomeFragment : Fragment() { .distinctUntilChanged() .collect { if (it.name != lastAppliedWallpaperName) { - applyWallpaper(wallpaperName = it.name, orientationChange = false) + applyWallpaper( + wallpaperName = it.name, + orientationChange = false, + orientation = requireContext().resources.configuration.orientation, + ) } } } diff --git a/app/src/main/java/org/mozilla/fenix/home/toolbar/SearchSelectorBinding.kt b/app/src/main/java/org/mozilla/fenix/home/toolbar/SearchSelectorBinding.kt index 3696c628d..6a6b92684 100644 --- a/app/src/main/java/org/mozilla/fenix/home/toolbar/SearchSelectorBinding.kt +++ b/app/src/main/java/org/mozilla/fenix/home/toolbar/SearchSelectorBinding.kt @@ -20,6 +20,7 @@ import mozilla.components.support.ktx.android.content.getColorFromAttr import org.mozilla.fenix.GleanMetrics.UnifiedSearch import org.mozilla.fenix.R import org.mozilla.fenix.databinding.FragmentHomeBinding +import org.mozilla.fenix.ext.increaseTapAreaVertically import org.mozilla.fenix.ext.settings import org.mozilla.fenix.search.toolbar.SearchSelectorMenu @@ -51,6 +52,8 @@ class SearchSelectorBinding( orientation = orientation, ) } + + increaseTapAreaVertically(SEARCH_SELECTOR_INCREASE_HEIGHT_DPS) } } @@ -76,4 +79,8 @@ class SearchSelectorBinding( binding.searchSelectorButton.setIcon(icon, name) } } + + companion object { + const val SEARCH_SELECTOR_INCREASE_HEIGHT_DPS = 10 + } } diff --git a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapter.kt b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapter.kt index 0a56a0c9c..a480f861a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapter.kt +++ b/app/src/main/java/org/mozilla/fenix/home/topsites/TopSitesPagerAdapter.kt @@ -97,6 +97,7 @@ class TopSitesPagerAdapter( } override fun areContentsTheSame(oldItem: List, newItem: List): Boolean { + @Suppress("DiffUtilEquals") return newItem.zip(oldItem).all { (new, old) -> new == old } } diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/HomeNotificationPermissionDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/onboarding/HomeNotificationPermissionDialogFragment.kt deleted file mode 100644 index be4a22e1b..000000000 --- a/app/src/main/java/org/mozilla/fenix/onboarding/HomeNotificationPermissionDialogFragment.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.onboarding - -import android.annotation.SuppressLint -import android.content.pm.ActivityInfo -import android.os.Build -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.annotation.RequiresApi -import androidx.compose.ui.platform.ComposeView -import androidx.fragment.app.DialogFragment -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.requireComponents -import org.mozilla.fenix.ext.settings -import org.mozilla.fenix.onboarding.view.NotificationPermissionDialogScreen -import org.mozilla.fenix.theme.FirefoxTheme - -/** - * Dialog displaying notification pre-permission prompt. - */ -class HomeNotificationPermissionDialogFragment : DialogFragment() { - - @SuppressLint("SourceLockedOrientationActivity") - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setStyle(STYLE_NO_TITLE, R.style.HomeOnboardingDialogStyle) - activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - } - - override fun onDestroy() { - super.onDestroy() - activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED - } - - @RequiresApi(Build.VERSION_CODES.TIRAMISU) - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View = ComposeView(requireContext()).apply { - setContent { - FirefoxTheme { - NotificationPermissionDialogScreen( - onDismiss = ::onDismiss, - grantNotificationPermission = { - ensureMarketingChannelExists(context.applicationContext) - requireComponents.notificationsDelegate.requestNotificationPermission() - onDismiss() - }, - ) - } - } - } - - private fun onDismiss() { - dismiss() - context?.settings()?.isNotificationPrePermissionShown = true - } -} diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingFragment.kt b/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingFragment.kt index d46adfac3..e91ed3842 100644 --- a/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/onboarding/OnboardingFragment.kt @@ -51,7 +51,7 @@ class OnboardingFragment : Fragment() { private val pagesToDisplay by lazy { pagesToDisplay( - shouldShowDefaultBrowserCard(requireContext()), + isNotDefaultBrowser(requireContext()), canShowNotificationPage(requireContext()), canShowAddWidgetCard(), ) @@ -62,6 +62,7 @@ class OnboardingFragment : Fragment() { @SuppressLint("SourceLockedOrientationActivity") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val context = requireContext() if (pagesToDisplay.isEmpty()) { /* do not continue if there's no onboarding pages to display */ onFinish(null) @@ -71,8 +72,14 @@ class OnboardingFragment : Fragment() { activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } val filter = IntentFilter(WidgetPinnedReceiver.ACTION) - LocalBroadcastManager.getInstance(requireContext()) + LocalBroadcastManager.getInstance(context) .registerReceiver(pinAppWidgetReceiver, filter) + + if (isNotDefaultBrowser(context) && + pagesToDisplay.none { it.type == OnboardingPageUiData.Type.DEFAULT_BROWSER } + ) { + promptToSetAsDefaultBrowser() + } } @RequiresApi(Build.VERSION_CODES.TIRAMISU) @@ -108,11 +115,7 @@ class OnboardingFragment : Fragment() { OnboardingScreen( pagesToDisplay = pagesToDisplay, onMakeFirefoxDefaultClick = { - activity?.openSetDefaultBrowserOption(useCustomTab = true) - telemetryRecorder.onSetToDefaultClick( - sequenceId = pagesToDisplay.telemetrySequenceId(), - sequencePosition = pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER), - ) + promptToSetAsDefaultBrowser() }, onSkipDefaultClick = { telemetryRecorder.onSkipSetToDefaultClick( @@ -211,7 +214,7 @@ class OnboardingFragment : Fragment() { ) } - private fun shouldShowDefaultBrowserCard(context: Context) = + private fun isNotDefaultBrowser(context: Context) = !BrowsersCache.all(context.applicationContext).isDefaultBrowser private fun canShowNotificationPage(context: Context) = @@ -257,4 +260,12 @@ class OnboardingFragment : Fragment() { jexlConditions, ) { condition -> jexlHelper.evalJexlSafe(condition) } } + + private fun promptToSetAsDefaultBrowser() { + activity?.openSetDefaultBrowserOption(useCustomTab = true) + telemetryRecorder.onSetToDefaultClick( + sequenceId = pagesToDisplay.telemetrySequenceId(), + sequencePosition = pagesToDisplay.sequencePosition(OnboardingPageUiData.Type.DEFAULT_BROWSER), + ) + } } diff --git a/app/src/main/java/org/mozilla/fenix/onboarding/view/NotificationPermissionDialogScreen.kt b/app/src/main/java/org/mozilla/fenix/onboarding/view/NotificationPermissionDialogScreen.kt deleted file mode 100644 index 702b98a1f..000000000 --- a/app/src/main/java/org/mozilla/fenix/onboarding/view/NotificationPermissionDialogScreen.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.onboarding.view - -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import mozilla.components.service.glean.private.NoExtras -import org.mozilla.fenix.GleanMetrics.Onboarding -import org.mozilla.fenix.R -import org.mozilla.fenix.compose.annotation.LightDarkPreview -import org.mozilla.fenix.theme.FirefoxTheme - -/** - * A screen for displaying notification pre permission prompt. - * - * @param onDismiss Invoked when the user clicks on the close or the negative button. - * @param grantNotificationPermission Invoked when the user clicks on the positive button. - */ -@Composable -fun NotificationPermissionDialogScreen( - onDismiss: () -> Unit, - grantNotificationPermission: () -> Unit, -) { - OnboardingPage( - pageState = OnboardingPageState( - imageRes = R.drawable.ic_notification_permission, - title = stringResource( - id = R.string.onboarding_home_enable_notifications_title, - formatArgs = arrayOf(stringResource(R.string.app_name)), - ), - description = stringResource( - id = R.string.onboarding_home_enable_notifications_description, - formatArgs = arrayOf(stringResource(R.string.app_name)), - ), - primaryButton = Action( - text = stringResource(id = R.string.onboarding_home_enable_notifications_positive_button), - onClick = { - grantNotificationPermission() - Onboarding.notifPppPositiveBtnClick.record(NoExtras()) - }, - ), - secondaryButton = Action( - text = stringResource(id = R.string.onboarding_home_enable_notifications_negative_button), - onClick = { - onDismiss() - Onboarding.notifPppNegativeBtnClick.record(NoExtras()) - }, - ), - onRecordImpressionEvent = { Onboarding.notifPppImpression.record(NoExtras()) }, - ), - onDismiss = { - onDismiss() - Onboarding.notifPppCloseClick.record(NoExtras()) - }, - modifier = Modifier - .statusBarsPadding() - .navigationBarsPadding(), - ) -} - -@LightDarkPreview -@Composable -private fun NotificationPermissionScreenPreview() { - FirefoxTheme { - NotificationPermissionDialogScreen( - grantNotificationPermission = {}, - onDismiss = { }, - ) - } -} diff --git a/app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt b/app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt index a71b0e3cc..28a8211e5 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt @@ -23,9 +23,17 @@ private const val PROFILER_SERVER_HEADER = "application/vnd.firefox-profiler+jso private const val TOKEN = "profileToken" private const val PROFILER_DATA_URL = "https://profiler.firefox.com/public/" +// IMPORTANT NOTE: Please keep the profiler presets in sync with their Firefox Desktop counterparts: +// https://searchfox.org/mozilla-central/rev/c130c69b7b863d5e28ab9524b65c27c7a9507c48/devtools/client/performance-new/shared/background.jsm.js#121 + private val firefox_features = arrayOf( - "screenshots", "js", "leaf", "stackwalk", "cpu", "java", - "processcpu", "ipcmessages", "java", + "screenshots", + "js", + "stackwalk", + "cpu", + "java", + "processcpu", + "ipcmessages", ) private val firefox_threads = arrayOf( "GeckoMain", @@ -45,11 +53,11 @@ private val graphics_threads = arrayOf( "SceneBuilder", "WrWorker", "CanvasWorkers", + "TextureUpdate", ) private val media_features = arrayOf( "js", - "leaf", "stackwalk", "cpu", "audiocallbacktracing", @@ -61,17 +69,17 @@ private val media_threads = arrayOf( "cubeb", "audio", "BackgroundThreadPool", "camera", "capture", "Compositor", "decoder", "GeckoMain", "gmp", "graph", "grph", "InotifyEventThread", "IPDL Background", "media", "ModuleProcessThread", "PacerThread", "RemVidChild", "RenderBackend", "Renderer", "Socket Thread", "SwComposite", - "webrtc", + "webrtc", "TextureUpdate", ) private val networking_features = arrayOf( "screenshots", "js", - "leaf", "stackwalk", "cpu", "java", "processcpu", + "bandwidth", "ipcmessages", ) @@ -133,6 +141,7 @@ object ProfilerUtils { "Accept" to PROFILER_SERVER_HEADER, ), body = Request.Body.fromFile(outputFile), + conservative = true, ) return context.components.core.client.fetch(request) } diff --git a/app/src/main/java/org/mozilla/fenix/perf/StartupPathProvider.kt b/app/src/main/java/org/mozilla/fenix/perf/StartupPathProvider.kt index 1cd626306..d6b0abe1c 100644 --- a/app/src/main/java/org/mozilla/fenix/perf/StartupPathProvider.kt +++ b/app/src/main/java/org/mozilla/fenix/perf/StartupPathProvider.kt @@ -100,7 +100,6 @@ class StartupPathProvider { override fun onStop(owner: LifecycleOwner) { // Clear existing state. - startupPathForActivity = StartupPath.NOT_SET wasResumedSinceStartedState = false } } diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt index 74e830fce..4ab17e66a 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogController.kt @@ -143,6 +143,7 @@ class SearchDialogController( override fun handleEditingCancelled() { clearToolbarFocus() dismissDialogAndGoBack() + store.dispatch(AwesomeBarAction.EngagementFinished(abandoned = true)) } override fun handleTextChanged(text: String) { diff --git a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt index f6fd7de78..c41d5ea4c 100644 --- a/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/search/SearchDialogFragment.kt @@ -959,7 +959,7 @@ class SearchDialogFragment : AppCompatDialogFragment(), UserInteractionHandler { internal fun getPreviousDestination(): NavBackStackEntry? { // This duplicates the platform functionality for "previousBackStackEntry" but additionally skips this entry. - val descendingEntries = findNavController().backQueue.reversed().iterator() + val descendingEntries = findNavController().currentBackStack.value.reversed().iterator() // Throw the topmost destination away. if (descendingEntries.hasNext()) { descendingEntries.next() diff --git a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt index 86b2aabeb..2d91285fe 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SecretSettingsFragment.kt @@ -23,6 +23,7 @@ import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar +import org.mozilla.fenix.GleanMetrics.DebugDrawer as DebugDrawerMetrics class SecretSettingsFragment : PreferenceFragmentCompat() { @@ -87,7 +88,8 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { onPreferenceChangeListener = object : Preference.OnPreferenceChangeListener { override fun onPreferenceChange(preference: Preference, newValue: Any?): Boolean { val newBooleanValue = newValue as? Boolean ?: return false - val ingestionScheduler = requireContext().components.fxSuggest.ingestionScheduler + val ingestionScheduler = + requireContext().components.fxSuggest.ingestionScheduler if (newBooleanValue) { ingestionScheduler.startPeriodicIngestion() } else { @@ -108,13 +110,13 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { } lifecycleScope.launch { - // During initial development, this will only be available in Nightly or Debug builds. requirePreference(R.string.pref_key_enable_debug_drawer).apply { - isVisible = Config.channel.isNightlyOrDebug + isVisible = true isChecked = debugSettingsRepository.debugDrawerEnabled.first() onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> debugSettingsRepository.setDebugDrawerEnabled(enabled = newValue as Boolean) + DebugDrawerMetrics.debugDrawerEnabled.set(newValue) true } } @@ -128,6 +130,12 @@ class SecretSettingsFragment : PreferenceFragmentCompat() { requirePreference(R.string.pref_key_custom_sponsored_stories_parameters).apply { isVisible = Config.channel.isNightlyOrDebug } + + requirePreference(R.string.pref_key_remote_server_prod).apply { + isVisible = true + isChecked = context.settings().useProductionRemoteSettingsServer + onPreferenceChangeListener = SharedPreferenceUpdater() + } } override fun onPreferenceTreeClick(preference: Preference): Boolean { diff --git a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt index 118662dac..81df60037 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/SettingsFragment.kt @@ -261,143 +261,112 @@ class SettingsFragment : PreferenceFragmentCompat() { recyclerView.isVerticalScrollBarEnabled = false val directions: NavDirections? = when (preference.key) { + /* Top level account preferences. + Note: Only ONE of these preferences is visible at a time. */ resources.getString(R.string.pref_key_sign_in) -> { SettingsMetrics.signIntoSync.add() SettingsFragmentDirections.actionSettingsFragmentToTurnOnSyncFragment( entrypoint = FenixFxAEntryPoint.SettingsMenu, ) } - resources.getString(R.string.pref_key_tabs) -> { - SettingsFragmentDirections.actionSettingsFragmentToTabsSettingsFragment() + + resources.getString(R.string.pref_key_account) -> { + SettingsFragmentDirections.actionSettingsFragmentToAccountSettingsFragment() } - resources.getString(R.string.pref_key_home) -> { - SettingsFragmentDirections.actionSettingsFragmentToHomeSettingsFragment() + + resources.getString(R.string.pref_key_account_auth_error) -> { + SettingsFragmentDirections.actionSettingsFragmentToAccountProblemFragment( + entrypoint = FenixFxAEntryPoint.SettingsMenu, + ) } + + /* General preferences */ resources.getString(R.string.pref_key_search_settings) -> { SettingsFragmentDirections.actionSettingsFragmentToSearchEngineFragment() } - resources.getString(R.string.pref_key_tracking_protection_settings) -> { - TrackingProtection.etpSettings.record(NoExtras()) - SettingsFragmentDirections.actionSettingsFragmentToTrackingProtectionFragment() - } - resources.getString(R.string.pref_key_site_permissions) -> { - SettingsFragmentDirections.actionSettingsFragmentToSitePermissionsFragment() - } - resources.getString(R.string.pref_key_private_browsing) -> { - SettingsFragmentDirections.actionSettingsFragmentToPrivateBrowsingFragment() - } - resources.getString(R.string.pref_key_https_only_settings) -> { - SettingsFragmentDirections.actionSettingsFragmentToHttpsOnlyFragment() - } - resources.getString(R.string.pref_key_accessibility) -> { - SettingsFragmentDirections.actionSettingsFragmentToAccessibilityFragment() - } - resources.getString(R.string.pref_key_language) -> { - SettingsFragmentDirections.actionSettingsFragmentToLocaleSettingsFragment() - } - resources.getString(R.string.pref_key_addons) -> { - Addons.openAddonsInSettings.record(mozilla.components.service.glean.private.NoExtras()) - SettingsFragmentDirections.actionSettingsFragmentToAddonsFragment() - } - resources.getString(R.string.pref_key_open_links_in_apps) -> { - SettingsFragmentDirections.actionSettingsFragmentToOpenLinksInAppsFragment() - } - resources.getString(R.string.pref_key_data_choices) -> { - SettingsFragmentDirections.actionSettingsFragmentToDataChoicesFragment() - } - resources.getString(R.string.pref_key_sync_debug) -> { - SettingsFragmentDirections.actionSettingsFragmentToSyncDebugFragment() + + resources.getString(R.string.pref_key_tabs) -> { + SettingsFragmentDirections.actionSettingsFragmentToTabsSettingsFragment() } - resources.getString(R.string.pref_key_help) -> { - (activity as HomeActivity).openToBrowserAndLoad( - searchTermOrURL = SupportUtils.getSumoURLForTopic( - requireContext(), - SupportUtils.SumoTopic.HELP, - ), - newTab = true, - from = BrowserDirection.FromSettings, - ) - null + + resources.getString(R.string.pref_key_home) -> { + SettingsFragmentDirections.actionSettingsFragmentToHomeSettingsFragment() } - resources.getString(R.string.pref_key_rate) -> { - try { - startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(SupportUtils.RATE_APP_URL))) - } catch (e: ActivityNotFoundException) { - // Device without the play store installed. - // Opening the play store website. - (activity as HomeActivity).openToBrowserAndLoad( - searchTermOrURL = SupportUtils.FENIX_PLAY_STORE_URL, - newTab = true, - from = BrowserDirection.FromSettings, - ) - } - null + + resources.getString(R.string.pref_key_customize) -> { + SettingsFragmentDirections.actionSettingsFragmentToCustomizationFragment() } + resources.getString(R.string.pref_key_passwords) -> { SettingsMetrics.passwords.record() SettingsFragmentDirections.actionSettingsFragmentToSavedLoginsAuthFragment() } + resources.getString(R.string.pref_key_credit_cards) -> { SettingsMetrics.autofill.record() SettingsFragmentDirections.actionSettingsFragmentToAutofillSettingFragment() } - resources.getString(R.string.pref_key_about) -> { - SettingsFragmentDirections.actionSettingsFragmentToAboutFragment() + + resources.getString(R.string.pref_key_accessibility) -> { + SettingsFragmentDirections.actionSettingsFragmentToAccessibilityFragment() } - resources.getString(R.string.pref_key_account) -> { - SettingsFragmentDirections.actionSettingsFragmentToAccountSettingsFragment() + + resources.getString(R.string.pref_key_language) -> { + SettingsFragmentDirections.actionSettingsFragmentToLocaleSettingsFragment() } - resources.getString(R.string.pref_key_account_auth_error) -> { - SettingsFragmentDirections.actionSettingsFragmentToAccountProblemFragment( - entrypoint = FenixFxAEntryPoint.SettingsMenu, - ) + + /* Privacy and security preferences */ + resources.getString(R.string.pref_key_private_browsing) -> { + SettingsFragmentDirections.actionSettingsFragmentToPrivateBrowsingFragment() + } + + resources.getString(R.string.pref_key_https_only_settings) -> { + SettingsFragmentDirections.actionSettingsFragmentToHttpsOnlyFragment() + } + + resources.getString(R.string.pref_key_tracking_protection_settings) -> { + TrackingProtection.etpSettings.record(NoExtras()) + SettingsFragmentDirections.actionSettingsFragmentToTrackingProtectionFragment() + } + + resources.getString(R.string.pref_key_site_permissions) -> { + SettingsFragmentDirections.actionSettingsFragmentToSitePermissionsFragment() } + resources.getString(R.string.pref_key_delete_browsing_data) -> { SettingsFragmentDirections.actionSettingsFragmentToDeleteBrowsingDataFragment() } + resources.getString(R.string.pref_key_delete_browsing_data_on_quit_preference) -> { SettingsFragmentDirections.actionSettingsFragmentToDeleteBrowsingDataOnQuitFragment() } + resources.getString(R.string.pref_key_notifications) -> { context?.navigateToNotificationsSettings {} null } - resources.getString(R.string.pref_key_customize) -> { - SettingsFragmentDirections.actionSettingsFragmentToCustomizationFragment() - } - resources.getString(R.string.pref_key_privacy_link) -> { - val intent = SupportUtils.createCustomTabIntent( - requireContext(), - SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE), - ) - startActivity(intent) - null - } - resources.getString(R.string.pref_key_your_rights) -> { - val context = requireContext() - val intent = SupportUtils.createCustomTabIntent( - context, - SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS), - ) - startActivity(intent) - null - } - resources.getString(R.string.pref_key_debug_settings) -> { - SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment() - } - resources.getString(R.string.pref_key_secret_debug_info) -> { - SettingsFragmentDirections.actionSettingsFragmentToSecretInfoSettingsFragment() + + resources.getString(R.string.pref_key_data_choices) -> { + SettingsFragmentDirections.actionSettingsFragmentToDataChoicesFragment() } - resources.getString(R.string.pref_key_nimbus_experiments) -> { - SettingsFragmentDirections.actionSettingsFragmentToNimbusExperimentsFragment() + + /* Advanced preferences */ + resources.getString(R.string.pref_key_addons) -> { + Addons.openAddonsInSettings.record(mozilla.components.service.glean.private.NoExtras()) + SettingsFragmentDirections.actionSettingsFragmentToAddonsFragment() } + + // Only displayed when secret settings are enabled resources.getString(R.string.pref_key_install_local_addon) -> { addonFilePicker.launch() null } + + // Only displayed when secret settings are enabled resources.getString(R.string.pref_key_override_amo_collection) -> { val context = requireContext() - val dialogView = LayoutInflater.from(context).inflate(R.layout.amo_collection_override_dialog, null) + val dialogView = LayoutInflater.from(context) + .inflate(R.layout.amo_collection_override_dialog, null) val binding = AmoCollectionOverrideDialogBinding.bind(dialogView) AlertDialog.Builder(context).apply { @@ -409,7 +378,8 @@ class SettingsFragment : PreferenceFragmentCompat() { setPositiveButton(R.string.customize_addon_collection_ok) { _, _ -> context.settings().overrideAmoUser = binding.customAmoUser.text.toString() - context.settings().overrideAmoCollection = binding.customAmoCollection.text.toString() + context.settings().overrideAmoCollection = + binding.customAmoCollection.text.toString() Toast.makeText( context, @@ -434,6 +404,51 @@ class SettingsFragment : PreferenceFragmentCompat() { null } + + resources.getString(R.string.pref_key_open_links_in_apps) -> { + SettingsFragmentDirections.actionSettingsFragmentToOpenLinksInAppsFragment() + } + + resources.getString(R.string.pref_key_sync_debug) -> { + SettingsFragmentDirections.actionSettingsFragmentToSyncDebugFragment() + } + + /* About preferences */ + resources.getString(R.string.pref_key_rate) -> { + try { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(SupportUtils.RATE_APP_URL))) + } catch (e: ActivityNotFoundException) { + // Device without the play store installed. + // Opening the play store website. + (activity as HomeActivity).openToBrowserAndLoad( + searchTermOrURL = SupportUtils.FENIX_PLAY_STORE_URL, + newTab = true, + from = BrowserDirection.FromSettings, + ) + } + null + } + + resources.getString(R.string.pref_key_about) -> { + SettingsFragmentDirections.actionSettingsFragmentToAboutFragment() + } + + // Only displayed when secret settings are enabled + resources.getString(R.string.pref_key_debug_settings) -> { + SettingsFragmentDirections.actionSettingsFragmentToSecretSettingsFragment() + } + + // Only displayed when secret settings are enabled + resources.getString(R.string.pref_key_secret_debug_info) -> { + SettingsFragmentDirections.actionSettingsFragmentToSecretInfoSettingsFragment() + } + + // Only displayed when secret settings are enabled + resources.getString(R.string.pref_key_nimbus_experiments) -> { + SettingsFragmentDirections.actionSettingsFragmentToNimbusExperimentsFragment() + } + + // Only displayed when secret settings are enabled resources.getString(R.string.pref_key_start_profiler) -> { if (profilerViewModel.getProfilerState().value == true) { SettingsFragmentDirections.actionSettingsFragmentToStopProfilerDialog() @@ -441,6 +456,7 @@ class SettingsFragment : PreferenceFragmentCompat() { SettingsFragmentDirections.actionSettingsFragmentToStartProfilerDialog() } } + else -> null } directions?.let { navigateFromSettings(directions) } diff --git a/app/src/main/java/org/mozilla/fenix/settings/search/SearchStringValidator.kt b/app/src/main/java/org/mozilla/fenix/settings/search/SearchStringValidator.kt index 5249dcd17..0ae278057 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/search/SearchStringValidator.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/search/SearchStringValidator.kt @@ -28,7 +28,7 @@ object SearchStringValidator { } // read the response stream to ensure the body is closed correctly. workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=1603114 - response.body.close() + response.close() return if (response.isSuccess || isTestQueryParamNotFound(response.status) ) { diff --git a/app/src/main/java/org/mozilla/fenix/shopping/middleware/ReviewQualityCheckNavigationMiddleware.kt b/app/src/main/java/org/mozilla/fenix/shopping/middleware/ReviewQualityCheckNavigationMiddleware.kt index 91b846fce..aaa1c4673 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/middleware/ReviewQualityCheckNavigationMiddleware.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/middleware/ReviewQualityCheckNavigationMiddleware.kt @@ -13,7 +13,8 @@ import org.mozilla.fenix.shopping.store.ReviewQualityCheckState private const val POWERED_BY_URL = "https://www.fakespot.com/review-checker?utm_source=review-checker" + "&utm_campaign=fakespot-by-mozilla&utm_medium=inproduct&utm_term=core-sheet" -private const val PRIVACY_POLICY_URL = "https://www.fakespot.com/privacy-policy" +private const val PRIVACY_POLICY_URL = "https://www.mozilla.org/en-US/privacy/firefox/#review-checker" + + "?utm_source=review-checker&utm_campaign=privacy-policy&utm_medium=in-product&utm_term=opt-in-screen" private const val TERMS_OF_USE_URL = "https://www.fakespot.com/terms" /** diff --git a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt index e5c53777b..0ab8bca52 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckContextualOnboarding.kt @@ -61,7 +61,7 @@ fun ReviewQualityCheckContextualOnboarding( val learnMoreText = stringResource(id = R.string.review_quality_check_contextual_onboarding_learn_more_link) val privacyPolicyText = - stringResource(id = R.string.review_quality_check_contextual_onboarding_privacy_policy) + stringResource(id = R.string.review_quality_check_contextual_onboarding_privacy_policy_3) val termsOfUseText = stringResource(id = R.string.review_quality_check_contextual_onboarding_terms_use) val titleContentDescription = @@ -113,9 +113,10 @@ fun ReviewQualityCheckContextualOnboarding( LinkText( text = stringResource( - id = R.string.review_quality_check_contextual_onboarding_caption, - stringResource(id = R.string.shopping_product_name), + id = R.string.review_quality_check_contextual_onboarding_caption_4, + stringResource(id = R.string.firefox), privacyPolicyText, + stringResource(id = R.string.shopping_product_name), termsOfUseText, ), linkTextStates = listOf( diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt index cff61af7d..cfa020a33 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTray.kt @@ -626,5 +626,6 @@ private fun generateFakeSyncedTab(tabName: String, tabUrl: String): SyncedTabsLi history = listOf(TabEntry(tabName, tabUrl, null)), active = 0, lastUsed = 0L, + inactive = false, ), ) diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt index 2779acc4f..13e9c1d4c 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayBanner.kt @@ -13,12 +13,9 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.Icon import androidx.compose.material.IconButton -import androidx.compose.material.LocalContentAlpha -import androidx.compose.material.LocalContentColor import androidx.compose.material.Tab import androidx.compose.material.TabRow import androidx.compose.material.Text @@ -35,27 +32,22 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.semantics.testTag -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import mozilla.components.browser.state.state.ContentState import mozilla.components.browser.state.state.TabSessionState import mozilla.components.lib.state.ext.observeAsComposableState -import mozilla.components.ui.tabcounter.TabCounter import org.mozilla.fenix.R import org.mozilla.fenix.compose.Banner import org.mozilla.fenix.compose.BottomSheetHandle import org.mozilla.fenix.compose.ContextualMenu import org.mozilla.fenix.compose.Divider import org.mozilla.fenix.compose.MenuItem +import org.mozilla.fenix.compose.TabCounter import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.tabstray.ext.getMenuItems import org.mozilla.fenix.theme.FirefoxTheme @@ -232,7 +224,7 @@ private fun SingleSelectBanner( selectedContentColor = selectedColor, unselectedContentColor = inactiveColor, ) { - NormalTabsTabIcon(normalTabCount = normalTabCount) + TabCounter(tabCount = normalTabCount) } Tab( @@ -293,85 +285,6 @@ private fun SingleSelectBanner( } } -private const val MAX_VISIBLE_TABS = 99 -private const val SO_MANY_TABS_OPEN = "∞" -private val NORMAL_TABS_BOTTOM_PADDING = 0.5.dp -private const val ONE_DIGIT_SIZE_RATIO = 0.5f -private const val TWO_DIGITS_SIZE_RATIO = 0.4f - -@Composable -@Suppress("MagicNumber") -private fun NormalTabsTabIcon(normalTabCount: Int) { - val normalTabCountText: String - val tabCountTextRatio: Float - val needsBottomPaddingForInfiniteTabs: Boolean - - when (normalTabCount) { - in 0..9 -> { - normalTabCountText = normalTabCount.toString() - tabCountTextRatio = ONE_DIGIT_SIZE_RATIO - needsBottomPaddingForInfiniteTabs = false - } - - in 10..MAX_VISIBLE_TABS -> { - normalTabCountText = normalTabCount.toString() - tabCountTextRatio = TWO_DIGITS_SIZE_RATIO - needsBottomPaddingForInfiniteTabs = false - } - - else -> { - normalTabCountText = SO_MANY_TABS_OPEN - tabCountTextRatio = ONE_DIGIT_SIZE_RATIO - needsBottomPaddingForInfiniteTabs = true - } - } - - val normalTabsContentDescription = if (normalTabCount == 1) { - stringResource(id = R.string.mozac_tab_counter_open_tab_tray_single) - } else { - stringResource( - id = R.string.mozac_tab_counter_open_tab_tray_plural, - normalTabCount.toString(), - ) - } - - val counterBoxWidthDp = - dimensionResource(id = mozilla.components.ui.tabcounter.R.dimen.mozac_tab_counter_box_width_height) - val counterBoxWidthPx = LocalDensity.current.run { counterBoxWidthDp.roundToPx() } - val counterTabsTextSize = (tabCountTextRatio * counterBoxWidthPx).toInt() - - val normalTabsTextModifier = if (needsBottomPaddingForInfiniteTabs) { - val bottomPadding = with(LocalDensity.current) { counterTabsTextSize.toDp() / 4 } - Modifier.padding(bottom = bottomPadding) - } else { - Modifier.padding(bottom = NORMAL_TABS_BOTTOM_PADDING) - } - - Box( - modifier = Modifier - .semantics(mergeDescendants = true) { - testTag = TabsTrayTestTag.normalTabsCounter - }, - contentAlignment = Alignment.Center, - ) { - Icon( - painter = painterResource( - id = mozilla.components.ui.tabcounter.R.drawable.mozac_ui_tabcounter_box, - ), - contentDescription = normalTabsContentDescription, - ) - - Text( - text = normalTabCountText, - modifier = normalTabsTextModifier, - color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current), - fontSize = with(LocalDensity.current) { counterTabsTextSize.toDp().toSp() }, - fontWeight = FontWeight.W700, - textAlign = TextAlign.Center, - ) - } -} - /** * Banner displayed in multi select mode. * @@ -470,7 +383,7 @@ private fun TabsTrayBannerPreview() { @Composable private fun TabsTrayBannerInfinityPreview() { TabsTrayBannerPreviewRoot( - normalTabCount = TabCounter.MAX_VISIBLE_TABS + 1, + normalTabCount = 200, ) } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayTabLayouts.kt b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayTabLayouts.kt index 9d8e32404..2ad848576 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayTabLayouts.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/TabsTrayTabLayouts.kt @@ -94,6 +94,7 @@ fun TabLayout( tabs.forEachIndexed { index, tab -> if (tab.id == selectedTabId) { selectedTabIndex = index + return@forEachIndexed } } } diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabSorter.kt b/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabSorter.kt index 8ad653c27..7f7c62d15 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabSorter.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/browser/TabSorter.kt @@ -6,12 +6,12 @@ package org.mozilla.fenix.tabstray.browser import mozilla.components.browser.state.state.TabPartition import mozilla.components.browser.state.state.TabSessionState +import mozilla.components.browser.state.state.isActive import mozilla.components.browser.tabstray.TabsTray import mozilla.components.feature.tabs.tabstray.TabsFeature import org.mozilla.fenix.ext.maxActiveTime import org.mozilla.fenix.tabstray.TabsTrayAction import org.mozilla.fenix.tabstray.TabsTrayStore -import org.mozilla.fenix.tabstray.ext.isActive import org.mozilla.fenix.utils.Settings /** diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt b/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt index 5fb9f02d6..7419aa65b 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/ext/TabSessionState.kt @@ -5,14 +5,9 @@ package org.mozilla.fenix.tabstray.ext import mozilla.components.browser.state.state.TabSessionState +import mozilla.components.browser.state.state.isActive import mozilla.components.support.ktx.kotlin.trimmed -fun TabSessionState.isActive(maxActiveTime: Long): Boolean { - val lastActiveTime = maxOf(lastAccess, createdAt) - val now = System.currentTimeMillis() - return (now - lastActiveTime <= maxActiveTime) -} - /** * Returns true if the [TabSessionState] has a search term. */ diff --git a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabs.kt b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabs.kt index 489914cd8..fe3976044 100644 --- a/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabs.kt +++ b/app/src/main/java/org/mozilla/fenix/tabstray/syncedtabs/SyncedTabs.kt @@ -309,5 +309,6 @@ private fun generateFakeTab(tabName: String, tabUrl: String): SyncedTabsListItem history = listOf(TabEntry(tabName, tabUrl, null)), active = 0, lastUsed = 0L, + inactive = false, ), ) diff --git a/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt b/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt index 3b448bdb4..53c1fc8fe 100644 --- a/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt +++ b/app/src/main/java/org/mozilla/fenix/telemetry/TelemetryMiddleware.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.telemetry import android.content.Context +import mozilla.components.browser.state.action.AwesomeBarAction import mozilla.components.browser.state.action.BrowserAction import mozilla.components.browser.state.action.ContentAction import mozilla.components.browser.state.action.DownloadAction @@ -25,6 +26,7 @@ import mozilla.telemetry.glean.internal.TimerId import mozilla.telemetry.glean.private.NoExtras import org.mozilla.fenix.Config import org.mozilla.fenix.GleanMetrics.Addons +import org.mozilla.fenix.GleanMetrics.Awesomebar import org.mozilla.fenix.GleanMetrics.Events import org.mozilla.fenix.GleanMetrics.Metrics import org.mozilla.fenix.components.metrics.Event @@ -59,7 +61,7 @@ class TelemetryMiddleware( private val logger = Logger("TelemetryMiddleware") - @Suppress("TooGenericExceptionCaught", "ComplexMethod", "NestedBlockDepth") + @Suppress("TooGenericExceptionCaught", "ComplexMethod", "NestedBlockDepth", "LongMethod") override fun invoke( context: MiddlewareContext, next: (BrowserAction) -> Unit, @@ -144,6 +146,13 @@ class TelemetryMiddleware( is ExtensionsProcessAction.DisabledAction -> { Addons.extensionsProcessUiDisable.add() } + is AwesomeBarAction.EngagementFinished -> { + if (action.abandoned) { + Awesomebar.abandonment.record() + } else { + Awesomebar.engagement.record() + } + } else -> { // no-op } diff --git a/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt b/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt index 458a23dc5..2bdc1467a 100644 --- a/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt +++ b/app/src/main/java/org/mozilla/fenix/theme/FirefoxTheme.kt @@ -104,7 +104,7 @@ private val darkColorPalette = FirefoxColors( layerWarning = PhotonColors.Yellow70A77, layerConfirmation = PhotonColors.Green80, layerError = PhotonColors.Pink80, - layerInfo = PhotonColors.Blue50A80, + layerInfo = PhotonColors.Blue50, actionPrimary = PhotonColors.Violet60, actionSecondary = PhotonColors.LightGrey30, actionTertiary = PhotonColors.DarkGrey10, @@ -112,7 +112,7 @@ private val darkColorPalette = FirefoxColors( actionWarning = PhotonColors.Yellow40A41, actionConfirmation = PhotonColors.Green70, actionError = PhotonColors.Pink70A69, - actionInfo = PhotonColors.Blue30, + actionInfo = PhotonColors.Blue60, formDefault = PhotonColors.LightGrey05, formSelected = PhotonColors.Violet40, formSurface = PhotonColors.DarkGrey05, diff --git a/app/src/main/java/org/mozilla/fenix/translations/TranslationsBottomSheet.kt b/app/src/main/java/org/mozilla/fenix/translations/TranslationsBottomSheet.kt index c598677aa..efab01c24 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/TranslationsBottomSheet.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/TranslationsBottomSheet.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp +import mozilla.components.concept.engine.translate.Language import mozilla.components.concept.engine.translate.TranslationError import org.mozilla.fenix.theme.FirefoxTheme @@ -127,25 +128,36 @@ internal fun TranslationsOptionsAnimation( } @Composable +@Suppress("LongParameterList") internal fun TranslationsDialog( learnMoreUrl: String, showFirstTimeTranslation: Boolean, + translateFromLanguages: List?, + translateToLanguages: List?, + initialFrom: Language? = null, + initialTo: Language? = null, translationError: TranslationError? = null, onSettingClicked: () -> Unit, onLearnMoreClicked: () -> Unit, onTranslateButtonClick: () -> Unit, onNotNowButtonClick: () -> Unit, + onFromSelected: (Language) -> Unit, + onToSelected: (Language) -> Unit, ) { TranslationsDialogBottomSheet( learnMoreUrl = learnMoreUrl, showFirstTimeTranslation = showFirstTimeTranslation, translationError = translationError, - translateFromLanguages = getTranslateFromLanguageList(), - translateToLanguages = getTranslateToLanguageList(), + translateFromLanguages = translateFromLanguages, + translateToLanguages = translateToLanguages, + initialFrom = initialFrom, + initialTo = initialTo, onSettingClicked = onSettingClicked, onLearnMoreClicked = onLearnMoreClicked, onTranslateButtonClicked = onTranslateButtonClick, onNotNowButtonClicked = onNotNowButtonClick, + onFromSelected = onFromSelected, + onToSelected = onToSelected, ) } diff --git a/app/src/main/java/org/mozilla/fenix/translations/TranslationsController.kt b/app/src/main/java/org/mozilla/fenix/translations/TranslationsController.kt deleted file mode 100644 index f29014ae8..000000000 --- a/app/src/main/java/org/mozilla/fenix/translations/TranslationsController.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.translations - -import mozilla.components.browser.state.selector.findTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.concept.engine.translate.DetectedLanguages -import mozilla.components.concept.engine.translate.TranslationOptions -import mozilla.components.feature.session.SessionUseCases -import mozilla.components.support.base.log.logger.Logger - -/** - * Manages requests to complete operations with other components. - * - * @param translationUseCase The use case for performing a translation. - * @param browserStore The browser store to use for this controller. - * @param tabId The tab to perform operations or complete requests for. - */ -class TranslationsController( - private val translationUseCase: SessionUseCases.TranslateUseCase, - private val browserStore: BrowserStore, - private val tabId: String, - -) { - private val logger = Logger("TranslationsController") - - /** - * Retrieves detected information about the language on the browser page, the user's preferred - * language, and if the detected page language is supported. - * - * @return The [DetectedLanguages] object that contains page and user preference information. - */ - fun getDetectedLanguages(): DetectedLanguages? { - logger.info("Retrieving translations language support from the browser store.") - return browserStore.state.findTab(tabId)?.translationsState?.translationEngineState?.detectedLanguages - } - - /** - * Translates the page on the given [tabId]. Will fallback to default expectations if - * [fromLanguage] and [toLanguage] are not provided. - * - * @param tabId The ID of the tab to translate. - * @param fromLanguage The BCP-47 language code to translate from. If null, the default will - * be set to the page language. - * @param toLanguage The BCP-47 language code to translate to. If null, the default will - * be set to the user's preferred language. - * @param options Optional options to specify and additional criteria for the translation. - */ - fun translate( - tabId: String?, - fromLanguage: String?, - toLanguage: String?, - options: TranslationOptions?, - ) { - if (fromLanguage != null && toLanguage != null) { - logger.info("Requesting a translation.") - translationUseCase.invoke(tabId, fromLanguage, toLanguage, options) - return - } - - // Fallback to find defaults - var defaultFromLanguage = fromLanguage - var defaultToLanguage = toLanguage - val detectedLanguages = getDetectedLanguages() - - if (defaultFromLanguage == null) { - defaultFromLanguage = detectedLanguages?.documentLangTag - logger.info("Setting translating to use a default 'from' of $defaultFromLanguage.") - } - - if (defaultToLanguage == null) { - defaultToLanguage = detectedLanguages?.userPreferredLangTag - logger.info("Setting translating to use a default 'to' of $defaultToLanguage.") - } - - if (defaultFromLanguage != null && defaultToLanguage != null) { - logger.info("Requesting a translation based on defaults.") - translationUseCase.invoke(tabId, defaultFromLanguage, defaultToLanguage, options) - return - } - } -} diff --git a/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogBottomSheet.kt b/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogBottomSheet.kt index ce75ba701..18b1f11cf 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogBottomSheet.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogBottomSheet.kt @@ -69,26 +69,34 @@ private val ICON_SIZE = 24.dp * * @param learnMoreUrl The learn more link for translations website. * @param showFirstTimeTranslation Whether translations first flow should be shown. - * @param translationError The type of translation errors that can occur. * @param translateFromLanguages Translation menu items to be shown in the translate from dropdown. * @param translateToLanguages Translation menu items are to be shown in the translate to dropdown. + * @param initialFrom The initial selection for the translate from dropdown. + * @param initialTo The initial selection for the translate to dropdown. + * @param translationError The type of translation errors that can occur. * @param onSettingClicked Invoked when the user clicks on the settings button. * @param onLearnMoreClicked Invoked when the user clicks on the "Learn More" button. * @param onTranslateButtonClicked Invoked when the user clicks on the "Translate" button. * @param onNotNowButtonClicked Invoked when the user clicks on the "Not Now" button. + * @param onFromSelected Invoked when the user selects an item on the from dropdown. + * @param onToSelected Invoked when the user selects an item on the to dropdown. */ @Composable @Suppress("LongParameterList") fun TranslationsDialogBottomSheet( learnMoreUrl: String, showFirstTimeTranslation: Boolean, + translateFromLanguages: List?, + translateToLanguages: List?, + initialFrom: Language? = null, + initialTo: Language? = null, translationError: TranslationError? = null, - translateFromLanguages: List, - translateToLanguages: List, onSettingClicked: () -> Unit, onLearnMoreClicked: () -> Unit, onTranslateButtonClicked: () -> Unit, onNotNowButtonClicked: () -> Unit, + onFromSelected: (Language) -> Unit, + onToSelected: (Language) -> Unit, ) { var orientation by remember { mutableIntStateOf(Configuration.ORIENTATION_PORTRAIT) } @@ -127,12 +135,18 @@ fun TranslationsDialogBottomSheet( Spacer(modifier = Modifier.height(14.dp)) - if (translationError !is TranslationError.CouldNotLoadLanguagesError) { + if (translationError !is TranslationError.CouldNotLoadLanguagesError && + translateFromLanguages != null && translateToLanguages != null + ) { when (orientation) { Configuration.ORIENTATION_LANDSCAPE -> { TranslationsDialogContentInLandscapeMode( translateFromLanguages = translateFromLanguages, translateToLanguages = translateToLanguages, + initialFrom = initialFrom, + initialTo = initialTo, + onFromSelected = onFromSelected, + onToSelected = onToSelected, ) } @@ -140,6 +154,10 @@ fun TranslationsDialogBottomSheet( TranslationsDialogContentInPortraitMode( translateFromLanguages = translateFromLanguages, translateToLanguages = translateToLanguages, + initialFrom = initialFrom, + initialTo = initialTo, + onFromSelected = onFromSelected, + onToSelected = onToSelected, ) } } @@ -159,12 +177,19 @@ fun TranslationsDialogBottomSheet( private fun TranslationsDialogContentInPortraitMode( translateFromLanguages: List, translateToLanguages: List, + initialFrom: Language? = null, + initialTo: Language? = null, + onFromSelected: (Language) -> Unit, + onToSelected: (Language) -> Unit, + ) { Column { TranslationsDropdown( header = stringResource(id = R.string.translations_bottom_sheet_translate_from), modifier = Modifier.fillMaxWidth(), translateLanguages = translateFromLanguages, + initiallySelected = initialFrom, + onLanguageSelection = onFromSelected, ) Spacer(modifier = Modifier.height(16.dp)) @@ -173,6 +198,8 @@ private fun TranslationsDialogContentInPortraitMode( header = stringResource(id = R.string.translations_bottom_sheet_translate_to), modifier = Modifier.fillMaxWidth(), translateLanguages = translateToLanguages, + initiallySelected = initialTo, + onLanguageSelection = onToSelected, ) } } @@ -181,6 +208,10 @@ private fun TranslationsDialogContentInPortraitMode( private fun TranslationsDialogContentInLandscapeMode( translateFromLanguages: List, translateToLanguages: List, + initialFrom: Language? = null, + initialTo: Language? = null, + onFromSelected: (Language) -> Unit, + onToSelected: (Language) -> Unit, ) { Column { Row { @@ -189,6 +220,8 @@ private fun TranslationsDialogContentInLandscapeMode( modifier = Modifier.weight(1f), isInLandscapeMode = true, translateLanguages = translateFromLanguages, + initiallySelected = initialFrom, + onLanguageSelection = onFromSelected, ) Spacer(modifier = Modifier.width(16.dp)) @@ -198,6 +231,8 @@ private fun TranslationsDialogContentInLandscapeMode( modifier = Modifier.weight(1f), isInLandscapeMode = true, translateLanguages = translateToLanguages, + initiallySelected = initialTo, + onLanguageSelection = onToSelected, ) } } @@ -318,23 +353,29 @@ private fun TranslationsDialogInfoMessage( } } +/** + * Creates a dropdown with language selection to use to select languages for translation. + * + * @param header The title of the dropdown. + * @param translateLanguages The language choices the dropdown should provide. + * @param modifier Any modifiers for the component. + * @param isInLandscapeMode If the item should layout for landscape mode. + * @param initiallySelected The language initially selected, if null will show "Choose a language". + * @param onLanguageSelection Callback for the selected language. + */ @Composable private fun TranslationsDropdown( header: String, translateLanguages: List, modifier: Modifier = Modifier, isInLandscapeMode: Boolean = false, + initiallySelected: Language? = null, + onLanguageSelection: (Language) -> Unit, ) { val density = LocalDensity.current var expanded by remember { mutableStateOf(false) } - var selectedLanguage by remember { - mutableStateOf( - translateLanguages.last().localizedDisplayName, - ) - } - var contextMenuWidthDp by remember { mutableStateOf(0.dp) } @@ -355,15 +396,18 @@ private fun TranslationsDropdown( Spacer(modifier = Modifier.height(4.dp)) + var initialValue = stringResource(R.string.translations_bottom_sheet_default_dropdown_selection) + initiallySelected?.localizedDisplayName?.let { + initialValue = it + } + Row { - selectedLanguage?.let { - Text( - text = it, - modifier = Modifier.weight(1f), - color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.subtitle1, - ) - } + Text( + text = initialValue, + modifier = Modifier.weight(1f), + color = FirefoxTheme.colors.textPrimary, + style = FirefoxTheme.typography.subtitle1, + ) Spacer(modifier = Modifier.width(10.dp)) @@ -379,10 +423,12 @@ private fun TranslationsDropdown( onDismissRequest = { expanded = false }, - menuItems = getContextMenuItems(translateLanguages = translateLanguages) { - expanded = false - selectedLanguage = it.localizedDisplayName - }, + + menuItems = getContextMenuItems( + translateLanguages = translateLanguages, + onClickItem = onLanguageSelection, + ), + modifier = Modifier .onGloballyPositioned { coordinates -> contextMenuWidthDp = with(density) { @@ -505,10 +551,14 @@ private fun TranslationsDialogBottomSheetPreview() { translationError = TranslationError.LanguageNotSupportedError(null), translateFromLanguages = getTranslateFromLanguageList(), translateToLanguages = getTranslateToLanguageList(), + initialFrom = null, + initialTo = null, onSettingClicked = {}, onLearnMoreClicked = {}, onTranslateButtonClicked = {}, onNotNowButtonClicked = {}, + onToSelected = {}, + onFromSelected = {}, ) } } @@ -518,14 +568,14 @@ internal fun getTranslateFromLanguageList(): List { return mutableListOf().apply { add( Language( - code = Locale.CHINA.toLanguageTag(), - localizedDisplayName = Locale.CHINA.displayLanguage, + code = Locale.ENGLISH.toLanguageTag(), + localizedDisplayName = Locale.ENGLISH.displayLanguage, ), ) add( Language( - code = Locale.ENGLISH.toLanguageTag(), - localizedDisplayName = Locale.ENGLISH.displayLanguage, + code = Locale.FRENCH.toLanguageTag(), + localizedDisplayName = Locale.FRENCH.displayLanguage, ), ) add( @@ -536,8 +586,8 @@ internal fun getTranslateFromLanguageList(): List { ) add( Language( - code = Locale.JAPANESE.toLanguageTag(), - localizedDisplayName = Locale.JAPANESE.displayLanguage, + code = Locale.ITALIAN.toLanguageTag(), + localizedDisplayName = Locale.ITALIAN.displayLanguage, ), ) } @@ -548,14 +598,8 @@ internal fun getTranslateToLanguageList(): List { return mutableListOf().apply { add( Language( - code = Locale.KOREAN.toLanguageTag(), - localizedDisplayName = Locale.KOREAN.displayLanguage, - ), - ) - add( - Language( - code = Locale.CANADA.toLanguageTag(), - localizedDisplayName = Locale.CANADA.displayLanguage, + code = Locale.ENGLISH.toLanguageTag(), + localizedDisplayName = Locale.ENGLISH.displayLanguage, ), ) add( @@ -566,14 +610,14 @@ internal fun getTranslateToLanguageList(): List { ) add( Language( - code = Locale.ITALY.toLanguageTag(), - localizedDisplayName = Locale.ITALY.displayLanguage, + code = Locale.GERMAN.toLanguageTag(), + localizedDisplayName = Locale.GERMAN.displayLanguage, ), ) add( Language( - code = Locale.GERMAN.toLanguageTag(), - localizedDisplayName = Locale.GERMAN.displayLanguage, + code = Locale.ITALIAN.toLanguageTag(), + localizedDisplayName = Locale.ITALIAN.displayLanguage, ), ) } diff --git a/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogFragment.kt b/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogFragment.kt index 78c0cd73a..e94bc22ce 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/TranslationsDialogFragment.kt @@ -23,6 +23,13 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import mozilla.components.browser.state.action.TranslationsAction +import mozilla.components.browser.state.selector.findTab +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.engine.translate.TranslationOperation +import mozilla.components.concept.engine.translate.initialFromLanguage +import mozilla.components.concept.engine.translate.initialToLanguage +import mozilla.components.lib.state.ext.observeAsComposableState import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R @@ -45,7 +52,7 @@ class TranslationsDialogFragment : BottomSheetDialogFragment() { private var behavior: BottomSheetBehavior? = null private val args by navArgs() - private lateinit var interactor: TranslationsInteractor + private val browserStore: BrowserStore by lazy { requireComponents.core.store } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = super.onCreateDialog(savedInstanceState).apply { @@ -63,18 +70,41 @@ class TranslationsDialogFragment : BottomSheetDialogFragment() { container: ViewGroup?, savedInstanceState: Bundle?, ): View = ComposeView(requireContext()).apply { - interactor = TranslationsInteractor( - translationsController = TranslationsController( - translationUseCase = requireComponents.useCases.sessionUseCases.translate, - browserStore = requireComponents.core.store, + // Signalling need to fetch languages + browserStore.dispatch( + TranslationsAction.OperationRequestedAction( tabId = args.sessionId, + operation = TranslationOperation.FETCH_SUPPORTED_LANGUAGES, ), ) setContent { + val translationsState = browserStore.observeAsComposableState { + state -> + state.findTab(args.sessionId) + ?.translationsState + }.value + + var fromSelected by remember { + mutableStateOf( + translationsState?.translationEngineState + ?.initialFromLanguage(translationsState.supportedLanguages?.fromLanguages), + ) + } + + var toSelected by remember { + mutableStateOf( + translationsState?.translationEngineState + ?.initialToLanguage(translationsState.supportedLanguages?.toLanguages), + ) + } + FirefoxTheme { var translationsVisibility by remember { - mutableStateOf(args.translationsDialogAccessPoint == TranslationsDialogAccessPoint.Translations) + mutableStateOf( + args.translationsDialogAccessPoint == + TranslationsDialogAccessPoint.Translations, + ) } var translationsHeightDp by remember { @@ -115,6 +145,10 @@ class TranslationsDialogFragment : BottomSheetDialogFragment() { TranslationsDialog( learnMoreUrl = learnMoreUrl, showFirstTimeTranslation = context.settings().showFirstTimeTranslation, + translateFromLanguages = translationsState?.supportedLanguages?.fromLanguages, + translateToLanguages = translationsState?.supportedLanguages?.toLanguages, + initialFrom = fromSelected, + initialTo = toSelected, onSettingClicked = { translationsVisibility = false }, @@ -126,14 +160,24 @@ class TranslationsDialogFragment : BottomSheetDialogFragment() { ) }, onTranslateButtonClick = { - interactor.onTranslate( - tabId = args.sessionId, - fromLanguage = null, - toLanguage = null, - null, - ) + fromSelected?.code?.let { fromLanguage -> + toSelected?.code?.let { toLanguage -> + TranslationsAction.TranslateAction( + tabId = args.sessionId, + fromLanguage = fromLanguage, + toLanguage = toLanguage, + options = null, + ) + } + }?.let { + browserStore.dispatch( + it, + ) + } }, onNotNowButtonClick = { dismiss() }, + onFromSelected = { fromSelected = it }, + onToSelected = { toSelected = it }, ) } } diff --git a/app/src/main/java/org/mozilla/fenix/translations/TranslationsInteractor.kt b/app/src/main/java/org/mozilla/fenix/translations/TranslationsInteractor.kt deleted file mode 100644 index cf98bd616..000000000 --- a/app/src/main/java/org/mozilla/fenix/translations/TranslationsInteractor.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.translations - -import mozilla.components.concept.engine.translate.DetectedLanguages -import mozilla.components.concept.engine.translate.TranslationOptions -import mozilla.components.support.base.log.logger.Logger - -/** - * Manages coordinating the functionality interactions for use in the views. - * - * @param translationsController The translations controller that requests data and - * interactions. - */ -class TranslationsInteractor( - private val translationsController: TranslationsController, -) { - private val logger = Logger("TranslationsInteractor") - - /** - * Retrieves the [DetectedLanguages] applicable to the page. - * - * @return The [DetectedLanguages] object that contains page and user preference information. - */ - fun detectedLanguages(): DetectedLanguages? { - logger.info("Requesting translations language support from the controller.") - return translationsController.getDetectedLanguages() - } - - /** - * Translates the page on the given [tabId]. - * If null is provided for [fromLanguage] or [toLanguage], the engine will attempt to - * find a sensible default. - * - * @param tabId The ID of the tab to translate. - * @param fromLanguage The BCP-47 language code to translate from. Usually will be the detected - * page language. If set as null, will revert to a default page language, if known. - * @param toLanguage The BCP-47 language code to translate to. Usually will be the user's - * preferred language. If set as null, will revert to a default of the user's preferred - * language, if known. - * @param options Optional options to specify and additional criteria for the translation. - */ - fun onTranslate( - tabId: String?, - fromLanguage: String?, - toLanguage: String?, - options: TranslationOptions?, - ) { - logger.info("Requesting a translation from the controller.") - translationsController.translate(tabId, fromLanguage, toLanguage, options) - } -} diff --git a/app/src/main/java/org/mozilla/fenix/translations/preferences/automatic/AutomaticTranslationPreference.kt b/app/src/main/java/org/mozilla/fenix/translations/preferences/automatic/AutomaticTranslationPreference.kt index a267d249b..4ce45c4e2 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/preferences/automatic/AutomaticTranslationPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/preferences/automatic/AutomaticTranslationPreference.kt @@ -78,25 +78,25 @@ internal fun getAutomaticTranslationListPreferences(): List().apply { add( AutomaticTranslationItemPreference( - displayName = Locale.CANADA.displayName, + displayName = Locale.ENGLISH.displayLanguage, automaticTranslationOptionPreference = AutomaticTranslationOptionPreference.AlwaysTranslate(), ), ) add( AutomaticTranslationItemPreference( - displayName = Locale.FRANCE.displayName, + displayName = Locale.FRENCH.displayLanguage, automaticTranslationOptionPreference = AutomaticTranslationOptionPreference.OfferToTranslate(), ), ) add( AutomaticTranslationItemPreference( - displayName = Locale.GERMANY.displayName, + displayName = Locale.GERMAN.displayLanguage, automaticTranslationOptionPreference = AutomaticTranslationOptionPreference.NeverTranslate(), ), ) add( AutomaticTranslationItemPreference( - displayName = Locale.CHINA.displayName, + displayName = Locale.ITALIAN.displayLanguage, automaticTranslationOptionPreference = AutomaticTranslationOptionPreference.AlwaysTranslate(), ), ) diff --git a/app/src/main/java/org/mozilla/fenix/translations/preferences/downloadlanguages/DownloadLanguagesPreference.kt b/app/src/main/java/org/mozilla/fenix/translations/preferences/downloadlanguages/DownloadLanguagesPreference.kt index 7089d3d1e..aaf9976e7 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/preferences/downloadlanguages/DownloadLanguagesPreference.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/preferences/downloadlanguages/DownloadLanguagesPreference.kt @@ -386,11 +386,11 @@ internal fun getLanguageListPreference(): List { DownloadLanguageItemPreference( languageModel = TranslationsController.RuntimeTranslation.LanguageModel( TranslationsController.Language( - Locale.CHINA.toLanguageTag(), - Locale.CHINA.displayLanguage, + Locale.FRENCH.toLanguageTag(), + Locale.FRENCH.displayLanguage, ), false, - 4000, + 30000000, ), state = DownloadLanguageItemStatePreference( type = DownloadLanguageItemTypePreference.GeneralLanguage, @@ -402,28 +402,11 @@ internal fun getLanguageListPreference(): List { DownloadLanguageItemPreference( languageModel = TranslationsController.RuntimeTranslation.LanguageModel( TranslationsController.Language( - Locale.KOREAN.toLanguageTag(), - Locale.KOREAN.displayLanguage, + Locale.GERMAN.toLanguageTag(), + Locale.GERMAN.displayLanguage, ), false, - 3000, - ), - state = DownloadLanguageItemStatePreference( - type = DownloadLanguageItemTypePreference.GeneralLanguage, - status = DownloadLanguageItemStatusPreference.NotDownloaded, - ), - ), - ) - - add( - DownloadLanguageItemPreference( - languageModel = TranslationsController.RuntimeTranslation.LanguageModel( - TranslationsController.Language( - Locale.FRANCE.toLanguageTag(), - Locale.FRANCE.displayLanguage, - ), - false, - 2000, + 30000000, ), state = DownloadLanguageItemStatePreference( type = DownloadLanguageItemTypePreference.GeneralLanguage, @@ -439,7 +422,7 @@ internal fun getLanguageListPreference(): List { Locale.ITALIAN.displayLanguage, ), false, - 1000, + 30000000, ), state = DownloadLanguageItemStatePreference( type = DownloadLanguageItemTypePreference.GeneralLanguage, @@ -455,7 +438,7 @@ internal fun getLanguageListPreference(): List { Locale.ENGLISH.displayLanguage, ), true, - 3000, + 30000000, ), state = DownloadLanguageItemStatePreference( type = DownloadLanguageItemTypePreference.PivotLanguage, @@ -463,22 +446,6 @@ internal fun getLanguageListPreference(): List { ), ), ) - add( - DownloadLanguageItemPreference( - languageModel = TranslationsController.RuntimeTranslation.LanguageModel( - TranslationsController.Language( - Locale.JAPANESE.toLanguageTag(), - Locale.JAPANESE.displayLanguage, - ), - true, - 3000, - ), - state = DownloadLanguageItemStatePreference( - type = DownloadLanguageItemTypePreference.GeneralLanguage, - status = DownloadLanguageItemStatusPreference.NotDownloaded, - ), - ), - ) add( DownloadLanguageItemPreference( languageModel = TranslationsController.RuntimeTranslation.LanguageModel( @@ -487,7 +454,7 @@ internal fun getLanguageListPreference(): List { stringResource(id = R.string.download_language_all_languages_item_preference), ), true, - 300000, + 90000000, ), state = DownloadLanguageItemStatePreference( type = DownloadLanguageItemTypePreference.AllLanguages, diff --git a/app/src/main/java/org/mozilla/fenix/translations/preferences/nevertranslatesite/NeverTranslateSitePreference.kt b/app/src/main/java/org/mozilla/fenix/translations/preferences/nevertranslatesite/NeverTranslateSitePreference.kt index 76f521c5c..e8cf6c1a4 100644 --- a/app/src/main/java/org/mozilla/fenix/translations/preferences/nevertranslatesite/NeverTranslateSitePreference.kt +++ b/app/src/main/java/org/mozilla/fenix/translations/preferences/nevertranslatesite/NeverTranslateSitePreference.kt @@ -82,12 +82,7 @@ internal fun getNeverTranslateListItemsPreference(): List().apply { add( NeverTranslateSiteListItemPreference( - websiteUrl = "expedia.ca", - ), - ) - add( - NeverTranslateSiteListItemPreference( - websiteUrl = "wikipedia.com", + websiteUrl = "mozilla.org", ), ) } diff --git a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt index 1e49927de..f7863727b 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/Settings.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/Settings.kt @@ -767,6 +767,11 @@ class Settings(private val appContext: Context) : PreferencesHolder { true, ) + val useProductionRemoteSettingsServer by booleanPreference( + key = appContext.getPreferenceKey(R.string.pref_key_remote_server_prod), + default = true, + ) + val enabledTotalCookieProtection: Boolean get() = mr2022Sections[Mr2022Section.TCP_FEATURE] == true @@ -1497,7 +1502,7 @@ class Settings(private val appContext: Context) : PreferencesHolder { var isPullToRefreshEnabledInBrowser by booleanPreference( appContext.getPreferenceKey(R.string.pref_key_website_pull_to_refresh), - default = Config.channel.isNightlyOrDebug, + default = true, ) var isDynamicToolbarEnabled by booleanPreference( @@ -1707,23 +1712,6 @@ class Settings(private val appContext: Context) : PreferencesHolder { default = setOf(), ) - /** - * Indicates if notification pre permission prompt feature is enabled. - */ - var notificationPrePermissionPromptEnabled by lazyFeatureFlagPreference( - key = appContext.getPreferenceKey(R.string.pref_key_notification_pre_permission_prompt_enabled), - default = { FxNimbus.features.prePermissionNotificationPrompt.value().enabled }, - featureFlag = true, - ) - - /** - * Indicates if notification permission prompt has been shown to the user. - */ - var isNotificationPrePermissionShown by booleanPreference( - key = appContext.getPreferenceKey(R.string.pref_key_is_notification_pre_permission_prompt_shown), - default = false, - ) - /** * Returns whether onboarding should be shown to the user. * diff --git a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperDownloader.kt b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperDownloader.kt index 2beff12a7..c0f72944c 100644 --- a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperDownloader.kt +++ b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperDownloader.kt @@ -73,11 +73,13 @@ class WallpaperDownloader( val request = Request( url = "$remoteHost/$remotePath", method = Request.Method.GET, + conservative = true, ) return@withContext Result.runCatching { val response = client.fetch(request) if (!response.isSuccess) { + response.close() throw IllegalStateException() } localFile.parentFile?.mkdirs() diff --git a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcher.kt b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcher.kt index 96a50ee57..74b24f954 100644 --- a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcher.kt +++ b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcher.kt @@ -32,7 +32,7 @@ class WallpaperMetadataFetcher( */ suspend fun downloadWallpaperList(): List = withContext(Dispatchers.IO) { Result.runCatching { - val request = Request(url = metadataUrl, method = Request.Method.GET) + val request = Request(url = metadataUrl, method = Request.Method.GET, conservative = true) val response = client.fetch(request) response.body.useBufferedReader { val json = it.readText() diff --git a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpapersUseCases.kt b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpapersUseCases.kt index 8d9eb7077..cdb70c163 100644 --- a/app/src/main/java/org/mozilla/fenix/wallpapers/WallpapersUseCases.kt +++ b/app/src/main/java/org/mozilla/fenix/wallpapers/WallpapersUseCases.kt @@ -5,14 +5,13 @@ package org.mozilla.fenix.wallpapers import android.content.Context +import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.BitmapFactory -import androidx.annotation.UiContext import androidx.annotation.VisibleForTesting import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import mozilla.components.concept.fetch.Client -import mozilla.components.support.utils.ext.isLandscape import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.appstate.AppAction import org.mozilla.fenix.ext.settings @@ -160,25 +159,25 @@ class WallpapersUseCases( /** * Load the bitmap for a [wallpaper], if available. * - * @param context The context used to get wallpaper orientation. * @param wallpaper The wallpaper to load a bitmap for. + * @param orientation The orientation of wallpaper. */ - suspend operator fun invoke(@UiContext context: Context, wallpaper: Wallpaper): Bitmap? + suspend operator fun invoke(wallpaper: Wallpaper, orientation: Int): Bitmap? } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal class DefaultLoadBitmapUseCase( private val getFilesDir: suspend () -> File, ) : LoadBitmapUseCase { - override suspend fun invoke(@UiContext context: Context, wallpaper: Wallpaper): Bitmap? = - loadWallpaperFromDisk(context, wallpaper) + override suspend fun invoke(wallpaper: Wallpaper, orientation: Int): Bitmap? = + loadWallpaperFromDisk(wallpaper, orientation) @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal suspend fun loadWallpaperFromDisk( - @UiContext context: Context, wallpaper: Wallpaper, + orientation: Int, ): Bitmap? = Result.runCatching { - val path = wallpaper.getLocalPathFromContext(context) + val path = wallpaper.getLocalPathFromContext(orientation) withContext(Dispatchers.IO) { val file = File(getFilesDir(), path) BitmapFactory.decodeStream(file.inputStream()) @@ -189,13 +188,13 @@ class WallpapersUseCases( * Get the expected local path on disk for a wallpaper. This will differ depending * on orientation and app theme. */ - private fun Wallpaper.getLocalPathFromContext(@UiContext context: Context): String { - val orientation = if (context.isLandscape()) { + private fun Wallpaper.getLocalPathFromContext(orientation: Int): String { + val orientationWallpaper = if (orientation == Configuration.ORIENTATION_LANDSCAPE) { Wallpaper.ImageType.Landscape } else { Wallpaper.ImageType.Portrait } - return Wallpaper.getLocalPath(name, orientation) + return Wallpaper.getLocalPath(name, orientationWallpaper) } } diff --git a/app/src/main/res/drawable/ic_onboarding_key_features.xml b/app/src/main/res/drawable/ic_onboarding_key_features.xml new file mode 100644 index 000000000..c5eeaffcf --- /dev/null +++ b/app/src/main/res/drawable/ic_onboarding_key_features.xml @@ -0,0 +1,423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml b/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml new file mode 100644 index 000000000..820fd340e --- /dev/null +++ b/app/src/main/res/drawable/ic_onboarding_key_features_icons_only.xml @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_add_on_details.xml b/app/src/main/res/layout/fragment_add_on_details.xml index 457ae4689..1ab400991 100644 --- a/app/src/main/res/layout/fragment_add_on_details.xml +++ b/app/src/main/res/layout/fragment_add_on_details.xml @@ -32,7 +32,9 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="20dp" + android:gravity="center" + android:minHeight="48dp" + android:layout_marginTop="10dp" android:text="@string/mozac_feature_addons_author" app:layout_constraintEnd_toStartOf="@+id/author_text" app:layout_constraintHorizontal_chainStyle="spread_inside" @@ -44,18 +46,20 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:gravity="center" + android:minHeight="48dp" android:layout_alignParentEnd="true" - android:layout_marginTop="20dp" + android:layout_marginTop="10dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/author_label" app:layout_constraintTop_toBottomOf="@+id/details" + android:importantForAccessibility="no" tools:text="@tools:sample/full_names" /> @@ -100,7 +106,8 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dp" + android:gravity="center" + android:minHeight="48dp" android:text="@string/mozac_feature_addons_last_updated" app:layout_constraintEnd_toStartOf="@+id/last_updated_text" app:layout_constraintHorizontal_chainStyle="spread_inside" @@ -112,17 +119,18 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dp" + android:gravity="center" + android:minHeight="48dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/last_updated_label" app:layout_constraintTop_toBottomOf="@+id/version_divider" + android:importantForAccessibility="no" tools:text="Oct 16, 2019" /> @@ -132,7 +140,10 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dp" + android:gravity="center" + android:minHeight="48dp" + android:clickable="true" + android:focusable="true" android:text="@string/mozac_feature_addons_home_page" android:textColor="?textAccent" app:layout_constraintStart_toStartOf="parent" @@ -142,7 +153,6 @@ android:id="@+id/home_page_divider" android:layout_width="match_parent" android:layout_height="1dp" - android:layout_marginTop="10dp" android:background="?android:attr/listDivider" android:importantForAccessibility="no" app:layout_constraintTop_toBottomOf="@+id/home_page_label" /> @@ -151,7 +161,6 @@ android:id="@+id/rating" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="10dp" app:layout_constraintTop_toBottomOf="@+id/home_page_divider"> @@ -208,7 +222,10 @@ style="@style/AboutHeaderContentText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="10dp" + android:gravity="center" + android:minHeight="48dp" + android:clickable="true" + android:focusable="true" android:text="@string/mozac_feature_addons_more_info_link" android:textColor="?textAccent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index 11a149c4e..f3815ca3c 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -43,10 +43,6 @@ android:id="@+id/action_global_home_onboarding_dialog" app:destination="@id/homeOnboardingDialogFragment" /> - - - - diff --git a/app/src/main/res/raw/initial_experiments.json b/app/src/main/res/raw/initial_experiments.json index 1d486af1d..bf0615994 100644 --- a/app/src/main/res/raw/initial_experiments.json +++ b/app/src/main/res/raw/initial_experiments.json @@ -223,32 +223,36 @@ }, { "schemaVersion": "1.12.0", - "slug": "beta-fx-122-android-set-to-default-notifications-timing-experiment", - "id": "beta-fx-122-android-set-to-default-notifications-timing-experiment", + "slug": "android-optimize-set-as-default-browser-screen-release", + "id": "android-optimize-set-as-default-browser-screen-release", "arguments": {}, - "application": "org.mozilla.firefox", + "application": "org.mozilla.firefox_beta", "appName": "fenix", "appId": "org.mozilla.firefox", "channel": "release", - "userFacingName": "Fx 122 Android set to default notifications timing experiment", - "userFacingDescription": "Timing test for the set to default message on Firefox for Android (Fenix).", - "isEnrollmentPaused": true, + "userFacingName": "Android - Optimize “Set as Default Browser” Screen Release", + "userFacingDescription": "This experiment is designed to optimize the set-to-default browser experience on Android.", + "isEnrollmentPaused": false, "isRollout": false, "bucketConfig": { "randomizationUnit": "nimbus_id", - "namespace": "fenix-messaging-release-19", + "namespace": "fenix-juno-onboarding-release-6", "start": 0, "count": 10000, "total": 10000 }, "featureIds": [ - "messaging" + "juno-onboarding" ], "probeSets": [], "outcomes": [ { - "slug": "default-browser", + "slug": "onboarding", "priority": "primary" + }, + { + "slug": "default-browser", + "priority": "secondary" } ], "branches": [ @@ -262,19 +266,28 @@ }, "features": [ { - "featureId": "messaging", + "featureId": "juno-onboarding", + "enabled": true, + "value": {} + } + ] + }, + { + "slug": "treatment-a", + "ratio": 1, + "feature": { + "featureId": "this-is-included-for-mobile-pre-96-support", + "enabled": false, + "value": {} + }, + "features": [ + { + "featureId": "juno-onboarding", "enabled": true, "value": { - "messages": { - "{experiment}-en": { - "is-control": true, - "surface": "notification", - "style": "NOTIFICATION", - "action": "MAKE_DEFAULT_BROWSER", - "trigger": [ - "I_AM_NOT_DEFAULT_BROWSER" - ], - "experiment": "{experiment}" + "cards": { + "default-browser": { + "enabled": false } } } @@ -282,7 +295,7 @@ ] }, { - "slug": "treatment-a", + "slug": "treatment-b", "ratio": 1, "feature": { "featureId": "this-is-included-for-mobile-pre-96-support", @@ -291,21 +304,13 @@ }, "features": [ { - "featureId": "messaging", + "featureId": "juno-onboarding", "enabled": true, "value": { - "messages": { - "{experiment}-en": { - "title": "Firefox is Fast and Private", - "text": "Make Firefox your default browser", - "surface": "notification", - "style": "NOTIFICATION", - "action": "MAKE_DEFAULT_BROWSER", - "trigger": [ - "DAY_1_AFTER_INSTALL", - "I_AM_NOT_DEFAULT_BROWSER" - ], - "experiment": "{experiment}" + "cards": { + "default-browser": { + "title": "juno_onboarding_default_browser_title_nimbus_3", + "body": "juno_onboarding_default_browser_description_nimbus_4" } } } @@ -313,7 +318,7 @@ ] }, { - "slug": "treatment-b", + "slug": "treatment-c", "ratio": 1, "feature": { "featureId": "this-is-included-for-mobile-pre-96-support", @@ -322,21 +327,14 @@ }, "features": [ { - "featureId": "messaging", + "featureId": "juno-onboarding", "enabled": true, "value": { - "messages": { - "{experiment}-en": { - "title": "Firefox is Fast and Private", - "text": "Make Firefox your default browser", - "surface": "notification", - "style": "NOTIFICATION", - "action": "MAKE_DEFAULT_BROWSER", - "trigger": [ - "DAY_3_AFTER_INSTALL", - "I_AM_NOT_DEFAULT_BROWSER" - ], - "experiment": "{experiment}" + "cards": { + "default-browser": { + "title": "juno_onboarding_default_browser_title_nimbus_4", + "body": "", + "image-res": "ic_onboarding_key_features" } } } @@ -344,7 +342,7 @@ ] }, { - "slug": "treatment-c", + "slug": "treatment-d", "ratio": 1, "feature": { "featureId": "this-is-included-for-mobile-pre-96-support", @@ -353,42 +351,175 @@ }, "features": [ { - "featureId": "messaging", + "featureId": "juno-onboarding", "enabled": true, "value": { - "messages": { - "{experiment}-en": { - "title": "Firefox is Fast and Private", - "text": "Make Firefox your default browser", - "surface": "notification", - "style": "NOTIFICATION", - "action": "MAKE_DEFAULT_BROWSER", - "trigger": [ - "DAY_6_AFTER_INSTALL", - "I_AM_NOT_DEFAULT_BROWSER" - ], - "experiment": "{experiment}" + "cards": { + "default-browser": { + "title": "juno_onboarding_default_browser_title_nimbus_4", + "body": "juno_onboarding_default_browser_description_nimbus_5", + "image-res": "ic_onboarding_key_features_icons_only" } - }, - "triggers": { - "DAY_6_AFTER_INSTALL": "days_since_install == 6" } } } ] } ], - "targeting": "((is_already_enrolled) || ((isFirstRun == 'true') && (app_version|versionCompare('122.!') >= 0) && (language in ['en'])))", - "startDate": "2024-01-23", - "enrollmentEndDate": "2024-02-14", + "targeting": "((is_already_enrolled) || ((isFirstRun == 'true') && (app_version|versionCompare('124.!') >= 0) && (language in ['en'])))", + "startDate": "2024-03-12", + "enrollmentEndDate": null, "endDate": null, - "proposedDuration": 43, - "proposedEnrollment": 14, + "proposedDuration": 35, + "proposedEnrollment": 21, "referenceBranch": "control", "featureValidationOptOut": false, "localizations": null, "locales": null, - "publishedDate": null + "publishedDate": "2024-03-12T15:23:02.314682Z" + }, + { + "schemaVersion": "1.12.0", + "slug": "splash-screen-max-duration-test-lower-times", + "id": "splash-screen-max-duration-test-lower-times", + "arguments": {}, + "application": "org.mozilla.firefox", + "appName": "fenix", + "appId": "org.mozilla.firefox", + "channel": "release", + "userFacingName": "Splash screen max duration test - lower times", + "userFacingDescription": "Testing a splashscreen on app launch.", + "isEnrollmentPaused": false, + "isRollout": false, + "bucketConfig": { + "randomizationUnit": "nimbus_id", + "namespace": "fenix-splash-screen-release-3", + "start": 0, + "count": 10000, + "total": 10000 + }, + "featureIds": [ + "no-feature-fenix" + ], + "probeSets": [], + "outcomes": [], + "branches": [ + { + "slug": "onboarding", + "priority": "primary" + }, + { + "slug": "default-browser", + "priority": "primary" + } + ], + "targeting": "((is_already_enrolled) || ((app_version|versionCompare('123.!') >= 0)))", + "startDate": "2024-01-25", + "enrollmentEndDate": null, + "endDate": null, + "proposedDuration": 60, + "proposedEnrollment": 30, + "referenceBranch": "holdback", + "featureValidationOptOut": false, + "localizations": null, + "locales": null, + "publishedDate": "2024-01-25T17:36:03.153458Z" + }, + { + "schemaVersion": "1.12.0", + "slug": "android-long-term-holdback-validation-first-run-sub-experiment", + "id": "android-long-term-holdback-validation-first-run-sub-experiment", + "arguments": {}, + "application": "org.mozilla.firefox_beta", + "appName": "fenix", + "appId": "org.mozilla.firefox_beta", + "channel": "beta", + "userFacingName": "Android Long-term Holdback Validation - First-run Sub-Experiment", + "userFacingDescription": "This is an internal test of new experiment tooling", + "isEnrollmentPaused": false, + "isRollout": false, + "bucketConfig": { + "randomizationUnit": "nimbus_id", + "namespace": "fenix-nimbus-is-ready-beta-1", + "start": 0, + "count": 10000, + "total": 10000 + }, + "featureIds": [ + "nimbus-is-ready" + ], + "probeSets": [], + "outcomes": [], + "branches": [ + { + "slug": "control", + "ratio": 1, + "feature": { + "featureId": "this-is-included-for-mobile-pre-96-support", + "enabled": false, + "value": {} + }, + "features": [ + { + "featureId": "nimbus-is-ready", + "enabled": true, + "value": { + "enabled": true, + "maximum_duration_ms": 0 + } + } + ] + }, + { + "slug": "treatment-a", + "ratio": 1, + "feature": { + "featureId": "this-is-included-for-mobile-pre-96-support", + "enabled": false, + "value": {} + }, + "features": [ + { + "featureId": "splash-screen", + "enabled": true, + "value": { + "enabled": true, + "maximum_duration_ms": 1750 + } + } + ] + }, + { + "slug": "treatment-b", + "ratio": 1, + "feature": { + "featureId": "this-is-included-for-mobile-pre-96-support", + "enabled": false, + "value": {} + }, + "features": [ + { + "featureId": "nimbus-is-ready", + "enabled": true, + "value": { + "enabled": true, + "maximum_duration_ms": 2500 + } + } + ] + } + ], + "targeting": "((is_already_enrolled) || ((isFirstRun == 'true') && (app_version|versionCompare('124.!') >= 0) && (region in ['AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW'])))", + "startDate": "2024-03-13", + "enrollmentEndDate": null, + "endDate": null, + "proposedDuration": 56, + "proposedEnrollment": 28, + "referenceBranch": "control", + "featureValidationOptOut": false, + "localizations": null, + "locales": null, + "publishedDate": "2024-03-13T15:04:41.938148Z" } ] } diff --git a/app/src/main/res/raw/keep.xml b/app/src/main/res/raw/keep.xml index c19db331d..9a17666f9 100644 --- a/app/src/main/res/raw/keep.xml +++ b/app/src/main/res/raw/keep.xml @@ -1,3 +1,3 @@ + tools:keep="@drawable/onboarding_ctd_default_browser,@drawable-night/onboarding_ctd_default_browser,@drawable/onboarding_ctd_sync,@drawable/onboarding_ctd_notification,@drawable/ic_onboarding_key_features.xml,@drawable/ic_onboarding_key_features_icons_only.xml" /> diff --git a/app/src/main/res/values-azb/strings.xml b/app/src/main/res/values-azb/strings.xml index 1c5e4b0c8..eaf9def6d 100644 --- a/app/src/main/res/values-azb/strings.xml +++ b/app/src/main/res/values-azb/strings.xml @@ -544,7 +544,7 @@ اؤزل دؤنگل سرور - موْزیلا حسابیْ/دؤنگل سروری دگیشدیریلدی. دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیخیلیر... + موْزیلا حسابیْ/دؤنگل سروری دگیشدیریلدی. دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیخیلیر… حساب @@ -611,9 +611,16 @@ خاریجی یئندیرمه موْدیری. + + Gecko قیدلرینی گوجلندیر + + دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیْخیلیر… + تاخیلان‌لار + + تاخیلانیْ فایل‌دان قوْش بیلدیریش‌لر @@ -621,21 +628,111 @@ ایجازه وئریلمه‌دی + + + اؤزل تاخیْلان مجموعه‌سی تامام لغو + + مجموعه آدیْ + + مجموعه صاحیبی (قوللانیجیْ آیدی‌سی) + + تاخیْلان مجموعه‌‌سی ایصلاح اوْلدوُ. دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیْخیلیر… + + + + قاباقکی تاغ‌لارا قاییت + + سوْن بوکمارک‌لار + + سون باخیلان‌لار + + + دوشوندوروجو ناغیل‌لار + + %sطرفیندن گوج آلینان مقاله‌لر + + اسپانسرلی ناغیل‌لار + + + دال پرده‌لر + + + اسپانسرلی شوْرتکات‌لار + + + + دال پرده: %1$s + + دال پرده گونجللندی! + + گؤستر + + دال پرده یئندیریلنمه‌دی + + گئنه چالیش + + دال پرده دگیشیله بیلمه‌دی آرتیق بیلین + + کلاسیک %s + + + هونرمند سئری‌سی + + باغیْمسیز سس‌لر مجموعه‌سی. %s + + + باغیْمسیز سس‌لر مجموعه‌سی. + + بیر رنگ سپمه‌سی ایمتیحان ائله‌یین + + سیزینله دانیشان بیر دال پرده سئچین. + + داها چوْخ دال پرده‌لری آراشدیْرین + + + + ایندی یئنی تاخیْلان‌لار وار + + فایرفاکسیْ اؤزوُنوز ائتمک ایمکانیْ وئرن 100 دن چوْخ یئنی اوُزانتیا باخیْن. + + تاخیلان‌لاریْ آراشدیْر + + + + تاخیلان‌لار گئچیجی اوْلاراق گوُجدن سالیْنمیش. + + + بیر و یا نئچه تاخیْلانین ایشی دایاندیریلدیْ، بوُدا سیستمیزی ثابیتسیز ائله‌دی. %1$s تاخیلانی(لاریْ) یئنی‌دن باشلاتماغا باشاریْسیز اوْلدو. \n\n تاخیلانلار ایندیکی اوتورومونوزدا یئنی‌دن ایشه سالیْنمیاجاق. \n\n تاخیلانی(لار)ین سیلینمه‌سی و یا ایشدن سالینماسیْ بو موُشکولو حل ائلیه بیلر. + + تاخیلان‌لاریْ یئنی‌دن باشلاتماغا چالیْشین + + تاخیلان‌لاریْ گوُجسوز ائتمه‌گه ایدامه وئرین + + + + حساب مودیریتی + + رمزینیزی دگیشدیرین، دیتا یئغمایی ایداره ائدین ویا حسابینیزی سیلین. ایندی دؤنگل‌لندیر + + نه‌یین دؤنگل ائدیله‌جه‌گینی سئچین گئچمیش بوُکمارک‌لار + + گیریش‌لر رمز‌لر @@ -643,6 +740,82 @@ چیخیش + + جهاز آدی + + جهاز آدیْ بوْش اوْلمالیدیر + + دؤنگل‌لنیر… + + دؤنگل خطا وئردی. سوْن باشاریْ: %s + + + دؤنگل خطا وئردی. سوْن دؤنگل: یوْخدور + + سوْن دؤنگل: %s + + + سوْن دؤنگل: هئچ + + + %1$s - %2$s %3$s + + اعتباری کارتلار + + + اؤدمه آپاری‌ْلاری + + آدرس‌لر + + + + آلیْنان تاغ‌لار + + آیریْ فایرفاکس جهازلاریندان آلینان تاغلارا اوچون بیلدیریش‌لر + + تاغ آلیندیْ + + + %s-دن آلینان تاغ + + + + آیریْ توُتمالار + + بوتون سایتلار اوچون آچیْن + + آیری‌ْ توتمالار سئچیلمیش سایتلار اوچون ایزلنمه قوْروماسینیْ ایشدن سالماغا ایمکان وئریر. + + آرتیق بیلین + + + ایشه آلما و فنی دیتالار + + %1$s داها یاخچیْ ائتمک اوچون موُروچونوز حاقیندا ایشله‌ییش،ایشه آلما، دوْنانیم و اؤزللشدیرمه دیتالارینی موزیلا ایله پایلاشیر. + + بازارلاما دیتاسیْ + + اساس ایشه آلما بیلگی‌لرینی موبایل بازارلاما ایش اوْرتاغیمیز Adjust ایله پایلاشیر. + + آراشدیرمالار + + + موزیلایا آراشدیرمالار قوْشماغینا و ایجرا ائتمه‌سینه ایجازه وئریر. + + + + دیتالارینیزیْ دؤنگل ائدین و ساخلایین + + یئنی‌دن باغلانماق اوچون گیریش ائدین + + حساب قالدیْر + + + + firefox.com/pair آدرسینه گؤرونن QR کوْدونو اسکن ائله‌یین]]> + اوست @@ -657,6 +830,9 @@ باتری ساخلیان طرفیندن تنظیم‌لنیر + + جهاز تمینی نظره آل + رفرش اوچون چک @@ -664,6 +840,11 @@ آلت‌لر چوبوغونو گیزلتمک اوچون اسکرول ائله‌ + + تاغ‌لاریْ دگیشدیرمک اوچون ادوات چوُبوغونو یانالار طرف چکین + + تاغ‌لاریْ آچماق اوچون ادوات چوُبوغونو یوخاریا چکین + یئندیرنلر @@ -671,6 +852,507 @@ بوُکمارک‌لار + + دستکتاپ بوکمارک‌لاریْ + + بوکمارک منوسو + + بوکمارک‌لار ادوات چوبوغو + + باشقا بوکمارک‌لار + + گئچمیش + + یئنی تاغ + + تنظیم‌‎لر + + باغلا + + + %d آچیلسین؟ + + چوْخلو تاغ‌لاریْن آچیلماسیْ صفحه‌لر دوْلورکن %s سوُرعتینی یاواشلاتا بیلر. ایدامه وئرمه‌گه آرخایینسیز؟ + + تاغ‌لاریْ آچ + + لغو + + + %d صفحه + + %d صفحه‌ + + + سوْن باغلانان تاغ‌لار + + بوتون گئچمیشی گؤستر + + %d تاغ + + %d تاغ + + بو یاخین زاماندا باغلانان تاغ یوخ + + + + تاغ‌لار + + تاغ گؤروُنوشو + + لیست + + شبکه‌لی + + تاغ‌لاریْ باغلا + + هئچ زامان + + + بیر گوندن سوْنرا + + بیر هفته‌دن سوْنرا + + بیر آیدان سوْنرا + + آچیق تاغلاریْ اوْتوماتیک باغلا + + + + آچیلیش اکرانی + + آنایارپاق + + + سوْن تاغ + + دؤرد ساعاتلیق حرکتسیزلیکدن سونرا آچیلان اصلی صفحه + + ال‌ ایله باغلاییْن + + + بیر گۆندن سوْنرا باغلایین + + + بیر هفته سونرا باغلا + + بیر آی سونرا باغلا + + آنایارپاق‌دا آچ + + سون تاغدا آچ + + دؤرد ساعاتدان سونرا آنایارپاق‌دا آچ + + + + کؤهنه تاغلاری ایشده اولمایان تاغا آپار + + ایکی هفته‌ده باخمادیغینیز تاغلار ایشده اولمایان بؤلومه آپاریلیر. + + + + قالدیر + + + + ایشده + + + %1$s ایمکانی وار هردن بیر آراشدیرمالاری نصب ائلیه و چالیشدیرا. + + آرتیق بیلین + + + دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیخاجاق + + تامام + + لغو + + دگیشمه‌لری یئرینه سالماق اوچون اپلیکیشن‌دن چیْخیلیر… + + + + آچیْق تاغ‌لار + + گیزلی تاغ‌لار + + دؤنگل‌لنمیش تاغ‌لار + + تاغ آرتیر + + گیزلی تاغ آرتیر + + گیزلی + + دؤنگل + + بوتون تاغ‌لاری پایلاش + + سوْن باغلانان تاغ‌لار + + سون باغلانان‌لار + + حساب تنظیم‌لری + + تاغ تنظیم‌لری + + بوتون تاغ‌لاریْ باغلا + + بوکمارک + + باغلا + + + سئچیلمیش تاغ‌لاری پایلاش + + سئچیلن تاغ‌لار منوسو + + تاغی مجموعه‌دن چیخار + + تاغ‌لاری سئچین + + تاغی باغلا + + %s تاغی باغلا + + آچیق تاغ‌لار منوسونو آچ + + تاغ‌لاریْ مجموعه‌ده ساخلاییْن + + مجموعه‌نی سیل + + + مجموعه‌نی یئنی‌دن آدلاندیْر + + تاغ‌لاریْ آچ + + مجموعه آدیْ + + یئنی‌دن آدلاندیْر + + قالدیر + + گئچمیش‌دن سیل + + + %1$s (گیزلی حالت) + + + + آختاریش شرطلرینی گیر + + گئچمیشی سیل + + گئچمیش سیلیندی + + %1$s سیلیندی + + سیل + + %1$d سئچیلیدی + + بوگون + + دوُنن + + سوْن 7 گون + + سوْن 30 گون + + + + داها قدیمی + + گئچمیش یوخدور + + + + یئندیرمه‌لر فالدیریلدیْ + + %1$s قالدیریلدیْ + + هئچ یئندیریلمیش فایل یوخدور + + %1$d سئچیلیدی + + قالدیر + + + + + باغیشلایین، %1$s بو صفحه‌نی دولدورا بیلمه‌دی. + + + سیْنماق راپورتونو موْزیلایا گؤندر + + تاغی باغلا + + تاغی گئنه آل + + + + بو قوْولوغو سیلمک ایسته‌دیگینیزه آرخایینسیز؟ + + %s سئچیلن موریدلری سیله‌جک. + + لغو + + قوْولوق اکله + + بوکمارک ساخلاندی! + + دوزه‌لیش + + دوزه‌لیش + + + کوْپی + + پایلاش + + + یئنی تاغدا آچ + + گیزلی تاغدا آچ + + هامیْسینی یئنی تاغ‌لاردا آچ + + هامیْسینی گیزلی تاغ‌لاردا آچ + + سیل + + ساخلا + + %1$d سئچیلیدی + + بوکمارک دوز‌ه‌لیشی + + قوْولوق دوزه‌لیشی + + دؤنگل ائدیلن بوکمارک‌لاری گؤرمک اوچون اوْتوروُم آچین + + URL + + قوْولوق + + آد + + قوْولوق اکله + + قوْولوق سئچ + + + بیر عنوان وئرمه‌لیسیز + + گئچرسیز URL + + هئچ بوکمارک بوردا یوخ + + %1$s سیلیندی + + بوکمارک‌لار سیلیندی + + سئچیلن قوْولوق سیلینیر + + لغو + + + آختاریش شرطلرینی گیر + + + + تنظیم‌لره گئدین + + یئیین تنظیم‌لر صفحه‌سی + + توصیه اولموش + + ایجازه‌لری پوز + + تامام + + لغو + + ایجازه‌‌نی پوْز + + + تامام + + لغو + + بوتون سایتلارداکی ایجازه‌لری پوْز + + اؤزاؤزونه چالما + + + کامرا + + میکروفون + + قونوم + + بیلدیریش‌ + + قالیجی ساخلاما + + سایتلار آراسی کوکی‌لر + + DRM ایله کونترول اولونان موحتوا + + + ایجازه ایسته‌یین + + مسدود اوْلوندو + + ایجازه وئریلدی + + اندروید طرفیندن مسدود اوْلوندو + + آیریْ توُتمالار + + + باغلیْ + + استاندارد + + بَرک + + اؤزل + + + سس و ویدئویا ایجازه وئر + + سس و ویدئویا ایجازه وئر + + + یالنیز موبایل سلولاردا سس و ویدئونو بلوْکلا + + سس و ویدئو وایفای‌ اوستونده چالیناجاق + + یالنیز سس مسدودو + + یالنیز سس مسدودو + + سس و ویدئویو مسدود ائله + + سس و ویدئویو مسدود ائله + + آچیق + + باغلیْ + + آچیق + + باغلیْ + + + + مجموعه‌لر + + مجموعه‌لر منوسو + + سیزین اوچون اؤنملی اولان شئی‌لری یئغین. \n داها سوْنرا یئیین گیریش اوچون اوْخشار آختاریش‌لاریْ، سایتلاریْ و تاغ‌لاریْ قروُپلاشدیرین. + + + تاغ‌لاری سئچین + + مجموعه سئچین + + مجموعه‌ آدی + + یئنی مجموعه اکله + + + هامیسینی سئچ + + هامیسینی سئچمه + + ساخلاناجاق تاغ‌لاری سئچ + + %d تاغ سئچیلدی + + %d تاغ سئچیلدی + + تاغ‌لار ساخلاندیْ! + + مجموعه ساخلاندیْ! + + + تاغ ساخلاندیْ! + + باغلا + + ساخلا + + گؤستر + + تامام + + لغو + + + %d مجموعه‌سی + + + + پایلاش + + پایلاش + + PDF اولاراق ساخلا + + PDF یارادیلانمادیْ + + باغلا + + بو صفحه‌ پرینت اوْلانمیر + + پرینت + + جهازا گؤندر + + بوتون عمل‌لر + + یاخین‌دا ایشله‌دیلمیش + + کلیپ‌بوردا کوْپی ائله + + کلیپ‌بوْردا کوْپی اوْلوندو + + دؤنگله گیریش + + دیتا دؤنگلی و ساخلاماسی + + بوتون جهازلارا گؤندر + + دونگلی کَس + + آفلاین + + باشقا جهازا باغلا + + + بیر تاغ گؤندرمک اوچون آزی بیر باشقا جهازدا فایرفاکسا داخیل اوْلون. + + آنلادیم + diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 4351428f7..5cdc0a0a1 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -242,6 +242,7 @@ Уладкаваць хатнюю старонку + Хатні экран @@ -249,6 +250,14 @@ Сцерці гісторыю аглядання + + Перакласці старонку + + + Старонка перакладзена з %1$s на %2$s. + Абраная мова @@ -260,8 +269,6 @@ Сканаваць - - Пашукавік Налады пошукавых сістэм @@ -316,23 +323,36 @@ - Апавяшчэнні дапамогуць вам зрабіць больш з %s + Апавяшчэнні дапамогуць вам зрабіць больш з %s - Сінхранізуйце свае карткі паміж прыладамі, кіруйце сцягваннямі, атрымлівайце парады, як максімальна выкарыстоўваць ахову прыватнасці %s, і многае іншае. + Сінхранізуйце свае карткі паміж прыладамі, кіруйце сцягваннямі, атрымлівайце парады, як максімальна выкарыстоўваць ахову прыватнасці %s, і многае іншае. - Працягнуць + Працягнуць - Не зараз + Не зараз + + Паведамленне аб прыватнасці Firefox + + Даведайцеся больш у нашым паведамленні аб прыватнасці Нам падабаецца забяспечваць вашу бяспеку + + Даведайцеся, чаму мільёны людзей любяць Firefox - Наш браўзер, падтрыманы некамерцыйнай арганізацыяй, дапамагае абмяжоўваць кампаніі ад сачэння за вамі ў Інтэрнэце.\n\nДаведайцеся больш у нашым паведамленні аб прыватнасці. + Наш браўзер, падтрыманы некамерцыйнай арганізацыяй, дапамагае не даваць кампаніям таемна сачыць за вамі ў сеціве. + + Больш за 100 мільёнаў чалавек абараняюць сваю прыватнасць, выбіраючы браўзер, які падтрымліваецца некамерцыйнай арганізацыяй. + + Вядомыя трэкеры? Блакуюцца аўтаматычна. Пашырэнні? Паспрабуйце ўсе 700. PDF? Наш убудаваны чытальнік дазваляе лёгка імі кіраваць. + + Наш браўзер, падтрыманы некамерцыйнай арганізацыяй, дапамагае абмяжоўваць кампаніі ад сачэння за вамі ў Інтэрнэце.\n\nДаведайцеся больш у нашым паведамленні аб прыватнасці. - паведамленні аб прыватнасці + паведамленні аб прыватнасці Зрабіць прадвызначаным браўзерам @@ -435,21 +455,11 @@ Рэжым «Толькі HTTPS» - - Памяншэнне колькасці банераў кукі Блакіроўшчык банераў кукі Блакіроўшчык банераў кукі ў прыватным праглядзе - - Памяншаць колькасць банераў кукі - - Выключана - - Уключана - - - %1$s аўтаматычна спрабуе адхіліць запыты файлаў кукі на банерах кукі. + Выключана для гэтага сайта @@ -468,36 +478,17 @@ Сайт зараз не падтрымліваецца - Уключыць памяншэнне колькасці банераў кукі для %1$s? - Уключыць блакіроўшчык банераў кукі для %1$s? - - Выключыць памяншэнне колькасці банераў кукі для %1$s? Выключыць блакіроўшчык банераў кукі для %1$s? %1$s не можа аўтаматычна адхіляць запыты кукаў на гэтым сайце. Вы можаце адправіць запыт на падтрымку гэтага сайта ў будучыні. - - %1$s выдаліць файлы кукі гэтага сайта і абновіць старонку. Выдаленне ўсіх файлаў кукі можа прывесці да выхаду з сістэмы або ачышчэння кошыка для пакупак. Выключыць, і %1$s выдаліць файлы кукі і перазагрузіць гэты сайт. Гэта можа прывесці да выхаду з уліковага запісу або ачышчэння кошыка. - %1$s спрабуе аўтаматычна адхіляць усе запыты файлаў кукі на сайтах, якія падтрымліваюцца. - Уключыце, і %1$s паспрабуе аўтаматычна адхіляць банеры кукі на гэтым сайце. - - Дазволіць %1$s адхіляць банеры кукі? - - %1$s можа аўтаматычна адхіляць многія запыты банераў кукі. - - Не зараз - - Вы ўбачыце менш запытаў пра кукі - - - Дазволіць %1$s толькі што адмовіўся ад кукі для вас @@ -715,7 +706,9 @@ Закладкі - Лагіны + Лагіны + + Паролі Адкрытыя карткі @@ -741,7 +734,9 @@ %1$s на %2$s %3$s - Крэдытныя карты + Крэдытныя карты + + Спосабы аплаты Адрасы @@ -1285,8 +1280,6 @@ Адхіліць - Немагчыма надрукаваць - Немагчыма надрукаваць гэту старонку Друкаваць @@ -1698,9 +1691,13 @@ Вы можаце лёгка дадаць гэты вэб-сайт на хатні экран вашай прылады, каб мець да яго імгненны доступ і аглядаць хутчэй, нібыта гэта асобная праграма. - Лагіны і паролі + Лагіны і паролі + + Паролі + + Захаванне лагінаў і пароляў - Захаванне лагінаў і пароляў + Захоўваць паролі Пытаць пра захаванне @@ -1715,29 +1712,42 @@ Запаўняць імёны карыстальнікаў і паролі ў іншых праграмах на вашай прыладзе. - Дадаць лагін + Дадаць лагін - - Сінхранізацыя лагінаў + + Дадаць пароль + + + Сінхранізацыя лагінаў + + Сінхранізаваць паролі - Сінхранізаваць лагіны паміж прыладамі + Сінхранізаваць лагіны паміж прыладамі + + Сінхранізаваць паролі паміж прыладамі - Захаваныя лагіны + Захаваныя лагіны + + Захаваныя паролі - Лагіны, якія вы захаваеце альбо сінхранізуеце праз %s, з’явяцца тут. + Лагіны, якія вы захаваеце альбо сінхранізуеце праз %s, з’явяцца тут. - Даведацца больш пра сінхранізацыю. + Даведацца больш пра сінхранізацыю. + + Даведайцеся больш пра сінхранізацыю Выключэнні - Не захаваныя лагіны і паролі з’явяцца тут. + Не захаваныя лагіны і паролі з’явяцца тут. - Лагіны і паролі не будуць захаваны для гэтых сайтаў. + Лагіны і паролі не будуць захаваны для гэтых сайтаў. Выдаліць усе выключэнні - Шукаць лагіны + Шукаць лагіны + + Пошук пароляў Сайт @@ -1766,12 +1776,16 @@ Схаваць пароль - Разблакуйце, каб пабачыць захаваныя лагіны + Разблакуйце, каб пабачыць захаваныя лагіны + + Разблакуйце, каб пабачыць захаваныя паролі - Абараніце свае лагіны і паролі + Абараніце свае лагіны і паролі + + Абараніце захаваныя паролі - Наладзьце графічны ключ, пін ці пароль для блакавання прылады, каб абараніць захаваныя лагіны і паролі ад крадзяжу, калі Вашай прыладай завалодае хтосьці іншы. + Наладзьце графічны ключ, пін ці пароль для блакавання прылады, каб абараніць захаваныя лагіны і паролі ад крадзяжу, калі Вашай прыладай завалодае хтосьці іншы. Пазней @@ -1788,7 +1802,7 @@ Апошняе выкарыстанне - Меню сартавання лагінаў + Меню сартавання лагінаў @@ -1796,30 +1810,40 @@ Адрасы - Крэдытныя карты + Крэдытныя карты + + Спосабы аплаты - Захоўваць і аўтаматычна запаўняць карты + Захоўваць і аўтаматычна запаўняць карты + + Захоўваць і запаўняць спосабы аплаты - Дадзеныя зашыфраваны + Дадзеныя зашыфраваны Сінхранізаваць карты паміж прыладамі Сінхранізаваць карты - Дадаць крэдытную карту + Дадаць крэдытную карту + + Дадаць карту - Кіраванне захаванымі картамі + Кіраванне захаванымі картамі + + Кіраваць картамі Дадаць адрас Кіраваць адрасамі - Захоўваць і аўтаматычна запаўняць адрасы + Захоўваць і аўтаматычна запаўняць адрасы + + Захоўваць і запаўняць адрасы - Уключаць звесткі, такія як нумары, адрасы электроннай пошты і дастаўкі + Уключаць звесткі, такія як нумары, адрасы электроннай пошты і дастаўкі Дадаць карту @@ -1841,7 +1865,9 @@ Выдаліць карту - Вы ўпэўнены, што жадаеце выдаліць гэту крэдытную карту? + Вы ўпэўнены, што жадаеце выдаліць гэту крэдытную карту? + + Выдаліць карту? Выдаліць @@ -1854,16 +1880,22 @@ Захаваныя карты - Калі ласка, увядзіце сапраўдны нумар крэдытнай карты + Калі ласка, увядзіце сапраўдны нумар крэдытнай карты + + Увядзіце сапраўдны нумар карты - Калі ласка, запоўніце гэтае поле + Калі ласка, запоўніце гэтае поле + + Дадайце імя Разблакуйце, каб пабачыць захаваныя карты - Абараніце свае крэдытныя карты + Абараніце свае крэдытныя карты + + Абараніце захаваныя спосабы аплаты - Наладзьце графічны ключ, пін або пароль для блакавання прылады, каб абараніць захаваныя крэдытныя карты, калі хтось іншы атрымае доступ да вашай прылады. + Наладзьце графічны ключ, пін або пароль для блакавання прылады, каб абараніць захаваныя крэдытныя карты, калі хтось іншы атрымае доступ да вашай прылады. Наладзіць зараз @@ -1872,7 +1904,7 @@ Разблакуйце сваю прыладу - Разблакуйце, каб выкарыстаць захаваную інфармацыю крэдытнай карты + Разблакуйце, каб выкарыстаць захаваную інфармацыю крэдытнай карты Дадаць адрас @@ -1881,11 +1913,13 @@ Кіраваць адрасамі - Імя + Імя - Імя па бацьку + Імя па бацьку - Прозвішча + Прозвішча + + Назва Вуліца @@ -1910,7 +1944,9 @@ Выдаліць адрас - Вы ўпэўнены, што жадаеце выдаліць гэты адрас? + Вы ўпэўнены, што жадаеце выдаліць гэты адрас? + + Выдаліць гэты адрас? Выдаліць @@ -2014,31 +2050,53 @@ Змяніць - Вы сапраўды хочаце выдаліць гэтае лагін? + Вы сапраўды хочаце выдаліць гэтае лагін? + + Вы ўпэўнены, што хочаце выдаліць гэты пароль? Выдаліць Адмяніць - Налады лагіна + Налады лагіна + + Параметры пароля - Тэкставае поле для рэдагавання вэб-адраса для ўваходу ў сістэму. + Тэкставае поле для рэдагавання вэб-адраса для ўваходу ў сістэму. + + Тэкставае поле для рэдагавання адраса сайта. - Тэкставае поле для рэдагавання імені карыстальніка для ўваходу ў сістэму. + Тэкставае поле для рэдагавання імені карыстальніка для ўваходу ў сістэму. + + Тэкставае поле для рэдагавання імя карыстальніка. - Тэкставае поле для рэдагавання пароля для ўваходу ў сістэму. + Тэкставае поле для рэдагавання пароля для ўваходу ў сістэму. + + Тэкставае поле для рэдагавання пароля. - Захаваць змены ва ўваходных даных. + Захаваць змены ва ўваходных даных. + + Захаваць змены. - Рэдагаванне + Рэдагаванне + + Змяніць пароль - Дадаць новы лагін + Дадаць новы лагін + + Дадаць пароль - Патрабуецца пароль + Патрабуецца пароль + + Увядзіце пароль + + Патрабуецца імя карыстальніка - Патрабуецца імя карыстальніка + Увядзіце імя карыстальніка Патрабуецца імя хоста + + Увядзіце вэб-адрас Галасавы пошук @@ -2136,6 +2194,9 @@ Пошук %s + + Змяніць прадвызначаны браўзер + Наладзьце аўтаматычнае адкрыццё спасылак з сайтаў, пошты і паведамленняў у Firefox. @@ -2145,7 +2206,7 @@ Пстрыкніце, каб атрымаць падрабязнасці - Перайсці ўверх + Перайсці ўверх Закрыць @@ -2186,7 +2247,7 @@ Скарэктаваны рэйтынг - Ненадзейныя водгукі выдалены + На аснове надзейных водгукаў Асноўныя моманты з апошніх водгукаў @@ -2207,8 +2268,6 @@ Асноўныя моманты з водгукаў пра %s за апошнія 80 дзён, якія мы лічым надзейнымі.]]> Даведайцеся больш пра %s. - - як %s ад Mozilla вызначае якасць водгукаў як %s вызначае якасць водгукаў @@ -2243,10 +2302,8 @@ Калі вы ўбачыце гэты прадукт ізноў у наяўнасці, паведаміце нам пра гэта, і мы будзем правяраць водгукі. Паведаміць, што прадукт ёсць у наяўнасці - - Праверка якасці водгукаў - - Праверка якасці водгукаў + + Праверка якасці водгукаў (%s) Гэта можа заняць каля 60 секунд. @@ -2290,13 +2347,19 @@ Даведацца больш - Выбіраючы «Так, паспрабаваць», вы пагаджаецеся з %2$s і %3$s ад %1$s ад Mozilla. + Выбіраючы «Так, паспрабаваць», вы пагаджаецеся з %2$s і %3$s ад %1$s ад Mozilla. Выбіраючы «Так, паспрабаваць», вы згаджаецеся з наступным ад %1$s: + + Выбіраючы «Так, паспрабаваць», вы пагаджаецеся з %2$s ад %1$s і %4$s ад %3$s. + + Выбіраючы «Так, паспрабаваць», вы пагаджаецеся з %2$s ад %1$s і %4$s ад %3$s. - палітыкай прыватнасці + палітыкай прыватнасці Палітыка прыватнасці + + паведамленні аб прыватнасці ўмовамі выкарыстання @@ -2366,6 +2429,14 @@ Перакласці старонку? + + Старонка перакладзена з %1$s на %2$s + + Паспрабуйце прыватныя пераклады ў %1$s + + Дзеля вашай прыватнасці пераклады ніколі не пакідаюць вашу прыладу. Новыя мовы і паляпшэнні хутка! %1$s Падрабязней @@ -2375,6 +2446,8 @@ Перакласці на Не зараз + + Паказаць арыгінал Гатова @@ -2385,13 +2458,29 @@ Пераклад Ідзе пераклад + + Выбраць мову Узнікла праблема з перакладам. Калі ласка, паспрабуйце яшчэ раз. + + Не ўдалося загрузіць мовы. Праверце інтэрнэт-злучэнне і паўтарыце спробу. На жаль, мы пакуль не падтрымліваем %1$s. Падрабязней + + + Пераклад… + + + + Сцягнуць мову ў рэжыме эканоміі трафіку (%1$s)? + + Параметры перакладу @@ -2403,6 +2492,10 @@ Ніколі не перакладаць %1$s Ніколі не перакладаць гэты сайт + + Перавызначае ўсе іншыя налады + + Перавызначае прапановы перакладу Налады перакладу @@ -2413,6 +2506,8 @@ Пераклады Прапаноўваць пераклад, калі гэта магчыма + + Заўсёды сцягваць мовы ў рэжыме эканоміі трафіку Налады перакладу @@ -2487,6 +2582,8 @@ Скасаваць + + Заўсёды сцягваць у рэжыме эканоміі трафіку Сцягнуць @@ -2511,4 +2608,14 @@ Прыватныя Усяго - + + Інструмент стварэння картак + + Колькасць картак для стварэння + + Дадаць да актыўных картак + + Дадаць да неактыўных картак + + Дадаць да прыватных картак + diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index da30f796d..9bd73cd5b 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -257,6 +257,11 @@ Превеждане на страницатa + + Страницата е преведена от %1$s на %2$s. + Избран език @@ -334,12 +339,22 @@ бележка за поверителността на Firefox - + + Научете повече в нашата политика за поверителност Обичаме да ви пазим в безопасност + + Разберете защо милиони обичат Firefox + + Безопасно сърфиране с повече възможности за избор Нашият браузър с нестопанска цел помага да спрете компаниите да ви следват тайно в мрежата. + Повече от 100 милиона души защитават поверителността си, като избират браузър, поддържан от организация с нестопанска цел. + + Познати тракери? Автоматично блокиране. Разширения? Опитайте всички 700. PDF файлове? Вграденият четец ги прави лесни за управление. + Нашият четец, разработван от организация с нестопанска цел ви помага да не бъдете следени тайно в мрежата.\n\nНаучете повече в нашето съобщение за поверителност. @@ -692,9 +707,9 @@ Отметки - Регистрации + Регистрации - Пароли + Пароли Отворени раздели @@ -719,9 +734,9 @@ %1$s на %2$s %3$s - Банкови карти + Банкови карти - Начини на плащане + Начини на плащане Адреси @@ -1675,13 +1690,13 @@ Можете лесно да добавите тази страница към началния екран, за да имате бърз достъп до нея, подобно на приложение. - Регистрации и пароли + Регистрации и пароли - Пароли + Пароли - Запазване на регистрации и пароли + Запазване на регистрации и пароли - Запазване на пароли + Запазване на пароли Питане за запазване @@ -1696,48 +1711,48 @@ Попълват се потребителски имена и пароли в други приложения на устройството. - Добавяне на регистрация + Добавяне на регистрация - Добавяне на парола + Добавяне на парола - - Синхронизиране на регистрации - Синхронизиране на пароли + Синхронизиране на регистрации + + Синхронизиране на пароли - Синхронизиране на регистрации между устройства + Синхронизиране на регистрации между устройства - Синхронизиране на пароли между устройства + Синхронизиране на пароли между устройства - Запазени регистрации + Запазени регистрации - Запазени пароли + Запазени пароли - Тук се показват нещата, които запазвате или синхронизирате във %s. + Тук се показват нещата, които запазвате или синхронизирате във %s. - Паролите, които запазите или синхронизирате с %s ще бъдат изброени тук. Всички запазени пароли са шифровани. + Паролите, които запазите или синхронизирате с %s ще бъдат изброени тук. Всички запазени пароли са шифровани. - Научете повече за Sync. + Научете повече за Sync. - Научете повече за синхронизирането + Научете повече за синхронизирането Изключения - Тук се показват регистрации и пароли, които не са запазени. + Тук се показват регистрации и пароли, които не са запазени. - %s няма да запазва пароли за сайтове, изброени тук. + %s няма да запазва пароли за сайтове, изброени тук. - Следните страници няма да запазват регистрации и пароли. + Следните страници няма да запазват регистрации и пароли. - %s няма да запази пароли за тези сайтове. + %s няма да запази пароли за тези сайтове. Изтриване на всички - Търсене на регистрация + Търсене на регистрация - Търсене на пароли + Търсене на пароли Страница @@ -1766,17 +1781,17 @@ Скриване на парола - Отключете, за да видите запазените регистрации + Отключете, за да видите запазените регистрации - Отключете, за да видите запазените пароли + Отключете, за да видите запазените пароли - Защитете вашите данни за вход + Защитете вашите данни за вход - Защитете запазените пароли + Защитете запазените пароли - Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените регистрации и пароли, в случай че някой друг има достъп до него. + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените регистрации и пароли, в случай че някой друг има достъп до него. - Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените пароли от достъп, ако някой друг има вашето устройство. + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените пароли от достъп, ако някой друг има вашето устройство. По-късно @@ -1792,7 +1807,10 @@ Последно използване - Меню за сортиране на регистрации + Меню за сортиране на регистрации + + + Меню за сортиране на пароли Меню за сортиране на пароли @@ -1803,41 +1821,44 @@ Адреси - Банкови карти + Банкови карти - Начини на плащане + Начини на плащане - Запазване и автоматично попълване на карти + Запазване и автоматично попълване на карти - Запазване и попълване на начини на плащане + Запазване и попълване на начини на плащане - Данните са криптирани + Данните са криптирани - %s шифрова всички запазени от вас начини на плащане + %s шифрова всички запазени от вас начини на плащане Синхронизиране на карти между устройства Синхронизиране на карти - Добавяне на карта + Добавяне на карта - Добавяне на карта + Добавяне на карта - Управление на карти + Управление на карти - Управление на карти + Управление на карти Добавяне на адрес Управление на адреси - Запазване и попълване на адреси + Запазване и попълване на адреси - Запазване и попълване на адреси + Запазване и попълване на адреси - Включително номера, електронни адреси и адреси за доставка + Включително номера, електронни адреси и адреси за доставка + + + Включва телефонни номера и имейл адреси Включва телефонни номера и имейл адреси @@ -1861,9 +1882,9 @@ Изтриване на картата - Сигурни ли сте, че искате да премахнете тази банкова карта? + Сигурни ли сте, че искате да премахнете тази банкова карта? - Изтриване на картата? + Изтриване на картата? Премахване @@ -1875,23 +1896,23 @@ Запазени карти - Моля, въведете валиден номер на банкова карта + Моля, въведете валиден номер на банкова карта - Въведете валиден номер на карта + Въведете валиден номер на карта - Попълнете полето + Попълнете полето - Добавяне на име + Добавяне на име Отключете, за да видите запазените карти - Защитете банковите си карти + Защитете банковите си карти - Защитете запазените начини на плащане + Защитете запазените начини на плащане - Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените банкови карти, в случай че някой друг има достъп до него. + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените банкови карти, в случай че някой друг има достъп до него. - Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените методи на плащане от достъп, ако някой друг има вашето устройство. + Настройте фигура, PIN или парола за отключване на устройството, за да защитите запазените методи на плащане от достъп, ако някой друг има вашето устройство. Настройване @@ -1900,10 +1921,10 @@ Отключете устройството си - Отключете, за да използвате запазената банкова карта + Отключете, за да използвате запазената банкова карта - Отключете, за да използвате запазените методи на плащане + Отключете, за да използвате запазените методи на плащане Добавяне на адрес @@ -1911,12 +1932,14 @@ Управление на адреси - Първо име + Първо име - Презиме + Презиме - Фамилия + Фамилия + + Име Адрес @@ -1941,9 +1964,9 @@ Премахване на адреса - Сигурни ли сте, че искате да премахнете този адрес? + Сигурни ли сте, че искате да премахнете този адрес? - Изтриване на този адрес? + Изтриване на този адрес? Премахване @@ -2043,49 +2066,49 @@ Редактиране - Сигурни ли сте, че искате да изтриете тези данни за вход? + Сигурни ли сте, че искате да изтриете тези данни за вход? - Сигурни ли сте, че искате да изтриете тази парола? + Сигурни ли сте, че искате да изтриете тази парола? Изтриване Отказ - Настройки за вход + Настройки за вход - Опции за парола + Опции за парола - Текстовото поле за редактиране на адреса на регистрация. + Текстовото поле за редактиране на адреса на регистрация. - Текстовото поле за редактиране на адреса на уебсайта. + Текстовото поле за редактиране на адреса на уебсайта. - Текстовото поле за редактиране на потребителското име на регистрация. + Текстовото поле за редактиране на потребителското име на регистрация. - Текстовото поле за редактиране на потребителското име. + Текстовото поле за редактиране на потребителското име. - Текстовото поле за редактиране на паролата на регистрация. + Текстовото поле за редактиране на паролата на регистрация. - Текстовото поле за редактиране на паролата. + Текстовото поле за редактиране на паролата. - Запазване на промените на регистрацията. + Запазване на промените на регистрацията. - Запазване на промените. + Запазване на промените. - Редактиране + Редактиране - Редактиране на паролата + Редактиране на паролата - Добавете регистрация + Добавете регистрация - Добавяне на парола + Добавяне на парола - Паролата е задължителна + Паролата е задължителна - Въведете парола + Въведете парола - Потребителското име е задължително + Потребителското име е задължително - Въведете потребителско име + Въведете потребителско име Името на хоста е задължително @@ -2195,7 +2218,7 @@ Натиснете за подробности - Придвижване нагоре + Придвижване нагоре Затваряне @@ -2236,8 +2259,6 @@ Коригиран рейтинг - Ненадеждните отзиви са премахнати - Въз основа на надеждни отзиви Акценти от скорошни рецензии @@ -2294,10 +2315,6 @@ Ако видите, че продуктът е отново в наличност, докладвайте и ще работим върху проверка на отзивите. Докладвайте продукта е наличен - - Проверяване на качеството на отзива - - Проверяване на качеството на отзива Проверка на качеството на рецензията (%s) @@ -2343,13 +2360,19 @@ Научете повече - Избирайки „Да, пробвайте“ вие се съгласявате с %1$s на Mozilla %2$s и %3$s + Избирайки „Да, пробвайте“ вие се съгласявате с %1$s на Mozilla %2$s и %3$s С избирането на „Да, изпробвайте“ вие се съгласявате със следното от %1$s: + + Избирайки „Да, изпробвайте“ вие се съгласявате с %2$s на %1$s и %4$s на %3$s. + + Избирайки „Да, изпробвайте“ вие се съгласявате с %2$s на %1$s и %4$s на %3$s. - декларация за поверителност + политика за личните данни Политика на поверителност + + политика на поверителност условия за ползване @@ -2419,6 +2442,10 @@ език. Превеждане на страницата? + + Страницата е преведена от %1$s на %2$s Опитайте с поверителни преводи след %1$s @@ -2431,6 +2458,8 @@ Превеждане на Не сега + + Показване на оригинала Готово @@ -2453,6 +2482,16 @@ Научете повече + + Превеждане… + + + Изтегляне на езика в режим за икономия на данни (%1$s)? + + Настройки на превода diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index f9fc661f1..f06ba7aef 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -67,6 +67,11 @@ Na lezel roud ebet war an trevnad-mañ + + Pa vez serret hoc’h holl ivinelloù prevez e vez dilamet ho toupinoù, ho roll istor hag ho roadennoù lec’hienn gant %1$s. %2$s @@ -313,7 +318,6 @@ Ket bremañ - Ho surentez a zo talvoudus deomp Ardeiñ ar gont + + Cheñch ho ker-tremen, merañ dastumadeg ho roadennoù pe dilemel ho kont Goubredañ bremañ @@ -619,9 +625,9 @@ Sinedoù - Titouroù kennaskañ + Titouroù kennaskañ - Gerioù-tremen + Gerioù-tremen Ivinelloù digor @@ -648,9 +654,9 @@ %1$s war %2$s %3$s - Kartennoù kred + Kartennoù kred - Doareoù paeañ + Doareoù paeañ Chomlecʼhioù @@ -1579,13 +1585,13 @@ Gallout a rit ouzhpennañ al lec’hienn-mañ da bennbajenn ho trevnad evit mont war-eeun ha merdeiñ primoc’h evel ma vefe un arload. - Titouroù kennaskañ + Titouroù kennaskañ - Gerioù-tremen + Gerioù-tremen - Enrollañ an titouroù kennaskañ + Enrollañ an titouroù kennaskañ - Enrollañ ar gerioù-tremen + Enrollañ ar gerioù-tremen Goulenn a-raok enrollañ @@ -1601,37 +1607,37 @@ Leuniañ anvioù-implijer ha gerioù-tremen en arloadoù-all war ho trevnad. - Ouzhpennañ titouroù kennaskañ + Ouzhpennañ titouroù kennaskañ - Ouzhpennañ ur ger-tremen + Ouzhpennañ ur ger-tremen - - Goubredañ an titouroù kennaskañ - Goubredañ ar gerioù-tremen + Goubredañ an titouroù kennaskañ + + Goubredañ ar gerioù-tremen - Goubredañ an titouroù kennaskañ dre an trevnadoù + Goubredañ an titouroù kennaskañ dre an trevnadoù - Titouroù kennaskañ enrollet + Titouroù kennaskañ enrollet - Gerioù-tremen enrollet + Gerioù-tremen enrollet - An titouroù kennaskañ a enrollit pe c’houbredit e %s a vo diskouezet amañ. + An titouroù kennaskañ a enrollit pe c’houbredit e %s a vo diskouezet amañ. - Gouzout hiroc’h diwar-benn Sync + Gouzout hiroc’h diwar-benn Sync Nemedennoù - An titouroù kennaskañ n’int ket enrollet a vo diskouezet amañ. + An titouroù kennaskañ n’int ket enrollet a vo diskouezet amañ. - Ne vo ket enrollet an titouroù kennaskañ evit al lec’hiennoù-mañ. + Ne vo ket enrollet an titouroù kennaskañ evit al lec’hiennoù-mañ. Dilemel an holl nemedennoù - Klask titouroù kennaskañ + Klask titouroù kennaskañ - Klask er gerioù-tremen + Klask er gerioù-tremen Lec’hienn @@ -1660,13 +1666,13 @@ Kuzhat ar ger-tremen - Dibrennit evit gwelet ho titouroù kennaskañ enrollet + Dibrennit evit gwelet ho titouroù kennaskañ enrollet - Diogelit ho titouroù kennaskañ + Diogelit ho titouroù kennaskañ - Diogelit ho kerioù-tremen enrollet + Diogelit ho kerioù-tremen enrollet - Arventennit ur patrom morailh, ur PIN pe ur ger-tremen evit gwareziñ ho titouroù kennaskañ enrollet da vezañ lennet gant unan bennak all. + Arventennit ur patrom morailh, ur PIN pe ur ger-tremen evit gwareziñ ho titouroù kennaskañ enrollet da vezañ lennet gant unan bennak all. Diwezhatoc’h @@ -1682,7 +1688,7 @@ Arver diwezhañ - Lañser rummañ an titouroù kennaskañ + Lañser rummañ an titouroù kennaskañ @@ -1690,39 +1696,39 @@ Chomlec’hioù - Kartennoù kred + Kartennoù kred - Doareoù paeañ + Doareoù paeañ - Enrollañ ha leuniañ ar c’hartennoù en un doare emgefreek + Enrollañ ha leuniañ ar c’hartennoù en un doare emgefreek - Enrollañ ha leuniañ an doareoù paeañ + Enrollañ ha leuniañ an doareoù paeañ - Rineget eo ar roadennoù + Rineget eo ar roadennoù Goubredañ ar c’hartennoù kred etre ho trevnadoù Goubredañ ar c\'hartennoù - Ouzhpennañ ur gartenn gred + Ouzhpennañ ur gartenn gred - Ouzhpennañ ur gartenn + Ouzhpennañ ur gartenn - Merañ ar c’hartennoù enrollet + Merañ ar c’hartennoù enrollet - Merañ ar c’hartennoù + Merañ ar c’hartennoù Ouzhpennañ ur chomlec’h Merañ ar chomlec’hioù - Enrollañ ha leuniañ ar chomlec’hioù en un doare emgefreek + Enrollañ ha leuniañ ar chomlec’hioù en un doare emgefreek - Enrollañ ha leuniañ ar chomlec’hioù + Enrollañ ha leuniañ ar chomlec’hioù - Enkorfañ a ra titouroù evel niverennoù, posteloù ha chomlec’hioù + Enkorfañ a ra titouroù evel niverennoù, posteloù ha chomlec’hioù Ouzhpennañ ur gartenn @@ -1744,9 +1750,9 @@ Dilemel ar gartenn - Ha fellout a ra deocʼh dilemel ar gartenn gred-mañ? + Ha fellout a ra deocʼh dilemel ar gartenn gred-mañ? - Dilemel ar gartenn? + Dilemel ar gartenn? Dilemel @@ -1759,23 +1765,23 @@ Kartennoù enrollet - Biziatait un niverenn kartenn gred talvoudek mar plij. + Biziatait un niverenn kartenn gred talvoudek mar plij. - Enankit un niverenn gartenn reizh + Enankit un niverenn gartenn reizh - Mar plij, leugnit ar maez-mañ + Mar plij, leugnit ar maez-mañ - Ouzhpennañ un anv + Ouzhpennañ un anv Dibrennit da welet ho kartennoù enrollet - Diogelit ho kartennoù kred + Diogelit ho kartennoù kred - Diogelit ho toareoù paeañ enrollet + Diogelit ho toareoù paeañ enrollet - Arventennit ur patrom prennañ, ur PIN pe ur ger-tremen evit gwareziñ ho kartennoù kred enrollet ma vez ho trevnad gant unan bennak all. + Arventennit ur patrom prennañ, ur PIN pe ur ger-tremen evit gwareziñ ho kartennoù kred enrollet ma vez ho trevnad gant unan bennak all. Arventennañ bremañ @@ -1784,7 +1790,7 @@ Dibrennit ho trevnad - Dibrennit evit implijout titouroù kartenn gred enrollet + Dibrennit evit implijout titouroù kartenn gred enrollet Ouzhpennañ ur chomlec’h @@ -1793,11 +1799,11 @@ Merañ ar chomlec’hioù - Añv bihan + Añv bihan - Anv kreiz + Anv kreiz - Anv familh + Anv familh Chomlec’h @@ -1822,9 +1828,9 @@ Dilemel ar chomlec’h - Ha sur oc’h e fell deoc’h dilemel ar chomlec’h-mañ? + Ha sur oc’h e fell deoc’h dilemel ar chomlec’h-mañ? - Dilemel ar chomlec’h-mañ? + Dilemel ar chomlec’h-mañ? Dilemel @@ -1921,41 +1927,41 @@ Embann - Sur oc’h e fell deoc’h dilemel an titour-kennaskañ-mañ? + Sur oc’h e fell deoc’h dilemel an titour-kennaskañ-mañ? - Sur ocʼh e fell deocʼh dilemel ar ger-tremen-mañ? + Sur ocʼh e fell deocʼh dilemel ar ger-tremen-mañ? Dilemel Nullañ - Dibarzhioù an titouroù kennaskañ + Dibarzhioù an titouroù kennaskañ - Ar vaezienn destenn kemmus evit chomlec’h web an titour kennaskañ. + Ar vaezienn destenn kemmus evit chomlec’h web an titour kennaskañ. - Ar vaezienn destenn kemmus evit anv arveriad an titour kennaskañ. + Ar vaezienn destenn kemmus evit anv arveriad an titour kennaskañ. - Ar vaezienn destenn kemmus evit ger-tremen an titour kennaskañ. + Ar vaezienn destenn kemmus evit ger-tremen an titour kennaskañ. - Enrollañ ar c’hemmoù d’an titouroù kennaskañ. + Enrollañ ar c’hemmoù d’an titouroù kennaskañ. - Enrollañ ar cʼhemmoù. + Enrollañ ar cʼhemmoù. - Embann + Embann - Aozañ ar ger-tremen + Aozañ ar ger-tremen - Ouzhpennañ titouroù kennaskañ nevez + Ouzhpennañ titouroù kennaskañ nevez - Ouzhpennañ ur ger-tremen + Ouzhpennañ ur ger-tremen - Ger-tremen azgoulennet + Ger-tremen azgoulennet - Enankit ur ger-tremen + Enankit ur ger-tremen - Anv-implijer rekis + Anv-implijer rekis - Enankit un anv-implijer + Enankit un anv-implijer Anv an ostiz rekis @@ -2055,7 +2061,7 @@ Klask %s - + Digeriñ liammoù al lec’hiennoù, posteloù ha kemennadennoù e Firefox en un doare emgefreek. @@ -2065,7 +2071,7 @@ Klikit da gaout muioc’h a vunudoù - Adpignat + Adpignat Serriñ @@ -2103,8 +2109,6 @@ Alioù disfizius Pegen fizius eo an alioù-se? - - Alioù disfizius dilamet Penaos e termenomp perzhded an alioù @@ -2123,6 +2127,8 @@ Produioù all Bruderezh gant %s + + Ar gwirier alioù a zo lusket gant %s %s gant Mozilla @@ -2133,10 +2139,6 @@ N\'eus ket a-walc’h a alioù c\'hoazh Dihegerz eo ar produ-mañ - - O wiriañ perzhded an ali - - O wiriañ perzhded an ali O wiriañ kalite an alioù (%s) @@ -2162,7 +2164,7 @@ Gouzout hiroc’h - politikerezh a-fet buhez prevez + politikerezh a-fet buhez prevez Politikerezh a-fet buhez prevez @@ -2249,6 +2251,8 @@ O treiñ + + Dibab ur yezh Ur gudenn zo bet gant an droidigezh. Klaskit en-dro. @@ -2281,9 +2285,24 @@ Troidigezh emgefreek + + + Goulenn treiñ ar bajenn (dre ziouer) + + %1$s a ginnigo deoc’h da dreiñ lec’hiennoù er yezh-mañ. + + Treiñ bepred + + %1$s a droio ar yezh-mañ ent emgefreek pa garg ar bajenn. Na dreiñ biken + + %1$s ne c’houlenno biken da dreiñ lec’hiennoù er yezh-mañ. + + + + Na dreiñ biken al lec’hiennoù-mañ Lemel %1$s @@ -2300,6 +2319,8 @@ Pellgargañ yezhoù Gouzout hiroc’h + + Yezhoù hegerz rekis Nullañ + + Niver a ivinelloù Oberiant diff --git a/app/src/main/res/values-bs/strings.xml b/app/src/main/res/values-bs/strings.xml index 819e7f7a9..c4c0dba38 100644 --- a/app/src/main/res/values-bs/strings.xml +++ b/app/src/main/res/values-bs/strings.xml @@ -245,6 +245,11 @@ Prevedi stranicu + + Stranica je prevedena sa %1$s na %2$s. + Izabrani jezik @@ -318,12 +323,22 @@ Firefox obavijest o privatnosti - + + Saznajte više u našoj obavijesti o privatnosti Volimo da vas čuvamo + + Saznajte zašto milioni vole Firefox + + Sigurno pretraživanje s više izbora Naš neprofitni pretraživač pomaže u sprečavanju kompanija da vas potajno prate širom interneta. + Više od 100 miliona ljudi štiti svoju privatnost odabirom pretraživača koji podržava neprofitna organizacija. + + Poznati tragači? Blokirani automatski. Ekstenzije? Isprobaj svih 700. PDF-ovi? Naš ugrađeni čitač čini ih laganim za upravljanje. + Naš neprofitni pretraživač pomaže spriječiti kompanije da vas potajno prate širom weba.\n\nSaznajte više u našem obavještenju o privatnosti. @@ -675,9 +690,9 @@ Zabilješke - Prijave + Prijave - Lozinke + Lozinke Otvori tabove @@ -703,9 +718,9 @@ %1$s na %2$s %3$s - Kreditne kartice + Kreditne kartice - Načini plaćanja + Načini plaćanja Adrese @@ -1640,13 +1655,13 @@ Ovu web stranicu možete lahko dodati na Početni ekran uređaja za brz pristup istoj i da surfate brže s iskustvom sličnom aplikaciji. - Prijave i lozinke + Prijave i lozinke - Lozinke + Lozinke - Spašene prijave i lozinke + Spašene prijave i lozinke - Sačuvaj lozinke + Sačuvaj lozinke Pitaj za spašavanje @@ -1661,48 +1676,48 @@ Unesite korisnička imena i lozinke u druge aplikacije na svom uređaju. - Dodaj prijavu + Dodaj prijavu - Dodaj lozinku + Dodaj lozinku - - Sinkroniziraj prijave - Sinhronizuj lozinke + Sinkroniziraj prijave + + Sinhronizuj lozinke - Sinhronizirajte prijave na svim uređajima + Sinhronizirajte prijave na svim uređajima - Sinhronizuj lozinke na svim uređajima + Sinhronizuj lozinke na svim uređajima - Spašene prijave + Spašene prijave - Sačuvane lozinke + Sačuvane lozinke - Prijave koje spasite ili sinhronizujete sa %s će se prikazati ovdje. + Prijave koje spasite ili sinhronizujete sa %s će se prikazati ovdje. - Lozinke koje sačuvate ili sinhronizujete sa %s će biti navedene ovdje. Sve lozinke koje sačuvate su šifrovane. + Lozinke koje sačuvate ili sinhronizujete sa %s će biti navedene ovdje. Sve lozinke koje sačuvate su šifrovane. - Saznajte više o Syncu. + Saznajte više o Syncu. - Saznajte više o sinhronizaciji + Saznajte više o sinhronizaciji Izuzeci - Prijave i lozinke koje nisu spašene će biti prikazane ovdje. + Prijave i lozinke koje nisu spašene će biti prikazane ovdje. - %s neće sačuvati lozinke za web stranice navedene ovdje. + %s neće sačuvati lozinke za web stranice navedene ovdje. - Prijave i lozinke neće biti spašene za ove web stranice. + Prijave i lozinke neće biti spašene za ove web stranice. - %s neće sačuvati lozinke za ove stranice. + %s neće sačuvati lozinke za ove stranice. Obriši sve izuzetke - Pretraži prijave + Pretraži prijave - Traži lozinke + Traži lozinke Stranica @@ -1731,17 +1746,17 @@ Sakrij lozinku - Otključajte za pregled spašenih prijava + Otključajte za pregled spašenih prijava - Otključajte da vidite sačuvane lozinke + Otključajte da vidite sačuvane lozinke - Osigurajte svoje prijave i lozinke + Osigurajte svoje prijave i lozinke - Osigurajte svoje sačuvane lozinke + Osigurajte svoje sačuvane lozinke - Podesite pattern za zaključavanje uređaja, PIN ili lozinku da zaštitite vaše spašene prijave i lozinke od pristupa druge osobe koja ima vaš uređaj. + Podesite pattern za zaključavanje uređaja, PIN ili lozinku da zaštitite vaše spašene prijave i lozinke od pristupa druge osobe koja ima vaš uređaj. - Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite svoje sačuvane lozinke od pristupa ako neko drugi ima vaš uređaj. + Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite svoje sačuvane lozinke od pristupa ako neko drugi ima vaš uređaj. Kasnije @@ -1758,7 +1773,10 @@ Zadnja upotreba - Sortiraj meni prijava + Sortiraj meni prijava + + + Meni za sortiranje lozinki Meni za sortiranje lozinki @@ -1769,40 +1787,43 @@ Adrese - Kreditne kartice + Kreditne kartice - Načini plaćanja + Načini plaćanja - Sačuvajte i automatski popunjavajte kartice + Sačuvajte i automatski popunjavajte kartice - Sačuvaj i popuni načine plaćanja + Sačuvaj i popuni načine plaćanja - Podaci su šifrovani + Podaci su šifrovani - %s šifruje sve načine plaćanja koje sačuvate + %s šifruje sve načine plaćanja koje sačuvate Sinhronizujte kartice na svim uređajima Sinhronizuj kartice - Dodaj kreditnu karticu + Dodaj kreditnu karticu - Dodaj karticu + Dodaj karticu - Upravljaj sačuvanim karticama + Upravljaj sačuvanim karticama - Upravljajte karticama + Upravljajte karticama Dodaj adresu Upravljaj adresama - Sačuvajte i automatski popunjavajte adrese + Sačuvajte i automatski popunjavajte adrese - Sačuvajte i popunite adrese + Sačuvajte i popunite adrese - Uključite informacije kao što su brojevi, e-mail i adrese za dostavu + Uključite informacije kao što su brojevi, e-mail i adrese za dostavu + + + Uključuje brojeve telefona i email adrese Uključuje brojeve telefona i email adrese @@ -1826,9 +1847,9 @@ Izbriši karticu - Jeste li sigurni da želite izbrisati ovu kreditnu karticu? + Jeste li sigurni da želite izbrisati ovu kreditnu karticu? - Izbrisati karticu? + Izbrisati karticu? Izbriši @@ -1840,23 +1861,23 @@ Sačuvane kartice - Unesite važeći broj kreditne kartice + Unesite važeći broj kreditne kartice - Unesite važeći broj kartice + Unesite važeći broj kartice - Molimo popunite ovo polje + Molimo popunite ovo polje - Dodaj ime + Dodaj ime Otključajte da vidite svoje sačuvane kartice - Osigurajte svoje kreditne kartice + Osigurajte svoje kreditne kartice - Osigurajte svoje sačuvane načine plaćanja + Osigurajte svoje sačuvane načine plaćanja - Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite svoje sačuvane kreditne kartice od pristupa ako neko drugi ima vaš uređaj. + Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite svoje sačuvane kreditne kartice od pristupa ako neko drugi ima vaš uređaj. - Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite sačuvane načine plaćanja od pristupa ako neko drugi ima vaš uređaj. + Postavite obrazac za zaključavanje uređaja, PIN ili lozinku da zaštitite sačuvane načine plaćanja od pristupa ako neko drugi ima vaš uređaj. Podesi odmah @@ -1864,10 +1885,10 @@ Otključajte svoj uređaj - Otključajte za korištenje sačuvanih podataka o kreditnoj kartici + Otključajte za korištenje sačuvanih podataka o kreditnoj kartici - Otključajte da koristite sačuvane načine plaćanja + Otključajte da koristite sačuvane načine plaćanja Dodaj adresu @@ -1875,11 +1896,13 @@ Upravljaj adresama - Ime + Ime - Srednje ime + Srednje ime - Prezime + Prezime + + Ime Adresa @@ -1903,9 +1926,9 @@ Izbriši adresu - Jeste li sigurni da želite izbrisati ovu adresu? + Jeste li sigurni da želite izbrisati ovu adresu? - Izbrisati ovu adresu? + Izbrisati ovu adresu? Izbriši @@ -2003,50 +2026,50 @@ Uredi - Da li ste sigurni da želite obrisati ovu prijavu? + Da li ste sigurni da želite obrisati ovu prijavu? - Jeste li sigurni da želite izbrisati ovu lozinku? + Jeste li sigurni da želite izbrisati ovu lozinku? Obriši Otkaži - Opcije prijave + Opcije prijave - Opcije lozinke + Opcije lozinke - Izmjenjivo tekstualno polje za web adresu prijave. + Izmjenjivo tekstualno polje za web adresu prijave. - Tekstualno polje koje se može uređivati za adresu web stranice. + Tekstualno polje koje se može uređivati za adresu web stranice. - Izmjenjivo tekstualno polje za korisničko ime prijave. + Izmjenjivo tekstualno polje za korisničko ime prijave. - Tekstualno polje koje se može uređivati za korisničko ime. + Tekstualno polje koje se može uređivati za korisničko ime. - Izmjenjivo tekstualno polje za lozinku prijave. + Izmjenjivo tekstualno polje za lozinku prijave. - Tekstualno polje koje se može uređivati za lozinku. + Tekstualno polje koje se može uređivati za lozinku. - Spasite izmjene za prijavu. + Spasite izmjene za prijavu. - Sačuvaj promjene. + Sačuvaj promjene. - Uredi + Uredi - Uredi lozinku + Uredi lozinku - Dodaj novu prijavu + Dodaj novu prijavu - Dodaj lozinku + Dodaj lozinku - Potrebna lozinka + Potrebna lozinka - Unesite lozinku + Unesite lozinku - Korisničko ime je obavezno + Korisničko ime je obavezno - Unesite korisničko ime + Unesite korisničko ime Ime hosta je obavezno @@ -2141,6 +2164,9 @@ %s pretraga + + Promijenite svoj zadani pretraživač + Postavi automatsko otvaranje linkova web stranica, e-maila i poruka u Firefoxu. @@ -2150,7 +2176,7 @@ Kliknite za više detalja - Idi prema gore + Idi prema gore Zatvori @@ -2190,8 +2216,6 @@ Prilagođena ocjena - Nepouzdane recenzije su uklonjene - Na osnovu pouzdanih recenzija Izdvajamo iz nedavnih recenzija @@ -2251,10 +2275,6 @@ Ako vidite da je ovaj proizvod ponovo na zalihama, prijavite ga i mi ćemo raditi na provjeri recenzija. Prijavite proizvod je na zalihama - - Provjera kvaliteta recenzije - - Provjera kvaliteta recenzije Provjera kvaliteta recenzije (%s) @@ -2300,13 +2320,19 @@ Saznajte više - Odabirom “Da, probaj” prihvatate %1$s od strane Mozilla-ine %2$s i %3$s. + Odabirom “Da, probaj” prihvatate %1$s od strane Mozilla-ine %2$s i %3$s. Odabirom “Da, probaj” prihvatate sljedeće od %1$s: + + Odabirom “Da, probaj” prihvatate %2$s %1$s i %4$s %3$s. + + Odabirom “Da, probaj” prihvatate %2$s %1$s i %4$s %3$s. - politika privatnosti + politika privatnosti Politika privatnosti + + obavještenje o privatnosti uslovi korištenja @@ -2377,6 +2403,10 @@ Prevesti ovu stranicu? + + Stranica je prevedena sa %1$s na %2$s Isprobajte privatne prijevode na %1$s @@ -2389,6 +2419,8 @@ Prevedi na Ne sada + + Prikaži original Gotovo @@ -2411,6 +2443,9 @@ Saznajte više + + Prevođenje… + Opcije prevođenja diff --git a/app/src/main/res/values-cak/strings.xml b/app/src/main/res/values-cak/strings.xml index 7b77ffa09..338cfa7d8 100644 --- a/app/src/main/res/values-cak/strings.xml +++ b/app/src/main/res/values-cak/strings.xml @@ -248,6 +248,7 @@ Tawichinaj ri ruxaq atikirib\'al + Rutikirib\'al ruwäch @@ -255,6 +256,9 @@ Tiyuj runatab\'al okem pa k\'amaya\'l + + Titzalq\'omïx ruxaq + Xcha\' ch\'ab\'äl @@ -266,8 +270,6 @@ Tiwachib\'ëx - - Kanob\'äl Runuk\'ulem kanob\'äl @@ -322,23 +324,26 @@ - Ri taq rutzijol yatkito\' richin nasamajij ch\'aqa\' chik pa %s + Ri taq rutzijol yatkito\' richin nasamajij ch\'aqa\' chik pa %s - Ke\'axima\' ri taq ruwi\' chi kikojol ri taq okisaxel, ke\'anuk\'samajij taq qasanïk, ke\'ak\'ulu\' taq na\'oj chi rij rub\'eyal nawïl ri rutzil ruchajixik richinanem %s chuqa\' ch\'aqa\' chik. + Ke\'axima\' ri taq ruwi\' chi kikojol ri taq okisaxel, ke\'anuk\'samajij taq qasanïk, ke\'ak\'ulu\' taq na\'oj chi rij rub\'eyal nawïl ri rutzil ruchajixik richinanem %s chuqa\' ch\'aqa\' chik. - Titikïr chik el + Titikïr chik el - Wakami mani + Wakami mani + + Firefox ichinan rutzijol + Niqa chi qawäch chi atqajikib\'an - Ri qokik\'amaya\'l majun ch\'akoj rojqan, yatruto\' chi ri ajk\'ayij taq moloj yatkitzeqelb\'ej pa ewan pa ajk\'amaya\'l.\n\nCh\'aqa\' chik taq na\'oj pa ri rutzijol ichinanem. + Ri qokik\'amaya\'l majun ch\'akoj rojqan, yatruto\' chi ri ajk\'ayij taq moloj yatkitzeqelb\'ej pa ewan pa ajk\'amaya\'l.\n\nCh\'aqa\' chik taq na\'oj pa ri rutzijol ichinanem. - ichinan na\'oj + ichinan na\'oj Tiya\' kan achi\'el kanob\'äl k\'o wi @@ -435,20 +440,10 @@ HTTPS-Only B\'anikil - - Kech\'utinirisäx kitzijol kuki Kiq\'atöy kitzijol cookie Ruq\'atöy kitzijol taq cookie pan ichinan okem - - Kech\'utinär ri taq kib\'aner koki - - Tichup - - Titzij - - %1$s nutojtob\'ej yeruxutuj ruyonil ri kik\'utuxik kuki pa ri taq kinimawuj kuki. Chupül pa re ruxaq re\' @@ -467,32 +462,13 @@ Wakami man koch\'el ta re ruxaq re\' - ¿La nitzij ri kich\'utinisaxik rutzijol kuki richin %1$s? - ¿La nitzij ri kiq\'atik taq kitzijol cookie richin %1$s? - ¿La nichup ri kich\'utinisaxik rutzijol kuki richin %1$s? - ¿La nichup ri ruq\'atoj kitzijol taq cookie richin %1$s? Man yeruq\'ät ta ri %1$s pa ruyonil ri taq kik\'utuj taq cookie pa re ruxaq re\'. Yatikïr natäq un k\'utuj richin nito\' re ruxaq re\' ri chwa\'q kab\'ij. - - %1$s xkeruyüj ri taq rukuki re ruxaq chuqa\' xtuk\'ëx re ruxaq. Xkeruyüj ronojel ri taq kuki, nitikïr nutz\'apij ri molojri\'ïl o yerujäm ri taq ruch\'ich\' loq\'oj. - - %1$s nitikïr nutojtob\'ej yeruxutuj pa ruyonil ronojel ri kik\'utuxik taq kuki pa koch\'el taq ruxaq. Toq nitzij, ri %1$s xtutojtob\'ej xkeruxutuj pa ruyonil ri taq kitzijol taq cookie pa re ruxaq re\'. - - ¿La niya\' q\'ij chi %1$s yeruxutuj ri kik\'utuxik taq kuki? - - %1$s nitikïr yeruxutuj pa ruyonil k\'ïy kik\'utuxik taq kuki. - - Wakami mani - - Xtatz\'ët jub\'a kik\'utuxik kuki - - - Tiya\' q\'ij %1$s k\'a b\'a\' keruxutuj taq cookie @@ -702,6 +678,8 @@ Taq yaketal Ketikirisäx molojri\'ïl + + Ewan taq tzij Kejaq ruwi\' @@ -729,6 +707,8 @@ Rutarjeta\' kre\'ito\' + + Rub\'eyal tojïk Taq ochochib\'äl @@ -1269,8 +1249,6 @@ Tewäx - Man tikirel ta xtz\'ajb\'äx - Man tikirel ta nitz\'ajb\'äx re ruxaq re\' Titz\'ajb\'äx @@ -1316,6 +1294,10 @@ Ketz\'apïx ichinan taq ruwi\' + + + La yetz\'apïx ichinan taq ruwi\'? + Markentin @@ -1658,8 +1640,12 @@ Kitikirisaxik molojri\'ïl chuqa\' ewan taq tzij + + Ewan taq tzij Keyak kitikirisaxik molojri\'ïl chuqa\' ewan taq tzij + + Keyak ewan taq tzij Tik\'utüx chi niyak @@ -1672,16 +1658,25 @@ Tatz\'aqatisaj rutikirib\'al molojri\'ïl + + Titz\'aqatisäx ewan tzij + Sync tikirisanïk molojri\'ïl + + Kexim ewan taq tzij Sync rutikirib\'al molojri\'ïl rik\'in okisaxel Xeyak kitikirisaxik mojojri\'ïl + + Xeyak ewan taq tzij Wawe\' xkeq\'alajin ri taq tikirisanïk molojri\'ïl xke\'ayäk o xke\'axïm rik\'in %s. Tawetamaj ch\'aqa\' chik chi rij ri Sync. + + Tawetamaj ch\'aqa\' chik chi rij ri sync Taq man relik ta @@ -1692,6 +1687,8 @@ Tiyuj ronojel man relik ta Kekanöx tikirib\'äl taq molojri\'ïl + + Kekanöx ewan taq tzij Ruxaq k\'amaya\'l @@ -1721,10 +1718,14 @@ Tewäx ewan tzij Man tiq\'at chik richin ye\'atz\'ët ri tikirib\'äl amolojri\'ïl e\'ayakon + + Man tiq\'at chik richin ye\'atz\'ët ri ewan taq tzij e\'ayakon Ke\'ajikib\'a\' kitikirisaxik amolojri\'ïl chuqa\' ewan taq atzij Tab\'ana\' runuk\'ulem jun retal ruq\'atoj okisab\'äl, jun PIN o jun ewan tzij richin nachajij ri kitikirib\'al amolojri\'ïl chuqa\' ewan taq atzij e\'ayakon we xa ta k\'o xtichapo ri awokisab\'al. + + Tab\'ana\' runuk\'ulem jun retal ruq\'atoj okisab\'äl, jun PIN o jun ewan tzij richin nachajij ri ewan taq atzij e\'ayakon we xa ta k\'o xtichapo ri awokisab\'al. Jub\'a\' chik na @@ -1753,6 +1754,8 @@ Taq ochochib\'äl Rutarjeta\' kre\'ito\' + + Rub\'eyal tojïk Keyak chuqa\' ruyon kenojisäx ri tarjeta\' @@ -1765,9 +1768,13 @@ Titz\'aqatisäx rutarjeta\' kre\'ito\' + + Titz\'aqatisäx tarjeta\' Kenuk\'samajïx yakon taq tarjeta\' + + Kenuk\'samajïx taq tarjeta\' Titz\'aqatisäx ochochib\'äl @@ -1775,6 +1782,9 @@ Keyak chuqa\' ruyon kenojisäx ri ochochib\'äl + + Keyak chuqa\' kenojisäx ri ochochib\'äl + Titz\'aqatisäx tarjeta\' @@ -1795,6 +1805,8 @@ Tiyuj tarjeta\' Tiyuj tarjeta\' + + La niyuj tarjeta\'? Tiyuj @@ -1811,6 +1823,8 @@ Tanojisaj re k\'ojlem re\' + + Titz\'aqatisäx jun b\'i\'aj Man tiq\'at chik richin ye\'atz\'ët ri tarjeta\' e\'ayakon @@ -1959,16 +1973,28 @@ Achi\'el: \nhttps://www.google.com/search?q=%s Ruk\'ojlem nuk\'el rutz\'ib\'axik rub\'i\' winäq pa ri rutikirib\'al molojri\'ïl. Ruk\'ojlem nuk\'el rutz\'ib\'axik ewan tzij pa ri rutikirib\'al molojri\'ïl. + + Ruk\'ojlem nuk\'el rutz\'ib\'axik ewan tzij. Keyaj taq jaloj richin ri rutikirib\'al molojri\'ïl. + + Keyak taq jaloj. Tinuk\' + + Tinuk\' ewan tzij Titz\'aqatisäx k\'ak\'a\' rub\'i\' taqoya\'l + + Titz\'aqatisäx ewan tzij Najowäx ewan tzij + + Titz\'ib\'äx jun ewan tzij Najowäx rub\'i\' okisanel + + Titz\'ib\'äx jun ewan rutzij okisaxel Najowäx rub\'i\' ruk\'u\'x k\'amb\'ey @@ -2052,7 +2078,7 @@ Achi\'el: \nhttps://www.google.com/search?q=%s Tikanöx pa %s - + Nub\'än kinuk\'ulem ximonel ajk\'amaya\'l taq ruxaq, taq taqoya\'l chuqa\' taq rutzijol richin yejaq pa ruyonil pa Firefox. @@ -2072,6 +2098,8 @@ Achi\'el: \nhttps://www.google.com/search?q=%s B\'anob\'äl richin yach\'ob\'on Tilitäj ch\'aqa\' chik + + B\'anon ruma %s. Tetamäx ch\'aqa\' chik diff --git a/app/src/main/res/values-co/strings.xml b/app/src/main/res/values-co/strings.xml index e41a5e4c1..c9093df23 100644 --- a/app/src/main/res/values-co/strings.xml +++ b/app/src/main/res/values-co/strings.xml @@ -258,6 +258,11 @@ Traduce a pagina + + Pagina tradutta in %2$s, l’origine hè in %1$s. + Lingua selezziunata @@ -335,12 +340,22 @@ Dichjarazione di cunfidenzialità di Firefox - + + Sapene di più in a nostra dichjarazione di cunfidenzialità A vostra prutezzione cunta per noi + + Scuprite perchè Firefox piace à milioni di persone + + A navigazione assicurizata cù più di scelta U nostru navigatore sustinutu da un urganismu senza scopu lucrativu impedisce l’imprese di seguitavvi da manera sicreta nant’à u Web. + Più di 10 milioni di persone prutegenu a so vita privata scigliendu un navigatore sustinutu da un’organizazione senza scopu lucrativu. + + Perseguitatori cunnisciuti ? Bluccati autumaticamente. Estensioni ? Ci n’hè più di 700 ; pruvatele. Schedarii PDF ? U nostru lettore integratu ne faciliteghja a ghjestione. + U nostru navigatore sustinutu da un urganismu senza scopu lucrativu impedisce l’imprese di seguitavvi da manera sicreta nant’à u Web.\n\nSapene di più in a nostra dichjarazione di cunfidenzialità. @@ -701,9 +716,9 @@ Indette - Identificazioni di cunnessione + Identificazioni di cunnessione - Parolle d’intesa + Parolle d’intesa Apre l’unghjette @@ -729,10 +744,10 @@ %1$s nant’à %2$s %3$s - Carte bancarie + Carte bancarie - Metode di pagamentu + Metode di pagamentu Indirizzi @@ -1675,13 +1690,13 @@ Hè faciule d’aghjunghje stu situ nant’à u screnu d’accolta di u vostru apparechju per accedeci direttamente è navigà più prestu cum’è s’ella fussi un’appiecazione. - Identificazioni è parolle d’intesa + Identificazioni è parolle d’intesa - Parolle d’intesa + Parolle d’intesa - Arregistrà l’identificazioni è e parolle d’intesa + Arregistrà l’identificazioni è e parolle d’intesa - Arregistrà e parolle d’intesa + Arregistrà e parolle d’intesa Dumandà per arregistrà @@ -1697,48 +1712,48 @@ Riimpiete nomi d’utilizatore è parolle d’intesa in l’altre appiecazioni nant’à u vostru apparechju. - Aghjunghje un’identificazione di cunnessione + Aghjunghje un’identificazione di cunnessione - Aghjunghje una parolla d’intesa + Aghjunghje una parolla d’intesa - - Sincrunizà l’identificazioni - Sincrunizà e parolle d’intesa + Sincrunizà l’identificazioni + + Sincrunizà e parolle d’intesa - Sincrunizà l’identificazioni di cunnessione trà l’apparechji + Sincrunizà l’identificazioni di cunnessione trà l’apparechji - Sincrunizà e parolle d’intesa trà l’apparechji + Sincrunizà e parolle d’intesa trà l’apparechji - Identificazioni di cunnessione arregistrate + Identificazioni di cunnessione arregistrate - Parolle d’intesa arregistrate + Parolle d’intesa arregistrate - L’identificazioni di cunnessione chì voi arregistrate o sincrunizate cù %s seranu affissate quì. + L’identificazioni di cunnessione chì voi arregistrate o sincrunizate cù %s seranu affissate quì. - E parolle d’intesa chì vo arregistrate o sincrunizate cù %s seranu affissate quì. Tutte e parolle d’intesa chì vo arregistrate sò cifrate. + E parolle d’intesa chì vo arregistrate o sincrunizate cù %s seranu affissate quì. Tutte e parolle d’intesa chì vo arregistrate sò cifrate. - Sapene di più nant’à Sync. + Sapene di più nant’à Sync. - Sapene di più nant’à a sincrunizazione + Sapene di più nant’à a sincrunizazione Eccezzioni - L’identificazioni è parolle d’intesa chì ùn sò micca arregistrate seranu affissate quì. + L’identificazioni è parolle d’intesa chì ùn sò micca arregistrate seranu affissate quì. - %s ùn arregistrerà micca e parolle d’intesa per i siti allistinati quì. + %s ùn arregistrerà micca e parolle d’intesa per i siti allistinati quì. - L’identificazioni è parolle d’intesa ùn seranu micca arregistrate per sti siti. + L’identificazioni è parolle d’intesa ùn seranu micca arregistrate per sti siti. - %s ùn arregistrerà micca e parolle d’intesa per sti siti. + %s ùn arregistrerà micca e parolle d’intesa per sti siti. Squassà tutte l’eccezzioni - Ricercà identificazioni di cunnessione + Ricercà identificazioni di cunnessione - Ricercà parolle d’intesa + Ricercà parolle d’intesa Situ @@ -1767,17 +1782,17 @@ Piattà a parolla d’intesa - Spalancate per affissà l’identificazioni di cunnessione arregistrate + Spalancate per affissà l’identificazioni di cunnessione arregistrate - Spalancate per affissà e vostre parolle d’intesa arregistrate + Spalancate per affissà e vostre parolle d’intesa arregistrate - Prutigite e vostre identificazioni di cunnessione è parolle d’intesa + Prutigite e vostre identificazioni di cunnessione è parolle d’intesa - Prutigite e vostre parolle d’intesa arregistrate + Prutigite e vostre parolle d’intesa arregistrate - Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre identificazioni di cunnessione è parolle d’intesa arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. + Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre identificazioni di cunnessione è parolle d’intesa arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. - Definite un dissegnu di chjuditura, un codice PIN o una parolla d’intesa per prutege e vostre parolle d’intesa arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. + Definite un dissegnu di chjuditura, un codice PIN o una parolla d’intesa per prutege e vostre parolle d’intesa arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. Dopu @@ -1795,7 +1810,10 @@ Ultimu impiegu - Listinu di classificazione di l’identificazioni + Listinu di classificazione di l’identificazioni + + + Listinu di classificazione di e parolle d’intesa Listinu di classificazione di e parolle d’intesa @@ -1806,40 +1824,43 @@ Indirizzi - Carte bancarie + Carte bancarie - Metode di pagamentu + Metode di pagamentu - Arregistrà è riempie autumaticamente e carte + Arregistrà è riempie autumaticamente e carte - Arregistrà è rinsignà e metode di pagamentu + Arregistrà è rinsignà e metode di pagamentu - I dati sò cifrati + I dati sò cifrati - %s cifra tutte e metode di pagamentu chì vo arregistrate + %s cifra tutte e metode di pagamentu chì vo arregistrate Sincrunizate e carte trà i vostri apparechji Sincrunizà e carte - Aghjunghje una carta bancaria + Aghjunghje una carta bancaria - Aghjunghje una carta + Aghjunghje una carta - Amministrà e carte arregistrate + Amministrà e carte arregistrate - Amministrà e carte + Amministrà e carte Aghjunghje un indirizzu Urganizà l’indirizzi - Arregistrà è riempie autumaticamente l’indirizzi + Arregistrà è riempie autumaticamente l’indirizzi - Arregistrà è rinsignà autumaticamente l’indirizzi + Arregistrà è rinsignà autumaticamente l’indirizzi - Include l’infurmazioni cum’è i numeri, i messaghji elettronichi è l’indirizzi di spedizione + Include l’infurmazioni cum’è i numeri, i messaghji elettronichi è l’indirizzi di spedizione + + + Include i numeri di telefonu è l’indirizzi elettronichi Include i numeri di telefonu è l’indirizzi elettronichi @@ -1864,9 +1885,9 @@ Squassà a carta - Vulete veramente squassà sta carta bancaria ? + Vulete veramente squassà sta carta bancaria ? - Squassà a carta ? + Squassà a carta ? Squassà @@ -1879,25 +1900,25 @@ Carte arregistrate - Ci vole à stampittà un numeru accettevule di carta bancaria + Ci vole à stampittà un numeru accettevule di carta bancaria - Stampittate un numeru di carta bancaria accettevule + Stampittate un numeru di carta bancaria accettevule - Ci vole à riempie stu campu + Ci vole à riempie stu campu - Aghjunghje un nome + Aghjunghje un nome Spalancate per affissà e vostre carte arregistrate - Prutege e vostre carte bancarie + Prutege e vostre carte bancarie - Prutigite e vostre metode di pagamentu arregistrate + Prutigite e vostre metode di pagamentu arregistrate - Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre carte arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. + Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre carte arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. - Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre metode di pagamentu arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. + Definite un dissegnu di chjusura, un codice PIN o una parolla d’intesa per prutege e vostre metode di pagamentu arregistrate s’ellu ci era qualchissia chì accidissi à u vostru apparechju. Cunfigurà subitu @@ -1905,10 +1926,10 @@ Spalancate u vostru apparechju - Spalancate per impiegà l’infurmazione di e carte bancarie arregistrate + Spalancate per impiegà l’infurmazione di e carte bancarie arregistrate - Spalancate per impiegà e metode di pagamentu arregistrate + Spalancate per impiegà e metode di pagamentu arregistrate Aghjunghje un indirizzu @@ -1916,11 +1937,13 @@ Urganizà l’indirizzi - Nome + Nome - Secondu nome + Secondu nome - Casata + Casata + + Nome cumpletu Indirizzu pustale @@ -1945,9 +1968,9 @@ Squassà l’indirizzu - Vulete veramente squassà st’indirizzu ? + Vulete veramente squassà st’indirizzu ? - Squassà st’indirizzu ? + Squassà st’indirizzu ? Squassà @@ -2046,49 +2069,49 @@ Mudificà - Vulete veramente squassà st’identificazione di cunnessione ? + Vulete veramente squassà st’identificazione di cunnessione ? - Vulete veramente squassà sta parolla d’intesa ? + Vulete veramente squassà sta parolla d’intesa ? Squassà Abbandunà - Ozzioni di l’identificazione + Ozzioni di l’identificazione - Ozzioni di parolla d’intesa + Ozzioni di parolla d’intesa - U campu di testu mudifichevule per l’indirizzu web di l’identificazione. + U campu di testu mudifichevule per l’indirizzu web di l’identificazione. - U campu di testu mudifichevule per l’indirizzu di u situ web. + U campu di testu mudifichevule per l’indirizzu di u situ web. - U campu di testu mudifichevule per u nome d’utilizatore di l’identificazione. + U campu di testu mudifichevule per u nome d’utilizatore di l’identificazione. - U campu di testu mudifichevule per u nome d’utilizatore. + U campu di testu mudifichevule per u nome d’utilizatore. - U campu di testu mudifichevule per a parolla d’intesa di l’identificazione. + U campu di testu mudifichevule per a parolla d’intesa di l’identificazione. - U campu di testu mudifichevule per a parolla d’intesa. + U campu di testu mudifichevule per a parolla d’intesa. - Arregistrà i cambiamenti di l’identificazione. + Arregistrà i cambiamenti di l’identificazione. - Arregistrà i cambiamenti. + Arregistrà i cambiamenti. - Mudificà + Mudificà - Mudificà a parolla d’intesa + Mudificà a parolla d’intesa - Aghjunghje una nova identificazione di cunnessione + Aghjunghje una nova identificazione di cunnessione - Aghjunghje una parolla d’intesa + Aghjunghje una parolla d’intesa - Parolla d’intesa richiesta + Parolla d’intesa richiesta - Stampittate una parolla d’intesa + Stampittate una parolla d’intesa - U nome d’utilizatore hè richiestu + U nome d’utilizatore hè richiestu - Stampittate un nome d’utilizatore + Stampittate un nome d’utilizatore U nome d’ospite hè richiestu @@ -2203,7 +2226,7 @@ Cliccu per sapene di più - Navigà insù + Navigà insù Chjode @@ -2245,8 +2268,6 @@ Valutazione rettificata - Avisi micca degni di cunfidenza cacciati - Nant’à a basa d’avisi degni di cunfidenza Messe in lume da l’avisi recente @@ -2308,10 +2329,6 @@ S’è vo fighjate chì stu pruduttu hè torna dispunibule, fatecilu sapè è cuntinueremu à cuntrollà l’avisi. Signalà chì u pruduttu hè dispunibule - - Cuntrollà a qualità di l’avisi - - Cuntrollà a qualità di l’avisi Cuntrollu di a qualità di l’avisi (%s) @@ -2357,13 +2374,19 @@ Sapene di più - A selezzione di « Sì, pruvallu » vole dì chì vo site d.accunsenti cù %2$s è %3$s di %1$s da Mozilla. + A selezzione di « Sì, pruvallu » vole dì chì vo site d.accunsenti cù %2$s è %3$s di %1$s da Mozilla. A selezzione di « Sì, pruvallu » vole dì chì vo accettate quell’elementi di %1$s : + + A selezzione di « Sì, pruvallu » vole dì chì vo site d’accunsenti cù a %2$s di %1$s è a %4$s di %3$s. + + A selezzione di « Sì, pruvallu » vole dì chì vo site d’accunsenti cù a %2$s di %1$s è a %4$s di %3$s. - pulitica di cunfidenzialità + pulitica di cunfidenzialità Pulitica di cunfidenzialità + + dichjarazione di cunfidenzialità cundizioni d’utilizazione @@ -2436,6 +2459,10 @@ Traduce sta pagina ? + + Pagina tradutta in %2$s, l’origine hè in %1$s Pruvà e traduzzioni private di %1$s @@ -2449,6 +2476,8 @@ Traduce versu Micca subitu + + Affissà a pagina d’origine Compiu @@ -2471,6 +2500,16 @@ Sapene di più + + + Traduzzione… + + Scaricà a lingua in modu di risparmiu di dati (%1$s) ? + + Ozzioni di traduzzione diff --git a/app/src/main/res/values-cy/strings.xml b/app/src/main/res/values-cy/strings.xml index c86dbcc71..81e6ef987 100644 --- a/app/src/main/res/values-cy/strings.xml +++ b/app/src/main/res/values-cy/strings.xml @@ -253,6 +253,11 @@ Cyfieithu\'r dudalen + + Tudalen wedi\'i chyfieithu o\'r %1$s i\'r %2$s. + Dewi iaith @@ -329,12 +334,22 @@ Hysbysiad preifatrwydd Firefox - + + Darllenwch ein hysbysiad preifatrwydd Rydyn ni wrth ein bodd yn eich cadw chi’n ddiogel + + Deall pam mae miliynau\'n caru Firefox + + Pori diogel gyda mwy o ddewisiadau Mae ein porwr gan gorff dim-er-elw\'n atal cwmnïau rhag eich dilyn yn gyfrinachol o amgylch y we. + Mae mwy na 100 miliwn o bobl yn diogelu eu preifatrwydd trwy ddewis porwr sy\'n cael ei gefnogi gan gorff dim-er-elw. + + Tracwyr hysbys? Wedi\'u rwystro\'n awtomatig. Estyniadau? Rhowch gynnig ar bob un o\'r 700. PDF? Mae ein darllenydd mewnol yn eu gwneud yn hawdd i\'w rheoli. + Mae ein porwr gan gorff dim-er-elw yn helpu i atal cwmnïau rhag eich dilyn yn gyfrinachol o amgylch y we.\n\nDarllenwch ragor yn ein hysbysiad preifatrwydd. @@ -691,9 +706,9 @@ Nodau Tudalen - Mewngofnodion + Mewngofnodion - Cyfrineiriau + Cyfrineiriau Tabiau agored @@ -719,9 +734,9 @@ %1$s o %2$s %3$s - Cardiau credyd + Cardiau credyd - Dulliau talu + Dulliau talu Cyfeiriadau @@ -1659,13 +1674,13 @@ Gallwch ychwanegu’r wefan hon yn hawdd i sgrin Cartref eich ffôn i gael mynediad ar unwaith a phori’n gyflymach gyda phrofiad tebyg i ap. - Mewngofnodion a chyfrineiriau + Mewngofnodion a chyfrineiriau - Cyfrineiriau + Cyfrineiriau - Cadw mewngofnodion a chyfrineiriau + Cadw mewngofnodion a chyfrineiriau - Cadw cyfrineiriau + Cadw cyfrineiriau Gofyn i gadw @@ -1680,48 +1695,48 @@ Llenwi enwau defnyddwyr a chyfrineiriau mewn apiau eraill ar eich dyfais. - Ychwanegu mewngofnod + Ychwanegu mewngofnod - Ychwanegu cyfrinair + Ychwanegu cyfrinair - - Cydweddu mewngofnodion - Cydweddu cyfrineiriau + Cydweddu mewngofnodion + + Cydweddu cyfrineiriau - Cydweddu mewngofnodion ar draws dyfeisiau + Cydweddu mewngofnodion ar draws dyfeisiau - Cydweddu cyfrineiriau ar draws dyfeisiau + Cydweddu cyfrineiriau ar draws dyfeisiau - Mewngofnodion wedi’u cadw + Mewngofnodion wedi’u cadw - Cyfrineiriau wedi\'u cadw + Cyfrineiriau wedi\'u cadw - Bydd y mewngofnodi rydych yn eu cadw neu’n cydweddu i %s i’w gweld yma. + Bydd y mewngofnodi rydych yn eu cadw neu’n cydweddu i %s i’w gweld yma. - Bydd y cyfrineiriau rydych yn eu cadw neu eu cydweddu i %s yn cael eu rhestru yma. Mae\'r holl gyfrineiriau rydych chi\'n eu cadw wedi\'u hamgryptio. + Bydd y cyfrineiriau rydych yn eu cadw neu eu cydweddu i %s yn cael eu rhestru yma. Mae\'r holl gyfrineiriau rydych chi\'n eu cadw wedi\'u hamgryptio. - Dysgu rhagor am Sync. + Dysgu rhagor am Sync. - Dysgwch fwy am gydweddu + Dysgwch fwy am gydweddu Eithriadau - Bydd mewngofnodion a chyfrineiriau sydd heb eu cadw i’w gweld yma. + Bydd mewngofnodion a chyfrineiriau sydd heb eu cadw i’w gweld yma. - Fydd %s ddim yn cadw cyfrineiriau ar gyfer gwefannau sy\'n cael eu rhestru yma. + Fydd %s ddim yn cadw cyfrineiriau ar gyfer gwefannau sy\'n cael eu rhestru yma. - Ni fydd mewngofnodion a chyfrineiriau’n cael eu cadw ar gyfer y gwefannau hyn. + Ni fydd mewngofnodion a chyfrineiriau’n cael eu cadw ar gyfer y gwefannau hyn. - Fydd %s ddim yn cadw cyfrineiriau ar gyfer y gwefannau hyn. + Fydd %s ddim yn cadw cyfrineiriau ar gyfer y gwefannau hyn. Dileu pob eithriad - Chwilio mewngofnodion + Chwilio mewngofnodion - Chwilio cyfrineiriau + Chwilio cyfrineiriau Gwefan @@ -1750,17 +1765,17 @@ Cuddio cyfrinair - Datgloi i weld eich mewngofnodi wedi’u cadw + Datgloi i weld eich mewngofnodi wedi’u cadw - Datgloi i weld eich cyfrineiriau wedi\'u cadw + Datgloi i weld eich cyfrineiriau wedi\'u cadw - Diogelu mewngofnodion a chyfrineiriau + Diogelu mewngofnodion a chyfrineiriau - Diogelwch eich cyfrineiriau wedi\'u cadw + Diogelwch eich cyfrineiriau wedi\'u cadw - Creu patrwm cloi dyfais, PIN, neu gyfrinair i ddiogelu eich mewngofnodion a’ch cyfrineiriau sydd wedi’u cadw rhag i rhywun arall sydd â mynediad i’ch dyfais. + Creu patrwm cloi dyfais, PIN, neu gyfrinair i ddiogelu eich mewngofnodion a’ch cyfrineiriau sydd wedi’u cadw rhag i rhywun arall sydd â mynediad i’ch dyfais. - Gosodwch batrwm clo dyfais, PIN, neu gyfrinair i ddiogelu eich cyfrineiriau sydd wedi\'u cadw rhag i rywun arall sydd â\'ch dyfais gael mynediad iddyn nhw. + Gosodwch batrwm clo dyfais, PIN, neu gyfrinair i ddiogelu eich cyfrineiriau sydd wedi\'u cadw rhag i rywun arall sydd â\'ch dyfais gael mynediad iddyn nhw. Yn hwyrach @@ -1777,7 +1792,10 @@ Defnyddiwyd Diwethaf - Trefnu dewislen mewngofnodi + Trefnu dewislen mewngofnodi + + + Didoli dewislen cyfrineiriau Didoli dewislen cyfrineiriau @@ -1788,40 +1806,43 @@ Cyfeiriadau - Cardiau credyd + Cardiau credyd - Dulliau talu + Dulliau talu - Cadw ac awtolanw cardiau + Cadw ac awtolanw cardiau - Cadw a llanw dulliau talu + Cadw a llanw dulliau talu - Mae data wedi’i amgryptio + Mae data wedi’i amgryptio - Mae %s yn amgryptio pob dull talu rydych yn ei gadw + Mae %s yn amgryptio pob dull talu rydych yn ei gadw Cydweddu cardiau ar draws dyfeisiau Cydweddu cardiau - Ychwanegu cerdyn credyd + Ychwanegu cerdyn credyd - Ychwanegu cerdyn + Ychwanegu cerdyn - Rheoli cardiau wedi’u cadw + Rheoli cardiau wedi’u cadw - Rheoli cardiau + Rheoli cardiau Ychwanegu cyfeiriad Rheoli cyfeiriadau - Cadw ac awtolanw cyfeiriadau + Cadw ac awtolanw cyfeiriadau - Cadw a llanw cyfeiriadau + Cadw a llanw cyfeiriadau - Cynhwyswch fanylion fel rhifau, cyfeiriadau e-bost a chludo + Cynhwyswch fanylion fel rhifau, cyfeiriadau e-bost a chludo + + + Yn cynnwys rhifau ffôn a chyfeiriadau e-bost Yn cynnwys rhifau ffôn a chyfeiriadau e-bost @@ -1845,9 +1866,9 @@ Dileu cerdyn - Ydych chi’n siŵr eich bod am ddileu’r cerdyn credyd yma? + Ydych chi’n siŵr eich bod am ddileu’r cerdyn credyd yma? - Dileu cerdyn? + Dileu cerdyn? Dileu @@ -1861,24 +1882,24 @@ Cardiau wedi’u cadw - Rhowch rif cerdyn credyd dilys + Rhowch rif cerdyn credyd dilys - Rhoi rif cerdyn dilys + Rhoi rif cerdyn dilys - Llanwch y maes yma. + Llanwch y maes yma. - Ychwanegu enw + Ychwanegu enw Datgloi i weld y cardiau rydych wedi’u cadw - Diogelwch eich cerdyn credyd + Diogelwch eich cerdyn credyd - Diogelu eich dulliau talu sydd wedi\'u cadw + Diogelu eich dulliau talu sydd wedi\'u cadw - Gosodwch batrwm cloi dyfais, PIN, neu gyfrinair i ddiogelu eich mewngofnodion a’ch cyfrineiriau sydd wedi’u cadw rhag i rhywun arall sydd â mynediad i’ch dyfais. + Gosodwch batrwm cloi dyfais, PIN, neu gyfrinair i ddiogelu eich mewngofnodion a’ch cyfrineiriau sydd wedi’u cadw rhag i rhywun arall sydd â mynediad i’ch dyfais. - Gosodwch batrwm clo dyfais, PIN, neu gyfrinair i ddiogelu eich dulliau talu rhag i rywun arall sydd â\'ch dyfais gael mynediad iddyn nhw. + Gosodwch batrwm clo dyfais, PIN, neu gyfrinair i ddiogelu eich dulliau talu rhag i rywun arall sydd â\'ch dyfais gael mynediad iddyn nhw. Gosod nawr @@ -1887,10 +1908,10 @@ Datgloi’ch dyfais - Datglowch i ddefnyddio manylion cerdyn credyd wedi’i storio + Datglowch i ddefnyddio manylion cerdyn credyd wedi’i storio - Datgloi i ddefnyddio dulliau talu wedi\'u cadw + Datgloi i ddefnyddio dulliau talu wedi\'u cadw Ychwanegu cyfeiriad @@ -1898,11 +1919,13 @@ Rheoli cyfeiriadau - Enw Cyntaf + Enw Cyntaf - Enw Canol + Enw Canol - Enw Olaf + Enw Olaf + + Enw Cyfeiriad Stryd @@ -1927,9 +1950,9 @@ Dileu cyfeiriad - Ydych chi’n siŵr eich bod am ddileu’r cyfeiriad hwn? + Ydych chi’n siŵr eich bod am ddileu’r cyfeiriad hwn? - Dileu\'r cyfeiriad hwn? + Dileu\'r cyfeiriad hwn? Dileu @@ -2027,49 +2050,49 @@ Golygu - Ydych chi’n siŵr eich bod eisiau dileu’r mewngofnod? + Ydych chi’n siŵr eich bod eisiau dileu’r mewngofnod? - Ydych chi\'n siŵr eich bod am ddileu\'r cyfrinair hwn? + Ydych chi\'n siŵr eich bod am ddileu\'r cyfrinair hwn? Dileu Diddymu - Dewisiadau mewngofnodi + Dewisiadau mewngofnodi - Dewisiadau cyfrineiriau + Dewisiadau cyfrineiriau - Maes testun golygadwy cyfeiriad gwe’r mewngofnodi. + Maes testun golygadwy cyfeiriad gwe’r mewngofnodi. - Maes testun golygadwy y wefan. + Maes testun golygadwy y wefan. - Maes testun golygadwy enw defnyddiwr y mewngofnodi. + Maes testun golygadwy enw defnyddiwr y mewngofnodi. - Maes testun golygadwy yr enw defnyddiwr. + Maes testun golygadwy yr enw defnyddiwr. - Maes testun golygadwy cyfrinair y mewngofnodi. + Maes testun golygadwy cyfrinair y mewngofnodi. - Maes testun golygadwy y cyfrinair. + Maes testun golygadwy y cyfrinair. - Cadw newidiadau i’r mewngofnodi. + Cadw newidiadau i’r mewngofnodi. - Cadw newidiadau. + Cadw newidiadau. - Golygu + Golygu - Golygu cyfrinair + Golygu cyfrinair - Ychwanegu mewngofnod newydd + Ychwanegu mewngofnod newydd - Ychwanegu cyfrinair + Ychwanegu cyfrinair - Mae angen cyfrinair + Mae angen cyfrinair - Rhowch gyfrinair + Rhowch gyfrinair - Mae angen enw defnyddiwr + Mae angen enw defnyddiwr - Rhoi enw defnyddiwr + Rhoi enw defnyddiwr Mae angen enw gwesteiwr @@ -2182,7 +2205,7 @@ Cliciwch am ragor o fanylion - Llywio i fyny + Llywio i fyny Cau @@ -2223,8 +2246,6 @@ Gradd wedi’i haddasu - Dilëwyd yr adolygiadau annibynadwy - Ar sail adolygiadau dibynadwy Uchafbwyntiau o adolygiadau diweddar @@ -2280,10 +2301,6 @@ Os ydych yn gweld fod y cynnyrch hwn nôl mewn stoc, rhowch wybod i ni ac fe wnawn ni ddiweddaru’r dadansoddiad. Adrodd fod cynnyrch mewn stoc - - Yn gwirio ansawdd adolygiadau - - Yn gwirio ansawdd adolygiadau Yn gwirio ansawdd adolygiadau (%s) @@ -2329,13 +2346,19 @@ Dysgu rhagor - Trwy ddewis “Iawn, rhoi cynnig arno” rydych yn cytuno i %2$s a %3$s %1$s gan Mozilla. + Trwy ddewis “Iawn, rhoi cynnig arno” rydych yn cytuno i %2$s a %3$s %1$s gan Mozilla. Wrth ddewis “Iawn, rhowch gynnig arni” rydych yn cytuno i’r canlynol o %1$s: + + Drwy ddewis “Iawn, rhoi cynnig arni” rydych yn cytuno i %2$s %1$s a %3$s %4$s. + + Drwy ddewis “Iawn, rhoi cynnig arni” rydych yn cytuno i %1$s %2$s a %3$s %4$s. - polisi preifatrwydd + polisi preifatrwydd Polisi preifatrwydd + + hysbysiad preifatrwydd telerau defnydd @@ -2406,6 +2429,10 @@ Cyfieithu\'r dudalen? + + Tudalen wedi\'i chyfieithu o\'r %1$s i\'r %2$s Rhowch gynnig ar gyfieithu preifat yn %1$s @@ -2418,6 +2445,8 @@ Cyfieithu i\'r Nid nawr + + Dangos y gwreiddiol Gorffen @@ -2441,6 +2470,16 @@ Darllen rhagor + + Wrthi\'n cyfieithu… + + + Llwytho i lawr iaith yn y modd cadw data (%1$s)? + + Dewisiadau Cyfieithu diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 1ecf296b4..8f7824d21 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -255,6 +255,11 @@ Oversæt side + + Side oversat fra %1$s til %2$s. + Valgt sprog @@ -331,12 +336,22 @@ Privatlivserklæring for Firefox - + + Læs mere i vores privatlivserklæring Vi elsker at holde dig sikker + + Find ud af, hvorfor millioner elsker Firefox + + Sikker browsing med flere valgmuligheder Vores browser er støttet af en nonprofit-organisation og forhindrer virksomheder i at følge dig rundt på nettet i det skjulte. + Mere end 100 millioner mennesker beskytter deres privatliv ved at vælge en browser, der er støttet af en nonprofit-organisation. + + Kendte sporings-mekanismer? Blokeret automatisk. Udvidelser? Prøv alle 700. PDF-filer? Vores indbyggede læser gør det nemt at håndtere dem. + Vores non-profit-støttede browser hjælper med at forhindre virksomheder i at følge dig rundt på nettet i hemmelighed.\n\nLæs mere i vores privatlivserklæring. @@ -689,9 +704,9 @@ Bogmærker - Logins + Logins - Adgangskoder + Adgangskoder Åbne faneblade @@ -717,9 +732,9 @@ %1$s på %2$s %3$s - Betalingskort + Betalingskort - Betalingsmetoder + Betalingsmetoder Adresser @@ -1654,13 +1669,13 @@ Du kan nemt føje dette websted til din enheds startskærm for at have hurtig adgang til det og browse hurtigere med en app-lignende oplevelse. - Logins og adgangskoder + Logins og adgangskoder - Adgangskoder + Adgangskoder - Gem logins og adgangskoder + Gem logins og adgangskoder - Gem adgangskoder + Gem adgangskoder Bed om at gemme @@ -1675,48 +1690,48 @@ Udfyld brugernavne og adgangskoder i andre apps på din enhed. - Tilføj login + Tilføj login - Tilføj adgangskode + Tilføj adgangskode - - Synkroniser logins - Synkroniser adgangskoder + Synkroniser logins + + Synkroniser adgangskoder - Synkroniser logins på tværs af enheder + Synkroniser logins på tværs af enheder - Synkroniser adgangskoder på tværs af enheder + Synkroniser adgangskoder på tværs af enheder - Gemte logins + Gemte logins - Gemte adgangskoder + Gemte adgangskoder - De logins, du gemmer eller synkroniserer til %s, vises her. + De logins, du gemmer eller synkroniserer til %s, vises her. - Adgangskoderne, du gemmer i eller synkroniserer med %s vil blive vist her. Alle dine gemte adgangskoder bliver krypteret. + Adgangskoderne, du gemmer i eller synkroniserer med %s vil blive vist her. Alle dine gemte adgangskoder bliver krypteret. - Læs mere om Sync. + Læs mere om Sync. - Læs mere om synkronisering + Læs mere om synkronisering Undtagelser - Logins og adgangskoder, der ikke er gemt, vises her. + Logins og adgangskoder, der ikke er gemt, vises her. - %s gemmer ikke adgangskoder til websteder vist her. + %s gemmer ikke adgangskoder til websteder vist her. - Logins og adgangskoder vil ikke blive gemt for disse websteder. + Logins og adgangskoder vil ikke blive gemt for disse websteder. - %s gemmer ikke adgangskoder til disse websteder. + %s gemmer ikke adgangskoder til disse websteder. Slet alle undtagelser - Søg efter logins + Søg efter logins - Søg efter adgangskoder + Søg efter adgangskoder Websted @@ -1744,17 +1759,17 @@ Skjul adgangskode - Lås op for at se dine gemte logins + Lås op for at se dine gemte logins - Lås op for at se dine gemte adgangskoder + Lås op for at se dine gemte adgangskoder - Gør dine logins og adgangskoder sikre + Gør dine logins og adgangskoder sikre - Gør dine gemte adgangskoder sikre + Gør dine gemte adgangskoder sikre - Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte logins og adgangskoder, hvis de har adgang til din enhed. + Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte logins og adgangskoder, hvis de har adgang til din enhed. - Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte adgangskoder, hvis de har adgang til din enhed. + Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte adgangskoder, hvis de har adgang til din enhed. Senere @@ -1772,7 +1787,10 @@ Senest brugt - Sortér menuen logins + Sortér menuen logins + + + Menuen sorter adgangskoder Menuen sorter adgangskoder @@ -1783,39 +1801,42 @@ Adresser - Betalingskort + Betalingskort - Betalingsmetoder + Betalingsmetoder - Gem og autofyld betalingskort + Gem og autofyld betalingskort - Gem og udfyld betalingsmetoder + Gem og udfyld betalingsmetoder - Data er krypteret + Data er krypteret - %s krypterer alle betalingsmetoder, du gemmer + %s krypterer alle betalingsmetoder, du gemmer Synkroniser kort på tværs af enheder Synkroniser kort - Tilføj betalingskort + Tilføj betalingskort - Tilføj kort + Tilføj kort - Håndter gemte kort + Håndter gemte kort - Håndter kort + Håndter kort Tilføj adresse Håndter adresser - Gem og autofyld adresser + Gem og autofyld adresser - Gem og udfyld adresser + Gem og udfyld adresser - Inkluderer oplysninger såsom telefonnumre, mail- og forsendelsesadresser + Inkluderer oplysninger såsom telefonnumre, mail- og forsendelsesadresser + + + Inkluderer telefonnumre og mailadresser Inkluderer telefonnumre og mailadresser @@ -1839,9 +1860,9 @@ Slet kort - Er du sikker på, at du vil slette dette betalingskort? + Er du sikker på, at du vil slette dette betalingskort? - Slet kort? + Slet kort? Slet @@ -1855,24 +1876,24 @@ Gemte kort - Indtast et gyldigt betalingskortnummer + Indtast et gyldigt betalingskortnummer - Indtast et gyldigt kortnummer + Indtast et gyldigt kortnummer - Udfyld dette felt + Udfyld dette felt - Tilføj navn + Tilføj navn Lås op for at se dine gemte betalingskort - Beskyt dine betalingskort + Beskyt dine betalingskort - Gør dine gemte betalingsmetoder sikre + Gør dine gemte betalingsmetoder sikre - Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte betalingskort, hvis de har adgang til din enhed. + Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte betalingskort, hvis de har adgang til din enhed. - Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte betalingsmetoder, hvis de har adgang til din enhed. + Indstil en pinkode, en adgangskode eller et låsemønster på din enhed for at forhindre, at andre mennesker får adgang til dine gemte betalingsmetoder, hvis de har adgang til din enhed. Indstil nu @@ -1880,10 +1901,10 @@ Lås din enhed op - Lås op for at anvende gemte informationer om betalingskort + Lås op for at anvende gemte informationer om betalingskort - Lås op for at bruge gemte betalingsmetoder + Lås op for at bruge gemte betalingsmetoder Tilføj adresse @@ -1891,11 +1912,13 @@ Håndter adresser - Fornavn + Fornavn - Mellemnavn + Mellemnavn - Efternavn + Efternavn + + Navn Postadresse @@ -1919,9 +1942,9 @@ Slet adresse - Er du sikker på, at du vil slette denne adresse? + Er du sikker på, at du vil slette denne adresse? - Slet denne adresse? + Slet denne adresse? Slet @@ -2020,49 +2043,49 @@ Rediger - Er du sikker på, at du vil slette dette login? + Er du sikker på, at du vil slette dette login? - Er du sikker på, at du vil slette denne adgangskode? + Er du sikker på, at du vil slette denne adgangskode? Slet Annuller - Login-indstillinger + Login-indstillinger - Adgangskode-indstillinger + Adgangskode-indstillinger - Det redigerbare tekstfelt for login’ets webadresse. + Det redigerbare tekstfelt for login’ets webadresse. - Det redigerbare tekstfelt for webadressen. + Det redigerbare tekstfelt for webadressen. - Det redigerbare tekstfelt for login’ets brugernavn. + Det redigerbare tekstfelt for login’ets brugernavn. - Det redigerbare tekstfelt for brugernavnet. + Det redigerbare tekstfelt for brugernavnet. - Det redigerbare tekstfelt for login’ets adgangskode. + Det redigerbare tekstfelt for login’ets adgangskode. - Det redigerbare tekstfelt for adgangskoden. + Det redigerbare tekstfelt for adgangskoden. - Gem ændringer til login. + Gem ændringer til login. - Gem ændringer. + Gem ændringer. - Rediger + Rediger - Rediger adgangskode + Rediger adgangskode - Tilføj nyt login + Tilføj nyt login - Tilføj adgangskode + Tilføj adgangskode - Adgangskode påkrævet + Adgangskode påkrævet - Indtast en adgangskode + Indtast en adgangskode - Brugernavn påkrævet + Brugernavn påkrævet - Indtast et brugernavn + Indtast et brugernavn Værtsnavn påkrævet @@ -2173,7 +2196,7 @@ Tryk for at se flere detaljer - Naviger op + Naviger op Luk @@ -2214,8 +2237,6 @@ Justeret bedømmelse - Upålidelige anmeldelser er blevet fjernet - Baseret på pålidelige anmeldelser Højdepunkter fra de seneste anmeldelser @@ -2273,10 +2294,6 @@ Hvis du lægger mærke til at produktet er på lager igen, må du gerne rapportere det. Så kan vi kontrollere anmeldelserne. Rapporter at produktet er på lager - - Kontrollerer kvaliteten af anmeldelser - - Kontrollerer kvaliteten af anmeldelser Kontrollerer kvaliteten af anmeldelser (%s) @@ -2323,13 +2340,19 @@ Læs mere - Ved at vælge "Ja, prøv det" accepterer du %1$s fra Mozillas %2$s og %3$s. + Ved at vælge “Ja, prøv det” accepterer du %1$s fra Mozillas %2$s og %3$s. - Ved at vælge "Ja, prøv det" accepterer du følgende fra %1$s: + Ved at vælge “Ja, prøv det” accepterer du følgende fra %1$s: + + Ved at vælge “Ja, prøv det” accepterer du %1$s\' %2$s og %3$ss %4$s. + + Ved at vælge “Ja, prøv det” accepterer du %1$s\' %2$s og %3$ss %4$s. - privatlivspolitik + privatlivspolitik Privatlivspolitik + + privatlivserklæring betingelser for brug @@ -2401,6 +2424,10 @@ Oversæt siden? + + Side oversat fra %1$s til %2$s Prøv private oversættelser i %1$s @@ -2413,6 +2440,8 @@ Oversæt til Ikke nu + + Vis oprindelig Færdig @@ -2435,6 +2464,16 @@ Læs mere + + + Oversætter… + + Hent sprog i datasparer-tilstand (%1$s)? + + Oversættelses-indstillinger diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 4fc1a8f62..a4747c98d 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -258,6 +258,11 @@ Seite übersetzen + + Seite von %1$s in %2$s übersetzt. + Gewählte Sprache @@ -336,12 +341,22 @@ Firefox-Datenschutzhinweis - + + Weitere Informationen finden Sie in unserem Datenschutzhinweis Wir schützen Sie gerne + + Erfahren Sie, warum Millionen Firefox lieben + + Sicheres Surfen mit mehr Auswahl Unser gemeinnütziger Browser verhindert, dass Unternehmen heimlich Ihre Aktivitäten im Internet verfolgen. + Mehr als 100 Millionen Menschen schützen ihre Privatsphäre, indem sie einen Browser wählen, der von einer gemeinnützigen Organisation unterstützt wird. + + Bekannte Elemente zur Aktivitätenverfolgung? Automatisch blockiert. Erweiterungen? Alle 700 PDFs ausprobieren? Unser eingebautes Lesezeichen macht sie einfach zu verwalten. + Unser gemeinnütziger Browser verhindert, dass Unternehmen heimlich Ihre Aktivitäten im Internet verfolgen.\n\nWeitere Informationen finden Sie in unserem Datenschutzhinweis. @@ -697,9 +712,9 @@ Lesezeichen - Zugangsdaten + Zugangsdaten - Passwörter + Passwörter Offene Tabs @@ -725,9 +740,9 @@ %1$s auf %2$s %3$s - Kreditkarten + Kreditkarten - Zahlungsmethoden + Zahlungsmethoden Adressen @@ -1695,13 +1710,13 @@ Sie können diese Website einfach zum Startbildschirm Ihres Geräts hinzufügen, um unmittelbaren Zugriff darauf zu haben und sie wie eine App zu nutzen. - Zugangsdaten und Passwörter + Zugangsdaten und Passwörter - Passwörter + Passwörter - Zugangsdaten und Passwörter speichern + Zugangsdaten und Passwörter speichern - Passwörter speichern + Passwörter speichern Zum Speichern nachfragen @@ -1717,47 +1732,47 @@ Benutzernamen und Passwörter auf Webseite bei Nutzung von anderen Apps auf Ihrem Gerät automatisch ausfüllen. - Zugangsdaten hinzufügen + Zugangsdaten hinzufügen - Passwort hinzufügen + Passwort hinzufügen - - Zugangsdaten synchronisieren - Passwörter synchronisieren + Zugangsdaten synchronisieren + + Passwörter synchronisieren - Zugangsdaten zwischen Geräten synchronisieren + Zugangsdaten zwischen Geräten synchronisieren - Passwörter geräteübergreifend synchronisieren + Passwörter geräteübergreifend synchronisieren - Gespeicherte Zugangsdaten + Gespeicherte Zugangsdaten - Gespeicherte Passwörter + Gespeicherte Passwörter - Die Zugangsdaten, die Sie speichern oder mit %s synchronisieren, werden hier angezeigt. + Die Zugangsdaten, die Sie speichern oder mit %s synchronisieren, werden hier angezeigt. - Die Passwörter, die Sie speichern oder mit %s synchronisieren, werden hier aufgelistet. Alle gespeicherten Passwörter werden verschlüsselt. + Die Passwörter, die Sie speichern oder mit %s synchronisieren, werden hier aufgelistet. Alle gespeicherten Passwörter werden verschlüsselt. - Erfahren Sie mehr über Sync. + Erfahren Sie mehr über Sync. - Weitere Informationen über Sync + Weitere Informationen über Sync Ausnahmen - Zugangsdaten und Passwörter, die nicht gespeichert werden, werden hier angezeigt. + Zugangsdaten und Passwörter, die nicht gespeichert werden, werden hier angezeigt. - %s speichert keine Passwörter für die hier aufgeführten Websites. + %s speichert keine Passwörter für die hier aufgeführten Websites. - Zugangsdaten und Passwörter werden für diese Websites nicht gespeichert. + Zugangsdaten und Passwörter werden für diese Websites nicht gespeichert. - %s speichert keine Passwörter für diese Websites. + %s speichert keine Passwörter für diese Websites. Alle Ausnahmen löschen - Zugangsdaten durchsuchen + Zugangsdaten durchsuchen - Passwörter durchsuchen + Passwörter durchsuchen Website @@ -1785,17 +1800,17 @@ Passwort verbergen - Zum Anzeigen Ihrer gespeicherten Zugangsdaten entsperren + Zum Anzeigen Ihrer gespeicherten Zugangsdaten entsperren - Zum Anzeigen Ihrer gespeicherten Passwörter entsperren + Zum Anzeigen Ihrer gespeicherten Passwörter entsperren - Sichern Sie Ihre Zugangsdaten und Passwörter + Sichern Sie Ihre Zugangsdaten und Passwörter - Sichern Sie Ihre gespeicherten Passwörter + Sichern Sie Ihre gespeicherten Passwörter - Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Zugangsdaten und Passwörter zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. + Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Zugangsdaten und Passwörter zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. - Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Passwörter zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. + Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Passwörter zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. Später @@ -1813,7 +1828,10 @@ Zuletzt verwendet - Menü mit Zugangsdaten sortieren + Menü mit Zugangsdaten sortieren + + + Menü „Passwörter sortieren“ Menü „Passwörter sortieren“ @@ -1824,40 +1842,43 @@ Adressen - Kreditkarten + Kreditkarten - Zahlungsmethoden + Zahlungsmethoden - Autovervollständigung für Kreditkartendaten + Autovervollständigung für Kreditkartendaten - Zahlungsmethoden speichern und ausfüllen + Zahlungsmethoden speichern und ausfüllen - Daten sind verschlüsselt + Daten sind verschlüsselt - %s verschlüsselt alle von Ihnen gespeicherten Zahlungsmethoden + %s verschlüsselt alle von Ihnen gespeicherten Zahlungsmethoden Karten zwischen Geräten synchronisieren Kreditkarten synchronisieren - Kreditkarte hinzufügen + Kreditkarte hinzufügen - Karte hinzufügen + Karte hinzufügen - Gespeicherte Karten verwalten + Gespeicherte Karten verwalten - Karten verwalten + Karten verwalten Adresse hinzufügen Adressen verwalten - Autovervollständigung für Adressen + Autovervollständigung für Adressen - Adressen speichern und ausfüllen + Adressen speichern und ausfüllen - Dies beinhaltetet Nummern, E-Mail- und Lieferadressen + Dies beinhaltetet Nummern, E-Mail- und Lieferadressen + + + Enthält Telefonnummern und E-Mail-Adressen Enthält Telefonnummern und E-Mail-Adressen @@ -1881,9 +1902,9 @@ Karte löschen - Soll diese Kreditkarte wirklich gelöscht werden? + Soll diese Kreditkarte wirklich gelöscht werden? - Karte löschen? + Karte löschen? Löschen @@ -1897,24 +1918,24 @@ Gespeicherte Karten - Bitte geben Sie eine gültige Kreditkartennummer ein + Bitte geben Sie eine gültige Kreditkartennummer ein - Geben Sie eine gültige Kartennummer ein + Geben Sie eine gültige Kartennummer ein - Bitte füllen Sie dieses Feld aus + Bitte füllen Sie dieses Feld aus - Fügen Sie einen Namen hinzu + Fügen Sie einen Namen hinzu Zum Anzeigen Ihrer gespeicherten Karten entsperren - Sichern Sie Ihre Kreditkarten + Sichern Sie Ihre Kreditkarten - Sichern Sie Ihre gespeicherten Zahlungsmethoden + Sichern Sie Ihre gespeicherten Zahlungsmethoden - Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Karten zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. + Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Karten zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. - Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Zahlungsmethoden zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. + Richten Sie ein Gerätesperrmuster, eine PIN oder ein Passwort ein, um zu verhindern, dass auf Ihre gespeicherten Zahlungsmethoden zugegriffen wird, wenn jemand anderes über Ihr Gerät verfügt. Jetzt einrichten @@ -1923,10 +1944,10 @@ Entsperren Sie Ihr Gerät - Entsperren, um gespeicherte Kreditkartendaten zu verwenden + Entsperren, um gespeicherte Kreditkartendaten zu verwenden - Zum Verwenden Ihrer gespeicherten Zahlungsmethoden entsperren + Zum Verwenden Ihrer gespeicherten Zahlungsmethoden entsperren Adresse hinzufügen @@ -1934,11 +1955,13 @@ Adressen verwalten - Vorname + Vorname - Zweiter Vorname + Zweiter Vorname - Nachname + Nachname + + Name Straße und Hausnummer @@ -1963,9 +1986,9 @@ Adresse löschen - Soll diese Adresse wirklich gelöscht werden? + Soll diese Adresse wirklich gelöscht werden? - Diese Adresse löschen? + Diese Adresse löschen? Löschen @@ -2063,49 +2086,49 @@ Bearbeiten - Sollen diese Zugangsdaten wirklich gelöscht werden? + Sollen diese Zugangsdaten wirklich gelöscht werden? - Soll dieses Passwort wirklich gelöscht werden? + Soll dieses Passwort wirklich gelöscht werden? Löschen Abbrechen - Optionen für Zugangsdaten + Optionen für Zugangsdaten - Passwort-Optionen + Passwort-Optionen - Das bearbeitbare Textfeld für die Internetadresse der Zugangsdaten. + Das bearbeitbare Textfeld für die Internetadresse der Zugangsdaten. - Das bearbeitbare Textfeld für die Adresse der Website. + Das bearbeitbare Textfeld für die Adresse der Website. - Das bearbeitbare Textfeld für den Benutzernamen der Zugangsdaten. + Das bearbeitbare Textfeld für den Benutzernamen der Zugangsdaten. - Das bearbeitbare Textfeld für den Benutzernamen. + Das bearbeitbare Textfeld für den Benutzernamen. - Das bearbeitbare Textfeld für das Passwort der Zugangsdaten. + Das bearbeitbare Textfeld für das Passwort der Zugangsdaten. - Das bearbeitbare Textfeld für das Passwort. + Das bearbeitbare Textfeld für das Passwort. - Änderungen an Zugangsdaten speichern. + Änderungen an Zugangsdaten speichern. - Änderungen speichern. + Änderungen speichern. - Bearbeiten + Bearbeiten - Passwort bearbeiten + Passwort bearbeiten - Neue Zugangsdaten hinzufügen + Neue Zugangsdaten hinzufügen - Passwort hinzufügen + Passwort hinzufügen - Passwort erforderlich + Passwort erforderlich - Passwort eingeben + Passwort eingeben - Benutzername erforderlich + Benutzername erforderlich - Benutzername eingeben + Benutzername eingeben Hostname erforderlich @@ -2217,7 +2240,7 @@ Klicken Sie hier für weitere Details - Nach oben navigieren + Nach oben navigieren Schließen @@ -2258,8 +2281,6 @@ Bewertungen angepasst - Unzuverlässige Bewertungen entfernt - Basierend auf zuverlässigen Bewertungen Highlights aus aktuellen Bewertungen @@ -2315,10 +2336,6 @@ Wenn Sie sehen, dass dieses Produkt wieder auf Lager ist, melden Sie es und wir arbeiten an der Überprüfung der Bewertungen. Melden, dass das Produkt vorrätig ist - - Qualität der Bewertung wird überprüft - - Qualität der Bewertung wird überprüft Qualität der Bewertungen wird überprüft (%s) @@ -2364,13 +2381,19 @@ Weitere Informationen - Indem Sie „Ja, ausprobieren“ auswählen, stimmen Sie der %2$s und den %3$s von %1$s zu, das von Mozilla angeboten wird. + Indem Sie „Ja, ausprobieren“ auswählen, stimmen Sie der %2$s und den %3$s von %1$s zu, das von Mozilla angeboten wird. Indem Sie „Ja, ausprobieren“ auswählen, stimmen Sie dem folgenden von %1$s zu: + + Indem Sie „Ja, ausprobieren“ auswählen, stimmen Sie dem %2$s von %1$s und dem %4$s von %3$s zu. + + Indem Sie „Ja, ausprobieren“ auswählen, stimmen Sie dem %2$s von %1$s und dem %4$s von %3$s zu. - Datenschutzerklärung + Datenschutzerklärung Datenschutzrichtlinie + + Datenschutzhinweis Nutzungsbedingungen @@ -2441,6 +2464,10 @@ Diese Seite übersetzen? + + Seite von %1$s in %2$s übersetzt Private Übersetzungen in %1$s ausprobieren @@ -2453,6 +2480,8 @@ Übersetzen auf Nicht jetzt + + Original anzeigen Fertig @@ -2475,6 +2504,16 @@ Weitere Informationen + + Wird übersetzt… + + + Sprache im Datensparmodus herunterladen (%1$s)? + + Übersetzungsoptionen diff --git a/app/src/main/res/values-dsb/strings.xml b/app/src/main/res/values-dsb/strings.xml index 629b72032..d1d9bf634 100644 --- a/app/src/main/res/values-dsb/strings.xml +++ b/app/src/main/res/values-dsb/strings.xml @@ -254,6 +254,11 @@ Bok pśełožyś + + Bok jo se pśełožył z rěcy %1$s do rěcy %2$s. + Wubrana rěc @@ -330,12 +335,22 @@ Powěźeńka priwatnosći Firefox - + + Zgóńśo wěcej w našej powěźeńce priwatnosći Šćitamy was rad + + Wuslěźćo, cogodla miliony luźi Firefox lubuju + + Wěste pśeglědowanje z wěcej wuběrkami Naš za wšykne wužytny wobglědowak pśedewześam zawoborujo, wam kšajźu pó interneśe slědowaś. + Wěcej ako 100 milionow luźi šćita swóju priwatnosć, gaž wobglědowak wuběraśo, kótaryž se wót njekomercielneje organizacije pódpěra. + + Znate pśeslědowaki? Blokuju se awtomatiski. Rozšyrjenja? Wopytajśo wšykne 700. PDF? Naš zatwarjony cytak wólažcujo je zastojaś. + Naš za wšykne wužytny wobglědowak tomu zajźujo, až pśedewześa wam kšajźu pó interneśe slěduju.\n\nDalšne informacije w našej powěźeńce priwatnosći. @@ -689,9 +704,9 @@ Cytańske znamjenja - Pśizjawjenja + Pśizjawjenja - Gronidła + Gronidła Wócynjone rejtarki @@ -717,9 +732,9 @@ %1$s wót %2$s %3$s - Kreditowe kórty + Kreditowe kórty - Płaśeńske metody + Płaśeńske metody Adrese @@ -1661,13 +1676,13 @@ Móžośo startowej wobrazowce swójogo rěda toś to websedło lažko pśidaś, aby direktny pśistup měł a malsnjej z dožywjenim nałoženja pśeglědował. - Pśizjawjenja a gronidła + Pśizjawjenja a gronidła - Gronidła + Gronidła - Pśizjawjenja a gronidła składowaś + Pśizjawjenja a gronidła składowaś - Gronidła składowaś + Gronidła składowaś Pśed składowanim se pšašaś @@ -1682,47 +1697,47 @@ Wužywaŕske mjenja a gronidła w drugich nałoženjach na wašom rěźe zasajźiś. - Pśizjawjenje pśidaś + Pśizjawjenje pśidaś - Gronidło pśidaś + Gronidło pśidaś - - Pśizjawjenja synchronizěrowaś - Gronidła synchronizěrowaś + Pśizjawjenja synchronizěrowaś + + Gronidła synchronizěrowaś - Pśizjawjenja mjazy rědami synchronizěrowaś + Pśizjawjenja mjazy rědami synchronizěrowaś - Gronidła pśez rědy synchronizěrowaś + Gronidła pśez rědy synchronizěrowaś - Skłaźone pśizjawjenja + Skłaźone pśizjawjenja - Skłaźone gronidła + Skłaźone gronidła - Pśizjawjenja, kótarež składujośo abo z %s synchronizěrujośo, se how pokažu. + Pśizjawjenja, kótarež składujośo abo z %s synchronizěrujośo, se how pokažu. - Gronidła, kótarež składujośo abo z %s synchronizěrujośo, se how nalicyju. Wšykne gronidła, kótarež składujośo, se koděruju. + Gronidła, kótarež składujośo abo z %s synchronizěrujośo, se how nalicyju. Wšykne gronidła, kótarež składujośo, se koděruju. - Zgóńśo wěcej wó Sync. + Zgóńśo wěcej wó Sync. - Zgóńśo wěcej wó sync + Zgóńśo wěcej wó sync Wuwześa - Pśizjawjenja a gronidła, kótarež se njeskładuju, se how pokažu. + Pśizjawjenja a gronidła, kótarež se njeskładuju, se how pokažu. - %s gronidła za sedła njeskładujo, kótarež su how nalicone. + %s gronidła za sedła njeskładujo, kótarež su how nalicone. - Pśizjawjenja a gronidła se za toś te sedła njeskładuju. + Pśizjawjenja a gronidła se za toś te sedła njeskładuju. - %s gronidła za toś te sedła njeskładujo. + %s gronidła za toś te sedła njeskładujo. Wšykne wuwześa wulašowaś - Pśizjawjenja pytaś + Pśizjawjenja pytaś - Gronidła pśepytaś + Gronidła pśepytaś Sedło @@ -1751,17 +1766,17 @@ Gronidła schowaś - Za zwobraznjowanje wašych skłaźonych pśizjawjenjow wótwóriś + Za zwobraznjowanje wašych skłaźonych pśizjawjenjow wótwóriś - Za zwobraznjowanje wašych skłaźonych kreditowych gronidłow wótwóriś + Za zwobraznjowanje wašych skłaźonych kreditowych gronidłow wótwóriś - Zawěsććo swóje pśizjawjenja a gronidła + Zawěsććo swóje pśizjawjenja a gronidła - Zawěsććo swóje skłaźone gronidła + Zawěsććo swóje skłaźone gronidła - Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym pśizjawjenjam a gronidłam zajźował, jolic něchten drugi ma waš rěd. + Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym pśizjawjenjam a gronidłam zajźował, jolic něchten drugi ma waš rěd. - Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym gronidłam zajźował, jolic něchten drugi ma waš rěd. + Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym gronidłam zajźował, jolic něchten drugi ma waš rěd. Pózdźej @@ -1779,7 +1794,10 @@ Slědnem wužyśu - Meni pśizjawjeńskich datow sortěrowaś + Meni pśizjawjeńskich datow sortěrowaś + + + Meni „Gronidła sortěrowaś“ Meni „Gronidła sortěrowaś“ @@ -1790,40 +1808,43 @@ Adrese - Kreditowe kórty + Kreditowe kórty - Płaśeńske metody + Płaśeńske metody - Kórty składowaś a awtomatiski wupołniś + Kórty składowaś a awtomatiski wupołniś - Płaśeńske metody składowaś a wupołniś + Płaśeńske metody składowaś a wupołniś - Daty su skoděrowane + Daty su skoděrowane - %s wšykne płaśeńske metody koděrujo, kótarež składujośo + %s wšykne płaśeńske metody koděrujo, kótarež składujośo Kórty pśez rědy synchronizěrowaś Kórty synchronizěrowaś - Kreditowu kórtu pśidaś + Kreditowu kórtu pśidaś - Kórtu pśidaś + Kórtu pśidaś - Skłaźone kórty zastojaś + Skłaźone kórty zastojaś - Kórty zastojaś + Kórty zastojaś Adresu pśidaś Adrese zastojaś - Adrese składowaś a awtomatiski wupołniś + Adrese składowaś a awtomatiski wupołniś - Adrese składowaś a wupołniś + Adrese składowaś a wupołniś - Informacije ako licby, e-mailowe a rozpósłańske adrese zapśimjeś + Informacije ako licby, e-mailowe a rozpósłańske adrese zapśimjeś + + + Wopśimujo telefonowe numery a e-mailowe adrese Wopśimujo telefonowe numery a e-mailowe adrese @@ -1847,9 +1868,9 @@ Kórtu wulašowaś - Cośo napšawdu toś tu kreditowu kórtu lašowaś? + Cośo napšawdu toś tu kreditowu kórtu lašowaś? - Kórtu wulašowaś? + Kórtu wulašowaś? Lašowaś @@ -1863,24 +1884,24 @@ Skłaźone kórty - Pšosym zapódajśo płaśiwy numer kreditoweje kórty + Pšosym zapódajśo płaśiwy numer kreditoweje kórty - Zapódajśo płaśiwy kórtowy numer + Zapódajśo płaśiwy kórtowy numer - Pšosym wupołńśo toś to pólo + Pšosym wupołńśo toś to pólo - Pśidajśo mě + Pśidajśo mě Za zwobraznjowanje wašych skłaźonych kreditowych kórtow wótwóriś - Kreditowe kórty zawěsćiś + Kreditowe kórty zawěsćiś - Zawěsććo swóje skłaźone płaśeńske metody + Zawěsććo swóje skłaźone płaśeńske metody - Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym kreditowym kórtam zajźował, jolic něchten drugi ma waš rěd. + Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym kreditowym kórtam zajźował, jolic něchten drugi ma waš rěd. - Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym płaśeńskim metodam zajźował, jolic něchten drugi ma waš rěd. + Nastajśo rědowy zastajeński muster, PIN abo gronidło, aby pśistupoju k swójim skłaźonym płaśeńskim metodam zajźował, jolic něchten drugi ma waš rěd. Něnto konfigurěrowaś @@ -1889,10 +1910,10 @@ Wótwóŕśo swój rěd - Blokěrowanje wótpóraś, aby se skłaźone informacije kreditoweje kórty wužywali + Blokěrowanje wótpóraś, aby se skłaźone informacije kreditoweje kórty wužywali - Wótwóriś, aby wy skłaźone płaśeńske metody wužywał + Wótwóriś, aby wy skłaźone płaśeńske metody wužywał Adresu pśidaś @@ -1900,11 +1921,13 @@ Adrese zastojaś - Pśedmě + Pśedmě - Druge pśedmě + Druge pśedmě - Familijowe mě + Familijowe mě + + Adresa drogi @@ -1929,9 +1952,9 @@ Adresu lašowaś - Cośo napšawdu toś tu adresu wulašowaś? + Cośo napšawdu toś tu adresu wulašowaś? - Toś tu adresu lašowaś? + Toś tu adresu lašowaś? Lašowaś @@ -2029,49 +2052,49 @@ Wobźěłaś - Cośo napšawdu toś to pśizjawjenje lašowaś? + Cośo napšawdu toś to pśizjawjenje lašowaś? - Cośo napšawdu toś to gronidło lašowaś? + Cośo napšawdu toś to gronidło lašowaś? Lašowaś Pśetergnuś - Pśizjawjeńske nastajenja + Pśizjawjeńske nastajenja - Gronidłowe nastajenja + Gronidłowe nastajenja - Wobźěłujobne tekstowe pólo za webadresu pśizjawjenja. + Wobźěłujobne tekstowe pólo za webadresu pśizjawjenja. - Wobźěłujobne tekstowe pólo za adresu websedła. + Wobźěłujobne tekstowe pólo za adresu websedła. - Wobźěłujobne tekstowe pólo za wužywaŕske mě pśizjawjenja. + Wobźěłujobne tekstowe pólo za wužywaŕske mě pśizjawjenja. - Wobźěłujobne tekstowe pólo za wužywaŕske mě. + Wobźěłujobne tekstowe pólo za wužywaŕske mě. - Wobźěłujobne tekstowe pólo za gronidło pśizjawjenja. + Wobźěłujobne tekstowe pólo za gronidło pśizjawjenja. - Wobźěłujobne tekstowe pólo za gronidło. + Wobźěłujobne tekstowe pólo za gronidło. - Změny pśizjawjenja składowaś + Změny pśizjawjenja składowaś - Změny składowaś. + Změny składowaś. - Wobźěłaś + Wobźěłaś - Gronidło wobźěłaś + Gronidło wobźěłaś - Nowe pśizjawjenje pśidaś + Nowe pśizjawjenje pśidaś - Gronidło pśidaś + Gronidło pśidaś - Gronidło trěbne + Gronidło trěbne - Gronidło zapódaś + Gronidło zapódaś - Wužywaŕske mě trěbne. + Wužywaŕske mě trěbne. - Wužywaŕske mě zapódaś + Wužywaŕske mě zapódaś Hostmě trěbne. @@ -2184,7 +2207,7 @@ Klikniśo za dalšne drobnostki - Górjej + Górjej Zacyniś @@ -2225,8 +2248,6 @@ Pśměrjone pógódnośowanje - Njespušćobne pógódnośenja wótwónoźone - Bazěrujo na spušćobnych pógódnośenjach Wjerški z nejnowšych pógódnośenjow @@ -2283,10 +2304,6 @@ To buźo jano pomagaś, kwalitu pógódnośenjow pósuźiś, nic kwalitu produkt Jolic wiźiśo, až toś ten produkt jo zasej na skłaźe, dajśo to k wěsći a buźomy na kontrolěrowanju pógódnośenjow źěłaś. K wěsći daś, až produkt jo na skłaźe - - Kontrola kwalitu pógódnośenjow - - Kontrola kwalitu pógódnośenjow Kontrola kwalitu pógódnośenjow (%s) @@ -2333,13 +2350,19 @@ To buźo jano pomagaś, kwalitu pógódnośenjow pósuźiś, nic kwalitu produkt Dalšne informacije - Gaž „Jo, wopytaś“ wuběraśo, zwólijośo do %2$s a %3$s Mozilla za %1$s. + Gaž „Jo, wopytaś“ wuběraśo, zwólijośo do %2$s a %3$s Mozilla za %1$s. Gaž „Jo, wopytaś“ wuběraśo, zwólijośo do slědujucego wót %1$s: + + Gaž „Jo, wopytaś“ wuběraśo, zwólijośo do %2$s %1$s a %4$s %3$s + + Gaž „Jo, wopytaś“ wuběraśo, zwólijośo do %2$s %1$s a %4$s %3$s - pšawidła priwatnosći + pšawidła priwatnosći Pšawidła priwatnosći + + powěźeńka priwatnosći wužywańske wuměnjenja @@ -2410,6 +2433,10 @@ To buźo jano pomagaś, kwalitu pógódnośenjow pósuźiś, nic kwalitu produkt Toś ten bok pśełožowaś? + + Bok jo se pśełožył z rěcy %1$s do rěcy %2$s Priwatne pśełožki w %1$s testowaś @@ -2422,6 +2449,8 @@ To buźo jano pomagaś, kwalitu pógódnośenjow pósuźiś, nic kwalitu produkt Celowa rěc Nic něnto + + Original pokazaś Dokóńcone @@ -2444,6 +2473,16 @@ To buźo jano pomagaś, kwalitu pógódnośenjow pósuźiś, nic kwalitu produkt Dalšne informacije + + Pśełožujo se… + + + Rěc w datowem žarjeńskem modusu ześěgnuś (%1$s)? + + Pśełožowańske nastajenja diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 28bb5798a..44b1e4554 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -260,6 +260,11 @@ Μετάφραση σελίδας + + Η σελίδα μεταφράστηκε από τα %1$s στα %2$s. + Επιλεγμένη γλώσσα @@ -338,9 +343,21 @@ Σημείωση απορρήτου του Firefox - + + Μάθετε περισσότερα στη σημείωση απορρήτου μας Μας αρέσει να σας προστατεύουμε + + Μάθετε γιατί εκατομμύρια άνθρωποι αγαπούν το Firefox + + Ασφαλής περιήγηση με περισσότερες επιλογές + + Το πρόγραμμα περιήγησης του μη κερδοσκοπικού μας οργανισμού σταματά τις εταιρείες από το να σας ακολουθούν κρυφά σε όλο το διαδίκτυο. + + Περισσότεροι από 100 εκατομμύρια χρήστες προστατεύουν το απόρρητό τους επιλέγοντας ένα πρόγραμμα περιήγησης που υποστηρίζεται από έναν μη κερδοσκοπικό οργανισμό. + + Γνωστοί ιχνηλάτες; Αποκλείονται αυτόματα. Επεκτάσεις; Δοκιμάστε και τις 700. PDF; Το ενσωματωμένο εργαλείο ανάγνωσης καθιστά εύκολη τη διαχείρισή τους. Το πρόγραμμα περιήγησης του μη κερδοσκοπικού μας οργανισμού σταματά τις εταιρείες από το να σας ακολουθούν κρυφά σε όλο το διαδίκτυο. @@ -700,9 +717,9 @@ Σελιδοδείκτες - Συνδέσεις + Συνδέσεις - Κωδικοί πρόσβασης + Κωδικοί πρόσβασης Ανοικτές καρτέλες @@ -728,9 +745,9 @@ %1$s στο %2$s %3$s - Πιστωτικές κάρτες + Πιστωτικές κάρτες - Μέθοδοι πληρωμής + Μέθοδοι πληρωμής Διευθύνσεις @@ -1561,7 +1578,7 @@ Απομόνωση cookie μεταξύ ιστοτόπων - Αποστολή αιτήματος μη πώλησης και κοινοποίησης των δεδομένων μου στους ιστοτόπους + Αποστολή αιτήματος μη πώλησης και κοινοποίησης δεδομένων στους ιστοτόπους Περιεχόμενο καταγραφής @@ -1680,13 +1697,13 @@ Μπορείτε εύκολα να προσθέσετε αυτόν τον ιστότοπο στην αρχική οθόνη για άμεση πρόσβαση και ταχύτερη περιήγηση, σαν να ήταν εφαρμογή. - Συνδέσεις και κωδικοί πρόσβασης + Συνδέσεις και κωδικοί πρόσβασης - Κωδικοί πρόσβασης + Κωδικοί πρόσβασης - Αποθήκευση συνδέσεων και κωδικών πρόσβασης + Αποθήκευση συνδέσεων και κωδικών πρόσβασης - Αποθήκευση κωδικών πρόσβασης + Αποθήκευση κωδικών πρόσβασης Ερώτηση για αποθήκευση @@ -1702,47 +1719,47 @@ Συμπλήρωση στοιχείων σύνδεσης σε άλλες εφαρμογές της συσκευής σας. - Προσθήκη σύνδεσης + Προσθήκη σύνδεσης - Προσθήκη κωδικού πρόσβασης + Προσθήκη κωδικού πρόσβασης - - Συγχρονισμός συνδέσεων - Συγχρονισμός κωδικών πρόσβασης + Συγχρονισμός συνδέσεων + + Συγχρονισμός κωδικών πρόσβασης - Συγχρονισμός συνδέσεων μεταξύ συσκευών + Συγχρονισμός συνδέσεων μεταξύ συσκευών - Συγχρονισμός κωδικών πρόσβασης μεταξύ των συσκευών σας + Συγχρονισμός κωδικών πρόσβασης μεταξύ των συσκευών σας - Αποθηκευμένες συνδέσεις + Αποθηκευμένες συνδέσεις - Αποθηκευμένοι κωδικοί πρόσβασης + Αποθηκευμένοι κωδικοί πρόσβασης - Οι συνδέσεις που αποθηκεύετε ή συγχρονίζετε στο %s θα εμφανίζονται εδώ. + Οι συνδέσεις που αποθηκεύετε ή συγχρονίζετε στο %s θα εμφανίζονται εδώ. - Οι κωδικοί πρόσβασης που αποθηκεύετε ή συγχρονίζετε στο %s θα εμφανίζονται εδώ. Όλοι οι κωδικοί πρόσβασης που αποθηκεύετε κρυπτογραφούνται. + Οι κωδικοί πρόσβασης που αποθηκεύετε ή συγχρονίζετε στο %s θα εμφανίζονται εδώ. Όλοι οι κωδικοί πρόσβασης που αποθηκεύετε κρυπτογραφούνται. - Μάθετε περισσότερα σχετικά με το Sync. + Μάθετε περισσότερα σχετικά με το Sync. - Μάθετε περισσότερα σχετικά με τον συγχρονισμό + Μάθετε περισσότερα σχετικά με τον συγχρονισμό Εξαιρέσεις - Εδώ εμφανίζονται οι συνδέσεις και οι κωδικοί πρόσβασης που δεν αποθηκεύονται. + Εδώ εμφανίζονται οι συνδέσεις και οι κωδικοί πρόσβασης που δεν αποθηκεύονται. - Το %s δεν θα αποθηκεύει κωδικούς πρόσβασης για τους ιστοτόπους που αναφέρονται εδώ. + Το %s δεν θα αποθηκεύει κωδικούς πρόσβασης για τους ιστοτόπους που αναφέρονται εδώ. - Δεν θα αποθηκεύονται στοιχεία σύνδεσης για τους εξής ιστοτόπους. + Δεν θα αποθηκεύονται στοιχεία σύνδεσης για τους εξής ιστοτόπους. - Το %s δεν θα αποθηκεύει κωδικούς πρόσβασης για αυτούς τους ιστοτόπους. + Το %s δεν θα αποθηκεύει κωδικούς πρόσβασης για αυτούς τους ιστοτόπους. Διαγραφή όλων των εξαιρέσεων - Αναζήτηση συνδέσεων + Αναζήτηση συνδέσεων - Αναζήτηση κωδικών πρόσβασης + Αναζήτηση κωδικών πρόσβασης Ιστότοπος @@ -1770,17 +1787,17 @@ Απόκρυψη κωδικού πρόσβασης - Ξεκλειδώστε για να δείτε τις αποθηκευμένες συνδέσεις σας + Ξεκλειδώστε για να δείτε τις αποθηκευμένες συνδέσεις σας - Ξεκλειδώστε για να δείτε τους αποθηκευμένους κωδικούς πρόσβασής σας + Ξεκλειδώστε για να δείτε τους αποθηκευμένους κωδικούς πρόσβασής σας - Προστασία στοιχείων σύνδεσης + Προστασία στοιχείων σύνδεσης - Προστασία των αποθηκευμένων κωδικών πρόσβασής σας + Προστασία των αποθηκευμένων κωδικών πρόσβασής σας - Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για προστασία των αποθηκευμένων στοιχείων σύνδεσης, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. + Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για προστασία των αποθηκευμένων στοιχείων σύνδεσης, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. - Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων κωδικών πρόσβασής σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. + Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων κωδικών πρόσβασής σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. Αργότερα @@ -1797,7 +1814,10 @@ Τελευταία χρήση - Ταξινόμηση μενού σύνδεσης + Ταξινόμηση μενού σύνδεσης + + + Μενού ταξινόμησης κωδικών πρόσβασης Μενού ταξινόμησης κωδικών πρόσβασης @@ -1808,41 +1828,44 @@ Διευθύνσεις - Πιστωτικές κάρτες + Πιστωτικές κάρτες - Μέθοδοι πληρωμής + Μέθοδοι πληρωμής - Αποθήκευση και αυτόματη συμπλήρωση στοιχείων καρτών + Αποθήκευση και αυτόματη συμπλήρωση στοιχείων καρτών - Αποθήκευση και συμπλήρωση μεθόδων πληρωμής + Αποθήκευση και συμπλήρωση μεθόδων πληρωμής - Τα δεδομένα κρυπτογραφούνται + Τα δεδομένα κρυπτογραφούνται - Το %s κρυπτογραφεί όλες τις μεθόδους πληρωμής που αποθηκεύετε + Το %s κρυπτογραφεί όλες τις μεθόδους πληρωμής που αποθηκεύετε Συγχρονισμός καρτών μεταξύ συσκευών Συγχρονισμός καρτών - Προσθήκη πιστωτικής κάρτας + Προσθήκη πιστωτικής κάρτας - Προσθήκη κάρτας + Προσθήκη κάρτας - Διαχείριση αποθηκευμένων καρτών + Διαχείριση αποθηκευμένων καρτών - Διαχείριση καρτών + Διαχείριση καρτών Προσθήκη διεύθυνσης Διαχείριση διευθύνσεων - Αποθήκευση και αυτόματη συμπλήρωση διευθύνσεων + Αποθήκευση και αυτόματη συμπλήρωση διευθύνσεων - Αποθήκευση και συμπλήρωση διευθύνσεων + Αποθήκευση και συμπλήρωση διευθύνσεων - Συμπεριλάβετε πληροφορίες, όπως αριθμούς, email και διευθύνσεις αποστολής + Συμπεριλάβετε πληροφορίες, όπως αριθμούς, email και διευθύνσεις αποστολής + + + Περιλαμβάνει αριθμούς τηλεφώνου και διευθύνσεις email Περιλαμβάνει αριθμούς τηλεφώνου και διευθύνσεις email @@ -1866,9 +1889,9 @@ Διαγραφή κάρτας - Θέλετε σίγουρα να διαγράψετε αυτήν την πιστωτική κάρτα; + Θέλετε σίγουρα να διαγράψετε αυτήν την πιστωτική κάρτα; - Διαγραφή κάρτας; + Διαγραφή κάρτας; Διαγραφή @@ -1882,24 +1905,24 @@ Αποθηκευμένες κάρτες - Παρακαλώ εισαγάγετε έναν έγκυρο αριθμό πιστωτικής κάρτας + Παρακαλώ εισαγάγετε έναν έγκυρο αριθμό πιστωτικής κάρτας - Εισαγάγετε έγκυρο αριθμό κάρτας + Εισαγάγετε έγκυρο αριθμό κάρτας - Παρακαλώ συμπληρώστε αυτό το πεδίο + Παρακαλώ συμπληρώστε αυτό το πεδίο - Προσθήκη ονόματος + Προσθήκη ονόματος Ξεκλειδώστε για να δείτε τις αποθηκευμένες κάρτες σας - Ασφαλίστε τις πιστωτικές κάρτες σας + Ασφαλίστε τις πιστωτικές κάρτες σας - Προστασία των αποθηκευμένων μεθόδων πληρωμής σας + Προστασία των αποθηκευμένων μεθόδων πληρωμής σας - Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων πιστωτικών καρτών σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. + Ορίστε ένα μοτίβο κλειδώματος συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων πιστωτικών καρτών σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. - Ορίστε ένα μοτίβο κλειδώματος της συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων καρτών σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. + Ορίστε ένα μοτίβο κλειδώματος της συσκευής, ένα ΡΙΝ ή έναν κωδικό πρόσβασης για την προστασία των αποθηκευμένων καρτών σας, σε περίπτωση που κάποιος τρίτος αποκτήσει πρόσβαση στη συσκευή σας. Ρύθμιση τώρα @@ -1908,10 +1931,10 @@ Ξεκλειδώστε τη συσκευή σας - Ξεκλειδώστε για χρήση των στοιχείων πιστωτικής κάρτας + Ξεκλειδώστε για χρήση των στοιχείων πιστωτικής κάρτας - Ξεκλειδώστε για χρήση των αποθηκευμένων μεθόδων πληρωμής + Ξεκλειδώστε για χρήση των αποθηκευμένων μεθόδων πληρωμής Προσθήκη διεύθυνσης @@ -1919,11 +1942,13 @@ Διαχείριση διευθύνσεων - Όνομα + Όνομα - Μεσαίο όνομα + Μεσαίο όνομα - Επώνυμο + Επώνυμο + + Όνομα Διεύθυνση @@ -1948,9 +1973,9 @@ Διαγραφή διεύθυνσης - Θέλετε σίγουρα να διαγράψετε αυτήν τη διεύθυνση; + Θέλετε σίγουρα να διαγράψετε αυτήν τη διεύθυνση; - Διαγραφή διεύθυνσης; + Διαγραφή διεύθυνσης; Διαγραφή @@ -2051,49 +2076,49 @@ Επεξεργασία - Θέλετε σίγουρα να διαγράψετε αυτή τη σύνδεση; + Θέλετε σίγουρα να διαγράψετε αυτή τη σύνδεση; - Θέλετε σίγουρα να διαγράψετε αυτόν τον κωδικό πρόσβασης; + Θέλετε σίγουρα να διαγράψετε αυτόν τον κωδικό πρόσβασης; Διαγραφή Ακύρωση - Επιλογές σύνδεσης + Επιλογές σύνδεσης - Επιλογές κωδικών πρόσβασης + Επιλογές κωδικών πρόσβασης - Το επεξεργάσιμο πεδίο κειμένου της διεύθυνσης ιστού της σύνδεσης. + Το επεξεργάσιμο πεδίο κειμένου της διεύθυνσης ιστού της σύνδεσης. - Το επεξεργάσιμο πεδίο κειμένου της διεύθυνσης ιστοτόπου. + Το επεξεργάσιμο πεδίο κειμένου της διεύθυνσης ιστοτόπου. - Το επεξεργάσιμο πεδίο κειμένου για το όνομα χρήστη της σύνδεσης. + Το επεξεργάσιμο πεδίο κειμένου για το όνομα χρήστη της σύνδεσης. - Το επεξεργάσιμο πεδίο κειμένου για το όνομα χρήστη. + Το επεξεργάσιμο πεδίο κειμένου για το όνομα χρήστη. - Το επεξεργάσιμο πεδίο κειμένου για τον κωδικό πρόσβασης της σύνδεσης. + Το επεξεργάσιμο πεδίο κειμένου για τον κωδικό πρόσβασης της σύνδεσης. - Το επεξεργάσιμο πεδίο κειμένου για τον κωδικό πρόσβασης. + Το επεξεργάσιμο πεδίο κειμένου για τον κωδικό πρόσβασης. - Αποθήκευση αλλαγών στη σύνδεση. + Αποθήκευση αλλαγών στη σύνδεση. - Αποθήκευση αλλαγών. + Αποθήκευση αλλαγών. - Επεξεργασία + Επεξεργασία - Επεξεργασία κωδικού πρόσβασης + Επεξεργασία κωδικού πρόσβασης - Προσθήκη νέας σύνδεσης + Προσθήκη νέας σύνδεσης - Προσθήκη κωδικού πρόσβασης + Προσθήκη κωδικού πρόσβασης - Απαιτείται κωδικός πρόσβασης + Απαιτείται κωδικός πρόσβασης - Εισαγάγετε έναν κωδικό πρόσβασης + Εισαγάγετε έναν κωδικό πρόσβασης - Απαιτείται όνομα χρήστη + Απαιτείται όνομα χρήστη - Εισαγάγετε ένα όνομα χρήστη + Εισαγάγετε ένα όνομα χρήστη Απαιτείται όνομα κεντρικού υπολογιστή @@ -2206,7 +2231,7 @@ Πατήστε για περισσότερες λεπτομέρειες - Πλοήγηση προς τα πάνω + Πλοήγηση προς τα πάνω Κλείσιμο @@ -2247,8 +2272,6 @@ Αναπροσαρμοσμένη βαθμολογία - Οι αναξιόπιστες κριτικές αφαιρέθηκαν - Με βάση αξιόπιστες κριτικές Σημαντικά σημεία από πρόσφατες κριτικές @@ -2304,10 +2327,6 @@ Εάν παρατηρήσετε ότι αυτό το προϊόν είναι ξανά σε απόθεμα, αναφέρετέ το σε μας και θα αρχίσουμε τον έλεγχο των κριτικών. Αναφέρετε ότι το προϊόν είναι σε απόθεμα - - Έλεγχος ποιότητας κριτικής - - Έλεγχος ποιότητας κριτικής Έλεγχος ποιότητας κριτικής (%s) @@ -2353,13 +2372,19 @@ Μάθετε περισσότερα - Επιλέγοντας «Έναρξη δοκιμής», αποδέχεστε την %2$s και τους %3$s του %1$s, που παρέχεται από τη Mozilla. + Επιλέγοντας «Έναρξη δοκιμής», αποδέχεστε την %2$s και τους %3$s του %1$s, που παρέχεται από τη Mozilla. Επιλέγοντας «Έναρξη δοκιμής», συμφωνείτε με τα ακόλουθα από το %1$s: + + Επιλέγοντας «Έναρξη δοκιμής», αποδέχεστε τη %2$s του %1$s και τους %4$s του %3$s. + + Επιλέγοντας «Έναρξη δοκιμής», αποδέχεστε τη %2$s του %1$s και τους %4$s του %3$s. - πολιτική απορρήτου + πολιτική απορρήτου Πολιτική απορρήτου + + σημείωση απορρήτου όρους χρήσης @@ -2431,6 +2456,10 @@ Μετάφραση σελίδας; + + Η σελίδα μεταφράστηκε από τα %1$s στα %2$s Ιδιωτικές μεταφράσεις στο %1$s @@ -2443,6 +2472,8 @@ Μετάφραση σε Όχι τώρα + + Εμφάνιση πρωτότυπου Τέλος @@ -2465,6 +2496,16 @@ Μάθετε περισσότερα + + Μετάφραση… + + + Λήψη γλώσσας στη λειτουργία εξοικονόμησης δεδομένων (%1$s); + + Επιλογές μετάφρασης diff --git a/app/src/main/res/values-en-rGB/strings.xml b/app/src/main/res/values-en-rGB/strings.xml index 31dfb31b8..8153bb6d7 100644 --- a/app/src/main/res/values-en-rGB/strings.xml +++ b/app/src/main/res/values-en-rGB/strings.xml @@ -252,6 +252,11 @@ Translate page + + Page translated from %1$s to %2$s. + Selected language @@ -329,12 +334,22 @@ Firefox privacy notice - + + Learn more in our privacy notice We love keeping you safe + + Find out why millions love Firefox + + Safe browsing with more choices Our non-profit backed browser helps stop companies from secretly following you around the web. + More than 100 million people protect their privacy by choosing a browser that’s backed by a nonprofit. + + Known trackers? Blocked automatically. Extensions? Try all 700. PDFs? Our built-in reader makes them easy to manage. + Our non-profit backed browser helps stop companies from secretly following you around the web.\n\nLearn more in our privacy notice. @@ -496,7 +511,7 @@ Secure site not available - Most likely, the web site simply does not support HTTPs. + Most likely, the web site simply does not support HTTPS. However, it’s also possible that an attacker is involved. If you continue to the web site, you should not enter any sensitive info. If you continue, HTTPS-Only mode will be turned off temporarily for the site. @@ -688,9 +703,9 @@ Bookmarks - Logins + Logins - Passwords + Passwords Open tabs @@ -716,9 +731,9 @@ %1$s on %2$s %3$s - Credit cards + Credit cards - Payment methods + Payment methods Addresses @@ -1653,13 +1668,13 @@ You can easily add this web site to your device’s Home screen to have instant access and browse faster with an app-like experience. - Logins and passwords + Logins and passwords - Passwords + Passwords - Save logins and passwords + Save logins and passwords - Save passwords + Save passwords Ask to save @@ -1675,48 +1690,48 @@ Fill usernames and passwords in other apps on your device. - Add login + Add login - Add password + Add password - - Synchronise logins - Synchronise passwords + Synchronise logins + + Synchronise passwords - Synchronise logins across devices + Synchronise logins across devices - Synchronise passwords across devices + Synchronise passwords across devices - Saved logins + Saved logins - Saved passwords + Saved passwords - The logins you save or synchronise to %s will show up here. + The logins you save or synchronise to %s will show up here. - The passwords you save or synchronise to %s will be listed here. All passwords you save are encrypted. + The passwords you save or synchronise to %s will be listed here. All passwords you save are encrypted. - Learn more about Sync. + Learn more about Sync. - Learn more about Sync + Learn more about Sync Exceptions - Logins and passwords that are not saved will be shown here. + Logins and passwords that are not saved will be shown here. - %s won’t save passwords for sites listed here. + %s won’t save passwords for sites listed here. - Logins and passwords will not be saved for these sites. + Logins and passwords will not be saved for these sites. - %s won’t save passwords for these sites. + %s won’t save passwords for these sites. Delete all exceptions - Search logins + Search logins - Search passwords + Search passwords Site @@ -1744,17 +1759,17 @@ Hide password - Unlock to view your saved logins + Unlock to view your saved logins - Unlock to view your saved passwords + Unlock to view your saved passwords - Secure your logins and passwords + Secure your logins and passwords - Secure your saved passwords + Secure your saved passwords - Set up a device lock pattern, PIN, or password to protect your saved logins and passwords from being accessed if someone else has your device. + Set up a device lock pattern, PIN, or password to protect your saved logins and passwords from being accessed if someone else has your device. - Set up a device lock pattern, PIN, or password to protect your saved passwords from being accessed if someone else has your device. + Set up a device lock pattern, PIN, or password to protect your saved passwords from being accessed if someone else has your device. Later @@ -1771,7 +1786,10 @@ Last used - Sort logins menu + Sort logins menu + + + Sort passwords menu Sort passwords menu @@ -1782,40 +1800,43 @@ Addresses - Credit cards + Credit cards - Payment methods + Payment methods - Save and autofill cards + Save and autofill cards - Save and fill payment methods + Save and fill payment methods - Data is encrypted + Data is encrypted - %s encrypts all payment methods you save + %s encrypts all payment methods you save Synchronise cards across devices Synchronise cards - Add credit card + Add credit card - Add card + Add card - Manage saved cards + Manage saved cards - Manage cards + Manage cards Add address Manage addresses - Save and autofill addresses + Save and autofill addresses - Save and fill addresses + Save and fill addresses - Include information like numbers, email and shipping addresses + Include information like numbers, email and shipping addresses + + + Includes phone numbers and email addresses Includes phone numbers and email addresses @@ -1839,9 +1860,9 @@ Delete card - Are you sure you want to delete this credit card? + Are you sure you want to delete this credit card? - Delete card? + Delete card? Delete @@ -1855,24 +1876,24 @@ Saved cards - Please enter a valid credit card number + Please enter a valid credit card number - Enter a valid card number + Enter a valid card number - Please fill out this field + Please fill out this field - Add a name + Add a name Unlock to view your saved cards - Secure your credit cards + Secure your credit cards - Secure your saved payment methods + Secure your saved payment methods - Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. + Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. - Set up a device lock pattern, PIN, or password to protect your saved payment methods from being accessed if someone else has your device. + Set up a device lock pattern, PIN, or password to protect your saved payment methods from being accessed if someone else has your device. Set up now @@ -1880,10 +1901,10 @@ Unlock your device - Unlock to use stored credit card information + Unlock to use stored credit card information - Unlock to use saved payment methods + Unlock to use saved payment methods Add address @@ -1891,11 +1912,13 @@ Manage addresses - First Name + First Name - Middle Name + Middle Name - Last Name + Last Name + + Name Street Address @@ -1920,9 +1943,9 @@ Delete address - Are you sure you want to delete this address? + Are you sure you want to delete this address? - Delete this address? + Delete this address? Delete @@ -2020,49 +2043,49 @@ Edit - Are you sure you want to delete this login? + Are you sure you want to delete this login? - Are you sure you want to delete this password? + Are you sure you want to delete this password? Delete Cancel - Login options + Login options - Password options + Password options - The editable text field for the web address of the login. + The editable text field for the web address of the login. - The editable text field for the web site address. + The editable text field for the web site address. - The editable text field for the username of the login. + The editable text field for the username of the login. - The editable text field for the username. + The editable text field for the username. - The editable text field for the password of the login. + The editable text field for the password of the login. - The editable text field for the password. + The editable text field for the password. - Save changes to login. + Save changes to login. - Save changes. + Save changes. - Edit + Edit - Edit password + Edit password - Add new login + Add new login - Add password + Add password - Password required + Password required - Enter a password + Enter a password - Username required + Username required - Enter a username + Enter a username Hostname required @@ -2174,7 +2197,7 @@ Click for more details - Navigate up + Navigate up Close @@ -2215,8 +2238,6 @@ Adjusted rating - Unreliable reviews removed - Based on reliable reviews Highlights from recent reviews @@ -2272,10 +2293,6 @@ If you see this product is back in stock, report it and we’ll work on checking the reviews. Report product is in stock - - Checking review quality - - Checking review quality Checking review quality (%s) @@ -2321,13 +2338,19 @@ Learn more - By selecting “Yes, try it” you agree to %1$s by Mozilla’s %2$s and %3$s. + By selecting “Yes, try it” you agree to %1$s by Mozilla’s %2$s and %3$s. By selecting “Yes, try it” you agree to the following from %1$s: + + By selecting “Yes, try it” you agree to %1$s’s %2$s and %3$s’s %4$s. + + By selecting “Yes, try it” you agree to %1$s’s %2$s and %3$s’s %4$s. - privacy policy + privacy policy Privacy policy + + privacy notice terms of use @@ -2398,6 +2421,10 @@ Translate this page? + + Page translated from %1$s to %2$s Try private translations in %1$s @@ -2410,6 +2437,8 @@ Translate to Not now + + Show original Done @@ -2432,6 +2461,16 @@ Learn more + + Translating… + + + Download language in data saving mode (%1$s)? + + Translation Options diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index adae84f57..63481c0df 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -250,6 +250,11 @@ Traduki paĝon + + Paĝo tradukita el la %1$s en la %2$sn. + Elektita lingvo @@ -326,12 +331,22 @@ Rimarko de Firefox pri privateco - + + Pli da informo en nia rimarko pri privateco Ni amas teni vin sekura + + Malkovru kial milionoj da personoj amas Firefox + + Sekura retumo kun pli da elektebloj Nia retumilo, subtenata de nenprofitcela organizo, helpas eviti ke entreprenoj kaŝe sekvu vin tra la reto. + Pli ol 100 milionoj da personoj protektas sian privatecon per la elekto de retumilo farita de neprofitcela organizo. + + Kio pri konataj spuriloj? Aŭtomate blokitaj. Kio pri etendaĵoj? Testu ĉiujn 700. Kaj pri PDFs? Nia integrita legilo faciligas pritrakti ilin. + Nia retumilo, subtenata de nenprofitcela organizo, helpas eviti ke entreprenoj kaŝe sekvu vin tra la reto.\n\nPli da informo en nia rimarko pri privateco. @@ -689,9 +704,9 @@ legosignojn - legitimilojn + legitimilojn - Pasvortoj + Pasvortoj Malfermitaj langetoj @@ -717,9 +732,9 @@ %1$s en %2$s %3$s - Kreditkartoj + Kreditkartoj - Pagmetodoj + Pagmetodoj Adresoj @@ -1670,13 +1685,13 @@ Vi povas facile aldoni tiun ĉi retejon al la hejmpaĝo de via aparato, por havi tujan aliron kaj retumi pli rapide per kvazaŭprograma sperto. - Legitimiloj kaj pasvortoj + Legitimiloj kaj pasvortoj - Pasvortoj + Pasvortoj - Konservi legitimilojn kaj pasvortojn + Konservi legitimilojn kaj pasvortojn - Konservi pasvortojn + Konservi pasvortojn Demandi antaŭ ol konservi @@ -1691,48 +1706,48 @@ Plenigi nomojn de uzanto kaj pasvortojn en aliaj programoj en via aparato. - Aldoni legitimilon + Aldoni legitimilon - Aldoni pasvorton + Aldoni pasvorton - - Speguli legitimilojn - Speguli pasvortojn + Speguli legitimilojn + + Speguli pasvortojn - Speguli legitimilojn inter aparatoj + Speguli legitimilojn inter aparatoj - Speguli pasvortojn inter aparatoj + Speguli pasvortojn inter aparatoj - Konservitaj legitimiloj + Konservitaj legitimiloj - Konservitaj pasvortoj + Konservitaj pasvortoj - La legitimiloj, kiujn vi konservas aŭ spegulas al %s, aperos ĉi tie. + La legitimiloj, kiujn vi konservas aŭ spegulas al %s, aperos ĉi tie. - La pasvortoj konservitaj aŭ spegulitaj al %s estos listigitaj ĉi tie. Ĉiuj konservitaj pasvortoj estos ĉifritaj. + La pasvortoj konservitaj aŭ spegulitaj al %s estos listigitaj ĉi tie. Ĉiuj konservitaj pasvortoj estos ĉifritaj. - Pli da informo pri Spegulado. + Pli da informo pri Spegulado. - Pli da informo pri spegulado + Pli da informo pri spegulado Esceptoj - Nekonservitaj nomoj de uzantoj kaj pasvortoj estos montritaj ĉi tie. + Nekonservitaj nomoj de uzantoj kaj pasvortoj estos montritaj ĉi tie. - %s ne konservos pasvortojn por retejoj listigitaj ĉi tie. + %s ne konservos pasvortojn por retejoj listigitaj ĉi tie. - Nomoj de uzanto kaj pasvortoj por tiuj ĉi retejoj ne estos konservitaj. + Nomoj de uzanto kaj pasvortoj por tiuj ĉi retejoj ne estos konservitaj. - %s ne konservos pasvortojn por tiuj ĉi retejoj. + %s ne konservos pasvortojn por tiuj ĉi retejoj. Forigi ĉiujn esceptojn - Serĉi legitimilojn + Serĉi legitimilojn - Serĉi pasvortojn + Serĉi pasvortojn Retejo @@ -1760,18 +1775,18 @@ Kaŝi pasvorton - Malŝlosu por vidi viajn konservitajn legitimilojn + Malŝlosu por vidi viajn konservitajn legitimilojn - Malŝlosi por vidi viajn konservitajn pasvortojn + Malŝlosi por vidi viajn konservitajn pasvortojn - Protektu viajn legitimilojn kaj pasvortojn + Protektu viajn legitimilojn kaj pasvortojn - Protektu viajn konservitajn pasvortojn + Protektu viajn konservitajn pasvortojn - Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn legitimilojn kaj pasvortojn se iu alia havas vian aparaton. + Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn legitimilojn kaj pasvortojn se iu alia havas vian aparaton. - Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn pasvortojn se iu alia havas vian aparaton. + Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn pasvortojn se iu alia havas vian aparaton. Poste @@ -1788,7 +1803,10 @@ Laste uzita - Ordigi menuon de legitimiloj + Ordigi menuon de legitimiloj + + + Menuo por ordigi pasvortojn Menuo por ordigi pasvortojn @@ -1799,39 +1817,42 @@ Adresoj - Kreditkartoj + Kreditkartoj - Pagmetodoj + Pagmetodoj - Konservi kaj aŭtomate plenigi kreditkartojn + Konservi kaj aŭtomate plenigi kreditkartojn - Konservi kaj aŭtomate plenigi pagmetodojn + Konservi kaj aŭtomate plenigi pagmetodojn - La datumoj estas ĉifritaj + La datumoj estas ĉifritaj - %s ĉifras ĉiujn pagmetodojn, kiujn vi konservis + %s ĉifras ĉiujn pagmetodojn, kiujn vi konservis Speguli kreditkartojn inter aparatoj Speguli kreditkartojn - Aldoni kreditkarton + Aldoni kreditkarton - Aldoni kreditkarton + Aldoni kreditkarton - Administri konservitajn kreditkartojn + Administri konservitajn kreditkartojn - Administri kartojn + Administri kartojn Aldoni adreson Administri adresojn - Konservi kaj aŭtomate plenigi adresojn + Konservi kaj aŭtomate plenigi adresojn - Konservi kaj aŭtomate plenigi adresojn + Konservi kaj aŭtomate plenigi adresojn - Inkluzivi informojn kiel numerojn, retpoŝtajn kaj liverajn adresojn + Inkluzivi informojn kiel numerojn, retpoŝtajn kaj liverajn adresojn + + + Telefonnumeroj kaj retpoŝtaj adresoj inkluzivitaj Telefonnumeroj kaj retpoŝtaj adresoj inkluzivitaj @@ -1856,9 +1877,9 @@ Forigi kreditkarton - Ĉu vi certe volas forigi tiun ĉi kreditkarton? + Ĉu vi certe volas forigi tiun ĉi kreditkarton? - Ĉu forigi karton? + Ĉu forigi karton? Forigi @@ -1871,24 +1892,24 @@ Konservitaj kreditkartoj - Bonvolu tajpi validan kreditkaran numeron + Bonvolu tajpi validan kreditkaran numeron - Tajpu validan numeron de karto + Tajpu validan numeron de karto - Bonvolu plenigi tiun ĉi kampon + Bonvolu plenigi tiun ĉi kampon - Aldoni nomon + Aldoni nomon Malŝlosu por vidi viajn konservitajn kreditkartojn - Sekurigu viajn kreditkartojn + Sekurigu viajn kreditkartojn - Protektu viajn konservitajn pagmetodojn + Protektu viajn konservitajn pagmetodojn - Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn kreditkartojn se iu alia havas vian aparaton. + Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn kreditkartojn se iu alia havas vian aparaton. - Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn pagmetodojn se iu alia havas vian aparaton. + Difinu blokan desegnon, PIN aŭ pasvorton por protekti viajn konservitajn pagmetodojn se iu alia havas vian aparaton. Agordi nun @@ -1896,10 +1917,10 @@ Malbloki vian aparaton - Malŝlosu por uzi la konservitan informon pri kreditkartojn + Malŝlosu por uzi la konservitan informon pri kreditkartojn - Malŝlosu por uzi konservitajn pagmetodojn + Malŝlosu por uzi konservitajn pagmetodojn Aldoni adreson @@ -1907,11 +1928,13 @@ Administri adresojn - Persona nomo + Persona nomo - Dua nomo + Dua nomo - Familia nomo + Familia nomo + + Nomo Strata adreso @@ -1936,9 +1959,9 @@ Forigi adreson - Ĉu vi certe volas forigi tiun ĉi adreson? + Ĉu vi certe volas forigi tiun ĉi adreson? - Ĉu forigi tiun ĉi adreson? + Ĉu forigi tiun ĉi adreson? Forigi @@ -2037,49 +2060,49 @@ Modifi - Ĉu vi certe volas forigi tiun ĉi legitimilon? + Ĉu vi certe volas forigi tiun ĉi legitimilon? - Ĉu vi certe volas forigi tiun ĉi pasvorton? + Ĉu vi certe volas forigi tiun ĉi pasvorton? Forigi Nuligi - Preferoj de komenco de seanco + Preferoj de komenco de seanco - Pasvortaj elektebloj + Pasvortaj elektebloj - La modifebla teksta kampo de la retadreso por komenci seancon. + La modifebla teksta kampo de la retadreso por komenci seancon. - La modifebla teksta kampo de la reteja retadreso. + La modifebla teksta kampo de la reteja retadreso. - La modifebla teksta kampo de la nomo de uzanto por komenci seancon. + La modifebla teksta kampo de la nomo de uzanto por komenci seancon. - La modifebla teksta kampo de la uzanto. + La modifebla teksta kampo de la uzanto. - La modifebla teksta kampo de la pasvorto por komenci seancon. + La modifebla teksta kampo de la pasvorto por komenci seancon. - La modifebla teksta kampo de la pasvorto. + La modifebla teksta kampo de la pasvorto. - Konservi ŝanĝojn je komenco de seanco. + Konservi ŝanĝojn je komenco de seanco. - Konservi ŝanĝojn. + Konservi ŝanĝojn. - Modifi + Modifi - Modifi pasvorton + Modifi pasvorton - Aldoni novan legitimilon + Aldoni novan legitimilon - Aldoni pasvorton + Aldoni pasvorton - Pasvorto postulata + Pasvorto postulata - Tajpu pasvorton + Tajpu pasvorton - Nomo de uzanto postulata + Nomo de uzanto postulata - Tajpu nomon de uzanto + Tajpu nomon de uzanto Nomo de servilo postulata @@ -2194,7 +2217,7 @@ Alklaku por havi pli da informo - Iri supren + Iri supren Fermi @@ -2235,8 +2258,6 @@ Alĝustigita taksado - Nefidindaj recenzoj forigitaj - Bazita sur fidindaj recenzoj Elstaraĵoj el ĵusaj recenzoj @@ -2293,10 +2314,6 @@ Se vi vidas ke denove estas stoko de tiu ĉi produko, raportu tion kaj ni kontrolos la recenzojn. Raporti ke denove estas stoko de tiu ĉi produkto - - Kvalito de recenzoj estas taksata - - Kvalito de recenzoj estas taksata Kvalito de recenzoj estas taksata (%s) @@ -2343,13 +2360,19 @@ Pli da informo - Se vi elektas “Jes, provi ĝin” vi akceptas la %2$s kaj %3$s de %1$s de Mozilla. + Se vi elektas “Jes, provi ĝin” vi akceptas la %2$s kaj %3$s de %1$s de Mozilla. Se vi elektas “Jes, provi ĝin” vi akceptas la jenon el %1$s: + + Se vi elektas “Jes, provi ĝin” vi akceptas la jenon: %2$s de %1$s kaj %4$s de %3$s. + + Se vi elektas “Jes, provi ĝin” vi akceptas la jenon: %2$s de %1$s kaj %4$s de %3$s. - politiko pri privateco + politiko pri privateco Politiko pri privateco + + rimarko pri privateco kondiĉoj de uzo @@ -2420,6 +2443,10 @@ Ĉu traduki ĉi tiun paĝon? + + Paĝo tradukita el la %1$s en la %2$sn Provu privatajn tradukojn en %1$s @@ -2432,6 +2459,8 @@ Traduki en Ne nun + + Montri originalon Farita @@ -2453,6 +2482,16 @@ Pli da informo + + + Traduko… + + Ĉu elŝuti lingvon dum datumŝpara reĝimo (%1$s)? + + Tradukaj elektebloj diff --git a/app/src/main/res/values-es-rAR/strings.xml b/app/src/main/res/values-es-rAR/strings.xml index b3f03c4ba..6b130be04 100644 --- a/app/src/main/res/values-es-rAR/strings.xml +++ b/app/src/main/res/values-es-rAR/strings.xml @@ -257,6 +257,11 @@ Traducir página + + Página traducida de %1$s a %2$s. + Idioma seleccionado @@ -338,12 +343,22 @@ Aviso de privacidad de Firefox - + + Conocé más en nuestra nota de privacidad Nos encanta mantenerte seguro + + Descubrí por qué millones aman Firefox + + Navegación segura con más opciones Nuestro navegador respaldado sin fines de lucro ayuda a evitar que las empresas te sigan en secreto por la web. + Más de 100 millones de personas protegen su privacidad eligiendo un navegador respaldado por una organización sin fines de lucro. + + ¿Rastreadores conocidos? Bloqueados automáticamente. Extensiones? Probá las 700. ¿PDFs? Nuestro lector incorporado los hace fáciles de administrar. + Nuestro navegador respaldado sin fines de lucro ayuda a evitar que las empresas te sigan en secreto por la web.\n\nMás información en nuestro aviso de privacidad. @@ -505,7 +520,7 @@ Sitio seguro no disponible - Lo más probable es que el sitio web simplemente no sea compatible con HTTPs. + Lo más probable es que el sitio web simplemente no sea compatible con HTTPS. Sin embargo, también es posible que un atacante esté involucrado. Si continúa al sitio web, no debe ingresar ninguna información sensible. Si continúa, el modo solo HTTPS se desactivará temporalmente para el sitio. @@ -697,9 +712,9 @@ Marcadores - Inicios de sesión + Inicios de sesión - Contraseñas + Contraseñas Pestañas abiertas @@ -727,9 +742,9 @@ %1$s en %2$s %3$s - Tarjetas de crédito + Tarjetas de crédito - Métodos de pago + Métodos de pago Direcciones @@ -1685,13 +1700,13 @@ Podés agregar este sitio a la pantalla de inicio del dispositivo fácilmente para tener acceso instantáneo y navegar más rápido con una experiencia similar a la de una aplicación. - Inicios de sesión y contraseñas + Inicios de sesión y contraseñas - Contraseñas + Contraseñas - Guardar inicios de sesión y contraseñas + Guardar inicios de sesión y contraseñas - Guardar contraseñas + Guardar contraseñas Solicitar guardar @@ -1706,47 +1721,47 @@ Completar nombres de usuario y contraseñas en otras aplicaciones de tu dispositivo. - Agregar inicio de sesión + Agregar inicio de sesión - Agregar contraseña + Agregar contraseña - - Sincronizar inicios de sesión - Sincronizar contraseñas + Sincronizar inicios de sesión + + Sincronizar contraseñas - Sincronizar inicios de sesión entre dispositivos + Sincronizar inicios de sesión entre dispositivos - Sincronizar contraseñas entre dispositivos + Sincronizar contraseñas entre dispositivos - Inicios de sesión guardados + Inicios de sesión guardados - Contraseñas guardadas + Contraseñas guardadas - Aquí se van a ver los inicios de sesión que guardes o sincronices con %s. + Aquí se van a ver los inicios de sesión que guardes o sincronices con %s. - Las contraseñas que guardés o sincronicés con %s aparecerán acá. Todas las contraseñas que guardés están encriptadas. + Las contraseñas que guardés o sincronicés con %s aparecerán acá. Todas las contraseñas que guardés están encriptadas. - Conocé más acerca de Sync. + Conocé más acerca de Sync. - Conocé más acerca de la sincronización + Conocé más acerca de la sincronización Excepciones - Los inicios de sesión y las contraseñas que no se guardan se mostrarán aquí. + Los inicios de sesión y las contraseñas que no se guardan se mostrarán aquí. - %s no guardará las contraseñas de los sitios listados acá. + %s no guardará las contraseñas de los sitios listados acá. - Los inicios de sesión y las contraseñas no se van a guardar para estos sitios. + Los inicios de sesión y las contraseñas no se van a guardar para estos sitios. - %s no guardará las contraseñas de estos sitios. + %s no guardará las contraseñas de estos sitios. Eliminar todas las excepciones - Buscar inicios de sesión + Buscar inicios de sesión - Buscar contraseñas + Buscar contraseñas Sitio @@ -1774,17 +1789,17 @@ Ocultar contraseña - Desbloqueá para ver tus inicios de sesión guardados + Desbloqueá para ver tus inicios de sesión guardados - Desbloqueá para ver las contraseñas guardadas + Desbloqueá para ver las contraseñas guardadas - Asegurá inicios de sesión y contraseñas + Asegurá inicios de sesión y contraseñas - Asegurá tus contraseñas guardadas + Asegurá tus contraseñas guardadas - Configurá un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus inicios de sesión y contraseñas guardadas por si alguien más tiene tu dispositivo. + Configurá un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus inicios de sesión y contraseñas guardadas por si alguien más tiene tu dispositivo. - Configurá un patrón de bloqueo del dispositivo, PIN o contraseña para proteger el acceso a tus contraseñas guardadas si alguien más tiene tu dispositivo. + Configurá un patrón de bloqueo del dispositivo, PIN o contraseña para proteger el acceso a tus contraseñas guardadas si alguien más tiene tu dispositivo. Más tarde @@ -1801,7 +1816,10 @@ Usado por última vez - Ordenar menú de inicio de sesión + Ordenar menú de inicio de sesión + + + Menú ordenar contraseñas Menú ordenar contraseñas @@ -1812,40 +1830,43 @@ Direcciones - Tarjetas de crédito + Tarjetas de crédito - Métodos de pago + Métodos de pago - Guardar y autocompletar tarjetas + Guardar y autocompletar tarjetas - Guardar y completar métodos de pago + Guardar y completar métodos de pago - Los datos están cifrados + Los datos están cifrados - %s cifra todos los métodos de pago guardados + %s cifra todos los métodos de pago guardados Sincronizar tarjetas entre dispositivos Sincronizar tarjetas - Agregar tarjeta de crédito + Agregar tarjeta de crédito - Agregar tarjeta + Agregar tarjeta - Administrar tarjetas guardadas + Administrar tarjetas guardadas - Administrar tarjetas + Administrar tarjetas Agregar dirección Administrar direcciones - Guardar y autocompletar direcciones + Guardar y autocompletar direcciones - Guardar y completar direcciones + Guardar y completar direcciones - Incluir información como números, correos electrónicos y direcciones de envíos + Incluir información como números, correos electrónicos y direcciones de envíos + + + Incluye números de teléfono y direcciones de correo electrónico Incluye números de teléfono y direcciones de correo electrónico @@ -1869,9 +1890,9 @@ Borrar tarjeta - ¿Estás seguro de querer borrar esta tarjeta de crédito? + ¿Estás seguro de querer borrar esta tarjeta de crédito? - ¿Borrar tarjeta? + ¿Borrar tarjeta? Borrar @@ -1885,25 +1906,25 @@ Tarjetas guardadas - Ingresá un número de tarjeta de crédito válido + Ingresá un número de tarjeta de crédito válido - Ingresá un número de tarjeta válido + Ingresá un número de tarjeta válido - Se debe completar este campo + Se debe completar este campo - Agregar un nombre + Agregar un nombre Desbloqueá para ver las tarjetas guardadas - Asegurá tus tarjetas de crédito + Asegurá tus tarjetas de crédito - Asegurá tus métodos de pago guardados + Asegurá tus métodos de pago guardados - Configurá un patrón de bloqueo del dispositivo, PIN o contraseña para proteger el acceso a tus tarjetas de crédito guardadas si alguien más tiene tu dispositivo. + Configurá un patrón de bloqueo del dispositivo, PIN o contraseña para proteger el acceso a tus tarjetas de crédito guardadas si alguien más tiene tu dispositivo. - Configurá un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus métodos de pago guardados por si otra persona accede a tu dispositivo. + Configurá un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus métodos de pago guardados por si otra persona accede a tu dispositivo. Configurar ahora @@ -1912,10 +1933,10 @@ Desbloqueá tu dispositivo - Desbloquear para usar la información almacenada de la tarjeta de crédito + Desbloquear para usar la información almacenada de la tarjeta de crédito - Desbloquear para usar los métodos de pago guardados + Desbloquear para usar los métodos de pago guardados Agregar dirección @@ -1923,11 +1944,13 @@ Administrar direcciones - Primer Nombre + Primer Nombre - Segundo nombre + Segundo nombre - Apellido + Apellido + + Nombre Dirección @@ -1952,9 +1975,9 @@ Borrar dirección - ¿Estás seguro de querer borrar esta dirección? + ¿Estás seguro de querer borrar esta dirección? - ¿Borrar esta dirección? + ¿Borrar esta dirección? Borrar @@ -2054,49 +2077,49 @@ Editar - ¿Estás seguro de que querés eliminar este inicio de sesión? + ¿Estás seguro de que querés eliminar este inicio de sesión? - ¿Estás seguro de que querés eliminar esta contraseña? + ¿Estás seguro de que querés eliminar esta contraseña? Eliminar Cancelar - Opciones de inicio de sesión + Opciones de inicio de sesión - Opciones de contraseña + Opciones de contraseña - El campo de texto editable para la dirección web del inicio de sesión. + El campo de texto editable para la dirección web del inicio de sesión. - El campo de texto editable para la dirección del sitio web. + El campo de texto editable para la dirección del sitio web. - El campo de texto editable para el nombre de usuario del inicio de sesión. + El campo de texto editable para el nombre de usuario del inicio de sesión. - El campo de texto editable para el nombre de usuario. + El campo de texto editable para el nombre de usuario. - El campo de texto editable para la contraseña del inicio de sesión. + El campo de texto editable para la contraseña del inicio de sesión. - El campo de texto editable para la contraseña. + El campo de texto editable para la contraseña. - Guardar cambios para el inicio de sesión. + Guardar cambios para el inicio de sesión. - Guardar cambios. + Guardar cambios. - Editar + Editar - Editar contraseña + Editar contraseña - Agregar nuevo inicio de sesión + Agregar nuevo inicio de sesión - Agregar contraseña + Agregar contraseña - Se necesita contraseña + Se necesita contraseña - Ingresar una contraseña + Ingresar una contraseña - Se requiere nombre de usuario + Se requiere nombre de usuario - Ingresar un nombre de usuario + Ingresar un nombre de usuario Se requiere nombre de host @@ -2210,7 +2233,7 @@ Hacer clic aquí para más detalles - Navegar hacia arriba + Navegar hacia arriba Cerrar @@ -2251,8 +2274,6 @@ Calificación ajustada - Revisiones no confiables eliminadas - Basado en revisiones confiables Destacados de revisiones recientes @@ -2308,10 +2329,6 @@ Si ves que este producto está nuevamente en stock, informanos y trabajaremos en verificar las revisiones. Informar que el producto está en stock - - Verificando la calidad de la revisión - - Verificando la calidad de la revisión Verificando la calidad de la revisión (%s) @@ -2357,13 +2374,19 @@ Conocer más - Al seleccionar “Si, probarlo” Estás de acuerdo con %1$s de Mozilla %2$s y %3$s. + Al seleccionar “Si, probarlo” Estás de acuerdo con %1$s de Mozilla %2$s y %3$s. Al seleccionar “Sí, probarlo” aceptás lo siguiente de %1$s: + + Al seleccionar “Si, probarlo” Estás de acuerdo con %2$s de %1$s y %4$s de %3$s. + + Al seleccionar “Si, probarlo” Estás de acuerdo con %2$s de %1$s y %4$s de %3$s. - política de privacidad + política de privacidad Política de privacidad + + nota de privacidad términos de uso @@ -2434,6 +2457,10 @@ ¿Traducir esta página? + + Página traducida de %1$s a %2$s Probar traducciones privadas en %1$s @@ -2446,6 +2473,8 @@ Traducir a No ahora + + Mostrar el original Listo @@ -2468,6 +2497,16 @@ Conocer más + + Traduciendo… + + + ¿Descargar idioma en modo de ahorro de datos (%1$s)? + + Opciones de traducción diff --git a/app/src/main/res/values-es-rCL/strings.xml b/app/src/main/res/values-es-rCL/strings.xml index 883e691fa..29c83d695 100644 --- a/app/src/main/res/values-es-rCL/strings.xml +++ b/app/src/main/res/values-es-rCL/strings.xml @@ -253,6 +253,11 @@ Traducir página + + Página traducida de %1$s a %2$s. + Idioma seleccionado @@ -330,12 +335,22 @@ Aviso de privacidad de Firefox - + + Aprende más en nuestra política de privacidad Nos encanta mantenerte a salvo + + Averigua por qué millones de personas aman Firefox + + Navegación segura con más opciones Nuestro navegador respaldado por una organización sin fines de lucro ayuda a evitar que las empresas te sigan en secreto por la web. + Más de 100 millones de personas protegen su privacidad eligiendo un navegador respaldado por una organización sin fines de lucro. + + ¿Rastreadores conocidos? Bloqueados automáticamente. ¿Extensiones? Prueba las 700. ¿PDF? Nuestro lector incorporado los hace fáciles de administrar. + Nuestro navegador respaldado por una organización sin fines de lucro ayuda a evitar que las empresas te sigan en secreto en la web.\n\nObtén más información en nuestro aviso de privacidad. @@ -690,9 +705,9 @@ Marcadores - Credenciales + Credenciales - Contraseñas + Contraseñas Pestañas abiertas @@ -718,9 +733,9 @@ %1$s en %2$s %3$s - Tarjetas de crédito + Tarjetas de crédito - Métodos de pago + Métodos de pago Direcciones @@ -1658,13 +1673,13 @@ Puedes añadir fácilmente este sitio web a tu pantalla de inicio de tu dispositivo para tener acceso instantáneo y navegar rápidamente, consiguiendo una experiencia similar a la de una aplicación real. - Credenciales y contraseñas + Credenciales y contraseñas - Contraseñas + Contraseñas - Guardar credenciales y contraseñas + Guardar credenciales y contraseñas - Guardar contraseñas + Guardar contraseñas Preguntar si guardar @@ -1679,48 +1694,48 @@ Completa los nombres de usuario y contraseñas en otras aplicaciones de tu dispositivo. - Añadir conexión + Añadir conexión - Añadir contraseña + Añadir contraseña - - Sincronizar credenciales - Sincronizar contraseñas + Sincronizar credenciales + + Sincronizar contraseñas - Sincronizar credenciales en todos los dispositivos + Sincronizar credenciales en todos los dispositivos - Sincronizar contraseñas entre dispositivos + Sincronizar contraseñas entre dispositivos - Credenciales guardadas + Credenciales guardadas - Contraseñas guardadas + Contraseñas guardadas - Las credenciales que guardas o sincronizas con %s serán mostradas aquí. + Las credenciales que guardas o sincronizas con %s serán mostradas aquí. - Las contraseñas que guardes o sincronices con %s aparecerán aquí. Todas las contraseñas que guardes quedan cifradas. + Las contraseñas que guardes o sincronices con %s aparecerán aquí. Todas las contraseñas que guardes quedan cifradas. - Aprender más acerca de Sync. + Aprender más acerca de Sync. - Aprende más acerca de la sincronización + Aprende más acerca de la sincronización Excepciones - Las credenciales y contraseñas que no son guardadas serán mostradas aquí. + Las credenciales y contraseñas que no son guardadas serán mostradas aquí. - %s no guardará las contraseñas de los sitios listados aquí. + %s no guardará las contraseñas de los sitios listados aquí. - Las credenciales y contraseñas no serán guardadas para estos sitios. + Las credenciales y contraseñas no serán guardadas para estos sitios. - %s no guardará las contraseñas para estos sitios. + %s no guardará las contraseñas para estos sitios. Eliminar todas las excepciones - Buscar credenciales + Buscar credenciales - Buscar contraseñas + Buscar contraseñas Sitio @@ -1748,17 +1763,17 @@ Ocultar contraseña - Desbloquea para ver tus credenciales guardadas + Desbloquea para ver tus credenciales guardadas - Desbloquea para ver tus contraseñas guardadas + Desbloquea para ver tus contraseñas guardadas - Asegura tus credenciales y contraseñas + Asegura tus credenciales y contraseñas - Asegura tus contraseñas guardadas + Asegura tus contraseñas guardadas - Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus credenciales y contraseñas guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus credenciales y contraseñas guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. - Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus contraseñas guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus contraseñas guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. Más tarde @@ -1776,7 +1791,10 @@ Último uso - Menú para ordenar credenciales + Menú para ordenar credenciales + + + Menú ordenar contraseñas Menú ordenar contraseñas @@ -1787,40 +1805,43 @@ Direcciones - Tarjetas de crédito + Tarjetas de crédito - Métodos de pago + Métodos de pago - Guardar y autocompletar tarjetas + Guardar y autocompletar tarjetas - Guardar y completar métodos de pago + Guardar y completar métodos de pago - Los datos están encriptados + Los datos están encriptados - %s cifra todos los métodos de pago que guardas + %s cifra todos los métodos de pago que guardas Sincronizar tarjetas entre dispositivos Sincronizar tarjetas - Añadir tarjeta de crédito + Añadir tarjeta de crédito - Añadir tarjeta + Añadir tarjeta - Gestionar tarjetas guardadas + Gestionar tarjetas guardadas - Gestionar tarjetas + Gestionar tarjetas Añadir dirección Administrar direcciones - Guardar y autocompletar direcciones + Guardar y autocompletar direcciones - Guardar y completar direcciones + Guardar y completar direcciones - Incluye información como números, correos electrónicos y direcciones + Incluye información como números, correos electrónicos y direcciones + + + Incluye números de teléfono y direcciones de correo electrónico Incluye números de teléfono y direcciones de correo electrónico @@ -1844,9 +1865,9 @@ Eliminar tarjeta - ¿De verdad quieres eliminar esta tarjeta de crédito? + ¿De verdad quieres eliminar esta tarjeta de crédito? - ¿Eliminar tarjeta? + ¿Eliminar tarjeta? Eliminar @@ -1860,24 +1881,24 @@ Tarjetas guardadas - Por favor, ingresa un número de tarjeta de crédito válido + Por favor, ingresa un número de tarjeta de crédito válido - Ingresa un número de tarjeta válido + Ingresa un número de tarjeta válido - Complete este campo + Complete este campo - Añadir un nombre + Añadir un nombre Desbloquea para ver tus tarjetas guardadas - Asegura tus tarjetas de crédito + Asegura tus tarjetas de crédito - Asegura tus métodos de pago guardados + Asegura tus métodos de pago guardados - Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus tarjetas de crédito guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus tarjetas de crédito guardadas, y así no sean accedidas si alguien más tiene tu dispositivo. - Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus métodos de pago guardados, y así no sean accedidos si alguien más tiene tu dispositivo. + Configura un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus métodos de pago guardados, y así no sean accedidos si alguien más tiene tu dispositivo. Configurar ahora @@ -1885,10 +1906,10 @@ Desbloquea tu dispositivo - Desbloquea para usar información de la tarjeta de crédito almacenada + Desbloquea para usar información de la tarjeta de crédito almacenada - Desbloquea para usar métodos de pago guardados + Desbloquea para usar métodos de pago guardados Añadir dirección @@ -1896,11 +1917,13 @@ Administrar direcciones - Primer nombre + Primer nombre - Segundo nombre + Segundo nombre - Apellidos + Apellidos + + Nombre Dirección @@ -1925,9 +1948,9 @@ Eliminar dirección - ¿De verdad quieres eliminar esta dirección? + ¿De verdad quieres eliminar esta dirección? - ¿Eliminar esta dirección? + ¿Eliminar esta dirección? Eliminar @@ -2025,49 +2048,49 @@ Editar - ¿De verdad quieres eliminar esta conexión? + ¿De verdad quieres eliminar esta conexión? - ¿Estas seguro de eliminar esta contraseña? + ¿Estas seguro de eliminar esta contraseña? Eliminar Cancelar - Opciones de credenciales + Opciones de credenciales - Opciones de contraseña + Opciones de contraseña - El campo de texto editable para la dirección web de la credencial. + El campo de texto editable para la dirección web de la credencial. - El campo de texto editable para la dirección del sitio web. + El campo de texto editable para la dirección del sitio web. - El campo de texto editable para el nombre de usuario de la credencial. + El campo de texto editable para el nombre de usuario de la credencial. - El campo de texto editable para el nombre de usuario. + El campo de texto editable para el nombre de usuario. - El campo de texto editable para la contraseña de la credencial. + El campo de texto editable para la contraseña de la credencial. - El campo de texto editable para la contraseña. + El campo de texto editable para la contraseña. - Guardar cambios a la credencial. + Guardar cambios a la credencial. - Guardar cambios. + Guardar cambios. - Editar + Editar - Editar contraseña + Editar contraseña - Añadir nueva credencial + Añadir nueva credencial - Añadir contraseña + Añadir contraseña - Contraseña requerida + Contraseña requerida - Ingresar una contraseña + Ingresar una contraseña - Nombre de usuario requerido + Nombre de usuario requerido - Ingresar un nombre de usuario + Ingresar un nombre de usuario Nombre de servidor requerido @@ -2167,6 +2190,9 @@ Buscar con %s + + Cambia tu navegador predeterminado + Configura enlaces de sitios web, correos electrónicos y mensajes para que se abran automáticamente en Firefox. @@ -2176,7 +2202,7 @@ Clic para más detalles - Navegar hacia arriba + Navegar hacia arriba Cerrar @@ -2217,8 +2243,6 @@ Calificación ajustada - Se eliminaron las reseñas poco confiables - Basado en revisiones confiables Aspectos destacados de reseñas recientes @@ -2275,10 +2299,6 @@ Si ves que este producto vuelve a estar disponible, infórmalo y trabajaremos para verificar las reseñas. Informar que el producto está en stock - - Comprobando la calidad de la reseña - - Comprobando la calidad de la reseña Comprobando la calidad de la reseña (%s) @@ -2324,13 +2344,19 @@ Aprender más - Al seleccionar “Sí, probarlo”, aceptas la %2$s y %3$s de %1$s de Mozilla. + Al seleccionar “Sí, probarlo”, aceptas la %2$s y %3$s de %1$s de Mozilla. Al seleccionar "Sí, probarlo", aceptas lo siguiente de %1$s: + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. - política de privacidad + política de privacidad Política de privacidad + + política de privacidad términos de uso @@ -2401,6 +2427,10 @@ ¿Traducir esta página? + + Página traducida de %1$s a %2$s Prueba traducciones privadas en %1$s @@ -2413,6 +2443,8 @@ Traducir a Ahora no + + Mostrar original Hecho @@ -2435,6 +2467,16 @@ Aprender más + + Traduciendo… + + + ¿Descargar idioma en modo de ahorro de datos (%1$s)? + + Opciones de traducción diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 21ab60347..3b5f17cf9 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -247,6 +247,7 @@ Personalizar la página de inicio + Pantalla de inicio @@ -254,6 +255,14 @@ Eliminar historial de navegación + + Traducir página + + + Página traducida de %1$s a %2$s. + Idioma seleccionado @@ -265,8 +274,6 @@ Escanear - - Buscador Ajustes del buscador @@ -322,24 +329,34 @@ - Las notificaciones te ayudan a hacer más con %s + Las notificaciones te ayudan a hacer más con %s - Sincroniza tus pestañas entre dispositivos, administra descargas, obtén consejos sobre cómo aprovechar al máximo la protección de privacidad de %s y más. + Sincroniza tus pestañas entre dispositivos, administra descargas, obtén consejos sobre cómo aprovechar al máximo la protección de privacidad de %s y más. - Continuar + Continuar - Ahora no + Ahora no Aviso de privacidad de Firefox - + + Saber más en nuestro aviso de privacidad Nos encanta mantenerte a salvo + + Descubre por qué millones aman Firefox + + Navegación segura con más opciones Nuestro navegador respaldado por una organización sin ánimo de lucro ayuda a evitar que las empresas te sigan en secreto por la web. + Más de 100 millones de personas protegen su privacidad eligiendo un navegador respaldado por una organización sin ánimo de lucro. + + ¿Rastreadores conocidos? Bloqueados automáticamente. ¿Extensiones? Más de 700. ¿PDF? Nuestro lector incorporado los hace fáciles de administrar. + Nuestro navegador respaldado por una organización sin ánimo de lucro ayuda a evitar que las empresas te sigan en secreto en la web.\n\nMás información en nuestro aviso de privacidad. @@ -448,21 +465,11 @@ Modo solo HTTPS - - Reducción de avisos de cookies Bloqueador de avisos de cookies Bloqueador de avisos de cookies en navegación privada - - Reducir los avisos de cookies - - Desactivado - - Activado - - - %1$s intenta rechazar automáticamente las solicitudes de cookies en los avisos de cookies. + Desactivada para este sitio @@ -480,35 +487,16 @@ Sitio actualmente no compatible - ¿Activar la reducción de aviso de cookies para %1$s? - ¿Activar el bloqueo de aviso de cookies para %1$s? - ¿Desactivar la reducción de aviso de cookies para %1$s? - ¿Desactivar el bloqueo de aviso de cookies para %1$s? %1$s no puede rechazar automáticamente los avisos de cookies en este sitio. Puede enviar una solicitud para admitir este sitio en el futuro. - - %1$s borrará las cookies de este sitio y recargará la página. Borrar todas las cookies puede cerrar tu sesión o vaciar los carritos de compras. Tras desactivarlo, %1$s borrará las cookies y recargará la página. Esto puede desconectarte del sitio o vaciar tu carrito de compra. - %1$s intenta rechazar automáticamente las solicitudes de cookies en sitios compatibles. - Al activarlo %1$s intentará rechazar automáticamente los avisos de cookies en este sitio. - - ¿Permitir que %1$s rechace los avisos de cookies? - - %1$s puede rechazar automáticamente muchas solicitudes de cookies. - - Ahora no - - Verás menos solicitudes de cookies - - - Permitir %1$s acaba de rechazar las cookies por ti @@ -724,7 +712,9 @@ Marcadores - Inicios de sesión + Inicios de sesión + + Contraseñas Pestañas abiertas @@ -750,7 +740,9 @@ %1$s en %2$s %3$s - Tarjetas de crédito + Tarjetas de crédito + + Métodos de pago Direcciones @@ -1306,8 +1298,6 @@ Descartar - No se puede imprimir - No se puede imprimir esta página Imprimir @@ -1719,9 +1709,13 @@ Puedes añadir fácilmente este sitio web a la pantalla de inicio de tu dispositivo para tener acceso instantáneo y navegar rápidamente, consiguiendo una experiencia similar a la de una aplicación real. - Inicios de sesión y contraseñas + Inicios de sesión y contraseñas + + Contraseñas + + Guardar inicios de sesión y contraseñas - Guardar inicios de sesión y contraseñas + Guardar contraseñas Preguntar antes de guardar @@ -1738,28 +1732,47 @@ Completar nombres de usuarios y contraseñas en otras aplicaciones de tu dispositivo. - Añadir cuenta + Añadir cuenta - - Inicios de sesión sincronizados + + Añadir contraseña + + + Inicios de sesión sincronizados + + Sincronizar contraseñas - Sincronizar inicios de sesión entre dispositivos + Sincronizar inicios de sesión entre dispositivos + + Sincronizar contraseñas entre dispositivos - Inicios de sesión guardados + Inicios de sesión guardados + + Contraseñas guardadas + + Los inicios de sesión que guardes o sincronices con %s se mostrarán aquí. - Los inicios de sesión que guardes o sincronices con %s se mostrarán aquí. + Las contraseñas que guardes o sincronices con %s aparecerán aquí. Todas las contraseñas que guardes quedan cifradas. - Saber más sobre Sync. + Saber más sobre Sync. + + Descubre más sobre Sync Excepciones - Los inicios de sesión y contraseñas no guardados aparecerán aquí. + Los inicios de sesión y contraseñas no guardados aparecerán aquí. + + %s no guardará contraseñas para los sitios que se listen aquí. - No se guardarán los inicios de sesión y contraseñas para estos sitios. + No se guardarán los inicios de sesión y contraseñas para estos sitios. + + %s no guardará las contraseñas para estos sitios. Eliminar todas las excepciones - Buscar inicios de sesión + Buscar inicios de sesión + + Buscar contraseñas Sitio @@ -1787,11 +1800,17 @@ Ocultar contraseña - Desbloquear para ver tus inicios de sesión guardados + Desbloquear para ver tus inicios de sesión guardados + + Desbloquea para ver tus contraseñas guardadas - Asegurar tus usuarios y contraseñas + Asegurar tus usuarios y contraseñas + + Asegura tus contraseñas guardadas + + Configura un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus usuarios y contraseñas guardados si alguien más tiene tu dispositivo. - Configura un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus usuarios y contraseñas guardados si alguien más tiene tu dispositivo. + Establece un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus contraseñas guardadas y evitar que sean accedidas por otras personas en caso de que alguien más tenga tu dispositivo. Más tarde @@ -1810,7 +1829,10 @@ Usado por última vez - Ordenar menú de inicio de sesión + Ordenar menú de inicio de sesión + + + Menú ordenar contraseñas @@ -1818,29 +1840,44 @@ Direcciones - Tarjetas de crédito + Tarjetas de crédito + + Métodos de pago - Guardar y autocompletar tarjetas + Guardar y autocompletar tarjetas + + Guardar y completar métodos de pago - Los datos están cifrados + Los datos están cifrados + + %s cifra todos los métodos de pago que guardes Sincronizar tarjetas entre dispositivos Sincronizar tarjetas - Añadir tarjeta de crédito + Añadir tarjeta de crédito + + Añadir tarjeta - Administrar tarjetas guardadas + Administrar tarjetas guardadas + + Administrar tarjetas Añadir dirección Administrar direcciones - Guardar y autocompletar direcciones + Guardar y autocompletar direcciones + + Guardar y completar direcciones - Incluir información como números, correos electrónicos y direcciones de envío + Incluir información como números, correos electrónicos y direcciones de envío + + + Incluye números de teléfono y direcciones de correo electrónico Añadir tarjeta @@ -1861,7 +1898,9 @@ Eliminar tarjeta - ¿Seguro que quieres eliminar esta tarjeta de crédito? + ¿Seguro que quieres eliminar esta tarjeta de crédito? + + ¿Eliminar tarjeta? Eliminar @@ -1875,16 +1914,24 @@ Tarjetas guardadas - Por favor, escriba un número válido de tarjeta de crédito + Por favor, escriba un número válido de tarjeta de crédito + + Introduce un número de tarjeta válido - Por favor, rellena este campo + Por favor, rellena este campo + + Añadir un nombre Desbloquear para ver tus tarjetas guardadas - Asegurar tus tarjetas de crédito + Asegurar tus tarjetas de crédito + + Protege tus métodos de pago guardados - Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. + Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. + + Establece un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus métodos de pago guardados y evitar que sean accedidos por otras personas en caso de que alguien más tenga tu dispositivo. Configurar ahora @@ -1892,8 +1939,10 @@ Desbloquear tu dispositivo - Desbloquear para usar la información de la tarjeta de crédito almacenada + Desbloquear para usar la información de la tarjeta de crédito almacenada + + Desbloquea para utilizar métodos de pago guardados Añadir dirección @@ -1901,11 +1950,13 @@ Administrar direcciones - Nombre + Nombre - Segundo nombre + Segundo nombre - Apellidos + Apellidos + + Nombre Domicilio @@ -1930,7 +1981,9 @@ Eliminar dirección - ¿Seguro que quieres eliminar esta dirección? + ¿Seguro que quieres eliminar esta dirección? + + ¿Eliminar esta dirección? Eliminar @@ -2029,31 +2082,53 @@ Editar - ¿Seguro que quieres eliminar este inicio de sesión? + ¿Seguro que quieres eliminar este inicio de sesión? + + ¿Estás seguro de que quieres eliminar esta contraseña? Eliminar Cancelar - Opciones de inicio de sesión + Opciones de inicio de sesión + + Opciones de contraseña - El campo de texto editable para la dirección web del inicio de sesión. + El campo de texto editable para la dirección web del inicio de sesión. + + El campo de texto editable para la dirección del sitio web. - El campo de texto editable para el nombre de usuario del inicio de sesión. + El campo de texto editable para el nombre de usuario del inicio de sesión. + + El campo de texto editable para el nombre de usuario. - El campo de texto editable para la contraseña del inicio de sesión. + El campo de texto editable para la contraseña del inicio de sesión. + + El campo de texto editable para la contraseña. - Guardar cambios para el inicio de sesión. + Guardar cambios para el inicio de sesión. + + Guardar cambios. - Editar + Editar + + Editar contraseña - Añadir nueva cuenta + Añadir nueva cuenta + + Añadir contraseña - Se necesita contraseña + Se necesita contraseña + + Introduce una contraseña + + Se requiere nombre de usuario - Se requiere nombre de usuario + Introduce un nombre de usuario Se requiere nombre de servidor + + Introduce una dirección web Búsqueda por voz @@ -2150,6 +2225,9 @@ Buscar con %s + + Cambia tu navegador predeterminado + Configura enlaces de sitios web, correos electrónicos y mensajes para que se abran automáticamente en Firefox. @@ -2159,7 +2237,7 @@ Clic para más detalles - Ir arriba + Ir arriba Cerrar @@ -2200,8 +2278,6 @@ Calificación ajustada - Se han eliminado las reseñas no fiables - Basado en revisiones fiables Aspectos destacados de reseñas recientes @@ -2223,8 +2299,6 @@ puntos destacados provienen de reseñas de %s de los últimos 80 días que creemos que son fiables.]]> Saber más sobre %s. - - cómo %s de Mozilla determina la calidad de las reseñas cómo determina %s la calidad de las reseñas @@ -2259,10 +2333,6 @@ Si ves que este producto vuelve a estar disponible, infórmanos y trabajaremos para actualizar el análisis. Informar que el producto está en stock - - Comprobando la calidad de la reseña - - Comprobando la calidad de la reseña Comprobando la calidad de la reseña (%s) @@ -2308,13 +2378,19 @@ Saber más - Al seleccionar “Sí, probarlo”, aceptas %1$s de %2$s y %3$s de Mozilla. + Al seleccionar “Sí, probarlo”, aceptas %1$s de %2$s y %3$s de Mozilla. Al seleccionar “Sí, probarlo”, aceptas lo siguiente de %1$s: + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. - política de privacidad + política de privacidad Política de privacidad + + aviso de privacidad términos de uso @@ -2385,6 +2461,10 @@ ¿Traducir esta página? + + Página traducida de %1$s a %2$s Probar traducciones privadas en %1$s @@ -2397,6 +2477,8 @@ Traducir a Ahora no + + Mostrar original Hecho @@ -2408,6 +2490,8 @@ Traducción en curso + + Selecciona un idioma Ha surgido un problema al traducir. Por favor inténtalo de nuevo. @@ -2417,6 +2501,16 @@ Saber más + + Traduciendo… + + + ¿Descargar idioma en modo de ahorro de datos (%1$s)? + + Opciones de traducción @@ -2428,6 +2522,10 @@ No traducir nunca %1$s No traducir nunca este sitio + + Anula todas las demás configuraciones + + Anula las ofertas de traducción Ajustes de traducción diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 21ab60347..1b7dc932a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -247,6 +247,7 @@ Personalizar la página de inicio + Pantalla de inicio @@ -254,6 +255,14 @@ Eliminar historial de navegación + + Traducir página + + + Página traducida de %1$s a %2$s. + Idioma seleccionado @@ -265,8 +274,6 @@ Escanear - - Buscador Ajustes del buscador @@ -322,24 +329,34 @@ - Las notificaciones te ayudan a hacer más con %s + Las notificaciones te ayudan a hacer más con %s - Sincroniza tus pestañas entre dispositivos, administra descargas, obtén consejos sobre cómo aprovechar al máximo la protección de privacidad de %s y más. + Sincroniza tus pestañas entre dispositivos, administra descargas, obtén consejos sobre cómo aprovechar al máximo la protección de privacidad de %s y más. - Continuar + Continuar - Ahora no + Ahora no Aviso de privacidad de Firefox - + + Saber más en nuestro aviso de privacidad Nos encanta mantenerte a salvo + + Descubre por qué millones aman Firefox + + Navegación segura con más opciones Nuestro navegador respaldado por una organización sin ánimo de lucro ayuda a evitar que las empresas te sigan en secreto por la web. + Más de 100 millones de personas protegen su privacidad eligiendo un navegador respaldado por una organización sin ánimo de lucro. + + ¿Rastreadores conocidos? Bloqueados automáticamente. ¿Extensiones? Más de 700. ¿PDF? Nuestro lector incorporado los hace fáciles de administrar. + Nuestro navegador respaldado por una organización sin ánimo de lucro ayuda a evitar que las empresas te sigan en secreto en la web.\n\nMás información en nuestro aviso de privacidad. @@ -448,21 +465,11 @@ Modo solo HTTPS - - Reducción de avisos de cookies Bloqueador de avisos de cookies Bloqueador de avisos de cookies en navegación privada - - Reducir los avisos de cookies - - Desactivado - - Activado - - - %1$s intenta rechazar automáticamente las solicitudes de cookies en los avisos de cookies. + Desactivada para este sitio @@ -480,35 +487,16 @@ Sitio actualmente no compatible - ¿Activar la reducción de aviso de cookies para %1$s? - ¿Activar el bloqueo de aviso de cookies para %1$s? - ¿Desactivar la reducción de aviso de cookies para %1$s? - ¿Desactivar el bloqueo de aviso de cookies para %1$s? %1$s no puede rechazar automáticamente los avisos de cookies en este sitio. Puede enviar una solicitud para admitir este sitio en el futuro. - - %1$s borrará las cookies de este sitio y recargará la página. Borrar todas las cookies puede cerrar tu sesión o vaciar los carritos de compras. Tras desactivarlo, %1$s borrará las cookies y recargará la página. Esto puede desconectarte del sitio o vaciar tu carrito de compra. - %1$s intenta rechazar automáticamente las solicitudes de cookies en sitios compatibles. - Al activarlo %1$s intentará rechazar automáticamente los avisos de cookies en este sitio. - - ¿Permitir que %1$s rechace los avisos de cookies? - - %1$s puede rechazar automáticamente muchas solicitudes de cookies. - - Ahora no - - Verás menos solicitudes de cookies - - - Permitir %1$s acaba de rechazar las cookies por ti @@ -724,7 +712,9 @@ Marcadores - Inicios de sesión + Inicios de sesión + + Contraseñas Pestañas abiertas @@ -750,7 +740,9 @@ %1$s en %2$s %3$s - Tarjetas de crédito + Tarjetas de crédito + + Métodos de pago Direcciones @@ -1306,8 +1298,6 @@ Descartar - No se puede imprimir - No se puede imprimir esta página Imprimir @@ -1719,9 +1709,13 @@ Puedes añadir fácilmente este sitio web a la pantalla de inicio de tu dispositivo para tener acceso instantáneo y navegar rápidamente, consiguiendo una experiencia similar a la de una aplicación real. - Inicios de sesión y contraseñas + Inicios de sesión y contraseñas + + Contraseñas + + Guardar inicios de sesión y contraseñas - Guardar inicios de sesión y contraseñas + Guardar contraseñas Preguntar antes de guardar @@ -1738,28 +1732,47 @@ Completar nombres de usuarios y contraseñas en otras aplicaciones de tu dispositivo. - Añadir cuenta + Añadir cuenta - - Inicios de sesión sincronizados + + Añadir contraseña + + + Inicios de sesión sincronizados + + Sincronizar contraseñas - Sincronizar inicios de sesión entre dispositivos + Sincronizar inicios de sesión entre dispositivos + + Sincronizar contraseñas entre dispositivos - Inicios de sesión guardados + Inicios de sesión guardados + + Contraseñas guardadas + + Los inicios de sesión que guardes o sincronices con %s se mostrarán aquí. - Los inicios de sesión que guardes o sincronices con %s se mostrarán aquí. + Las contraseñas que guardes o sincronices con %s aparecerán aquí. Todas las contraseñas que guardes quedan cifradas. - Saber más sobre Sync. + Saber más sobre Sync. + + Descubre más sobre Sync Excepciones - Los inicios de sesión y contraseñas no guardados aparecerán aquí. + Los inicios de sesión y contraseñas no guardados aparecerán aquí. + + %s no guardará contraseñas para los sitios que se listen aquí. - No se guardarán los inicios de sesión y contraseñas para estos sitios. + No se guardarán los inicios de sesión y contraseñas para estos sitios. + + %s no guardará las contraseñas para estos sitios. Eliminar todas las excepciones - Buscar inicios de sesión + Buscar inicios de sesión + + Buscar contraseñas Sitio @@ -1787,11 +1800,17 @@ Ocultar contraseña - Desbloquear para ver tus inicios de sesión guardados + Desbloquear para ver tus inicios de sesión guardados + + Desbloquea para ver tus contraseñas guardadas - Asegurar tus usuarios y contraseñas + Asegurar tus usuarios y contraseñas + + Asegura tus contraseñas guardadas + + Configura un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus usuarios y contraseñas guardados si alguien más tiene tu dispositivo. - Configura un patrón de bloqueo del dispositivo, un PIN o una contraseña para proteger el acceso a tus usuarios y contraseñas guardados si alguien más tiene tu dispositivo. + Establece un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus contraseñas guardadas y evitar que sean accedidas por otras personas en caso de que alguien más tenga tu dispositivo. Más tarde @@ -1810,7 +1829,10 @@ Usado por última vez - Ordenar menú de inicio de sesión + Ordenar menú de inicio de sesión + + + Menú ordenar contraseñas @@ -1818,29 +1840,44 @@ Direcciones - Tarjetas de crédito + Tarjetas de crédito + + Métodos de pago + + Guardar y autocompletar tarjetas - Guardar y autocompletar tarjetas + Guardar y completar métodos de pago - Los datos están cifrados + Los datos están cifrados + + %s cifra todos los métodos de pago que guardes Sincronizar tarjetas entre dispositivos Sincronizar tarjetas - Añadir tarjeta de crédito + Añadir tarjeta de crédito + + Añadir tarjeta - Administrar tarjetas guardadas + Administrar tarjetas guardadas + + Administrar tarjetas Añadir dirección Administrar direcciones - Guardar y autocompletar direcciones + Guardar y autocompletar direcciones + + Guardar y completar direcciones - Incluir información como números, correos electrónicos y direcciones de envío + Incluir información como números, correos electrónicos y direcciones de envío + + + Incluye números de teléfono y direcciones de correo electrónico Añadir tarjeta @@ -1861,7 +1898,9 @@ Eliminar tarjeta - ¿Seguro que quieres eliminar esta tarjeta de crédito? + ¿Seguro que quieres eliminar esta tarjeta de crédito? + + ¿Eliminar tarjeta? Eliminar @@ -1875,16 +1914,24 @@ Tarjetas guardadas - Por favor, escriba un número válido de tarjeta de crédito + Por favor, escriba un número válido de tarjeta de crédito + + Introduce un número de tarjeta válido - Por favor, rellena este campo + Por favor, rellena este campo + + Añadir un nombre Desbloquear para ver tus tarjetas guardadas - Asegurar tus tarjetas de crédito + Asegurar tus tarjetas de crédito + + Protege tus métodos de pago guardados + + Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. - Configura un patrón de bloqueo, PIN o contraseña para proteger el acceso a tus tarjetas guardadas si alguien más accede a tu dispositivo. + Establece un patrón de bloqueo de dispositivo, PIN o contraseña para proteger tus métodos de pago guardados y evitar que sean accedidos por otras personas en caso de que alguien más tenga tu dispositivo. Configurar ahora @@ -1892,8 +1939,10 @@ Desbloquear tu dispositivo - Desbloquear para usar la información de la tarjeta de crédito almacenada + Desbloquear para usar la información de la tarjeta de crédito almacenada + + Desbloquea para utilizar métodos de pago guardados Añadir dirección @@ -1901,11 +1950,13 @@ Administrar direcciones - Nombre + Nombre - Segundo nombre + Segundo nombre - Apellidos + Apellidos + + Nombre Domicilio @@ -1930,7 +1981,9 @@ Eliminar dirección - ¿Seguro que quieres eliminar esta dirección? + ¿Seguro que quieres eliminar esta dirección? + + ¿Eliminar esta dirección? Eliminar @@ -2029,31 +2082,53 @@ Editar - ¿Seguro que quieres eliminar este inicio de sesión? + ¿Seguro que quieres eliminar este inicio de sesión? + + ¿Estás seguro de que quieres eliminar esta contraseña? Eliminar Cancelar - Opciones de inicio de sesión + Opciones de inicio de sesión + + Opciones de contraseña - El campo de texto editable para la dirección web del inicio de sesión. + El campo de texto editable para la dirección web del inicio de sesión. + + El campo de texto editable para la dirección del sitio web. - El campo de texto editable para el nombre de usuario del inicio de sesión. + El campo de texto editable para el nombre de usuario del inicio de sesión. + + El campo de texto editable para el nombre de usuario. + + El campo de texto editable para la contraseña del inicio de sesión. - El campo de texto editable para la contraseña del inicio de sesión. + El campo de texto editable para la contraseña. - Guardar cambios para el inicio de sesión. + Guardar cambios para el inicio de sesión. + + Guardar cambios. - Editar + Editar + + Editar contraseña - Añadir nueva cuenta + Añadir nueva cuenta + + Añadir contraseña - Se necesita contraseña + Se necesita contraseña + + Introduce una contraseña - Se requiere nombre de usuario + Se requiere nombre de usuario + + Introduce un nombre de usuario Se requiere nombre de servidor + + Introduce una dirección web Búsqueda por voz @@ -2150,6 +2225,9 @@ Buscar con %s + + Cambia tu navegador predeterminado + Configura enlaces de sitios web, correos electrónicos y mensajes para que se abran automáticamente en Firefox. @@ -2159,7 +2237,7 @@ Clic para más detalles - Ir arriba + Ir arriba Cerrar @@ -2200,8 +2278,6 @@ Calificación ajustada - Se han eliminado las reseñas no fiables - Basado en revisiones fiables Aspectos destacados de reseñas recientes @@ -2223,8 +2299,6 @@ puntos destacados provienen de reseñas de %s de los últimos 80 días que creemos que son fiables.]]> Saber más sobre %s. - - cómo %s de Mozilla determina la calidad de las reseñas cómo determina %s la calidad de las reseñas @@ -2259,10 +2333,6 @@ Si ves que este producto vuelve a estar disponible, infórmanos y trabajaremos para actualizar el análisis. Informar que el producto está en stock - - Comprobando la calidad de la reseña - - Comprobando la calidad de la reseña Comprobando la calidad de la reseña (%s) @@ -2308,13 +2378,19 @@ Saber más - Al seleccionar “Sí, probarlo”, aceptas %1$s de %2$s y %3$s de Mozilla. + Al seleccionar “Sí, probarlo”, aceptas %1$s de %2$s y %3$s de Mozilla. Al seleccionar “Sí, probarlo”, aceptas lo siguiente de %1$s: + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. + + Al seleccionar “Sí, probarlo”, aceptas la %2$s de %1$s y los %4$s de %3$s. - política de privacidad + política de privacidad Política de privacidad + + aviso de privacidad términos de uso @@ -2385,6 +2461,10 @@ ¿Traducir esta página? + + Página traducida de %1$s a %2$s Probar traducciones privadas en %1$s @@ -2397,6 +2477,8 @@ Traducir a Ahora no + + Mostrar original Hecho @@ -2408,6 +2490,8 @@ Traducción en curso + + Selecciona un idioma Ha surgido un problema al traducir. Por favor inténtalo de nuevo. @@ -2417,6 +2501,9 @@ Saber más + + Traduciendo… + Opciones de traducción @@ -2428,6 +2515,10 @@ No traducir nunca %1$s No traducir nunca este sitio + + Anula todas las demás configuraciones + + Anula las ofertas de traducción Ajustes de traducción diff --git a/app/src/main/res/values-eu/strings.xml b/app/src/main/res/values-eu/strings.xml index e0e4cb55e..32872f234 100644 --- a/app/src/main/res/values-eu/strings.xml +++ b/app/src/main/res/values-eu/strings.xml @@ -245,6 +245,7 @@ Pertsonalizatu hasiera-orria + Hasiera-pantaila @@ -252,6 +253,14 @@ Ezabatu nabigatze-historia + + Itzuli orria + + + Orria %1$s hizkuntzatik %2$s hizkuntzara itzuli da. + Hautatutako hizkuntza @@ -263,8 +272,6 @@ Eskaneatu - - Bilaketa-motorra Bilaketa-motorren ezarpenak @@ -320,25 +327,40 @@ - Jakinarazpenek %s(r)i zuku gehiago ateratzen laguntzen dute + Jakinarazpenek %s(r)i zuku gehiago ateratzen laguntzen dute - Sinkronizatu zure fitxak gailuen artean, kudeatu deskargak, jaso aholkuak %s(r)en pribatutasun-babesari zuku gehien ateratzeko, eta gehiago. + Sinkronizatu zure fitxak gailuen artean, kudeatu deskargak, jaso aholkuak %s(r)en pribatutasun-babesari zuku gehien ateratzeko, eta gehiago. - Jarraitu + Jarraitu - Une honetan ez + Une honetan ez + + Firefoxen pribatutasun-oharra + + Argibide gehiago gure pribatutasun-oharrean Zu seguru mantentzea dugu xede + + Ezagutu zergatik milioika pertsonek atsegin duten Firefox + + Nabigatze segurua aukera gehiagorekin + + Irabazi asmorik gabeko erakundeak babestutako gure nabigatzaileak laguntzen du eragozten enpresek zure webeko jarraipena sekretupean egin dezaten. + + 100 milioi pertsona baino gehiagok beraien pribatutasuna babesten duten irabazi-asmorik gabeko batek sostengatutako nabigatzailea aukeratuz. + + Jarraipen-elementu ezagunak? Automatikoki blokeatzen dira. Hedapenak? Probatu denak, 700 guztira. PDFak? Integratutako gure irakurgailuarekin erraz kudea daitezke. - Irabazi asmorik gabeko erakundeak babestutako gure nabigatzaileak laguntzen du + Irabazi asmorik gabeko erakundeak babestutako gure nabigatzaileak laguntzen du eragozten enpresek zure webeko jarraipena sekretupean egin dezaten.\n\n Argibide gehiago gure pribatutasun-oharrean. - pribatutasun-oharrean + pribatutasun-oharrean Ezarri nabigatzaile lehenetsi gisa @@ -443,22 +465,11 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. HTTPS-Only modua - - Cookie iragarki-banden murrizpena Cookie iragarki-banden blokeatzailea Cookie iragarki-banden blokeatzailea nabigatze pribatuan - - Murriztu cookie iragarki-bandak - - Desaktibatuta - - Aktibatuta - - - Cookie iragarki-bandetako eskaerak automatikoki ukatzen saiatzen da %1$s. Desaktibatuta gune honetarako @@ -476,35 +487,16 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Une honetan gune honetarako euskarririk ez - Aktibatu cookie iragarki-banden murrizpena %1$s gunerako? - Aktibatu cookie iragarki-banden blokeatzailea %1$s gunerako? - Desaktibatu cookie iragarki-banden murrizpena %1$s gunerako? - Desaktibatu cookie iragarki-banden blokeatzailea %1$s gunerako? %1$s(e)k ezin ditu cookie-eskaerak automatikoki baztertu gune honetan. Etorkizunean gune honetarako euskarria gehitzeko eskaera bidal dezakezu. - - %1$s(e)k gune honetako cookieak garbitu eta orria berrituko du. Cookie guztiak garbitzean, saioak amaitu edo erosketa-orgak hustu litezke. Desaktibatu eta %1$s(e)k gune honetako cookieak garbitu eta orria berrituko du. Saioa amaitu edo erosketa-orgak hustu litezke. - Cookie eskaerak automatikoki ukatzen saiatzen da %1$s. - Aktibatu eta %1$s gune honetako cookie iragarki-bandak automatikoki ukatzen saiatuko da. - - Baimendu %1$s(r)i cookie iragarki-bandak ukatzen? - - %1$s(e)k automatikoki uka ditzake cookie iragarki-bandetako eskaerak. - - Une honetan ez - - Cookie eskaera gutxiago ikusiko dituzu - - - Baimendu %1$s(e)k cookieak ukatu ditu zure partez @@ -720,7 +712,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Laster-markak - Saio-hasierak + Saio-hasierak + + Pasahitzak Irekitako fitxak @@ -747,7 +741,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. %1$s / %2$s %3$s - Kreditu-txartelak + Kreditu-txartelak + + Ordainketa metodoak Helbideak @@ -1290,8 +1286,6 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Baztertu - Ezin da inprimatu - Ezin da orria inprimatu Inprimatu @@ -1696,9 +1690,13 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Modu errazean gehi dezakezu webgune hau zure gailuaren hasierako pantailan berehalako sarbidea izan eta aplikazio-moduko esperientziarekin azkarrago nabigatzeko. - Saio-hasierak eta pasahitzak + Saio-hasierak eta pasahitzak + + Pasahitzak + + Gorde saio-hasierak eta pasahitzak - Gorde saio-hasierak eta pasahitzak + Gorde pasahitzak Galdetu gorde aurretik @@ -1713,28 +1711,48 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Bete erabiltzaile-izen eta pasahitzak zure gailuko beste aplikazioetan. - Gehitu saio-hasiera + Gehitu saio-hasiera - - Sinkronizatu saio-hasierak + + Gehitu pasahitza + + + Sinkronizatu saio-hasierak + + Sinkronizatu pasahitzak - Sinkronizatu saio-hasierak gailuen artean + Sinkronizatu saio-hasierak gailuen artean + + Sinkronizatu pasahitzak gailuen artean - Gordetako saio-hasierak + Gordetako saio-hasierak + + Gordetako pasahitzak + + %s(e)n gordetzen edo sinkronizatzen dituzun saio-hasierak hemen agertuko dira. - %s(e)n gordetzen edo sinkronizatzen dituzun saio-hasierak hemen agertuko dira. + %s(e)n gordetzen edo sinkronizatzen dituzun pasahitzak hemen agertuko dira. Gordetzen dituzun pasahitz guztiak zifratuta daude. + - Sinkronizazioari buruzko argibide gehiago. + Sinkronizazioari buruzko argibide gehiago. + + Sinkronizazioari buruzko argibide gehiago Salbuespenak - Gorde gabeko saio-hasiera eta pasahitzak hemen erakutsiko dira. + Gorde gabeko saio-hasiera eta pasahitzak hemen erakutsiko dira. + + %s(e)k ez du pasahitzik gordeko hemen zerrendatutako guneetarako. - Gune hauetarako ez da saio-hasiera eta pasahitzik gordeko. + Gune hauetarako ez da saio-hasiera eta pasahitzik gordeko. + + %s(e)k ez du pasahitzik gordeko gune hauetarako. Ezabatu salbuespen guztiak - Bilatu saio-hasierak + Bilatu saio-hasierak + + Bilatu pasahitzak Gunea @@ -1762,11 +1780,17 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Ezkutatu pasahitza - Desblokeatu gordetako saio-hasierak ikusteko + Desblokeatu gordetako saio-hasierak ikusteko + + Desblokeatu gordetako pasahitzak ikusteko - Lortu zure saio-hasierak eta pasahitzak + Lortu zure saio-hasierak eta pasahitzak + + Bermatu gordetako zure pasahitzak + + Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza zure saio-hasierak eta pasahitzak babesteko zure gailua beste norbaitek izango balu. - Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza zure saio-hasierak eta pasahitzak babesteko zure gailua beste norbaitek izango balu. + Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza zure gordetako pasahitzak babesteko zure gailua beste norbaitek izango balu. Geroago @@ -1784,7 +1808,10 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Azkenekoz erabilia - Ordenatu saio-hasieren menua + Ordenatu saio-hasieren menua + + + Ordenatu pasahitzen menua @@ -1792,29 +1819,44 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Helbideak - Kreditu-txartelak + Kreditu-txartelak + + Ordainketa metodoak + + Gorde eta osatu automatikoki kreditu-txartelak - Gorde eta osatu automatikoki kreditu-txartelak + Gorde eta bete ordainketa metodoak - Datuak zifratuta daude + Datuak zifratuta daude + + Gordetzen dituzun ordainketa metodo guztiak zifratzen ditu %s(e)k Sinkronizatu txartelak gailuen artean Sinkronizatu txartelak - Gehitu kreditu-txartela + Gehitu kreditu-txartela + + Gehitu txartela - Kudeatu gordetako txartelak + Kudeatu gordetako txartelak + + Kudeatu txartelak Gehitu helbidea Kudeatu helbideak - Gorde eta osatu automatikoki helbideak + Gorde eta osatu automatikoki helbideak + + Gorde eta osatu helbideak - Kontuan izan zenbakiak, helbide elektronikoak eta bidalketa-helbideak + Kontuan izan zenbakiak, helbide elektronikoak eta bidalketa-helbideak + + + Telefono zenbakiak eta helbide elektronikoak ere baditu Gehitu txartela @@ -1835,7 +1877,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Ezabatu txartela - Ziur zaude kreditu-txartel hau ezabatu nahi duzula? + Ziur zaude kreditu-txartel hau ezabatu nahi duzula? + + Ezabatu txartela? Ezabatu @@ -1848,16 +1892,24 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Gordetako txartelak - Idatzi baliozko kreditu-txartel zenbakia + Idatzi baliozko kreditu-txartel zenbakia + + Idatzi baliozko txartel-zenbakia - Bete eremu hau mesedez + Bete eremu hau mesedez + + Gehitu izena Desblokeatu gordetako txartelak ikusteko - Bermatu zure kreditu-txartelak + Bermatu zure kreditu-txartelak + + Bermatu gordetako zure ordainketa metodoak + + Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza zure gordetako kreditu-txartelak babesteko zure gailua beste norbaitek izango balu. - Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza zure gordetako kreditu-txartelak babesteko zure gailua beste norbaitek izango balu. + Konfiguratu gailua blokeatzeko patroia, PINa edo pasahitza gordetako zure ordainketa metodoak babesteko zure gailua beste norbaitek izango balu. Konfiguratu orain @@ -1865,8 +1917,10 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Desblokeatu zure gailua - Desblokeatu gordetako kreditu txartelaren informazioa erabiltzeko + Desblokeatu gordetako kreditu txartelaren informazioa erabiltzeko + + Desblokeatu gordetako ordainketa metodoak erabiltzeko Gehitu helbidea @@ -1874,11 +1928,13 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Kudeatu helbideak - Izena + Izena - Bigarren izena + Bigarren izena - Abizena + Abizena + + Izena Helbidea @@ -1902,7 +1958,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Ezabatu helbidea - Ziur zaude helbide hau ezabatu nahi duzula? + Ziur zaude helbide hau ezabatu nahi duzula? + + Ezabatu helbidea? Ezabatu @@ -2000,31 +2058,53 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Editatu - Ziur zaude saio-hasiera hau ezabatu nahi duzula? + Ziur zaude saio-hasiera hau ezabatu nahi duzula? + + Ziur zaude pasahitz hau ezabatu nahi duzula? Ezabatu Utzi - Saio-hasieren aukerak + Saio-hasieren aukerak + + Pasahitzaren aukerak - Saio-hasieraren web helbiderako testu-eremu editagarria. + Saio-hasieraren web helbiderako testu-eremu editagarria. + + Webgunearen helbidearen testu-eremu editagarria. - Saio-hasieraren erabiltzaile-izenerako testu-eremu editagarria. + Saio-hasieraren erabiltzaile-izenerako testu-eremu editagarria. + + Erabiltzaile-izenaren testu-eremu editagarria. + + Saio-hasieraren pasahitzerako testu-eremu editagarria. - Saio-hasieraren pasahitzerako testu-eremu editagarria. + Pasahitzaren testu-eremu editagarria. - Gorde saio-hasieraren aldaketak. + Gorde saio-hasieraren aldaketak. + + Gorde aldaketak. - Editatu + Editatu + + Editatu pasahitza - Gehitu saio-hasiera berria + Gehitu saio-hasiera berria + + Gehitu pasahitza - Pasahitza behar da + Pasahitza behar da + + Idatzi pasahitz bat - Erabiltzaile-izena behar da + Erabiltzaile-izena behar da + + Idatzi erabiltzaile-izen bat Ostalari-izena behar da + + Idatzi web helbide bat Ahots bidezko bilaketa @@ -2121,6 +2201,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. %s bilaketa + + Aldatu zure nabigatzaile lehenetsia + Ireki webgune, posta elektroniko eta mezuetako loturak Firefoxen automatikoki. @@ -2130,7 +2213,7 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Egin klik xehetasun gehiagorako - Nabigatu gora + Nabigatu gora Itxi @@ -2171,8 +2254,6 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Egokitutako balorazioa - Balorazio fidagaitzak kenduta - Balorazio fidagarrietan oinarrituta Azken balorazioetan nabarmentzekoak @@ -2195,8 +2276,6 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Nabarmentzekoak %s(e)ko azken 80 egunetan fidagarriak direla uste ditugun balorazioak dira.]]> Argibide gehiago %s(r)i buruz. - - Mozillaren %s(e)k nola antzematen duen balorazioen kalitatea Nola antzematen duen %s(e)k balorazioen kalitatea @@ -2231,10 +2310,6 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Produktua berriz ere erabilgarri dagoela ikusten baduzu, jakinaraz iezaguzu eta balorazioak egiaztatzeari ekingo diogu. Jakinarazi produktua berriz ere erabilgarri dagoela - - Balorazioaren kalitatea egiaztatzen - - Balorazioaren kalitatea egiaztatzen Balorazioaren kalitatea egiaztatzen (%s) @@ -2281,13 +2356,19 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Argibide gehiago - "Bai, probatu" aukeratuta, Mozillaren %1$s(r)en %2$s eta %3$s onartzen dituzu. + "Bai, probatu" aukeratuta, Mozillaren %1$s(r)en %2$s eta %3$s onartzen dituzu. "Bai, probatu" hautatuz gero, ondorengoa onartzen duzu %1$s(e)tik: + + "Bai, probatu" aukeratuta, %1$s(r)en %2$s eta %3$s(r)en %4$s onartzen dituzu. + + "Bai, probatu" aukeratuta, %1$s(r)en %2$s eta %3$s(r)en %4$s onartzen dituzu. - pribatutasun-politika + pribatutasun-politika Pribatutasun-politika + + pribatutasun-oharra erabilera-baldintzak @@ -2358,6 +2439,10 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Itzuli orria? + + Orria %1$s hizkuntzatik %2$s hizkuntzara itzuli da Probatu itzulpen pribatuak %1$s(e)n @@ -2370,6 +2455,8 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Itzuli hona Une honetan ez + + Erakutsi jatorrizkoa Eginda @@ -2381,6 +2468,8 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Itzulpena burutzen + + Aukeratu hizkuntza Arazo bat gertatu da itzultzean. Saiatu berriro mesedez. @@ -2390,6 +2479,9 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Argibide gehiago + + Itzultzen… + Itzulpenen aukerak @@ -2402,6 +2494,10 @@ zure pasahitzak, laster-markak eta gehiago zifratzen du. Inoiz ez itzuli %1$s Inoiz ez itzuli gune hau + + Beste ezarpen guztiak baliogabetzen ditu + + Itzultzeko eskaintzak baliogabetzen ditu Itzulpenen ezarpenak diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index dd93a180e..83690f913 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -258,6 +258,11 @@ Käännä sivu + + Sivu käännetty kielestä %1$s kielelle %2$s. + Valittu kieli @@ -336,12 +341,22 @@ Firefoxin tietosuojakäytäntö - + + Lue lisää tietosuojakäytännöstämme Turvaamisesi on tärkeää meille + + Ota selvää, miksi miljoonat rakastavat Firefoxia + + Turvallista selausta ja enemmän vaihtoehtoja Voittoa tavoittelemattoman tahon tukema selaimemme auttaa estämään yrityksiä seuraamasta sinua salaa verkossa. + Yli 100 miljoonaa ihmistä suojaa yksityisyyttään valitsemalla voittoa tavoittelemattoman järjestön tukeman selaimen. + + Tunnetut seuraimet? Estetty automaattisesti. Laajennukset? Kokeile kaikkia 700:aa. PDF-tiedostoja? Sisäänrakennettu lukija tekee niistä helposti hallittavia. + Voittoa tavoittelemattoman tahon tukema selaimemme auttaa estämään yrityksiä seuraamasta sinua salaa verkossa.\n\nLisätietoja on tietosuojakäytännössämme. @@ -698,9 +713,9 @@ Kirjanmerkit - Kirjautumistiedot + Kirjautumistiedot - Salasanat + Salasanat Avoimet välilehdet @@ -726,9 +741,9 @@ %1$s laitteella %2$s %3$s - Luottokortit + Luottokortit - Maksutavat + Maksutavat Osoitteet @@ -1681,13 +1696,13 @@ Voit lisätä tämän sivuston laitteesi aloitusnäytölle, jolloin sivuston käyttö onnistuu nopeasti ja tarjoaa sovelluksen kaltaisen kokemuksen. - Käyttäjätunnukset ja salasanat + Käyttäjätunnukset ja salasanat - Salasanat + Salasanat - Tallenna käyttäjätunnukset ja salasanat + Tallenna käyttäjätunnukset ja salasanat - Tallenna salasanat + Tallenna salasanat Kysy tallennusta @@ -1703,47 +1718,47 @@ Täytä käyttäjätunnukset ja salasanat muissa laitteesi sovelluksissa. - Lisää kirjautumistieto + Lisää kirjautumistieto - Lisää salasana + Lisää salasana - - Synkronoi kirjautumistiedot - Synkronoi salasanat + Synkronoi kirjautumistiedot + + Synkronoi salasanat - Synkronoi kirjautumistiedot laitteiden välillä + Synkronoi kirjautumistiedot laitteiden välillä - Synkronoi salasanat eri laitteiden välillä + Synkronoi salasanat eri laitteiden välillä - Tallennetut kirjautumistiedot + Tallennetut kirjautumistiedot - Tallennetut salasanat + Tallennetut salasanat - %siin tallentamasi tai synkronoimasi kirjautumistiedot näkyvät täällä. + %siin tallentamasi tai synkronoimasi kirjautumistiedot näkyvät täällä. - %siin tallentamasi tai synkronoimasi salasanat näkyvät tässä. Kaikki tallentamasi salasanat ovat salattuja. + %siin tallentamasi tai synkronoimasi salasanat näkyvät tässä. Kaikki tallentamasi salasanat ovat salattuja. - Lue lisää Syncista. + Lue lisää Syncista. - Lisätietoja synkronoinnista + Lisätietoja synkronoinnista Poikkeukset - Käyttäjätunnukset ja salanat, joita ei tallenneta, näytetään täällä. + Käyttäjätunnukset ja salanat, joita ei tallenneta, näytetään täällä. - %s ei tallenna tässä lueteltujen sivustojen salasanoja. + %s ei tallenna tässä lueteltujen sivustojen salasanoja. - Käyttäjätunnuksia ja salasanoja ei tallenneta näille sivustoille. + Käyttäjätunnuksia ja salasanoja ei tallenneta näille sivustoille. - %s ei tallenna näiden sivustojen salasanoja. + %s ei tallenna näiden sivustojen salasanoja. Poista kaikki poikkeukset - Etsi kirjautumistiedoista + Etsi kirjautumistiedoista - Etsi salasanoja + Etsi salasanoja Sivusto @@ -1771,17 +1786,17 @@ Piilota salasana - Avaa lukitus nähdäksesi tallennetut kirjautumistiedot + Avaa lukitus nähdäksesi tallennetut kirjautumistiedot - Avaa lukitus nähdäksesi tallennetut salasanat + Avaa lukitus nähdäksesi tallennetut salasanat - Suojaa käyttäjätunnuksesi ja salasanasi + Suojaa käyttäjätunnuksesi ja salasanasi - Suojaa tallennetut salasanat + Suojaa tallennetut salasanat - Aseta laitteen avaukseen tarkoitettu kuvio, PIN-koodi tai salasana suojataksesi tallennetut kirjautumistiedot ja salasanat siltä varalta, että joku saa laitteesi haltuunsa. + Aseta laitteen avaukseen tarkoitettu kuvio, PIN-koodi tai salasana suojataksesi tallennetut kirjautumistiedot ja salasanat siltä varalta, että joku saa laitteesi haltuunsa. - Määritä laitteen lukituskuvio, PIN-koodi tai salasana suojataksesi tallennettuja salasanojasi, jos laitteesi on jollain toisella. + Määritä laitteen lukituskuvio, PIN-koodi tai salasana suojataksesi tallennettuja salasanojasi, jos laitteesi on jollain toisella. Myöhemmin @@ -1799,7 +1814,10 @@ Viimeksi käytetty - Järjestä kirjautumistietojen valikko + Järjestä kirjautumistietojen valikko + + + Salasanojen järjestysvalikko Salasanojen järjestysvalikko @@ -1810,40 +1828,43 @@ Osoitteet - Luottokortit + Luottokortit - Maksutavat + Maksutavat - Tallenna ja täytä kortit automaattisesti + Tallenna ja täytä kortit automaattisesti - Tallenna ja täytä maksutavat + Tallenna ja täytä maksutavat - Tiedot on salattu + Tiedot on salattu - %s salaa kaikki tallentamasi maksutavat + %s salaa kaikki tallentamasi maksutavat Synkronoi kortit laitteiden välillä Synkronoi kortit - Lisää luottokortti + Lisää luottokortti - Lisää kortti + Lisää kortti - Hallinnoi tallennettuja kortteja + Hallinnoi tallennettuja kortteja - Hallitse kortteja + Hallitse kortteja Lisää osoite Hallitse osoitteita - Tallenna ja täytä osoitteet automaattisesti + Tallenna ja täytä osoitteet automaattisesti - Tallenna ja täytä osoitteet + Tallenna ja täytä osoitteet - Sisällytä tiedot kuten numerot, sähköpostiosoitteet ja toimitusosoitteet + Sisällytä tiedot kuten numerot, sähköpostiosoitteet ja toimitusosoitteet + + + Sisältää puhelinnumerot ja sähköpostiosoitteet Sisältää puhelinnumerot ja sähköpostiosoitteet @@ -1867,9 +1888,9 @@ Poista kortti - Haluatko varmasti poistaa tämän luottokortin? + Haluatko varmasti poistaa tämän luottokortin? - Poistetaanko kortti? + Poistetaanko kortti? Poista @@ -1883,24 +1904,24 @@ Tallennetut kortit - Kirjoita kelvollinen luottokortin numero + Kirjoita kelvollinen luottokortin numero - Anna kelvollinen kortin numero + Anna kelvollinen kortin numero - Täytä tämä kenttä + Täytä tämä kenttä - Lisää nimi + Lisää nimi Avaa lukitus nähdäksesi tallennetut kortit - Suojaa luottokorttisi + Suojaa luottokorttisi - Suojaa tallennetut maksutavat + Suojaa tallennetut maksutavat - Aseta laitteen avaukseen tarkoitettu kuvio, PIN-koodi tai salasana suojataksesi tallennetut luottokorttitiedot siltä varalta, että joku saa laitteesi haltuunsa. + Aseta laitteen avaukseen tarkoitettu kuvio, PIN-koodi tai salasana suojataksesi tallennetut luottokorttitiedot siltä varalta, että joku saa laitteesi haltuunsa. - Määritä laitteen lukituskuvio, PIN-koodi tai salasana suojataksesi tallennettuja maksutapojasi, jos laitteesi on jollain toisella. + Määritä laitteen lukituskuvio, PIN-koodi tai salasana suojataksesi tallennettuja maksutapojasi, jos laitteesi on jollain toisella. Aseta nyt @@ -1909,10 +1930,10 @@ Avaa laitteen lukitus - Avaa lukitus käyttääksesi tallennettuja luottokorttitietoja + Avaa lukitus käyttääksesi tallennettuja luottokorttitietoja - Avaa lukitus käyttääksesi tallennettuja maksutapoja + Avaa lukitus käyttääksesi tallennettuja maksutapoja Lisää osoite @@ -1920,11 +1941,13 @@ Hallitse osoitteita - Etunimi + Etunimi - Toinen nimi + Toinen nimi - Sukunimi + Sukunimi + + Nimi Katuosoite @@ -1949,9 +1972,9 @@ Poista osoite - Haluatko varmasti poistaa tämän osoitteen? + Haluatko varmasti poistaa tämän osoitteen? - Poistetaanko tämä osoite? + Poistetaanko tämä osoite? Poista @@ -2050,49 +2073,49 @@ Muokkaa - Haluatko varmasti poistaa tämän kirjautumistiedon? + Haluatko varmasti poistaa tämän kirjautumistiedon? - Haluatko varmasti poistaa tämän salasanan? + Haluatko varmasti poistaa tämän salasanan? Poista Peruuta - Kirjautumistietojen valinnat + Kirjautumistietojen valinnat - Salasanojen asetukset + Salasanojen asetukset - Muokattava tekstikenttä kirjautumisen verkkosivua varten. + Muokattava tekstikenttä kirjautumisen verkkosivua varten. - Verkkosivuston muokattava tekstikenttä. + Verkkosivuston muokattava tekstikenttä. - Muokattava tekstikenttä kirjautumisen käyttäjätunnusta varten. + Muokattava tekstikenttä kirjautumisen käyttäjätunnusta varten. - Käyttäjätunnuksen muokattava tekstikenttä. + Käyttäjätunnuksen muokattava tekstikenttä. - Muokattava tekstikenttä kirjautumisen salasanaa varten. + Muokattava tekstikenttä kirjautumisen salasanaa varten. - Salasanan muokattava tekstikenttä. + Salasanan muokattava tekstikenttä. - Tallenna muutokset kirjautumistietoihin. + Tallenna muutokset kirjautumistietoihin. - Tallenna muutokset. + Tallenna muutokset. - Muokkaa + Muokkaa - Muokkaa salasanaa + Muokkaa salasanaa - Lisää uusi kirjautumistieto + Lisää uusi kirjautumistieto - Lisää salasana + Lisää salasana - Salasana vaaditaan + Salasana vaaditaan - Kirjoita salasana + Kirjoita salasana - Käyttäjätunnus vaaditaan + Käyttäjätunnus vaaditaan - Kirjoita käyttäjätunnus + Kirjoita käyttäjätunnus Isäntänimi vaaditaan @@ -2205,7 +2228,7 @@ Napsauta saadaksesi lisätietoja - Liiku ylöspäin + Liiku ylöspäin Sulje @@ -2246,8 +2269,6 @@ Oikaistu arvosana - Epäluotettavat arvostelut poistettu - Luotettavien arvostelujen pohjalta Kohokohdat viimeaikaisista arvosteluista @@ -2299,10 +2320,6 @@ Jos huomaat, että tämä tuote on jälleen varastossa, ilmoita siitä, niin tarkistamme arvostelut. Ilmoita, että tuoteta on varastossa - - Tarkistetaan arvostelun laatua - - Tarkistetaan arvostelun laatua Tarkistetaan arvostelun laatua (%s) @@ -2410,6 +2427,10 @@ Käännetäänkö sivu? + + Sivu käännetty kielestä %1$s kielelle %2$s Kokeile yksityisiä käännöksiä %1$sissa @@ -2422,6 +2443,8 @@ Käännä kielelle Ei nyt + + Näytä alkuperäinen Valmis @@ -2445,6 +2468,16 @@ Lue lisää + + Käännetään… + + + Ladataanko kieli datansäästötilassa (%1$s)? + + Käännösasetukset diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 0ca0df558..0f2fc1bfb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -258,6 +258,11 @@ Traduire la page + + Page traduite en %2$s, l’originale est en %1$s. + Langue sélectionnée @@ -336,12 +341,22 @@ Politique de confidentialité de Firefox - + + En savoir plus dans notre politique de confidentialité Votre protection compte pour nous + + Découvrez pourquoi des millions de personnes aiment Firefox + + La navigation sécurisée avec plus de choix Notre navigateur soutenu par une organisation à but non lucratif empêche les entreprises de vous suivre secrètement sur le Web. + Plus de 100 millions de personnes protègent leur vie privée en choisissant un navigateur soutenu par une organisation à but non lucratif. + + Les traqueurs connus ? Automatiquement bloqués. Des extensions ? Essayez les 700. Des fichiers PDF ? Notre lecteur intégré en facilite la gestion. + Notre navigateur soutenu par une organisation à but non lucratif empêche les entreprises de vous suivre secrètement sur le Web.\n\nPour en savoir plus, consultez notre politique de confidentialité. @@ -697,9 +712,9 @@ Marque-pages - Identifiants + Identifiants - Mots de passe + Mots de passe Onglets ouverts @@ -725,9 +740,9 @@ %1$s sur %2$s %3$s - Cartes bancaires + Cartes bancaires - Moyens de paiement + Moyens de paiement Adresses @@ -1695,13 +1710,13 @@ Vous pouvez facilement ajouter ce site à l’écran d’accueil de votre appareil pour y avoir accès directement et naviguer plus rapidement, comme si vous utilisiez une application. - Identifiants et mots de passe + Identifiants et mots de passe - Mots de passe + Mots de passe - Enregistrer les identifiants et les mots de passe + Enregistrer les identifiants et les mots de passe - Enregistrer les mots de passe + Enregistrer les mots de passe Demander pour enregistrer @@ -1717,47 +1732,47 @@ Remplit les noms d’utilisateur et les mots de passe dans d’autres applications sur votre appareil. - Ajouter un identifiant + Ajouter un identifiant - Ajouter un mot de passe + Ajouter un mot de passe - - Synchroniser les identifiants - Synchroniser les mots de passe + Synchroniser les identifiants + + Synchroniser les mots de passe - Synchroniser les identifiants entre vos appareils + Synchroniser les identifiants entre vos appareils - Synchronisez les mots de passe entre vos appareils + Synchronisez les mots de passe entre vos appareils - Identifiants enregistrés + Identifiants enregistrés - Mots de passe enregistrés + Mots de passe enregistrés - Les identifiants que vous enregistrez ou synchronisez avec %s s’afficheront ici. + Les identifiants que vous enregistrez ou synchronisez avec %s s’afficheront ici. - Les mots de passe que vous enregistrez ou synchronisez avec %s seront répertoriés ici. Tous les mots de passe que vous enregistrez sont chiffrés. + Les mots de passe que vous enregistrez ou synchronisez avec %s seront répertoriés ici. Tous les mots de passe que vous enregistrez sont chiffrés. - En savoir plus sur Sync. + En savoir plus sur Sync. - En savoir plus sur la synchronisation + En savoir plus sur la synchronisation Exceptions - Les identifiants et les mots de passe qui ne sont pas enregistrés seront affichés ici. + Les identifiants et les mots de passe qui ne sont pas enregistrés seront affichés ici. - %s n’enregistrera pas les mots de passe pour les sites listés ici. + %s n’enregistrera pas les mots de passe pour les sites listés ici. - Les identifiants et les mots de passe ne seront pas enregistrés pour ces sites. + Les identifiants et les mots de passe ne seront pas enregistrés pour ces sites. - %s n’enregistrera pas les mots de passe pour ces sites. + %s n’enregistrera pas les mots de passe pour ces sites. Supprimer toutes les exceptions - Rechercher des identifiants + Rechercher des identifiants - Rechercher des mots de passe + Rechercher des mots de passe Site @@ -1785,17 +1800,17 @@ Masquer le mot de passe - Déverrouillez pour afficher vos identifiants enregistrés + Déverrouillez pour afficher vos identifiants enregistrés - Déverrouillez pour afficher vos mots de passe enregistrés + Déverrouillez pour afficher vos mots de passe enregistrés - Protégez vos identifiants et mots de passe + Protégez vos identifiants et mots de passe - Sécurisez les mots de passe enregistrés + Sécurisez les mots de passe enregistrés - Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos identifiants de connexion et mots de passe enregistrés pour le cas où quelqu’un accède à votre appareil. + Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos identifiants de connexion et mots de passe enregistrés pour le cas où quelqu’un accède à votre appareil. - Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos mots de passe enregistrés si jamais quelqu’un accède à votre appareil. + Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos mots de passe enregistrés si jamais quelqu’un accède à votre appareil. Plus tard @@ -1812,7 +1827,10 @@ Dernière utilisation - Menu de tri des identifiants + Menu de tri des identifiants + + + Menu de tri des mots de passe Menu de tri des mots de passe @@ -1823,40 +1841,43 @@ Adresses - Cartes bancaires + Cartes bancaires - Moyens de paiement + Moyens de paiement - Enregistrer et remplir automatiquement les cartes + Enregistrer et remplir automatiquement les cartes - Enregistrer et renseigner les moyens de paiement + Enregistrer et renseigner les moyens de paiement - Les données sont chiffrées + Les données sont chiffrées - %s chiffre tous les moyens de paiement que vous enregistrez + %s chiffre tous les moyens de paiement que vous enregistrez Synchroniser les cartes entre vos appareils Synchroniser les cartes - Ajouter une carte bancaire + Ajouter une carte bancaire - Ajouter une carte + Ajouter une carte - Gérer les cartes enregistrées + Gérer les cartes enregistrées - Gérer les cartes + Gérer les cartes Ajouter une adresse Gérer les adresses - Enregistrer et remplir automatiquement les adresses + Enregistrer et remplir automatiquement les adresses - Enregistrer et remplir automatiquement les adresses + Enregistrer et remplir automatiquement les adresses - Cela comprend des informations telles que des numéros, des adresses e-mail et des adresses d’expédition + Cela comprend des informations telles que des numéros, des adresses e-mail et des adresses d’expédition + + + Y compris les numéros de téléphone et les adresses e-mail Y compris les numéros de téléphone et les adresses e-mail @@ -1880,9 +1901,9 @@ Supprimer la carte - Voulez-vous vraiment supprimer cette carte bancaire ? + Voulez-vous vraiment supprimer cette carte bancaire ? - Supprimer la carte ? + Supprimer la carte ? Supprimer @@ -1896,24 +1917,24 @@ Cartes enregistrées - Veuillez saisir un numéro de carte bancaire valide + Veuillez saisir un numéro de carte bancaire valide - Saisissez un numéro de carte valide + Saisissez un numéro de carte valide - Veuillez compléter ce champ + Veuillez compléter ce champ - Ajouter un nom + Ajouter un nom Déverrouillez pour afficher vos cartes enregistrées - Protégez vos cartes bancaires + Protégez vos cartes bancaires - Sécurisez vos moyens de paiement enregistrés + Sécurisez vos moyens de paiement enregistrés - Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos cartes bancaires enregistrées si jamais quelqu’un accède à votre appareil. + Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos cartes bancaires enregistrées si jamais quelqu’un accède à votre appareil. - Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos moyens de paiement enregistrés si jamais quelqu’un accède à votre appareil. + Configurez un schéma de verrouillage, un code PIN ou un mot de passe pour protéger vos moyens de paiement enregistrés si jamais quelqu’un accède à votre appareil. Configurer maintenant @@ -1921,10 +1942,10 @@ Déverrouillez votre appareil - Déverrouillez pour utiliser les informations de cartes bancaires enregistrées + Déverrouillez pour utiliser les informations de cartes bancaires enregistrées - Déverrouillez pour utiliser des moyens de paiement enregistrés + Déverrouillez pour utiliser des moyens de paiement enregistrés Ajouter une adresse @@ -1932,11 +1953,13 @@ Gérer les adresses - Prénom + Prénom - Deuxième prénom + Deuxième prénom - Nom de famille + Nom de famille + + Nom complet Adresse postale @@ -1961,9 +1984,9 @@ Supprimer l’adresse - Voulez-vous vraiment supprimer cette adresse ? + Voulez-vous vraiment supprimer cette adresse ? - Supprimer cette adresse ? + Supprimer cette adresse ? Supprimer @@ -2061,49 +2084,49 @@ Modifier - Voulez-vous vraiment supprimer cet identifiant ? + Voulez-vous vraiment supprimer cet identifiant ? - Voulez-vous vraiment supprimer ce mot de passe ? + Voulez-vous vraiment supprimer ce mot de passe ? Supprimer Annuler - Options de l’identifiant + Options de l’identifiant - Options de mot de passe + Options de mot de passe - Le champ de texte modifiable pour l’adresse web de l’identifiant. + Le champ de texte modifiable pour l’adresse web de l’identifiant. - Le champ de texte modifiable pour l’adresse du site web. + Le champ de texte modifiable pour l’adresse du site web. - Le champ de texte modifiable pour le nom d’utilisateur de l’identifiant. + Le champ de texte modifiable pour le nom d’utilisateur de l’identifiant. - Le champ de texte modifiable pour le nom d’utilisateur. + Le champ de texte modifiable pour le nom d’utilisateur. - Le champ de texte modifiable pour le mot de passe de l’identifiant. + Le champ de texte modifiable pour le mot de passe de l’identifiant. - Le champ de texte modifiable pour le mot de passe. + Le champ de texte modifiable pour le mot de passe. - Enregistrez les modifications de l’identifiant. + Enregistrez les modifications de l’identifiant. - Enregistrer les modifications. + Enregistrer les modifications. - Modifier + Modifier - Modifier le mot de passe + Modifier le mot de passe - Ajouter un nouvel identifiant + Ajouter un nouvel identifiant - Ajouter un mot de passe + Ajouter un mot de passe - Mot de passe requis + Mot de passe requis - Saisissez un mot de passe + Saisissez un mot de passe - Le nom d’utilisateur doit être renseigné. + Le nom d’utilisateur doit être renseigné. - Saisissez un nom d’utilisateur + Saisissez un nom d’utilisateur Le nom d’hôte est requis @@ -2216,7 +2239,7 @@ Cliquez pour plus de précisions - Remonter + Remonter Fermer @@ -2257,8 +2280,6 @@ Évaluation corrigée - Avis non fiables supprimés - Sur la base d’avis fiables Points essentiels des avis récents @@ -2315,10 +2336,6 @@ Si vous constatez le retour de ce produit en stock, signalez-le et nous travaillerons à évaluer les avis. Signaler que le produit est en stock - - Évaluation de la qualité des avis - - Évaluation de la qualité des avis Évaluation de la qualité des avis (%s) @@ -2364,13 +2381,19 @@ En savoir plus - En sélectionnant « Oui, l’essayer », vous acceptez la %2$s et les %3$s de %1$s par Mozilla. + En sélectionnant « Oui, l’essayer », vous acceptez la %2$s et les %3$s de %1$s par Mozilla. En sélectionnant « Oui, l’essayer » vous acceptez les éléments suivants de %1$s : + + En sélectionnant « Oui, l’essayer », vous acceptez la %2$s de %1$s et la %4$s de %3$s. + + En sélectionnant « Oui, l’essayer », vous acceptez la %2$s de %1$s et la %4$s de %3$s. - politique de confidentialité + politique de confidentialité Politique de confidentialité + + politique de confidentialité conditions d’utilisation @@ -2442,6 +2465,10 @@ Traduire cette page ? + + Page traduite en %2$s, l’originale est en %1$s Essayer les traductions privées de %1$s @@ -2454,6 +2481,8 @@ Langue cible : Plus tard + + Afficher la page d’origine Terminé @@ -2476,6 +2505,16 @@ En savoir plus + + Traduction… + + + Télécharger la langue en mode d’économie de données (%1$s) ? + + Options de traduction diff --git a/app/src/main/res/values-fur/strings.xml b/app/src/main/res/values-fur/strings.xml index 1360e9100..34bbf9c3f 100644 --- a/app/src/main/res/values-fur/strings.xml +++ b/app/src/main/res/values-fur/strings.xml @@ -97,7 +97,7 @@ - La nestre plui fuarte funzion di protezion de riservatece mai realizade e isole lis spiis inter-sît. + La nestre plui potente funzion di simpri pe protezion de riservatece e isole lis spiis inter-sît. Plui informazions su la Protezion Totâl dai Cookies @@ -253,6 +253,11 @@ Tradûs pagjine + + Pagjine voltade dal %1$s al %2$s. + Lenghe selezionade @@ -328,12 +333,22 @@ Informative su la riservatece di Firefox - + + Plui informazions te nestre informative su la riservatece Nus plâs tignîti di cont + + Scuvierç parcè che milions di personis a adorin Firefox + + Navigazion sigure cun plui sielte Il nestri navigadôr, supuartât di une organizazion cence fins di vuadagn, al bloche in automatic lis societâts che, di scuindon, a cirin di stâti daûr tes tôs ativitâts ator pal web. + Plui di 100 milions di personis a protezin la lôr riservatece sielzint un navigadôr che al è supuartât di une organizazion cence fins di vuadagn. + + Spiis cognossudis? Blocadis in automatic. Estensions? Provilis dutis, a \'nd è plui di 700. PDFs? Il nestri letôr integrât al rint plui facile la lôr gjestion. + Il nestri navigadôr, supuartât di une organizazion cence fins di vuadagn, ti jude a blocâ in automatic lis societâts che, di scuindon, a cirin di stâti daûr a ce che tu fasis in rêt.\n\nScuvierç di plui te nestre informative su la riservatece. @@ -696,9 +711,9 @@ Segnelibris - Credenziâls + Credenziâls - Passwords + Passwords Schedis viertis @@ -722,9 +737,9 @@ and the third is the device model. --> %1$s su %2$s %3$s - Cjartis di credit + Cjartis di credit - Metodis di paiament + Metodis di paiament Recapits @@ -1532,7 +1547,7 @@ Restritive - Protezion da lis spiis plui fuarte e prestazions plui sveltis, ma al è pussibil che cualchi sît nol funzioni ben. + Protezion da lis spiis plui potente e prestazions plui sveltis, ma al è pussibil che cualchi sît nol funzioni ben. Elements blocâts de protezion restritive da lis spiis @@ -1668,13 +1683,13 @@ Al è pussibil zontâ chest sît web ae schermade principâl dal dispositîf par doprâle cun plui sveltece, tant che e fos une aplicazion. - Credenziâls e passwords + Credenziâls e passwords - Passwords + Passwords - Salve credenziâls e passwords + Salve credenziâls e passwords - Salve passwords + Salve passwords Domande prime di salvâ @@ -1688,49 +1703,49 @@ Compile i nons utent e lis passwords in altris aplicazions dal to dispositîf. - Zonte credenziâl + Zonte credenziâl - Zonte password + Zonte password - - Sincronize lis credenziâls - Sincronize passwords + Sincronize lis credenziâls + + Sincronize passwords - Sincronize lis credenziâls tra dispositîfs + Sincronize lis credenziâls tra dispositîfs - Sincronize passwords tra i tiei dispositîfs + Sincronize passwords tra i tiei dispositîfs - Credenziâls salvadis + Credenziâls salvadis - Passwords salvadis + Passwords salvadis - Lis credenziâls che tu salvis o sincronizis su %s a vignaran fûr achì. + Lis credenziâls che tu salvis o sincronizis su %s a vignaran fûr achì. - Lis passwords salvadis o sincronizadis su %s a vignaran listadis achì. Dutis lis passwords che tu salvis a vegnin cifradis. + Lis passwords salvadis o sincronizadis su %s a vignaran listadis achì. Dutis lis passwords che tu salvis a vegnin cifradis. - Plui informazions su Sync. + Plui informazions su Sync. - Plui informazions su la sincronizazion + Plui informazions su la sincronizazion Ecezions - Lis credenziâls e lis passwords che no tu âs salvât a vignaran fûr achì. + Lis credenziâls e lis passwords che no tu âs salvât a vignaran fûr achì. - %s nol salvarà lis passwords pai sîts listâts achì. + %s nol salvarà lis passwords pai sîts listâts achì. - Lis credenziâls e lis passwords no vignaran salvadis par chescj sîts. + Lis credenziâls e lis passwords no vignaran salvadis par chescj sîts. - %s nol salvarà lis passwords par chescj sîts. + %s nol salvarà lis passwords par chescj sîts. Elimine dutis lis ecezions - Cîr credenziâls + Cîr credenziâls - Cîr tes passwords + Cîr tes passwords Sît @@ -1758,17 +1773,17 @@ Plate password - Sbloche par visualizâ lis credenziâls salvadis + Sbloche par visualizâ lis credenziâls salvadis - Sbloche par viodi lis passwords salvadis + Sbloche par viodi lis passwords salvadis - Protêç lis tôs credenziâls di acès + Protêç lis tôs credenziâls di acès - Protêç lis passwords salvadis + Protêç lis passwords salvadis - Configure une secuence di bloc, PIN o password par protezi lis tôs credenziâls e lis passwords salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. + Configure une secuence di bloc, PIN o password par protezi lis tôs credenziâls e lis passwords salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. - Configure une secuence di bloc, PIN o password par protezi lis passwords salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. + Configure une secuence di bloc, PIN o password par protezi lis passwords salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. Plui indenant @@ -1784,7 +1799,10 @@ Ultime doprade - Ordene il menù des credenziâls + Ordene il menù des credenziâls + + + Menù par ordenâ lis passwords Menù par ordenâ lis passwords @@ -1795,40 +1813,43 @@ Recapits - Cjartis di credit + Cjartis di credit - Metodis di paiament + Metodis di paiament - Salve e compile in automatic lis cjartis + Salve e compile in automatic lis cjartis - Salve e compile i metodis di paiament + Salve e compile i metodis di paiament - I dâts a son cifrâts + I dâts a son cifrâts - %s al cifre ducj i metodis di paiaments salvâts + %s al cifre ducj i metodis di paiaments salvâts Sincronize lis cjartis tra plui dispositîfs Sincronize cjartis di credit - Zonte cjarte di credit + Zonte cjarte di credit - Zonte cjarte + Zonte cjarte - Gjestìs cjartis salvadis + Gjestìs cjartis salvadis - Gjestìs cjartis + Gjestìs cjartis Zonte recapit Gjestìs recapits - Salve e compile in automatic i recapits + Salve e compile in automatic i recapits - Salve e compile direzions + Salve e compile direzions - Includi informazions come numars, e-mail e recapits di spedizion + Includi informazions come numars, e-mail e recapits di spedizion + + + Inclût numars di telefon e direzions e-mail Inclût numars di telefon e direzions e-mail @@ -1852,9 +1873,9 @@ Elimine cjarte - Eliminâ pardabon cheste cjarte di credit? + Eliminâ pardabon cheste cjarte di credit? - Eliminâ la cjarte? + Eliminâ la cjarte? Elimine @@ -1866,24 +1887,24 @@ Cjartis salvadis - Inserìs un numar di cjarte di credit valit + Inserìs un numar di cjarte di credit valit - Inserìs un numar di cjarte valit + Inserìs un numar di cjarte valit - Compile chest cjamp + Compile chest cjamp - Zonte un non + Zonte un non Sbloche par visualizâ lis cjartis di credit salvadis - Protêç lis tôs cjartis di credit + Protêç lis tôs cjartis di credit - Protêç i metodis di paiament salvâts + Protêç i metodis di paiament salvâts - Configure une secuence di bloc, PIN o password par protezi lis tôs cjartis di credit salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. + Configure une secuence di bloc, PIN o password par protezi lis tôs cjartis di credit salvadis, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâlis. - Configure une secuence di bloc, PIN o password par protezi i tiei metodis di paiament salvâts, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâju. + Configure une secuence di bloc, PIN o password par protezi i tiei metodis di paiament salvâts, cussì che se cualchidun altri al varà il to dispositîf nol rivarà a doprâju. Configure cumò @@ -1891,9 +1912,9 @@ Sbloche il dispositîf - Sbloche par doprâ lis informazions des cjartis di credit memorizadis + Sbloche par doprâ lis informazions des cjartis di credit memorizadis - Sbloche par doprâ i metodis di paiament + Sbloche par doprâ i metodis di paiament Zonte recapit @@ -1901,11 +1922,13 @@ Gjestìs recapits - Non + Non - Secont non + Secont non - Cognon + Cognon + + Non Recapit @@ -1929,9 +1952,9 @@ Elimine recapit - Eliminâ pardabon chest recapit? + Eliminâ pardabon chest recapit? - Eliminâ cheste direzion? + Eliminâ cheste direzion? Elimine @@ -2029,49 +2052,49 @@ Modifiche - Eliminâ pardabon cheste credenziâl? + Eliminâ pardabon cheste credenziâl? - Eliminâ pardabon cheste password? + Eliminâ pardabon cheste password? Elimine Anule - Opzions credenziâls + Opzions credenziâls - Opzions password + Opzions password - Il cjamp di test modificabil pe direzion web de credenziâl. + Il cjamp di test modificabil pe direzion web de credenziâl. - Il cjamp di test che si pues modificâ pe direzion dal sît web. + Il cjamp di test che si pues modificâ pe direzion dal sît web. - Il cjamp di test modificabil pal non utent de credenziâl. + Il cjamp di test modificabil pal non utent de credenziâl. - Il cjamp di test che si pues modificâ pal non utent. + Il cjamp di test che si pues modificâ pal non utent. - Il cjamp di test modificabil pe password de credenziâl. + Il cjamp di test modificabil pe password de credenziâl. - Il cjamp di test che si pues modificâ pe password. + Il cjamp di test che si pues modificâ pe password. - Salve lis modifichis ae credenziâl. + Salve lis modifichis ae credenziâl. - Salve modifichis. + Salve modifichis. - Modifiche + Modifiche - Modifiche password + Modifiche password - Zonte gnove credenziâl + Zonte gnove credenziâl - Zonte password + Zonte password - Password necessarie + Password necessarie - Inserìs une password + Inserìs une password - Non utent necessari + Non utent necessari - Inserìs un non utent + Inserìs un non utent Non servidôr necessari @@ -2175,7 +2198,7 @@ Fâs clic par vê plui detais - Va sù + Va sù Siere @@ -2215,8 +2238,6 @@ Valutazion retificade - Recensions inafidabilis gjavadis - Basât su recensions afidabilis In evidence da lis recensions resintis @@ -2279,10 +2300,6 @@ Segnale che il prodot al è disponibil - - Daûr a verificâ la cualitât recensions - - Daûr a verificâ la cualitât recensions Verifiche cualitât recensions (%s) @@ -2332,13 +2349,19 @@ Plui informazions - Selezionant “Sì, provilu” tu acetis la %2$s e i %3$s di %1$s di Mozilla. + Selezionant “Sì, provilu” tu acetis la %2$s e i %3$s di %1$s di Mozilla. Selezionant “Sì, provilu” tu acetis lis cundizions di %1$s: + + Selezionant “Sì, provile” tu acetis la %2$s di %1$s e lis %4$s di %3$s. + + Selezionant “Sì, provile” tu acetis la %2$s di %1$s e lis %4$s di %3$s. - informative su la riservatece + informative su la riservatece Informative su la riservatece + + informative su la riservatece tiermins di utilizazion @@ -2410,6 +2433,10 @@ Voltâ cheste pagjine? + + Pagjine voltade dal %1$s al %2$s Prove lis traduzions privadis in %1$s @@ -2422,6 +2449,8 @@ Tradûs par No cumò + + Mostre origjinâl Fat @@ -2445,6 +2474,16 @@ Plui informazions + + + Daûr a tradusi… + + Discjariâ la lenghe in modalitât Sparagn dâts (%1$s)? + + Opzions di traduzion diff --git a/app/src/main/res/values-fy-rNL/strings.xml b/app/src/main/res/values-fy-rNL/strings.xml index f6b4d6541..75f0410e7 100644 --- a/app/src/main/res/values-fy-rNL/strings.xml +++ b/app/src/main/res/values-fy-rNL/strings.xml @@ -255,6 +255,11 @@ Side oersette + + Side oerset fan it %1$s nei it %2$s. + Selektearre taal @@ -333,12 +338,22 @@ Firefox-privacyferklearring - + + Lês mear yn ús privacyferklearring Wy hâlde jo graach feilich + + Untdek wêrom miljoenen sa gek binne op Firefox + + Feilich sneupe mei mear kar Us troch in non-profitorganisaasje browser helpt bedriuwen foar te kommen dat bedriuwen jo stikem folgje op ynternet. + Mear as 100 miljoen minsken beskermje harren privacy troch in browser te kiezen dy’t stipe wurdt troch in non-profitorganisaasje. + + Bekende trackers? Automatysk blokkearre. Utwreidingen? Probearje se alle 700. PDF’s? Troch ús ynboude lêzer binne se ienfâldich te behearen. + Us troch in non-profitorganisaasje stipe browser helpt foar te kommen dat bedriuwen jo stikem folgje op ynternet.\n\nMear ynfo yn ús privacyferklearring. @@ -692,9 +707,9 @@ Blêdwizers - Oanmeldingen + Oanmeldingen - Wachtwurden + Wachtwurden Iepen ljeplêden @@ -720,9 +735,9 @@ %1$s op %2$s %3$s - Creditcards + Creditcards - Betellingsmetoaden + Betellingsmetoaden Adressen @@ -1658,13 +1673,13 @@ Jo kinne dizze website ienfâldich oan it startskerm fan jo apparaat tafoegje, om sa daliks tagong te hawwen en flugger te navigearjen mei in app-eftige ûnderfining. - Oanmeldingen en wachtwurden + Oanmeldingen en wachtwurden - Wachtwurden + Wachtwurden - Oanmeldingen en wachtwurden bewarje + Oanmeldingen en wachtwurden bewarje - Wachtwurden bewarje + Wachtwurden bewarje Freegje om te bewarjen @@ -1679,48 +1694,48 @@ Brûkersnammen en wachtwurden yn oare apps op jo apparaat ynfolje. - Oanmelding tafoegje + Oanmelding tafoegje - Wachtwurd tafoegje + Wachtwurd tafoegje - - Oanmeldingen syngronisearje - Wachtwurden syngronisearje + Oanmeldingen syngronisearje + + Wachtwurden syngronisearje - Oanmeldingen op apparaten syngronisearje + Oanmeldingen op apparaten syngronisearje - Wachtwurden syngronisearje tusken apparaten + Wachtwurden syngronisearje tusken apparaten - Bewarre oanmeldingen + Bewarre oanmeldingen - Bewarre wachtwurden + Bewarre wachtwurden - De oanmeldingen dy’t jo bewarje of syngronisearje mei %s wurde hjir toand. + De oanmeldingen dy’t jo bewarje of syngronisearje mei %s wurde hjir toand. - De wachtwurden dy’t jo bewarje of syngronisearje mei %s sille hjir fermeld wurde. Alle wachtwurden dy’t jo bewarje binne fersifere. + De wachtwurden dy’t jo bewarje of syngronisearje mei %s sille hjir fermeld wurde. Alle wachtwurden dy’t jo bewarje binne fersifere. - Mear ynfo oer Sync. + Mear ynfo oer Sync. - Mear ynfo oer syngronisaasje + Mear ynfo oer syngronisaasje Utsûnderingen - Net-bewarre oanmeldingen en wachtwurden wurde hjir werjûn. + Net-bewarre oanmeldingen en wachtwurden wurde hjir werjûn. - %s sil gjin wachtwurden foar de hjir fermelde websites bewarje. + %s sil gjin wachtwurden foar de hjir fermelde websites bewarje. - Oanmeldingen en wachtwurden wurde foar dizze websites net bewarre. + Oanmeldingen en wachtwurden wurde foar dizze websites net bewarre. - %s sil gjin wachtwurden foar dizze websites bewarje. + %s sil gjin wachtwurden foar dizze websites bewarje. Alle útsûnderingen fuortsmite - Oanmeldingen sykje + Oanmeldingen sykje - Wachtwurden sykje + Wachtwurden sykje Website @@ -1748,17 +1763,17 @@ Wachtwurd ferstopje - Untskoattelje om jo bewarre oanmeldingen te besjen + Untskoattelje om jo bewarre oanmeldingen te besjen - Untskoattelje om jo bewarre wachtwurden te besjen + Untskoattelje om jo bewarre wachtwurden te besjen - Befeiligje jo oanmeldingen en wachtwurden + Befeiligje jo oanmeldingen en wachtwurden - Befeiligje jo bewarre wachtwurden + Befeiligje jo bewarre wachtwurden - Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre oanmeldingen en wachtwurden te beskermjen tsjin tagong as in oar jo apparaat hat. + Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre oanmeldingen en wachtwurden te beskermjen tsjin tagong as in oar jo apparaat hat. - Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre wachtwurden te beskermjen tsjin tagong as in oar jo apparaat hat. + Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre wachtwurden te beskermjen tsjin tagong as in oar jo apparaat hat. Letter @@ -1775,7 +1790,10 @@ Lêst brûkt - Menu Oanmeldingen sortearje + Menu Oanmeldingen sortearje + + + Wachtwurdmenu sortearje Wachtwurdmenu sortearje @@ -1786,40 +1804,43 @@ Adressen - Creditcards + Creditcards - Betellingsmetoaden + Betellingsmetoaden - Kaarten bewarje en automatysk ynfolje + Kaarten bewarje en automatysk ynfolje - Betellingsmetoaden bewarje en ynfolje + Betellingsmetoaden bewarje en ynfolje - Gegevens binne fersifere + Gegevens binne fersifere - %s fersiferet alle betellingsmetoaden dy’t jo bewarje + %s fersiferet alle betellingsmetoaden dy’t jo bewarje Kaarten syngronisearje tusken apparaten Kaarten syngronisearje - Creditcard tafoegje + Creditcard tafoegje - Kaart tafoegje + Kaart tafoegje - Bewarre kaarten beheare + Bewarre kaarten beheare - Kaarten beheare + Kaarten beheare Adres tafoegje Adressen beheare - Adressen bewarje en automatysk ynfolje + Adressen bewarje en automatysk ynfolje - Adressen bewarje en ynfolje + Adressen bewarje en ynfolje - Ynformaasje lykas nûmers, e-mail- en ferstjoeradressen tafoegje + Ynformaasje lykas nûmers, e-mail- en ferstjoeradressen tafoegje + + + Ynklusyf telefoannûmers en e-mailadressen Ynklusyf telefoannûmers en e-mailadressen @@ -1844,9 +1865,9 @@ Kaart fuortsmite - Binne jo wis dat jo dizze creditcard fuortsmite wolle? + Binne jo wis dat jo dizze creditcard fuortsmite wolle? - Kaart fuortsmite? + Kaart fuortsmite? Fuortsmite @@ -1860,25 +1881,25 @@ Bewarre kaarten - Fier in jildich creditkaartnûmer yn + Fier in jildich creditkaartnûmer yn - Fier in jildich kaartnûmer yn + Fier in jildich kaartnûmer yn - Folje dit fjild yn + Folje dit fjild yn - Foegje in namme ta + Foegje in namme ta Untskoattelje om jo bewarre kaarten te besjen - Befeiligje jo creditcards + Befeiligje jo creditcards - Befeiligje jo bewarre betelmetoaden + Befeiligje jo bewarre betelmetoaden - Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre creditcards te beskermjen tsjin tagong as in oar jo apparaat hat. + Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre creditcards te beskermjen tsjin tagong as in oar jo apparaat hat. - Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre betellingsmetoaden te beskermjen tsjin tagong as in oar jo apparaat hat. + Stel in beskoattelingspatroan, pinkoade of wachtwurd foar jo apparaat yn om jo bewarre betellingsmetoaden te beskermjen tsjin tagong as in oar jo apparaat hat. No ynstelle @@ -1887,10 +1908,10 @@ Untskoattelje jo apparaat - Untskoattelje om bewarre creditkaartynformaasje te brûken + Untskoattelje om bewarre creditkaartynformaasje te brûken - Untskoattelje om bewarre betellingsmetoaden te brûken + Untskoattelje om bewarre betellingsmetoaden te brûken Adres tafoegje @@ -1898,11 +1919,13 @@ Adressen beheare - Foarnamme + Foarnamme - Twadde namme + Twadde namme - Efternamme + Efternamme + + Namme Adres @@ -1927,9 +1950,9 @@ Adres fuortsmite - Binne jo wis dat jo dit adres fuortsmite wolle? + Binne jo wis dat jo dit adres fuortsmite wolle? - Dit adres fuortsmite? + Dit adres fuortsmite? Fuortsmite @@ -2027,49 +2050,49 @@ Bewurkje - Binne jo wis dat jo dizze oanmelding fuortsmite wolle? + Binne jo wis dat jo dizze oanmelding fuortsmite wolle? - Binne jo wis dat jo dit wachtwurd fuortsmite wolle? + Binne jo wis dat jo dit wachtwurd fuortsmite wolle? Fuortsmite Annulearje - Oanmeldopsjes + Oanmeldopsjes - Wachtwurdopsjes + Wachtwurdopsjes - It bewurkbere tekstfjild foar it webadres fan de oanmelding. + It bewurkbere tekstfjild foar it webadres fan de oanmelding. - It bewurkbere tekstfjild foar it websiteadres. + It bewurkbere tekstfjild foar it websiteadres. - It bewurkbere tekstfjild foar de brûkersnamme fan de oanmelding. + It bewurkbere tekstfjild foar de brûkersnamme fan de oanmelding. - It bewurkbere tekstfjild foar de brûkersnamme. + It bewurkbere tekstfjild foar de brûkersnamme. - It bewurkbere tekstfjild foar it wachtwurd fan de oanmelding. + It bewurkbere tekstfjild foar it wachtwurd fan de oanmelding. - It bewurkbere tekstfjild foar it wachtwurd. + It bewurkbere tekstfjild foar it wachtwurd. - Wizigingen oan oanmelding bewarje. + Wizigingen oan oanmelding bewarje. - Wizigingen bewarje. + Wizigingen bewarje. - Bewurkje + Bewurkje - Wachtwurd bewurkje + Wachtwurd bewurkje - Nije oanmelding tafoegje + Nije oanmelding tafoegje - Wachtwurd tafoegje + Wachtwurd tafoegje - Wachtwurd fereaske + Wachtwurd fereaske - Folje in wachtwurd yn + Folje in wachtwurd yn - Brûkersnamme fereaske + Brûkersnamme fereaske - Folje in brûkersnamme yn + Folje in brûkersnamme yn Hostnamme fereaske @@ -2171,6 +2194,9 @@ Sykje mei %s + + Jo standertbrowser wikselje + Keppelingen fan websites, e-mail en berjochten automatysk yn Firefox iepenje. @@ -2180,7 +2206,7 @@ Klik foar mear details - Omheech + Omheech Slute @@ -2221,8 +2247,6 @@ Oanpaste wurdearring - Unbetroubere beoardielingen fuortsmiten - Basearre op betroubere beoardielingen Hichtepunten út resinte beoardielingen @@ -2280,10 +2304,6 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen As jo sjogge dat dit produkt wer op foarried is, meld it dan oan ús en wy sille wurkje om de beoardielingen te kontrolearjen. Rapportearje dat produkt op foarried is - - Beoardielingskwaliteit kontrolearje - - Beoardielingskwaliteit kontrolearje Beoardielingskwaliteit kontrolearje (%s) @@ -2330,13 +2350,19 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen Mear ynfo - Troch ‘Ja, probearje’ te selektearjen, geane jo akkoard mei it %2$s en de %3$s fan %1$s troch Mozilla. + Troch ‘Ja, probearje’ te selektearjen, geane jo akkoard mei it %2$s en de %3$s fan %1$s troch Mozilla. Troch ‘Ja, probearje’ te selektearjen, geane jo akkoard mei it folgjende fan %1$s: + + Troch ‘Ja, probearje’ te selektearjen, geane jo akkoard mei de %2$s fan %1$s en de %4$s fan %3$s. + + Troch ‘Ja, probearje’ te selektearjen, geane jo akkoard mei de %2$s fan %1$s en de %4$s fan %3$s. - privacybelied + privacybelied Privacybelied + + privacyferklearring brûksbetingsten @@ -2407,6 +2433,10 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen Dizze side oersette? + + Side oerset fan it %1$s nei it %2$s Probearje priveeoersettingen yn %1$s @@ -2419,6 +2449,8 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen Oersette nei it No net + + Orizjineel toane Dien @@ -2441,6 +2473,15 @@ Dizze analyze sil jo allinnich helpe om de beoardielingskwaliteit te beoardielen Mear ynfo + + Oersette… + + Taal downloade yn gegevensbesparringsmodus (%1$s)? + + Oersetopsjes diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 5655ba231..c17604d02 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -68,11 +68,6 @@ Non deixe rastro neste dispositivo - - %1$s elimina as súas cookies, o historial e os datos do sitio cando peche todas as súas fiestras privadas. %2$s Atopar na páxina + + Traducir a páxina Gardar na colección @@ -241,6 +238,7 @@ Editar Personalizar a páxina de inicio + Páxina de inicio @@ -248,6 +246,13 @@ Borrar o historial de navegación + + Traducir a páxina + + Páxina traducida de %1$s a %2$s. + Idioma seleccionado @@ -260,8 +265,6 @@ Escanear - - Motor de buscas Configuración do motor de busca @@ -315,39 +318,44 @@ - As notificacións axúdanlle a facer máis con %s + As notificacións axúdanlle a facer máis con %s - Sincronice as súas lapelas entre dispositivos, xestione as descargas, reciba consellos sobre como aproveitar ao máximo a protección da privacidade de %s e moito máis. + Sincronice as súas lapelas entre dispositivos, xestione as descargas, reciba consellos sobre como aproveitar ao máximo a protección da privacidade de %s e moito máis. - Continuar + Continuar - Agora non + Agora non - - Faga de Firefox o seu navegador de referencia + + Política de privacidade de Firefox + + Obtéña máis información no noso aviso de privacidade Encántanos telo seguro - - Firefox pon ás persoas por riba dos beneficios e defende a súa privacidade bloqueando os rastrexadores entre sitios.\n\nMáis información no noso aviso de privacidade. + Descubra por que millóns de persoas adoran Firefox + + Navegación segura con máis opcións + + O noso navegador sen ánimo de lucro axuda a evitar que as empresas o sigan en segredo pola web. + + Máis de 100 millóns de persoas protexen a súa privacidade escollendo un navegador que está apoiado por unha organización sen ánimo de lucro. - O noso navegador sen ánimo de lucro axuda a evitar que as empresas o sigan en segredo pola web.\n\nMáis información no noso aviso de privacidade. + Rastrexadores coñecidos? Bloqueados automaticamente. Extensións? Probe as 700. PDF? O noso lector integrado fai que sexan fáciles de xestionar. + + O noso navegador sen ánimo de lucro axuda a evitar que as empresas o sigan en segredo pola web.\n\nMáis información no noso aviso de privacidade. - política de privacidade + política de privacidade Estabelecer como navegador predeterminado Agora non - Alterne entre o teléfono e o portátil - Manteña todo cifrado cando salte entre dispositivos - - Recupere as lapelas e os contrasinais dos seus outros dispositivos para retomalo onde o deixou. Cando inicia sesión e sincroniza, está máis seguro. Firefox cifra os seus contrasinais, marcadores e moito máis. @@ -356,15 +364,9 @@ Agora non - - As notificacións axúdanlle a facer máis con Firefox As notificacións axúdanlle a estar máis seguro con Firefox - - Envía lapelas entre dispositivos, xestiona as descargas e recibe consellos para sacar o máximo proveito de Firefox. Envíe pestanas de forma segura entre os seus dispositivos e descubra outras funcións de privacidade en Firefox. @@ -406,8 +408,6 @@ Selecciona un - Xestionar os atallos de busca - Xestionar buscadores alternativos Edita os motores visibles no menú de busca @@ -421,8 +421,6 @@ Motores de busca Suxestións dos buscadores - - Barra de enderezos Preferencias da barra de enderezos @@ -456,20 +454,10 @@ Modo só HTTPS - - Redución do aviso de cookies Bloqueador de aviso de cookies Bloqueador de aviso de cookies na navegación privada - - Reducir os avisos de cookies - - Desactivado - - Activado - - %1$s tenta rexeitar automaticamente as solicitudes de cookies nos avisos de cookies. Desactivado para este sitio @@ -488,33 +476,15 @@ Sitio actualmente non soportado - Quere activar a redución do aviso de cookies para %1$s? - Quere activar o bloqueador do aviso de cookies para %1$s? - Quere desactivar a redución do aviso de cookies para %1$s? - Quere desactivar o bloqueador do aviso de cookies para %1$s? %1$s non pode rexeitar automaticamente as solicitudes de cookies neste sitio. Pode enviar unha solicitude para soportar este sitio no futuro. - %1$s borrará as cookies deste sitio e actualizará a páxina. Ao borrar todas as cookies, é posible que peche a sesión ou baleire os carriños da compra. - Desactivar e %1$s borrará as cookies e volverá cargar este sitio. Isto pode pechar a sesión ou baleirar os carriños da compra. - %1$s tenta rexeitar automaticamente todas as solicitudes de cookies en sitios compatibles. - Activar e %1$s tentará rexeitar automaticamente todos os avisos de cookies deste sitio. - - Quere permitir que %1$s rexeite os avisos de cookies? - - %1$s pode rexeitar automaticamente moitas solicitudes de avisos de cookies. - - Agora non - - Verá menos solicitudes de cookies - - Permitir %1$s acaba de rexeitar as cookies por ti @@ -543,14 +513,10 @@ Non obstante, tamén é posible que estea implicado un atacante. Se continúas ao sitio web, non debes introducir ningunha información confidencial. Se continúas, o modo só HTTPS desactivarase temporalmente para o sitio. Accesibilidade - - Servidor de contas de Firefox personalizado Servidor de contas de Mozilla personalizado Servidor de sincronización personalizado - - Modificouse o servidor de conta/sincronización de Firefox. Vaise saír da aplicación para aplicar os cambios… Conta de Mozilla/servidor de sincronización modificado. Saíndo da aplicación para aplicar os cambios… @@ -568,8 +534,6 @@ Acceda para sincronizar as lapelas, marcadores, contrasinais e moito máis. - Conta de Firefox - Conta de Mozilla Reconectar para retomar a sincronización @@ -581,8 +545,6 @@ Recollida de datos Depuración remota por USB - - Mostrar motores de busca Mostrar suxestións de busca @@ -711,12 +673,6 @@ Explorar os complementos - - - O complemento non é compatíbel - - O complemento xa está instalado - Os complementos están desactivados temporalmente @@ -741,7 +697,9 @@ Marcadores - Identificacións + Identificacións + + Contrasinais Lapelas abertas @@ -766,7 +724,9 @@ %1$s en %2$s %3$s - Tarxetas de crédito + Tarxetas de crédito + + Métodos de pago Enderezos @@ -1300,8 +1260,6 @@ Rexeitar - Non se puido imprimir - Non se pode imprimir esta páxina Imprimir @@ -1346,6 +1304,11 @@ Pechar lapelas privadas + + Pechar lapelas privadas? + + Toque ou pase o dedo nesta notificación para pechar as pestanas privadas. + Mercadotecnia @@ -1585,6 +1548,8 @@ Todas as cookies (pode causar erros nos sitios web) Illar as cookies entre sitios + + Dígalle aos sitios web que non compartan nin vendan datos Contido de rastrexo @@ -1696,9 +1661,13 @@ Pode engadir facilmente este sitio web á pantalla de inicio do dispositivo para ter acceso instantáneo e navegar máis rápido cunha experiencia semellante á dunha aplicación. - Identificacións e contrasinais + Identificacións e contrasinais + + Contrasinais - Gardar Inicios de sesión e contrasinais + Gardar Inicios de sesión e contrasinais + + Gardar contrasinais Preguntar para gardar @@ -1713,28 +1682,47 @@ Encher os nomes de usuario e os contrasinais noutras aplicacións do dispositivo. - Engadir credenciais + Engadir credenciais + + + Engadir contrasinal - - Sincronizar os inicios de sesión + + Sincronizar os inicios de sesión + + Sincronizar contrasinais - Sincronizar as credenciais entre dispositivos + Sincronizar as credenciais entre dispositivos + + Sincronizar os contrasinais entre dispositivos - Identificacións gardadas + Identificacións gardadas + + Contrasinais gardados - Os inicios de sesión que garde ou sincronice co %s aparecerán aquí. + Os inicios de sesión que garde ou sincronice co %s aparecerán aquí. + + Os contrasinais que garde ou sincronice con %s listaranse aquí. Todos os contrasinais que garde están cifrados. - Obteña máis información sobre Sync. + Obteña máis información sobre Sync. + + Obteña máis información sobre Sync Excepcións - Aquí mostraranse os inicios de sesión e os contrasinais que non se garden. + Aquí mostraranse os inicios de sesión e os contrasinais que non se garden. + + %s non gardará os contrasinais dos sitios que aparecen aquí. - Non se gardarán os inicios de sesión e os contrasinais para estes sitios. + Non se gardarán os inicios de sesión e os contrasinais para estes sitios. + + %s non gardará os contrasinais destes sitios. Eliminar todas as excepcións - Buscar inicios de sesións + Buscar inicios de sesións + + Buscar contrasinais Sitio @@ -1762,11 +1750,17 @@ Agochar contrasinal - Desbloquee para ver os seus inicios de sesión gardados + Desbloquee para ver os seus inicios de sesión gardados + + Desbloquear para ver os seus contrasinais gardados + + Protexa os seus inicios de sesión e contrasinais - Protexa os seus inicios de sesión e contrasinais + Protexa os seus contrasinais gardados + + Configure un padrón de bloqueo de dispositivo, PIN ou contrasinal para protexer os accesos e contrasinais gardados de que non sexan accedidos se outra persoa ten o seu dispositivo. - Configure un padrón de bloqueo de dispositivo, PIN ou contrasinal para protexer os accesos e contrasinais gardados de que non sexan accedidos se outra persoa ten o seu dispositivo. + Configure un padrón de bloqueo do dispositivo, un PIN ou un contrasinal para protexer o acceso aos seus contrasinais gardados se outra persoa ten o seu dispositivo. Máis tarde @@ -1782,7 +1776,10 @@ Usado por última vez - Ordenar o menú de inicio de sesión + Ordenar o menú de inicio de sesión + + + Menú de ordenar contrasinais @@ -1790,30 +1787,45 @@ Enderezos - Tarxetas de crédito + Tarxetas de crédito + + Métodos de pagamento + + Gardar e completar automaticamente as tarxetas - Gardar e completar automaticamente as tarxetas + Gardar e cubrir os métodos de pago - Os datos están cifrados + Os datos están cifrados + + %s cifra todos os métodos de pago que garda Sincronizar as tarxetas entre dispositivos Sincronizar as tarxetas - Engadir unha tarxeta de crédito + Engadir unha tarxeta de crédito + + Engadir a tarxeta - Xestionar as tarxetas gardadas + Xestionar as tarxetas gardadas + + Xestionar tarxetas Engadir enderezo Xestionar enderezos - Gardar e encher automaticamente enderezos + Gardar e encher automaticamente enderezos + + Gardar e completar os enderezos - Inclúe información como números, correo electrónico e enderezos de envío + Inclúe información como números, correo electrónico e enderezos de envío + + + Inclúe números de teléfono e enderezos de correo electrónico Engadir a tarxeta @@ -1834,7 +1846,9 @@ Eliminar a tarxeta - Seguro de que quere eliminar esta tarxeta de crédito? + Seguro de que quere eliminar esta tarxeta de crédito? + + Eliminar a tarxeta? Eliminar @@ -1846,15 +1860,23 @@ Tarxetas gardadas - Introduza un número de tarxeta válido + Introduza un número de tarxeta válido + + Introduza un número de tarxeta válido - Cubra este campo + Cubra este campo + + Engadir un nome Desbloquee para ver as súas tarxetas gardadas - Asegure as súas tarxetas de crédito + Asegure as súas tarxetas de crédito + + Protexa os seus métodos de pago gardados + + Configure un padrón de bloqueo de dispositivo, PIN ou contrasinal para evitar que outra persoa co seu dispositivo poida acceder a elas. - Configure un padrón de bloqueo de dispositivo, PIN ou contrasinal para evitar que outra persoa co seu dispositivo poida acceder a elas. + Configure un padrón de bloqueo do dispositivo, un PIN ou un contrasinal para protexer o acceso aos seus métodos de pago gardados se outra persoa ten o seu dispositivo. Configurar agora @@ -1862,7 +1884,9 @@ Desbloquear o dispositivo - Desbloquee para empregar a información almacenada de tarxetas de crédito + Desbloquee para empregar a información almacenada de tarxetas de crédito + + Desbloquee para usar os métodos de pago gardados Engadir enderezo @@ -1870,11 +1894,13 @@ Xestionar enderezos - Nome + Nome - Segundo nome + Segundo nome - Apelidos + Apelidos + + Nome Domicilio @@ -1898,7 +1924,9 @@ Eliminar enderezo - Seguro de que quere eliminar este enderezo? + Seguro de que quere eliminar este enderezo? + + Eliminar este enderezo? Eliminar @@ -1916,28 +1944,18 @@ Editar motor de busca - - Engadir - - Gardar Editar Eliminar - - Outro Nome - - Nome Nome do buscador URL da cadea de busca - Cadea de busca para usar - URL para usar para a busca Substitúír a consulta por «%s». Exemplo:\nhttps://www.google.com/search?q=%s @@ -2008,31 +2026,53 @@ Editar - Confirma que desexa eliminar este inicio de sesión? + Confirma que desexa eliminar este inicio de sesión? + + Seguro que quere eliminar este contrasinal? Eliminar Cancelar - Opcións de inicio de sesión + Opcións de inicio de sesión + + Opcións de contrasinal - O campo de texto editábel para o enderezo web do inicio de sesión. + O campo de texto editábel para o enderezo web do inicio de sesión. + + O campo de texto editable para o enderezo do sitio web. - O campo de texto editábel para o nome de usuario do inicio de sesión. + O campo de texto editábel para o nome de usuario do inicio de sesión. + + O campo de texto editable para o nome de usuario. + + O campo de texto editábel para o contrasinal do inicio de sesión. - O campo de texto editábel para o contrasinal do inicio de sesión. + O campo de texto editable para o contrasinal. - Gardar os cambios para iniciar sesión. + Gardar os cambios para iniciar sesión. + + Gardar cambios. - Editar + Editar + + Editar contrasinal - Engadir novas credenciais + Engadir novas credenciais + + Engadir contrasinal - Contrasinal obrigatorio + Contrasinal obrigatorio + + Introduza un contrasinal - Requírese un nome de usuario + Requírese un nome de usuario + + Introduza un nome de usuario Requírese un nome de servidor + + Introduza un enderezo web Busca por voz @@ -2123,6 +2163,9 @@ Buscar con %s + + Cambie o seu navegador predeterminado + Estabelecer ligazóns de sitios web, enderezos de correo electrónico e mensaxes para que se abran automaticamente no Firefox. @@ -2132,7 +2175,7 @@ Premer para obter máis detalles - Navegar cara arriba + Navegar cara arriba Pechar @@ -2161,8 +2204,6 @@ - Verificador de recensións - Verificador de recensións Recensións fiables @@ -2175,7 +2216,7 @@ Calificación axustada - Elimináronse as recensións pouco fiables + Baseado en recensións fiables Destacados das recensións recentes @@ -2187,22 +2228,16 @@ nota de A a F.]]> Recensións fiables. Cremos que as recensións son probablemente de clientes reais que deixaron recensións honestas e imparciais. - - Cremos que os comentarios son fiables. Cremos que hai unha mestura de recensións fiables e pouco fiables. Recensións pouco fiables. Cremos que as recensións probablemente sexan falsas ou de revisores tendenciosos. - - Cremos que os comentarios non son fiables. valoración axustada baséase só nas recensións que consideramos fiables.]]> destacados son de %s recensións dos últimos 80 días que consideramos fiables.]]> Máis información sobre %s. - - como %s de Mozilla determina a calidade da recensión como %s determina a calidade da revisión @@ -2210,8 +2245,6 @@ Mostrar anuncios no verificador de recensións - Verás anuncios ocasionais de produtos relevantes. Todos os anuncios deben cumprir os nosos estándares de calidade de recensións. %s - Verá anuncios ocasionais de produtos relevantes. Só anunciamos produtos con críticas fiables. %s Máis información @@ -2234,23 +2267,19 @@ Cando este produto teña máis recensións, poderemos comprobar a súa calidade. - O produto non está dispoñible + O produto non está dispoñible - Se ves que este produto está de novo en stock, infórmao e traballaremos en comprobar as recensións. + Se ves que este produto está de novo en stock, infórmao e traballaremos en comprobar as recensións. - Informar que este produto está de novo en stock - - Informar que o produto está en stock - - Comprobando a calidade da recensión - - Comprobando a calidade da recensión + Informar que o produto está en stock + + Comprobando a calidade da recensión (%s) Isto pode levar uns 60 segundos. - Grazas por informar! + Grazas por informar! - Deberíamos ter información sobre as recensións deste produto nun prazo de 24 horas. Volve a comprobalo máis tarde. + Deberíamos ter información sobre as recensións deste produto nun prazo de 24 horas. Volve a comprobalo máis tarde. Non podemos comprobar estas recensións @@ -2288,17 +2317,23 @@ Máis información - Ao seleccionar «Si, probalo», acepta %2$s e %3$s de %1$s de Mozilla. + Ao seleccionar «Si, probalo», acepta %2$s e %3$s de %1$s de Mozilla. - Ao seleccionar «Si, probalo», acepta o seguinte de %1$s: + Ao seleccionar «Si, probalo», acepta o seguinte de %1$s: + + Ao seleccionar «Si, probalo», acepta os %2$s de %1$s e os %4$s de %3$s. + + Ao seleccionar «Si, probalo», acepta os %2$s de %1$s e os %4$s de %3$s. - política de privacidade + política de privacidade - Política de privacidade + Política de privacidade + + política de privacidade - temos de uso + temos de uso - Temos de uso + Temos de uso Si, probalo @@ -2335,6 +2370,9 @@ Competitividade + + «%s» + contraer @@ -2352,4 +2390,226 @@ abrir a ligazón para saber máis %s, Título + + + Ligazóns + + Ligazóns dispoñibles + + + + + + Traducir esta páxina? + + Páxina traducida de %1$s a %2$s + + Probe as traducións privadas en %1$s + + Para a súa privacidade, as traducións nunca saen do seu dispositivo. Novos idiomas e melloras en breve! %1$s + + Máis información + + Traducir do + + Traducir a + + Agora non + + Amosar orixinal + + Feito + + Traducir + + Tentar de novo + + Traducindo + + Tradución en curso + + Escoller un idioma + + Houbo un problema ao traducir. Por favor, ténteo de novo. + + Non se puideron cargar os idiomas. Comprobe a súa conexión a Internet e ténteo de novo. + + Sentímolo, aínda non admitimos %1$s. + + Máis información + + Traducindo… + + + Descargar o idioma no modo de aforro de datos (%1$s)? + + + + + Opcións de tradución + + Ofrecer sempre a tradución + + Traducir sempre %1$s + + Non traducir nunca %1$s + + Non traducir nunca este sitio + + Sobrescribe todas as demais configuracións + + Sobrescribir as ofertas para traducir + + Configuración da tradución + + + Acerca das traducións en %1$s + + + + Traducións + + Ofrécese a traducir cando sexa posible + + Descargar sempre os idiomas no modo de aforro de datos + + Preferencias de tradución + + Tradución automática + + Non traducir nunca estes sitios + + Descargar idiomas + + + + Tradución automática + + + Seleccionar un idioma para xestionar as preferencias de «traducir sempre» e «nunca traducir». + + + + Ofrecer traducción (predeterminado) + + %1$s ofrecerá traducir sitios neste idioma. + + Traduce sempre + + %1$s traducirá este idioma automaticamente cando se cargue a páxina. + + Non traducir nunca + + + %1$s nunca ofrecerá traducir sitios neste idioma. + + + + Non traducir nunca estes sitios + + Para engadir un sitio novo: visíteo e seleccione «Non traducir nunca este sitio» no menú de tradución. + + Retirar %1$s + + Eliminar %1$s? + + Eliminar + + Cancelar + + + + Descargar idiomas + + Descargar idiomas completos para obter traducións máis rápidas e para traducir sen conexión. %1$s + + Máis información + + Idiomas dispoñíbeis + + requirido + + %1$s (%2$s) + + Descargar idiomas + + Todos os idiomas + + Eliminar + + En progreso + + Descargar + + Seleccionado + + + Eliminar %1$s (%2$s)? + + Se elimina este idioma, %1$s descargará idiomas parciais na súa caché mentres traduce. + + Eliminar todos os idiomas (%1$s)? + + Se elimina todos os idiomas, %1$s descargará linguas parciais na súa caché mentres traduce. + + Eliminar + + Cancelar + + + Descargar no modo de aforro de datos (%1$s)? + + Descargamos idiomas parciais na súa caché para manter as traducións privadas. + + Descargar sempre no modo de aforro de datos + + Descargar + + Descargar e traducir + + Cancelar + + + + Ferramentas de depuración + + Retroceder no historial + + Ferramentas de lapelas + + Número de lapelas + + Activo + + Inactivo + + Privado + + Total + + Ferramenta de creación de lapelas + + Cantidade de lapelas a crear + + Engadir ás lapelas activas + + Engadir ás lapelas inactivas + + Engadir ás lapelas privadas diff --git a/app/src/main/res/values-gn/strings.xml b/app/src/main/res/values-gn/strings.xml index 5d0da0318..87f693028 100644 --- a/app/src/main/res/values-gn/strings.xml +++ b/app/src/main/res/values-gn/strings.xml @@ -246,6 +246,7 @@ Emboava kuatiarogue ñepyrũgua + Mba’erechaha ñepyrũgua @@ -253,6 +254,14 @@ Embogue kundahára rembiasakue + + Emoñe’ẽasa kuatiarogue + + + Kuatiarogue moñe’ẽasapyre %1$s-gui %2$s-pe. + Ñe’ẽ poravopyre @@ -264,8 +273,6 @@ Moha’ãnga - - Hekaha mongu’eha Hekaha ñemboheko @@ -320,21 +327,27 @@ - Marandu’i ne pytyvõta ejapovéta %s ndive + Marandu’i ne pytyvõta ejapovéta %s ndive - Embojuehe tendayke mba’e’oka pa’ũme, eñangareko ñemboguejýre, ehendu ñemoñe’ẽ mba’éichapa eiporuporãta %s rekorosã ñemigua ha ambue. + Embojuehe tendayke mba’e’oka pa’ũme, eñangareko ñemboguejýre, ehendu ñemoñe’ẽ mba’éichapa eiporuporãta %s rekorosã ñemigua ha ambue. - Ku’ejey + Ku’ejey - Ani ko’ág̃a + Ani ko’ág̃a Firefox marandu’i ñemigua - + + Eikuaave ore marandu’i ñemigua rupive Rovy’ã eimére tekorosãme + + Ehecha mba’érepa hetaiterei ohayhúva Firefox + + Ñeikundaha tekorosãme hetaháicha Ore kundahára oykeko atyguasu viru’ỹgua oipytyvõ omboykévo umi mba’apohaguasu ani nde rapykueho ñanduti rupive. @@ -446,22 +459,11 @@ HTTPS ayvúpe añoite - - Kookie Banner Ñemomichĩ Ejoko Banner kookie rehegua Kookie ñe’ẽmondo jokoha ñeikundaha ñemíme - - Emomichĩ kookie banner - - - Mboguepyre - - Hendypyre - - %1$s omboykese ijehegui kookie mba’ejerure kookie marandu ñemurãme. Ogue ko tendápe @@ -479,36 +481,17 @@ Tenda ko’ág̃a ojokupyty’ỹva - ¿Emyandy kookie ñemurã momichĩ %1$s peg̃uarã? - ¿Emyandy Kookie Banner jokoha %1$s peg̃uarã? - - ¿Embogue kookie ñemurã momichĩ %1$s peg̃uarã? ¿Embogue Kookie Banner jokoha %1$s peg̃uarã? %1$s nomboykekuaái ijehegui kookie marandu ñemurã ko tendápe. Emba’ejerurekuaa omoneĩ hag̃ua ko tenda tenonderãve. - - %1$s omboguéta kookie ko tendagua ha omyanyhẽjeýta kuatiarogue. Emboguepaitérõ kookie ombotykuaa ne rembiapo térã omonandi ne mba’ejoguakue. Eipe’ãvo, %1$s omboguéta kookie ha omyanyhẽta tenda. Kóva ombotykuaa emba’apoha térã omonandi ejoguáva. - %1$s omboykese ijehegui umi kookie mba’ejerure tenda ojokupytývape. - Emyandývo, %1$s oñeha’ãta omboyke ijeheguiete umi kookie ñe’ẽmondo ko tendápe. - - ¿Emoneĩ %1$s tomboyke kookie ñe’ẽmondo? - - %1$s omboykekuaa ijehegui umi kookie mba’ejerure. - - Ani ko’ág̃a - - Ehecha’ivéta kookie mba’ejerure - - - Moneĩ %1$s omboyke kookie nde rehehápe @@ -730,9 +713,9 @@ Techaukaha - Tembiapo ñepyrũ + Tembiapo ñepyrũ - Ñe’ẽñemi + Ñe’ẽñemi Tendayke ijurujáva @@ -758,9 +741,9 @@ %1$s %2$s %3$s-pe - Kuatia’atã ñemurã + Kuatia’atã ñemurã - Mba’éicha ehepyme’ẽta + Mba’éicha ehepyme’ẽta Kundaharape @@ -1310,8 +1293,6 @@ Mboyke - Ndaikatúi embokuatia - Ndaikatúi emonguatia ko kuatiarogue Mbokuatia @@ -1728,13 +1709,13 @@ Ikatu embojuaju ko ñanduti renda ne mba’e’oka mba’erechaha ñepyrũgua rehe eike hag̃ua ha eikundaha pya’eve, peteĩ tembiporu’ícharamo. - Tembiapo ñepyrũ ha ñe’ẽñemi + Tembiapo ñepyrũ ha ñe’ẽñemi - Ñe’ẽñemi + Ñe’ẽñemi - Eñongatu tembiapo ñepyrũ ha ñe’ẽñemi + Eñongatu tembiapo ñepyrũ ha ñe’ẽñemi - Eñongatu ñe’ẽñemi + Eñongatu ñe’ẽñemi Ejerure ñemoneĩ eñongatu hag̃ua @@ -1751,39 +1732,41 @@ Emoĩmba ha eñongatu poruhára réra ha ñe’ẽñemi ambue tembiporu’ípe ne mba’e’oka pegua. - Embojuaju jeike + Embojuaju jeike - Embojuaju ñe’ẽñemi + Embojuaju ñe’ẽñemi - - Embojuehe tembiapo ñepyrũ - Embojuehe ñe’ẽñemi + Embojuehe tembiapo ñepyrũ + + Embojuehe ñe’ẽñemi - Embojuehe tembiapo ñepyrũ mba’e’oka pa’ũme + Embojuehe tembiapo ñepyrũ mba’e’oka pa’ũme + + Embojuehe ñe’ẽñemi mba’e’oka pa’ũme - Tembiapo ñepyrũ ñongatupyre + Tembiapo ñepyrũ ñongatupyre - Ñe’ẽñemi ñongatupyre + Ñe’ẽñemi ñongatupyre - Ko’ápe ojehecháta tembiapo ñepyrũ eñongatu térã embojuehéva %s ndive. + Ko’ápe ojehecháta tembiapo ñepyrũ eñongatu térã embojuehéva %s ndive. - Eikuaave Sync rehegua + Eikuaave Sync rehegua - Eikuaave ñembojuehe rehegua + Eikuaave ñembojuehe rehegua Oĩ’ỹva - Ápe ojehecháta tembiapo ñepyrũ ha ñe’ẽñemi oñeñongatu’ỹva. + Ápe ojehecháta tembiapo ñepyrũ ha ñe’ẽñemi oñeñongatu’ỹva. - Noñeñongatumo’ãi tembiapo ñepyrũ ha ñe’ẽñemi ko’ã tendápe g̃uarã. + Noñeñongatumo’ãi tembiapo ñepyrũ ha ñe’ẽñemi ko’ã tendápe g̃uarã. Emboguete opaite oĩ’ỹva - Eheka tembiapo ñepyrũ + Eheka tembiapo ñepyrũ - Eheka ñe’ẽñemi + Eheka ñe’ẽñemi Tenda @@ -1811,11 +1794,11 @@ Emokañy ñe’ẽñemi - Emyandyjey ehecha hag̃ua ne rembiapo ñepyrũ ñongatupyre + Emyandyjey ehecha hag̃ua ne rembiapo ñepyrũ ñongatupyre - Erekokuaa nde poruhára ha ñe’ẽñemi + Erekokuaa nde poruhára ha ñe’ẽñemi - Emboheko pe patrõ jokoháva mba’e’oka pegua, PIN térã ñe’ẽñemi emo’ã hag̃ua nde poruhára ha ñe’ẽñemi ñongatupyrépe jeike ambue orekórõ ne mba’e’oka. + Emboheko pe patrõ jokoháva mba’e’oka pegua, PIN térã ñe’ẽñemi emo’ã hag̃ua nde poruhára ha ñe’ẽñemi ñongatupyrépe jeike ambue orekórõ ne mba’e’oka. Upéi @@ -1834,7 +1817,10 @@ Jejuru paha - Emoĩporã poravorã tembiapo ñepyrũgua + Emoĩporã poravorã tembiapo ñepyrũgua + + + Emoĩporã ñe’ẽñemi poravorã Emoĩporã ñe’ẽñemi poravorã @@ -1845,40 +1831,40 @@ Kundaharape - Kuatia’atã ñemurã + Kuatia’atã ñemurã - Mba’éicha ehepyme’ẽta + Mba’éicha ehepyme’ẽta - Eñongatu ha emyanyhẽ kuatia’atã + Eñongatu ha emyanyhẽ kuatia’atã - Eñongatu ha emyanyhẽ mba’éicha ehepyme’ẽta + Eñongatu ha emyanyhẽ mba’éicha ehepyme’ẽta - Mba’ekuaarã ipapapypa + Mba’ekuaarã ipapapypa Embojuehe kuatia’atã mba’e’oka pa’ũme Embojuehe kuatia’atã - Embojuaju kuatia’atã ñemurã + Embojuaju kuatia’atã ñemurã - Embojuaju kuatia’atã + Embojuaju kuatia’atã - Eñangareko kuatia’atã ñongatupyrére + Eñangareko kuatia’atã ñongatupyrére - Eñangareko kuatia’atã + Eñangareko kuatia’atã Embojuaju kundaharape Kundaharape ñangareko - Eñongatu ha emyanyhẽ kundaharape + Eñongatu ha emyanyhẽ kundaharape - Eñongatu ha emyanyhẽ kundaharape + Eñongatu ha emyanyhẽ kundaharape - Emoĩ marandu ipapapy, ñanduti veve ha kundaharape ñemondorãva + Emoĩ marandu ipapapy, ñanduti veve ha kundaharape ñemondorãva Embojuaju kuatia’atã @@ -1899,9 +1885,9 @@ Emboguete kuatia’atã - ¿Emboguesépa añetehápe ko kuatia’atã ñemurã? + ¿Emboguesépa añetehápe ko kuatia’atã ñemurã? - ¿Emboguete kuatia’atã? + ¿Emboguete kuatia’atã? Mboguete @@ -1915,18 +1901,18 @@ Kuatia’atã ñongatupyre - Ikatúpiko ehai kuatia’atã ñemurã papapy oikóva + Ikatúpiko ehai kuatia’atã ñemurã papapy oikóva - Ikatúpiko emyanyhẽ ko kora + Ikatúpiko emyanyhẽ ko kora - Embojuaju téra + Embojuaju téra Embojuruja ehecha hag̃ua kuatia’atã ñongatupyre - Emohekorosã nde kuatia’atã ñemurã + Emohekorosã nde kuatia’atã ñemurã - Emboheko peteĩ jekokoha rape, PIN térã ñe’ẽñemi emo’ã hag̃ua nde kuatia’atã ñongatupyre ambue oikeséramo ne mba’e’okápe. + Emboheko peteĩ jekokoha rape, PIN térã ñe’ẽñemi emo’ã hag̃ua nde kuatia’atã ñongatupyre ambue oikeséramo ne mba’e’okápe. Emboheko ko’ág̃a @@ -1935,7 +1921,7 @@ Embojuruja ne mba’e’oka - Embojuruja eiporu hag̃ua kuatia’atã ñemurã marandu mbyatypyre + Embojuruja eiporu hag̃ua kuatia’atã ñemurã marandu mbyatypyre Embojuaju kundaharape @@ -1944,11 +1930,13 @@ Kundaharape ñangareko - Téra Peteĩha + Téra Peteĩha - Téra Mokõiha + Téra Mokõiha - Terajoapy + Terajoapy + + Téra Kundaharape @@ -1973,7 +1961,9 @@ Embogue kundaharape - ¿Añetehápepa remboguese ko kundaharape? + ¿Añetehápepa remboguese ko kundaharape? + + ¿Embogue kundaharape? Mboguete @@ -2073,41 +2063,41 @@ Mbosako’i - ¿Emboguese añetehápe ko tembiapo ñepyrũ? + ¿Emboguese añetehápe ko tembiapo ñepyrũ? Mboguete Heja - Jeporavorã tembiapo ñepyrũgua + Jeporavorã tembiapo ñepyrũgua - Ñe’ẽñemi jeporavorã + Ñe’ẽñemi jeporavorã - Moñe’ẽha kora isako’ikuaáava ñanduti kundaharape rembiapo ñepyrũme. + Moñe’ẽha kora isako’ikuaáava ñanduti kundaharape rembiapo ñepyrũme. - Moñe’ẽha kora isako’ikuaáava poruhára réra rembiapo ñepyrũme. + Moñe’ẽha kora isako’ikuaáava poruhára réra rembiapo ñepyrũme. - Moñe’ẽha kora isako’ikuaáava ñe’ẽñemi rembiapo ñepyrũme. + Moñe’ẽha kora isako’ikuaáava ñe’ẽñemi rembiapo ñepyrũme. - Eñongatu moambue tembiapo ñepyrũme. + Eñongatu moambue tembiapo ñepyrũme. - Moambue ñongatu. + Moambue ñongatu. - Mbosako’i + Mbosako’i - Embosako’i ñe’ẽñemi + Embosako’i ñe’ẽñemi - Embojuaju terarenda pyahu + Embojuaju terarenda pyahu - Embojuaju ñe’ẽñemi + Embojuaju ñe’ẽñemi - Tekotevẽ ñe’ẽñemi + Tekotevẽ ñe’ẽñemi - Emoinge ñe’ẽñemi + Emoinge ñe’ẽñemi - Poruhára réra jerurepyre + Poruhára réra jerurepyre - Ehai poruhára réra + Ehai poruhára réra Mohendahavusu réra jerurepyre @@ -2207,7 +2197,7 @@ Eheka %s ndive - + Emboheko ñanduti renda juajuha, ñanduti veve ha ñe’ẽmondo ijuruja hag̃ua ijehegui Firefox-pe. @@ -2217,7 +2207,7 @@ Eikutu ápe eikuaave hag̃ua - Eikundaha yvate gotyo + Eikundaha yvate gotyo Mboty @@ -2258,8 +2248,6 @@ Ñeha’ãmby ha’etéva - Oñemboguéta marandu’i jerovia’ỹha - Oiko hechajey jeroviahápe Mba’e iporãva marandu’i osẽramóvare @@ -2281,8 +2269,6 @@ kyta mba’eguasúva ou marandu’i %s 80 ára ohasaramóvagui ikatuha ejerovia.]]> Eikuaave ko’ãvare %s. - - mba’éichapa %s Mozilla mba’e ohechaukáta marandu’i iporãha mba’éicha %s oikuaa marandu’i iporãha @@ -2318,10 +2304,6 @@ Ehechárõ ko apopyre ojejoguakuaajeýma, oremomarandu ha romba’apóta hekopyahu hag̃ua ñehesa’ijo. Emomarandu apopyre ojeporukuaaha - - Ehechajey marandu’i porãngue - - Ehechajey marandu’i porãngue Ehechajey marandu’i porãngue (%s) @@ -2367,11 +2349,11 @@ Eikuaave - Eiporavóvo “Héẽ, eiporu”, emoneĩ %1$s %2$s-gua ha %3$s Mozilla mba’e. + Eiporavóvo “Héẽ, eiporu”, emoneĩ %1$s %2$s-gua ha %3$s Mozilla mba’e. Eiporavóvo “H’éẽ, eiporu”, emoneĩ upeigua %1$s mba’áva: - temiñemi porureko + temiñemi porureko Temiñemi porureko @@ -2457,6 +2439,8 @@ Emoñe’ẽasa pe Ani ko’ág̃a + + Ehechauka ypykuéva Oĩma @@ -2468,6 +2452,8 @@ Ñe’ẽasa oñemboguatáva + + Eiporavo peteĩ ñe’ẽ Iñapañuãi emoñe’ẽasakuévo. Eha’ãjey ag̃amieve. @@ -2477,6 +2463,11 @@ Kuaave + + + Ñemoñe’ẽasa… + + Ñe’ẽasa poravopyrã diff --git a/app/src/main/res/values-hsb/strings.xml b/app/src/main/res/values-hsb/strings.xml index a43969e12..4a36562f1 100644 --- a/app/src/main/res/values-hsb/strings.xml +++ b/app/src/main/res/values-hsb/strings.xml @@ -254,6 +254,11 @@ Stronu přełožić + + Strona je so z rěče %1$s do rěče %2$s přełožiła. + Wubrana rěč @@ -330,12 +335,22 @@ Zdźělenka priwatnosće Firefox - + + Zhońće wjace w našej zdźělence priwatnosće Škitamy was rady + + Wuslědźće, čehodla miliony ludźi Firefox lubuja + + Wěste přehladowanje z wjace wuběrami Naš powšitkownosći wužitny wobhladowak zadźěwa tomu, zo předewzaća wam skradźu po interneće slěduja. + Wjace hač 100 milionow ludźi škita swoju priwatnosć, hdyž wobhladowak wuběraće, kotryž so wot njekomercielneje organizacije podpěruje. + + Znate přesćěhowaki? Blokuja so awtomatisce. Rozšěrjenja? Wupruwujće wšě 700. PDF? Naš zatwarjeny čitak wosnadnja je rjadować. + Naš powšitkownosći wužitny wobhladowak tomu zadźěwa, zo předewzaća wam skradźu po interneće slěduja.\n\nDalše informacije w našej zdźělence priwatnosće. @@ -690,9 +705,9 @@ Zapołožki - Přizjewjenja + Přizjewjenja - Hesła + Hesła Wočinjene rajtarki @@ -719,9 +734,9 @@ %1$s wot %2$s %3$s - Kreditne karty + Kreditne karty - Płaćenske metody + Płaćenske metody Adresy @@ -1667,13 +1682,13 @@ Móžeće startowej wobrazowce swojeho grata tute websydło lochko přidać, zo byšće direktny přistup měł a spěšnišo z dožiwjenjom nałoženja přehladował. - Přizjewjenja a hesła + Přizjewjenja a hesła - Hesła + Hesła - Přizjewjenja a hesła składować + Přizjewjenja a hesła składować - Hesła składować + Hesła składować Před składowanjom so prašeć @@ -1689,47 +1704,47 @@ Wužiwarske mjena a hesła w druhich nałoženjach na wašim graće zasadźić. - Přizjewjenje přidać + Přizjewjenje přidać - Hesło přidać + Hesło přidać - - Přizjewjenja synchronizować - Hesła synchronizować + Přizjewjenja synchronizować + + Hesła synchronizować - Přizjewjenja mjez gratami synchronizować + Přizjewjenja mjez gratami synchronizować - Hesła přez graty synchronizować + Hesła přez graty synchronizować - Składowane přizjewjenja + Składowane přizjewjenja - Składowane hesła + Składowane hesła - Přizjewjenja, kotrež składujeće abo z %s synchronizujeće, so tu pokazaja. + Přizjewjenja, kotrež składujeće abo z %s synchronizujeće, so tu pokazaja. - Hesła, kotrež składujeće abo z %s synchronizujeće, so tu nalistuja. Wšě hesła, kotrež składujeće, so zaklučuja. + Hesła, kotrež składujeće abo z %s synchronizujeće, so tu nalistuja. Wšě hesła, kotrež składujeće, so zaklučuja. - Zhońće wjace wo Sync. + Zhońće wjace wo Sync. - Zhońće wjace wo sync + Zhońće wjace wo sync Wuwzaća - Přizjewjenja a hesła, kotrež so njeskładuja, so tu pokazaja. + Přizjewjenja a hesła, kotrež so njeskładuja, so tu pokazaja. - %s hesła za sydła njeskładuje, kotrež su tu nalistowane. + %s hesła za sydła njeskładuje, kotrež su tu nalistowane. - Přizjewjenja a hesła so za tute sydła njeskładuja. + Přizjewjenja a hesła so za tute sydła njeskładuja. - %s hesła za tute sydła njeskładuje. + %s hesła za tute sydła njeskładuje. Wšě wuwzaća zhašeć - Přizjewjenja pytać + Přizjewjenja pytać - Hesła přepytać + Hesła přepytać Sydło @@ -1757,17 +1772,17 @@ Hesło schować - Za zwobraznjenje wašich składowanych přizjewjenjow wotewrěć + Za zwobraznjenje wašich składowanych přizjewjenjow wotewrěć - Za zwobraznjenje wašich składowanych hesłow wotewrěć + Za zwobraznjenje wašich składowanych hesłow wotewrěć - Zawěsćće swoje přizjewjenja a hesła + Zawěsćće swoje přizjewjenja a hesła - Zawěsćće swoje składowane hesła + Zawěsćće swoje składowane hesła - Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym přizjewjenjam a hesłam zadźěwał, jeli něchtó druhi waš grat ma. + Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym přizjewjenjam a hesłam zadźěwał, jeli něchtó druhi waš grat ma. - Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym hesłam zadźěwał, jeli něchtó druhi waš grat ma. + Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym hesłam zadźěwał, jeli něchtó druhi waš grat ma. Pozdźišo @@ -1786,7 +1801,10 @@ Poslednim wužiću - Meni přizjewjenskich datow sortěrować + Meni přizjewjenskich datow sortěrować + + + Meni „Hesła sortěrować“ Meni „Hesła sortěrować“ @@ -1797,40 +1815,43 @@ Adresy - Kreditne karty + Kreditne karty - Płaćenske metody + Płaćenske metody - Karty składować a awtomatisce wupjelnić + Karty składować a awtomatisce wupjelnić - Płaćenske metody składować a wupjelnić + Płaćenske metody składować a wupjelnić - Daty su zaklučowane + Daty su zaklučowane - %s wšě płaćenske metody zaklučuje, kotrež składujeće + %s wšě płaćenske metody zaklučuje, kotrež składujeće Karty přez graty synchronizować Karty synchronizować - Kreditnu kartu přidać + Kreditnu kartu přidać - Kartu přidać + Kartu přidać - Składowane karty rjadować + Składowane karty rjadować - Karty rjadować + Karty rjadować Adresu přidać Adresy rjadować - Adresy składować a awtomatisce wupjelnić + Adresy składować a awtomatisce wupjelnić - Adresy składować a wupjelnić + Adresy składować a wupjelnić - Informacije kaž ličby, e-mejlowe a rozsyłanske adresy zapřijeć + Informacije kaž ličby, e-mejlowe a rozsyłanske adresy zapřijeć + + + Wobsahuje telefonowe čisła a e-mejlowe adresy Wobsahuje telefonowe čisła a e-mejlowe adresy @@ -1854,9 +1875,9 @@ Kartu zhašeć - Chceće woprawdźe tutu kreditnu kartu zhašeć? + Chceće woprawdźe tutu kreditnu kartu zhašeć? - Kartu zhašeć? + Kartu zhašeć? Zhašeć @@ -1870,24 +1891,24 @@ Składowane karty - Prošu zapodajće płaćiwe čisło kreditneje karty + Prošu zapodajće płaćiwe čisło kreditneje karty - Zapodajće płaćiwe kartowe čisło + Zapodajće płaćiwe kartowe čisło - Prošu wupjelńće tute polo + Prošu wupjelńće tute polo - Přidajće mjeno + Přidajće mjeno Za zwobraznjenje wašich składowanych kartow wotewrěć - Waše kreditne karty zawěsćić + Waše kreditne karty zawěsćić - Zawěsćće swoje składowane płaćenske metody + Zawěsćće swoje składowane płaćenske metody - Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym kreditnym kartam zadźěwał, jeli něchtó druhi waš grat ma. + Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym kreditnym kartam zadźěwał, jeli něchtó druhi waš grat ma. - Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym płácenskim metodam zadźěwał, jeli něchtó druhi waš grat ma. + Nastajće gratowy zawrjenski muster, PIN abo hesło, zo byšće přistupej k swojim składowanym płácenskim metodam zadźěwał, jeli něchtó druhi waš grat ma. Nětko konfigurować @@ -1896,10 +1917,10 @@ Wotewriće swój grat - Blokowanje zběhnyć, zo bychu so składowane informacije kreditneje karty wužiwali + Blokowanje zběhnyć, zo bychu so składowane informacije kreditneje karty wužiwali - Wotewrěć, zo byšće składowane płaćenske metody wužiwał + Wotewrěć, zo byšće składowane płaćenske metody wužiwał Adresu přidać @@ -1907,11 +1928,13 @@ Adresy rjadować - Předmjeno + Předmjeno - Druhe předmjeno + Druhe předmjeno - Swójbne mjeno + Swójbne mjeno + + Mjeno Dróhowa adresa @@ -1936,9 +1959,9 @@ Adresu zhašeć - Chceće woprawdźe tutu adresu zhašeć? + Chceće woprawdźe tutu adresu zhašeć? - Tutu adresu zhašeć? + Tutu adresu zhašeć? Zhašeć @@ -2037,49 +2060,49 @@ Wobdźěłać - Chceće woprawdźe tute přizjewjenje zhašeć? + Chceće woprawdźe tute přizjewjenje zhašeć? - Chceće woprawdźe tute hesło zhašeć? + Chceće woprawdźe tute hesło zhašeć? Zhašeć Přetorhnyć - Přizjewjenske nastajenja + Přizjewjenske nastajenja - Hesłowe nastajenja + Hesłowe nastajenja - Wobdźěłujomne tekstowe polo za webadresu přizjewjenja. + Wobdźěłujomne tekstowe polo za webadresu přizjewjenja. - Wobdźěłujomne tekstowe polo za adresu websydła. + Wobdźěłujomne tekstowe polo za adresu websydła. - Wobdźěłujomne tekstowe polo za wužiwarske mjeno přizjewjenja. + Wobdźěłujomne tekstowe polo za wužiwarske mjeno přizjewjenja. - Wobdźěłujomne tekstowe polo za wužiwarske mjeno. + Wobdźěłujomne tekstowe polo za wužiwarske mjeno. - Wobdźěłujomne tekstowe polo za hesło přizjewjenja. + Wobdźěłujomne tekstowe polo za hesło přizjewjenja. - Wobdźěłujomne tekstowe polo za hesło. + Wobdźěłujomne tekstowe polo za hesło. - Změny přizjewjenja składować + Změny přizjewjenja składować - Změny składować. + Změny składować. - Wobdźěłać + Wobdźěłać - Hesło wobdźěłać + Hesło wobdźěłać - Nowe přizjewjenje přidać + Nowe přizjewjenje přidać - Hesło přidać + Hesło přidać - Hesło trěbne + Hesło trěbne - Hesło zapodać + Hesło zapodać - Wužiwarske mjeno trěbne + Wužiwarske mjeno trěbne - Wužiwarske mjeno zapodać + Wužiwarske mjeno zapodać Hostmjeno trěbne @@ -2191,7 +2214,7 @@ Klikńće za dalše podrobnosće - Horje + Horje Začinić @@ -2232,8 +2255,6 @@ Přiměrjene hódnoćenje - Njespušćomne pohódnoćenja wotstronjene - Bazuje na spušćomnych pohódnoćenjach Wjerški z najnowšich pohódnoćenjow @@ -2290,10 +2311,6 @@ To budźe jenož pomhać, kwalitu pohódnoćenjow posudźić, nic kwalitu produk Jeli widźiće, zo tutón produkt je zaso na składźe, zdźělće to a budźemy na kontrolowanju pohódnoćenjow dźěłać. Zdźělić, zo produkt je na składźe - - Kontrola kwalitu pohódnoćenjow - - Kontrola kwalitu pohódnoćenjow Kontrola kwalitu pohódnoćenjow (%s) @@ -2339,13 +2356,19 @@ To budźe jenož pomhać, kwalitu pohódnoćenjow posudźić, nic kwalitu produk Dalše informacije - Hdyž „Haj, wupruwować“ wuběraće, zwoliće do %2$s a %3$s Mozilla za %1$s. + Hdyž „Haj, wupruwować“ wuběraće, zwoliće do %2$s a %3$s Mozilla za %1$s. Hdyž „Haj, wupruwować“ wuběraće, zwoliće do slědowaceho wot %1$s: + + Hdyž „Haj, wupruwować“ wuběraće, zwoliće do %2$s %1$s a %4$s %3$s + + Hdyž „Haj, wupruwować“ wuběraće, zwoliće do %2$s %1$s a %4$s %3$s - prawidła priwatnosće + prawidła priwatnosće Prawidła priwatnosće + + zdźělenka priwatnosće wužiwanske wuměnjenja @@ -2417,6 +2440,10 @@ To budźe jenož pomhać, kwalitu pohódnoćenjow posudźić, nic kwalitu produk Tutu stronu přełožować? + + Strona je so z rěče %1$s do rěče %2$s přełožiła Priwatne přełožki w %1$s testować @@ -2429,6 +2456,8 @@ To budźe jenož pomhać, kwalitu pohódnoćenjow posudźić, nic kwalitu produk Cilowa rěč Nic nětko + + Original pokazać Dokónčene @@ -2451,6 +2480,16 @@ To budźe jenož pomhać, kwalitu pohódnoćenjow posudźić, nic kwalitu produk Dalše informacije + + Přełožuje so… + + + Rěč w datowym lutowanskim modusu sćahnyć (%1$s)? + + Přełožowanske nastajenja diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 0550f503e..a5916217d 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -255,6 +255,11 @@ Oldal fordítása + + Az oldal lefordítva %1$s nyelvről %2$s nyelvre. + Kiválasztott nyelv @@ -333,12 +338,22 @@ Firefox adatvédelmi nyilatkozat - + + További információk az adatvédelmi nyilatkozatunkban Szeretjük biztonságban tartani Önt + + Tudja meg, hogy miért szeretik milliók a Firefoxot + + Biztonságos böngészés, több választási lehetőséggel A nonprofit szervezet által támogatott böngészőnk segít megakadályozni, hogy a cégek titokban kövessék Önt a weben. + Több mint 100 millió ember védi a magánszféráját azzal, hogy egy nonprofit szervezet által támogatott böngészőt választ. + + Ismert követők? Automatikusan blokkolva. Kiegészítők? Próbálja ki mind a 700-at. PDF-ek? A beépített olvasónk megkönnyíti a kezelésüket. + A nonprofit szervezet által támogatott böngészőnk segít megakadályozni, hogy a cégek titokban nyomon kövessék Önt az interneten.\n\nTovábbi információk az adatvédelmi nyilatkozatban találhatók. @@ -694,9 +709,9 @@ Könyvjelzők - Bejelentkezések + Bejelentkezések - Jelszavak + Jelszavak Nyitott lapok @@ -722,9 +737,9 @@ %1$s ezen: %2$s %3$s - Bankkártyák + Bankkártyák - Fizetési módok + Fizetési módok Címek @@ -799,9 +814,9 @@ Görgetés az eszköztár elrejtéséhez - Eszköztár oldalra seprése a lapok közti váltáshoz + Eszköztár oldalra csúsztatása a lapok közti váltáshoz - Eszköztár felfelé seprése a lapok megnyitásához + Eszköztár felfelé csúsztatása a lapok megnyitásához @@ -1674,13 +1689,13 @@ Könnyedén hozzáadhatja ezt a weboldalt az eszköze Kezdőképernyőhöz, és azonnal elérheti azt, így gyorsabban böngészve, miközben alkalmazásszerű élményt kap. - Bejelentkezések és jelszavak + Bejelentkezések és jelszavak - Jelszavak + Jelszavak - Bejelentkezések és jelszavak mentése + Bejelentkezések és jelszavak mentése - Jelszavak mentése + Jelszavak mentése Kérdés mentés előtt @@ -1695,47 +1710,47 @@ Felhasználónevek és jelszavak kitöltése más alkalmazásokban az eszközén. - Bejelentkezés hozzáadása + Bejelentkezés hozzáadása - Jelszó hozzáadása + Jelszó hozzáadása - - Bejelentkezések szinkronizálása - Jelszavak szinkronizálása + Bejelentkezések szinkronizálása + + Jelszavak szinkronizálása - Bejelentkezések szinkronizálása az eszközök között + Bejelentkezések szinkronizálása az eszközök között - Jelszavak szinkronizálása az eszközök közt + Jelszavak szinkronizálása az eszközök közt - Mentett bejelentkezések + Mentett bejelentkezések - Mentett jelszavak + Mentett jelszavak - Itt jelennek meg a mentett vagy a %s böngészővel szinkronizált bejelentkezések. + Itt jelennek meg a mentett vagy a %s böngészővel szinkronizált bejelentkezések. - Itt jelennek meg a %sba mentett vagy szinkronizált jelszavak. Az összes mentett jelszó titkosítva van. + Itt jelennek meg a %sba mentett vagy szinkronizált jelszavak. Az összes mentett jelszó titkosítva van. - Tudjon meg többet a Syncről. + Tudjon meg többet a Syncről. - Tudjon meg többet a szinkronizálásról + Tudjon meg többet a szinkronizálásról Kivételek - Itt jelennek meg a nem mentett bejelentkezések és jelszavak. + Itt jelennek meg a nem mentett bejelentkezések és jelszavak. - A %s nem menti el a jelszavakat az itt felsorolt webhelyektől. + A %s nem menti el a jelszavakat az itt felsorolt webhelyektől. - A bejelentkezéseket és a jelszavak nem lesznek elmentve ezeknél a webhelyeknél. + A bejelentkezéseket és a jelszavak nem lesznek elmentve ezeknél a webhelyeknél. - A %s nem menti el a jelszavakat ezekről a webhelyektől. + A %s nem menti el a jelszavakat ezekről a webhelyektől. Összes kivétel törlése - Bejelentkezések keresése + Bejelentkezések keresése - Jelszavak keresése + Jelszavak keresése Webhely @@ -1763,17 +1778,17 @@ Jelszó elrejtése - Feloldás a mentett bejelentkezések megtekintéshez + Feloldás a mentett bejelentkezések megtekintéshez - Feloldás a mentett jelszavak megtekintéshez + Feloldás a mentett jelszavak megtekintéshez - Helyezze biztonságba bejelentkezéseit és jelszavait + Helyezze biztonságba bejelentkezéseit és jelszavait - Helyezze biztonságba a mentett jelszavait + Helyezze biztonságba a mentett jelszavait - Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett bejelentkezéseit és jelszavait, ha valaki hozzáfér az eszközéhez. + Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett bejelentkezéseit és jelszavait, ha valaki hozzáfér az eszközéhez. - Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett jelszavait, ha valaki hozzáfér az eszközéhez. + Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett jelszavait, ha valaki hozzáfér az eszközéhez. Később @@ -1790,7 +1805,10 @@ Legutóbbi használat - Bejelentkezések menü rendezése + Bejelentkezések menü rendezése + + + Jelszavak rendezése menü Jelszavak rendezése menü @@ -1801,41 +1819,44 @@ Címek - Bankkártyák + Bankkártyák - Fizetési módok + Fizetési módok - Kártyák mentése és automatikus kitöltése + Kártyák mentése és automatikus kitöltése - Fizetési módok mentése és kitöltése + Fizetési módok mentése és kitöltése - Az adatok titkosítottak + Az adatok titkosítottak - A %s titkosítja az összes elmentett fizetési módot + A %s titkosítja az összes elmentett fizetési módot Kártyák szinkronizálása az eszközök közt Kártyák szinkronizálása - Bankkártya hozzáadása + Bankkártya hozzáadása - Kártya hozzáadása + Kártya hozzáadása - Mentett kártyák kezelése + Mentett kártyák kezelése - Kártyák kezelése + Kártyák kezelése Cím hozzáadása Címek kezelése - Címek mentése és automatikus kitöltése + Címek mentése és automatikus kitöltése - Címek mentése és kitöltése + Címek mentése és kitöltése - Olyan információk belevétele, mint a számok, e-mail-címek és szállítási címek + Olyan információk belevétele, mint a számok, e-mail-címek és szállítási címek + + + Telefonszámok és e-mail-címek belevétele Telefonszámok és e-mail-címek belevétele @@ -1859,9 +1880,9 @@ Kártya törlése - Biztos, hogy törli ezt a bankkártyát? + Biztos, hogy törli ezt a bankkártyát? - Törli a kártyát? + Törli a kártyát? Törlés @@ -1875,24 +1896,24 @@ Mentett kártyák - Adjon meg egy érvényes bankkártyaszámot + Adjon meg egy érvényes bankkártyaszámot - Adjon meg egy érvényes kártyaszámot + Adjon meg egy érvényes kártyaszámot - Töltse ki ezt a mezőt + Töltse ki ezt a mezőt - Adjon hozzá egy nevet + Adjon hozzá egy nevet Feloldás a mentett kártyák megtekintéshez - Biztosítsa bankkártyáit + Biztosítsa bankkártyáit - Helyezze biztonságba a fizetési módjait + Helyezze biztonságba a fizetési módjait - Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett bankkártyáit, ha valaki hozzáfér az eszközéhez. + Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett bankkártyáit, ha valaki hozzáfér az eszközéhez. - Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett fizetési módjait, ha valaki hozzáfér az eszközéhez. + Állítsa be az eszköz lezárási mintáját, PIN-kódját vagy jelszavát, hogy megvédje a mentett fizetési módjait, ha valaki hozzáfér az eszközéhez. Beállítás most @@ -1901,10 +1922,10 @@ Eszköz feloldása - Oldja fel, hogy a tárolt bankkártya-információkat használja + Oldja fel, hogy a tárolt bankkártya-információkat használja - Oldja fel a zárolást a mentett fizetési módok használatához + Oldja fel a zárolást a mentett fizetési módok használatához Cím hozzáadása @@ -1912,11 +1933,13 @@ Címek kezelése - Utónév + Utónév - Egyéb név + Egyéb név - Vezetéknév + Vezetéknév + + Név Utca, házszám @@ -1941,9 +1964,9 @@ Cím törlése - Biztos, hogy törli ezt a címet? + Biztos, hogy törli ezt a címet? - Törli ezt a címet? + Törli ezt a címet? Törlés @@ -2041,49 +2064,49 @@ Szerkesztés - Biztos, hogy törölni szeretné ezt a bejelentkezést? + Biztos, hogy törölni szeretné ezt a bejelentkezést? - Biztos, hogy törli ezt a jelszót? + Biztos, hogy törli ezt a jelszót? Törlés Mégse - Bejelentkezési lehetőségek + Bejelentkezési lehetőségek - Jelszóbeállítások + Jelszóbeállítások - A bejelentkezés webcíméhéz használandó szerkeszthető szövegmező. + A bejelentkezés webcíméhéz használandó szerkeszthető szövegmező. - A webhely címének szerkeszthető szövegmezője. + A webhely címének szerkeszthető szövegmezője. - A bejelentkezés felhasználónevéhez használandó szerkeszthető szövegmező. + A bejelentkezés felhasználónevéhez használandó szerkeszthető szövegmező. - A felhasználónév szerkeszthető szövegmezője. + A felhasználónév szerkeszthető szövegmezője. - A bejelentkezés jelszavához használandó szerkeszthető szövegmező. + A bejelentkezés jelszavához használandó szerkeszthető szövegmező. - A jelszó szerkeszthető szövegmezője. + A jelszó szerkeszthető szövegmezője. - Módosítások mentése a bejelentkezéshez. + Módosítások mentése a bejelentkezéshez. - Változások mentése. + Változások mentése. - Szerkesztés + Szerkesztés - Jelszó szerkesztése + Jelszó szerkesztése - Új bejelentkezés hozzáadása + Új bejelentkezés hozzáadása - Jelszó hozzáadása + Jelszó hozzáadása - Jelszó szükséges + Jelszó szükséges - Adjon meg egy jelszót + Adjon meg egy jelszót - Felhasználónév szükséges + Felhasználónév szükséges - Adjon meg egy felhasználónevet + Adjon meg egy felhasználónevet Gépnév szükséges @@ -2184,6 +2207,9 @@ %s keresés + + Az alapértelmezett böngésző módosítása + Állítsa be a webhelyek, e-mailek és üzenetek hivatkozásait, hogy azok automatikusan a Firefoxban nyíljanak meg. @@ -2193,7 +2219,7 @@ Kattintson a további részletekért - Navigálás fel + Navigálás fel Bezárás @@ -2234,8 +2260,6 @@ Módosított értékelés - A nem megbízható értékelések eltávolítva - Megbízható értékelések alapján Kiemelések a legutóbbi értékelésekből @@ -2293,10 +2317,6 @@ Ha úgy látja, hogy a termék újra raktáron van, akkor jelentse, és akkor dolgozni fogunk az értékelések ellenőrzésén. Jelentés, hogy a termék raktáron van - - Értékelési minőség ellenőrzése - - Értékelési minőség ellenőrzése Értékelési minőség ellenőrzése (%s) @@ -2344,13 +2364,19 @@ További tudnivalók - Az „Igen, kipróbálom” kiválasztásával elfogadja a következőt: a %1$s by Mozilla %2$s és %3$s. + Az „Igen, kipróbálom” kiválasztásával elfogadja a következőt: a %1$s by Mozilla %2$s és %3$s. Az „Igen, kipróbálás” kiválasztásával elfogadja a %1$s dokumentumait: + + Az „Igen, kipróbálom” kiválasztásával elfogadja a következőket: a %1$s %2$s és a %3$s %4$s. + + Az „Igen, kipróbálom” kiválasztásával elfogadja a következőket: a %1$s %2$s és a %3$s %4$s. - adatvédelmi irányelvei + adatvédelmi irányelvei Adatvédelmi irányelvek + + adatvédelmi nyilatkozatota felhasználási feltételei @@ -2423,6 +2449,10 @@ Lefordítja az oldalt? + + Az oldal lefordítva %1$s nyelvről %2$s nyelvre Próbálja ki a privát fordításokat a %1$sban @@ -2435,6 +2465,8 @@ Fordítás erre: Most nem + + Eredeti megjelenítése Kész @@ -2457,6 +2489,16 @@ További tudnivalók + + Fordítás… + + + Nyelv letöltése adattakarékos módban (%1$s)? + + Fordítási beállítások diff --git a/app/src/main/res/values-hy-rAM/strings.xml b/app/src/main/res/values-hy-rAM/strings.xml index 2e0696586..74041a5fd 100644 --- a/app/src/main/res/values-hy-rAM/strings.xml +++ b/app/src/main/res/values-hy-rAM/strings.xml @@ -253,6 +253,11 @@ Թարգմանել էջը + + Էջը թարգմանվել է %1$s-ից %2$s: + Ընտրված լեզուն @@ -329,12 +334,22 @@ Firefox֊ի գաղտնիության ծանուցում - + + Իմացեք ավելին մեր գաղտնիության ծանուցման մեջ Մենք սիրում ենք ձեզ ապահով պահել + + Պարզեք, թե ինչու են միլիոնավոր մարդիկ սիրում Firefox-ը + + Անվտանգ զննարկում ավելի շատ ընտրանքներով Մեր շահույթ չհետապնդող զննարկիչն օգնում է դադարեցնել ընկերությունների կողմից համացանցում ձեզ գաղտնի հետևելը: + Ավելի քան 100 միլիոն մարդ պաշտպանում է իր գաղտնիությունը՝ ընտրելով ոչ առևտրային կազմակերպության կողմից աջակցվող զննիչ: + + Հայտնի հետագծիչնե՞ր: Ինքնաշխատ արգելափակվում են: Ընդլայնումնե՞ր; Փորձե՞ք բոլոր 700-ը։ PDF ֆայլե՞ր: Մեր ներկառուցված ընթերցողը հեշտացնում է դրանց կառավարումը: + Մեր շահույթ չհետապնդող զննարկիչը օգնում է դադարեցնել ընկերություններին գաղտնի հետևել ձեզ համացանցում:\n\nԻմացեք ավելին մեր գաղտնիության ծանուցման մեջ: @@ -688,9 +703,9 @@ Էջանիշեր - Մուտքանուններ + Մուտքանուններ - Գաղտնաբառեր + Գաղտնաբառեր Բացել ներդիրներ @@ -716,9 +731,9 @@ %1$s-ը %2$s %3$s-ում - Բանկային քարտեր + Բանկային քարտեր - Վճարամիջոցներ + Վճարամիջոցներ Հասցեներ @@ -1658,13 +1673,13 @@ Հեշտությամբ կարող եք ավելացնել այս կայքը ձեր հեռախոսի Տնային էկրանին՝ ակնթարթորեն մատչելու և արագ դիտարկելու համար: - Մուտքանուններ և գաղտնաբառեր + Մուտքանուններ և գաղտնաբառեր - Գաղտնաբառեր + Գաղտնաբառեր - Պահպանել մուտքանունները և գաղտնաբառերը + Պահպանել մուտքանունները և գաղտնաբառերը - Պահել գաղտնաբառերը + Պահել գաղտնաբառերը Հարցնել պահպանելիս @@ -1679,47 +1694,47 @@ Լցրեք օգտվողի անուններն ու գաղտնաբառերը ձեր սարքի այլ հավելվածներում: - Ավելացնել մուտքագրում + Ավելացնել մուտքագրում - Հավելել գաղտնաբառ + Հավելել գաղտնաբառ - - Համաժամեցնել մուտքանունները - Համաժամեցնել գաղտնաբառերը + Համաժամեցնել մուտքանունները + + Համաժամեցնել գաղտնաբառերը - Համաժամեցնել մուտքագրումները սարքերի միջև + Համաժամեցնել մուտքագրումները սարքերի միջև - Համաժամեցնել գաղտնաբառերը սարքերի միջև + Համաժամեցնել գաղտնաբառերը սարքերի միջև - Պահպանված մուտքանուններ + Պահպանված մուտքանուններ - Պահված գաղտնաբառեր + Պահված գաղտնաբառեր - %s-ի հետ ձեր պահպանած կամ համաժամեցրած մուտքագրումները կցուցադրվեն այստեղ: + %s-ի հետ ձեր պահպանած կամ համաժամեցրած մուտքագրումները կցուցադրվեն այստեղ: - Այն գաղտնաբառերը, որոնք դուք պահում կամ համաժամացնում եք %s-ի հետ, կցուցադրվեն այստեղ: Ձեր պահած բոլոր գաղտնաբառերը գաղտնագրված են: + Այն գաղտնաբառերը, որոնք դուք պահում կամ համաժամացնում եք %s-ի հետ, կցուցադրվեն այստեղ: Ձեր պահած բոլոր գաղտնաբառերը գաղտնագրված են: - Իմանալ ավելին համաժամեցման մասին: + Իմանալ ավելին համաժամեցման մասին: - Իմանալ ավելին Սինքի մասին + Իմանալ ավելին Սինքի մասին Բացառություններ - Մուտքանունները և գաղտնաբառերը, որոնք չեն պահպանվել, կցուցադրվեն այստեղ: + Մուտքանունները և գաղտնաբառերը, որոնք չեն պահպանվել, կցուցադրվեն այստեղ: - %s-ը չի պահի այստեղ թվարկված կայքերի գաղտնաբառերը: + %s-ը չի պահի այստեղ թվարկված կայքերի գաղտնաբառերը: - Մուտքանունները և գաղտնաբառերը չեն պահպանվի այս կայքերի համար: + Մուտքանունները և գաղտնաբառերը չեն պահպանվի այս կայքերի համար: - %s-ը չի պահի այս կայքերի գաղտնաբառերը: + %s-ը չի պահի այս կայքերի գաղտնաբառերը: Ջնջել բոլոր բացառությունները - Որոնել մուտքանուններ + Որոնել մուտքանուններ - Որոնել գաղտնաբառեր + Որոնել գաղտնաբառեր Կայք @@ -1748,17 +1763,17 @@ Թաքցնել գաղտնաբառը - Ապակողպեք՝ դիտելու համար պահպանված մուտքանունները + Ապակողպեք՝ դիտելու համար պահպանված մուտքանունները - Ապակողպեք՝ դիտելու համար պահված գաղտնաբառերը + Ապակողպեք՝ դիտելու համար պահված գաղտնաբառերը - Անվտանգ դարձրեք ձեր մուտքանունները և գաղտնաբառերը + Անվտանգ դարձրեք ձեր մուտքանունները և գաղտնաբառերը - Անվտանգ դարձրեք ձեր պահված գաղտնաբառերը + Անվտանգ դարձրեք ձեր պահված գաղտնաբառերը - Ստեղծեք սարքի կողպեքի նմուշ, PIN կամ գաղտնաբառ՝ ձեր պահպանված մուտքանունները և գաղտնաբառերը մուտք գործելուց պաշտպանելու համար, եթե ձեր սարքը ուրիշի ձեռքն ընկնի: + Ստեղծեք սարքի կողպեքի նմուշ, PIN կամ գաղտնաբառ՝ ձեր պահպանված մուտքանունները և գաղտնաբառերը մուտք գործելուց պաշտպանելու համար, եթե ձեր սարքը ուրիշի ձեռքն ընկնի: - Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու պահված գաղտնաբառերն այն դեպքում, եթե որևէ մեկը ևս մուտք ունենա Ձեր սարքին: + Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու պահված գաղտնաբառերն այն դեպքում, եթե որևէ մեկը ևս մուտք ունենա Ձեր սարքին: Հետո @@ -1776,7 +1791,10 @@ Վերջին օգտագործվածը - Տեսակավորել մուտագրումների ցանկը + Տեսակավորել մուտագրումների ցանկը + + + Տեսակավորել գաղտնաբառերի ցանկը Տեսակավորել գաղտնաբառերի ցանկը @@ -1787,39 +1805,42 @@ Հասցեներ - Բանկային քարտեր + Բանկային քարտեր - Վճարամիջոցներ + Վճարամիջոցներ - Պահել և ինքնալրացնել քարտերը + Պահել և ինքնալրացնել քարտերը - Պահել և լրացնել վճարամիջոցները + Պահել և լրացնել վճարամիջոցները - Տվյալները գաղտնագրված են + Տվյալները գաղտնագրված են - %s-ը գաղտնագրում է ձեր պահած բոլոր վճարամիջոցները + %s-ը գաղտնագրում է ձեր պահած բոլոր վճարամիջոցները Համաժամեցնել քարտերը սարքերի միջև Համաժամեցնել քարտերը - Ավելացնել բանկային քարտ + Ավելացնել բանկային քարտ - Հավելել քարտ + Հավելել քարտ - Կառավարել պահված քարտերը + Կառավարել պահված քարտերը - Կառավարել քարտերը + Կառավարել քարտերը Ավելացնել հասցե Կառավարեք հասցեները - Պահել և ինքնալրացնել քարտերը + Պահել և ինքնալրացնել քարտերը - Պահել և լրացնել հասցեները + Պահել և լրացնել հասցեները - Ներառել տեղեկություններ, ինչպիսիք են համարները, էլ.փոստը և առաքման հասցեները + Ներառել տեղեկություններ, ինչպիսիք են համարները, էլ.փոստը և առաքման հասցեները + + + Ներառում է հեռախոսահամարներ և էլ. փոստի հասցեներ Ներառում է հեռախոսահամարներ և էլ. փոստի հասցեներ @@ -1843,9 +1864,9 @@ Ջնջել քարտը - Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս բանկային քարտը: + Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս բանկային քարտը: - Ջնջե՞լ քարտը + Ջնջե՞լ քարտը Ջնջել @@ -1859,24 +1880,24 @@ Պահպանված քարտեր - Մուտքագրեք բանկային վավեր քարտի համար + Մուտքագրեք բանկային վավեր քարտի համար - Մուտքագրեք ճիշտ քարտի համար + Մուտքագրեք ճիշտ քարտի համար - Լրացրեք այս դաշտը + Լրացրեք այս դաշտը - Հավելել անուն + Հավելել անուն Ապակողպեք՝ դիտելու համար պահպանված քարտերը - Անվտանգ դարձրեք ձեր բանկային քարտերը + Անվտանգ դարձրեք ձեր բանկային քարտերը - Անվտանգ դարձրեք ձեր պահած վճարամիջոցները + Անվտանգ դարձրեք ձեր պահած վճարամիջոցները - Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու պահված բանկային քարտերը այն դեպքում, եթե որևէ մեկը ևս մուտք ունի Ձեր սարքին: + Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու պահված բանկային քարտերը այն դեպքում, եթե որևէ մեկը ևս մուտք ունի Ձեր սարքին: - Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու ձեր քարտերն այն դեպքում, եթե որևէ մեկը ևս մուտք ունենա Ձեր սարքին: + Տեղակայեք սարքի կողպման նախշ, PIN կամ գաղտնաբառ՝ պաշտպանելու ձեր քարտերն այն դեպքում, եթե որևէ մեկը ևս մուտք ունենա Ձեր սարքին: Տեղակայել հիմա @@ -1884,10 +1905,10 @@ Ապակողպեք ձեր սարքը - Ապակողպեք՝ օգտագործելու համար բանկային քարտերի պահված տեղեկությունները + Ապակողպեք՝ օգտագործելու համար բանկային քարտերի պահված տեղեկությունները - Ապակողպեք՝ պահված վճարամիջոցն օգտագործելու համար + Ապակողպեք՝ պահված վճարամիջոցն օգտագործելու համար Ավելացնել հասցե @@ -1895,11 +1916,13 @@ Կառավարեք հասցեները - Անուն + Անուն - Հայրանուն + Հայրանուն - Ազգանուն + Ազգանուն + + Անուն Փողոցի հասցե @@ -1923,9 +1946,9 @@ Ջնջել հասցեն - Ջնջե՞լ այս հասցեն: + Ջնջե՞լ այս հասցեն: - Ջնջե՞լ այս հասցեն: + Ջնջե՞լ այս հասցեն: Ջնջել @@ -2022,49 +2045,49 @@ Խմբագրել - Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս մուտքանունը: + Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս մուտքանունը: - Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս գաղտնաբառը: + Համոզվա՞ծ եք, որ ցանկանում եք ջնջել այս գաղտնաբառը: Ջնջել Չեղարկել - Մուտքի ընտրանքներ + Մուտքի ընտրանքներ - Գաղտնաբառի ընտրանքներ + Գաղտնաբառի ընտրանքներ - Խմբագրելի տեքստի դաշտը մուտքի վեբ հասցեի համար: + Խմբագրելի տեքստի դաշտը մուտքի վեբ հասցեի համար: - Խմբագրելի տեքստի դաշտ կայքի հասցեի համար: + Խմբագրելի տեքստի դաշտ կայքի հասցեի համար: - Խմբագրելի տեքստի դաշտը մուտք գործողի համար: + Խմբագրելի տեքստի դաշտը մուտք գործողի համար: - Խմբագրելի տեքստի դաշտ օգտվողի անվան համար: + Խմբագրելի տեքստի դաշտ օգտվողի անվան համար: - Խմբագրելի տեքստի դաշտը մուտքի գաղտնաբառի համար: + Խմբագրելի տեքստի դաշտը մուտքի գաղտնաբառի համար: - Խմբագրելի տեքստի դաշտ գաղտնաբառի համար: + Խմբագրելի տեքստի դաշտ գաղտնաբառի համար: - Պահպանել փոփոխությունները մուտքագրման համար: + Պահպանել փոփոխությունները մուտքագրման համար: - Պահել փոփոխությունները: + Պահել փոփոխությունները: - Խմբագրել + Խմբագրել - Խմբագրել գաղտնաբառը + Խմբագրել գաղտնաբառը - Հավելել նոր մուտքագրում + Հավելել նոր մուտքագրում - Հավելել գաղտնաբառ + Հավելել գաղտնաբառ - Գաղտնաբառ է պահանջվում + Գաղտնաբառ է պահանջվում - Մուտքագրեք գաղտնաբառ + Մուտքագրեք գաղտնաբառ - Օգտվողի անունը պարտադիր է + Օգտվողի անունը պարտադիր է - Մուտքագրեք օգտվողի անունը + Մուտքագրեք օգտվողի անունը Հոսթի անունը պարտադիր է @@ -2177,7 +2200,7 @@ Սեղմեք` մանրամասների համար - Նավարկել վերև + Նավարկել վերև Փակել @@ -2218,8 +2241,6 @@ Ճշգրտված վարկանիշ - Անվստահելի կարծիքները հեռացվեցին - Հուսալի կարծիքների հիման վրա Գունանշումներ վերջին կարծիքներից @@ -2276,10 +2297,6 @@ Եթե տեսնեք, որ այս ապրանքը կրկին պահեստում է, հաղորդեք դրա մասին, և մենք կաշխատենք ստուգել ակնարկները: Զեկուցված ապրանքը պահեստում է - - Կարծիքի որակի ստուգում - - Կարծիքի որակի ստուգում Կարծիքի որակի ստուգում (%s) @@ -2326,13 +2343,19 @@ Իմանալ ավելին - Ընտրելով «Այո, փորձիր»՝ դուք համաձայնում եք %1$s-ը Mozilla-ի կողմիցի %2$s-ին և %3$s-ին: + Ընտրելով «Այո, փորձիր»՝ դուք համաձայնում եք %1$s-ը Mozilla-ի կողմիցի %2$s-ին և %3$s-ին: Ընտրելով «Այո, փորձիր»՝ դուք ընդունում եք %1$s-ը. + + Ընտրելով «Այո, փորձիր»՝ դուք համաձայնվում եք %1$s-ի %2$s-ին և %3$s-ի %4$s-ին: + + Ընտրելով «Այո, փորձիր»՝ դուք համաձայնվում եք %1$s-ի %2$s-ին և %3$s-ի %4$s-ին: - գաղտնիության դրույթներ + գաղտնիության դրույթներ Գաղտնիության դրույթներ + + գաղտնիության ծանուցում օգտվելու կանոններ @@ -2403,6 +2426,10 @@ Թարգմանե՞լ այս էջը։ + + Էջը թարգմանվել է %1$s-ից %2$s: Փորձեք անձնական թարգմանությունները %1$s-ով @@ -2415,6 +2442,8 @@ Թարգմանել հետևյալով՝ Ոչ հիմա + + Ցուցադրել բնօրինակը Պատրաստ է @@ -2437,6 +2466,15 @@ Իմանալ ավելին + + Թարգմանում է… + + Ներբեռնե՞լ լեզուն տվյալների պահման կերպում (%1$s): + + Թարգմանության ընտրանքներ diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 0970b4b78..4b4ecc5e5 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -257,6 +257,11 @@ Traducer le pagina + + Pagina traducite ab %1$s a %2$s. + Lingua seligite @@ -336,12 +341,22 @@ Aviso de confidentialitate de Firefox - + + Lege nostre aviso de confidentialitate A nos place mantener te secur + + Discoperi perque milliones ama Firefox + + Navigation secur con plus optiones Nostre navigator supportate per un organisation sin fin d lucro adjuta stoppar le companias de sequer secretemente tu movimentos circum le web. + Plus que 100 milliones de personas protege lor confidentialitate seligente un navigar supportate per un organisation a fin non lucrative. + + Traciatores note? Blocate automaticamente. Extensiones? Prova tote le 700. PDFs? Nostre lector integrate los rende facile a gerer. + Nostre navigator supportate per un organisation sin fin de lucro adjuta stoppar le companias de sequer te secretemente per le Web.\n\nSape plus in nostre Aviso de confidentialitate. @@ -699,9 +714,9 @@ Marcapaginas - Credentiales + Credentiales - Contrasignos + Contrasignos Schedas aperte @@ -727,9 +742,9 @@ %1$s sur %2$s %3$s - Cartas de credito + Cartas de credito - Methodos de pagamento + Methodos de pagamento Adresses @@ -1707,14 +1722,14 @@ Tu pote facilemente adder iste sito web al Pagina initial de tu apparato pro haber accesso instantanee e navigar plus veloce con un experientia simile al app. - Credentiales e contrasignos + Credentiales e contrasignos - Contrasignos + Contrasignos - Salvar credentiales e contrasignos + Salvar credentiales e contrasignos - Salvar contrasignos + Salvar contrasignos Demandar pro salvar @@ -1731,47 +1746,47 @@ Plenar nomines de usator e contrasignos in altere apps sur tu apparato. - Adder credentiales + Adder credentiales - Adder contrasigno + Adder contrasigno - - Synchronisar credentiales - Synchronisar contrasignos + Synchronisar credentiales + + Synchronisar contrasignos - Synchronisar credentiales inter le apparatos + Synchronisar credentiales inter le apparatos - Synchronisar contrasignos inter apparatos + Synchronisar contrasignos inter apparatos - Credentiales salvate + Credentiales salvate - Contrasignos salvate + Contrasignos salvate - Le credentiales que tu salva o synchronisa a in %s apparera hic. + Le credentiales que tu salva o synchronisa a in %s apparera hic. - Le contrasignos que tu salva o synchronisa in %s sera listate ci. Tote le contrasignos que tu salva es cryptate. + Le contrasignos que tu salva o synchronisa in %s sera listate ci. Tote le contrasignos que tu salva es cryptate. - Apprender plus re Sync. + Apprender plus re Sync. - Apprender plus re le synchronisation + Apprender plus re le synchronisation Exceptiones - Credentiales e contrasignos que non es salvate essera monstrate hic. + Credentiales e contrasignos que non es salvate essera monstrate hic. - %s non salvara le password pro le sitos ci listate. + %s non salvara le password pro le sitos ci listate. - Credentiales e contrasignos non sera salvate pro iste sitos. + Credentiales e contrasignos non sera salvate pro iste sitos. - %s non salvara le contrasignos pro iste sitos. + %s non salvara le contrasignos pro iste sitos. Deler tote le exceptiones - Cercar credentiales + Cercar credentiales - Cercar contrasignos + Cercar contrasignos Sito @@ -1799,17 +1814,17 @@ Celar contrasigno - Disbloca pro vider tu credentiales salvate + Disbloca pro vider tu credentiales salvate - Disbloca pro vider tu contrasignos salvate + Disbloca pro vider tu contrasignos salvate - Assecurar tu credentiales e contrasignos + Assecurar tu credentiales e contrasignos - Protege tu contrasignos salvate + Protege tu contrasignos salvate - Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu credentiales e contrasignos salvate de esser accedite, si alcuno altere ha tu apparato. + Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu credentiales e contrasignos salvate de esser accedite, si alcuno altere ha tu apparato. - Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu contrasignos de esser accedite, si alcuno altere ha tu apparato. + Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu contrasignos de esser accedite, si alcuno altere ha tu apparato. Plus tarde @@ -1827,7 +1842,10 @@ Ultimemente usate - Ordinar menu de credentiales + Ordinar menu de credentiales + + + Ordinar le menu del contrasignos Ordinar le menu del contrasignos @@ -1838,42 +1856,45 @@ Adresses - Cartas de credito + Cartas de credito - Methodos de pagamento + Methodos de pagamento - Gerer le cartas salvate + Gerer le cartas salvate - Salvar e compilar methodos de pagamento automaticamente + Salvar e compilar methodos de pagamento automaticamente - Datos es cryptate + Datos es cryptate - %s crypta tote tu methodos de pagamento salvate + %s crypta tote tu methodos de pagamento salvate Synchronisar cartas inter apparatos Synchronisar cartas - Adde un carta de credito + Adde un carta de credito - Adder carta + Adder carta - Gerer le cartas salvate + Gerer le cartas salvate - Gerer le cartas + Gerer le cartas Adder adresse Gerer adresses - Salvar e autoplenar adresses + Salvar e autoplenar adresses - Salvar e compilar automaticamente adresses + Salvar e compilar automaticamente adresses - Includer informationes como numeros, email e adresses de expedition + Includer informationes como numeros, email e adresses de expedition + + + Include numeros de telephono e adresses email Include numeros de telephono e adresses email @@ -1897,9 +1918,9 @@ Deler carta - Desira tu vermente deler iste carta de credito? + Desira tu vermente deler iste carta de credito? - Deler carta? + Deler carta? Deler @@ -1913,24 +1934,24 @@ Cartas salvate - Insere un numero valide de carta de credito + Insere un numero valide de carta de credito - Insere un numero de carta valide + Insere un numero de carta valide - Completa iste campo + Completa iste campo - Adde un nomine + Adde un nomine Disbloca pro vider tu cartas salvate - Protege tu carta de credito + Protege tu carta de credito - Protege tu methodo de pagamento salvate + Protege tu methodo de pagamento salvate - Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu cartas de credito de esser accedite, si alcuno altere ha tu apparato. + Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu cartas de credito de esser accedite, si alcuno altere ha tu apparato. - Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu methodos de pagamento salvate de esser accedite, si alcun altere ha tu apparato. + Implementa un patrono de blocada apparato, PIN o contrasigno pro proteger tu methodos de pagamento salvate de esser accedite, si alcun altere ha tu apparato. Implementar ora @@ -1939,10 +1960,10 @@ Disbloca tu apparato - Disbloca pro usar le informationes de carta de credito immagazinate + Disbloca pro usar le informationes de carta de credito immagazinate - Disblocar pro usar le methodo de pagamento salvate + Disblocar pro usar le methodo de pagamento salvate Adder adresse @@ -1950,11 +1971,13 @@ Gerer addresses - Prenomine + Prenomine - Nomine intermedie + Nomine intermedie - Nomine de familia + Nomine de familia + + Nomine Adresse del strata @@ -1979,9 +2002,9 @@ Deler adresses - Desira tu vermente deler iste adresses? + Desira tu vermente deler iste adresses? - Deler iste adresses? + Deler iste adresses? Deler @@ -2081,50 +2104,50 @@ Rediger - Desira tu vermente deler iste credentiales? + Desira tu vermente deler iste credentiales? - Desira tu vermente deler iste contrasigno? + Desira tu vermente deler iste contrasigno? Deler Cancellar - Optiones de apertura de session + Optiones de apertura de session - Optiones de contrasigno + Optiones de contrasigno - Le campo de texto redigibile pro le adresse web del credentiales. + Le campo de texto redigibile pro le adresse web del credentiales. - Le campo de texto redigibile pro le adresse del sito web. + Le campo de texto redigibile pro le adresse del sito web. - Le campo de texto redigibile pro le nomine de usator del accesso. + Le campo de texto redigibile pro le nomine de usator del accesso. - Le campo de texto redigibile pro le nomine de usator. + Le campo de texto redigibile pro le nomine de usator. - Le campo de texto redigibile pro le contrasigno del credentiales. + Le campo de texto redigibile pro le contrasigno del credentiales. - Le campo de texto redigibile pro le contrasigno. + Le campo de texto redigibile pro le contrasigno. - Salvar cambiamentos a credentiales. + Salvar cambiamentos a credentiales. - Salvar le cambiamentos. + Salvar le cambiamentos. - Rediger + Rediger - Modificar le contrasigno + Modificar le contrasigno - Adder nove credential + Adder nove credential - Adder contrasigno + Adder contrasigno - Contrasigno requirite + Contrasigno requirite - Insere un contrasigno + Insere un contrasigno - Nomine de usator necesse. + Nomine de usator necesse. - Insere un nomine de usator + Insere un nomine de usator Nomine de servitor necesse. @@ -2235,7 +2258,7 @@ Clicca pro altere detalios - Navigar + Navigar Clauder @@ -2276,8 +2299,6 @@ Classification adjustate - Recensiones non fidabile removite - Basate sur recensiones fidabile Aspectos notabile ab recensiones recente @@ -2334,11 +2355,7 @@ Si tu videra que iste producto es retro in stock, reporta lo e nos laborara pro controlar le recensiones. Reportar si le producto es in stock - - Controlante qualitate de recension - - Controlante qualitate de recension Controlante qualitate de recension (%s) @@ -2384,13 +2401,19 @@ Pro saper plus - Seligente “Si, prova lo” tu concorda con le %2$s e le %3$s de %1$s per Mozilla. + Seligente “Si, prova lo” tu concorda con le %2$s e le %3$s de %1$s per Mozilla. Eligente “Si, essaya lo” tu concorda con le sequente ab %1$s: + + Seligente “Si, prova lo” tu concorda con le %1$s’s %2$s e le %4$s de %3$s. + + Seligente “Si, prova lo” tu concorda con le %1$s’s %2$s e le %4$s de %3$s. - politica de confidentialitate + politica de confidentialitate Politica de confidentialitate + + aviso de confidentialitate terminos de uso @@ -2461,6 +2484,10 @@ Traducer iste pagina? + + Pagina traducite ab %1$s a %2$s Tentar traductiones private in %1$s @@ -2473,6 +2500,8 @@ Traducer in Non ora + + Monstrar original Facite @@ -2495,6 +2524,17 @@ Pro saper plus + + Traducente… + + + + Discargar le lingua dum in modo sparnio de datos (%1$s)? + + Optiones de traduction diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 22acc1e75..69992102f 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -67,6 +67,14 @@ Mitos umum tentang penjelajahan privat + + + Jangan tinggalkan jejak pada perangkat ini + + Siapa saja yang bisa melihat aktivitas saya? + Luncurkan tab pribadi Anda berikutnya dengan sekali ketuk. @@ -192,6 +200,8 @@ Sinkron ulang Temukan di laman + + Terjemahkan laman Simpan ke koleksi @@ -224,10 +234,15 @@ Ubahsuai halaman beranda + Layar beranda + + Hapus riwayat penjelajahan + Bahasa yang dipilih @@ -239,8 +254,6 @@ Pindai - - Mesin pencari Setelan mesin pencari @@ -297,49 +310,35 @@ - Notifikasi membantu Anda lakukan lebih banyak hal dengan %s + Notifikasi membantu Anda lakukan lebih banyak hal dengan %s - Sinkronkan tab Anda antar perangkat, kelola unduhan, dapatkan kiat tentang memanfaatkan perlindungan privasi %s, dan banyak lagi. + Sinkronkan tab Anda antar perangkat, kelola unduhan, dapatkan kiat tentang memanfaatkan perlindungan privasi %s, dan banyak lagi. - Lanjutkan + Lanjutkan - Jangan sekarang - - - - Jadikan Firefox sebagai peramban pilihan Anda - - Firefox mengutamakan masyarakat daripada laba dan membela privasi Anda dengan memblokir pelacak lintas situs.\n\n\nPelajari lebih lanjut dalam kebijakan privasi kami. + Jangan sekarang + - kebijakan privasi + kebijakan privasi Setel sebagai peramban baku Jangan sekarang - - Berpindah dari ponsel ke laptop dan sebaliknya - - Bawa tab dan kata sandi Anda dari perangkat lain untuk meneruskan jelajah terakhir. Masuk Jangan sekarang - - Notifikasi membantu Anda lakukan lebih banyak hal dengan Firefox - - Kirim tab antar perangkat, kelola unduhan, dan dapatkan kiat terbaik menggunakan Firefox. Aktifkan notifikasi Jangan sekarang + + Jangan sekarang + Buka di tab %1$s baru @@ -360,8 +359,6 @@ Tentang Pilih satu - - Kelola pintasan pencarian Sunting mesin peramban terlihat di menu pencarian @@ -370,8 +367,8 @@ Mesin pencari baku Cari - - Bilah alamat + + Mesin pencari Beri nilai di Google Play Mode Hanya HTTPS - - Pengurangan Spanduk Kuki Pemblokir Spanduk Kuki - - Kurangi spanduk kuki - - Nonaktif - - Aktif - - - %1$s secara otomatis coba menolak permintaan kuki di spanduk kuki. + Nonaktif untuk situs ini @@ -430,28 +417,8 @@ Permintaan dukungan terkirim Saat ini, situs tidak didukung - - Aktifkan Pengurangan Spanduk Kuki untuk %1$s? - - Nonaktifkan Pengurangan Spanduk Kuki untuk %1$s? %1$s tidak dapat secara otomatis menolak permintaan kuki di situs ini. Anda dapat mengirimkan permintaan dukungan untuk situs ini di masa mendatang. - - %1$s akan menghapus kuki situs ini dan menyegarkan laman ini. Membersihkan semua kuki dapat membuat Anda keluar dari suatu situs atau mengosongkan keranjang belanja. - - - %1$s mencoba secara otomatis menolak semua permintaan kuki di situs yang didukung. - - Izinkan %1$s untuk menolak spanduk kuki? - - %1$s dapat menolak permintaan spanduk kuki secara otomatis. - - Jangan sekarang - - Anda akan melihat lebih sedikit permintaan kuki - - - Izinkan Secara otomatis mencoba terhubung ke situs menggunakan protokol enkripsi HTTPS untuk meningkatkan keamanan. @@ -475,12 +442,8 @@ Namun, ada juga kemungkinan seorang penyerang terlibat. Jika melanjutkan ke situs web, Anda tidak boleh memasukkan info sensitif apa pun. Jika dilanjutkan, mode Hanya HTTPS akan dinonaktifkan sementara untuk situs ini. Aksesibilitas - - Penyedia Firefox Account khusus Penyedia Sync khusus - - Penyedia Firefox Account/Sync dimodifikasi. Keluar dari aplikasi untuk menerapkan pengubahan… Akun @@ -496,7 +459,7 @@ Masuk untuk menyinkronkan tab, markah, sandi, dan yang lainnya. - Firefox Account + Akun Mozilla Hubungkan kembali untuk melanjutkan sinkronisasi @@ -507,8 +470,6 @@ Pengumpulan data Pengawakutuan jarak jauh melalui USB - - Tampilkan mesin pencari Tampilkan saran pencarian @@ -528,6 +489,13 @@ URL lengkapi-otomatis + + Saran dari sponsor + + Saran dari %1$s + + Dapatkan rekomendasi dari web yang terkait dengan pencarian Anda Buka tautan di aplikasi @@ -548,6 +516,8 @@ Pengaya + + Pasang pengaya dari berkas Notifikasi @@ -608,6 +578,12 @@ %s Klasik + + Karya seniman + + Koleksi Suara Independen. %s + + Koleksi Suara Independen. Coba berbagai ragam warna @@ -615,15 +591,25 @@ Telusuri lebih banyak wallpaper - - - Pengaya tidak didukung - - Pengaya telah didukung + + + Pengaya baru kini tersedia + + Jelajahi pengaya + + + + Pengaya dinonaktifkan sementara + + Coba mulai ulang pengaya + + Lanjutkan dengan pengaya yang dinonaktifkan Kelola akun + + Ubah sandi Anda, kelola pengumpulan data, atau hapus akun Anda Sinkronkan sekarang @@ -633,7 +619,7 @@ Markah - Info Masuk + Info Masuk Tab terbuka @@ -660,7 +646,7 @@ %1$s dalam %2$s %3$s - Kartu kredit + Kartu kredit Alamat @@ -1202,7 +1188,7 @@ Tutup - Gagal mencetak + Gagal mencetak laman ini Cetak @@ -1247,6 +1233,7 @@ Tutup tab privat + Pemasaran @@ -1300,6 +1287,8 @@ Tab pribadi ditutup Tab pribadi ditutup + + Data penjelajahan pribadi telah dihapus URUNGKAN @@ -1345,10 +1334,15 @@ Tab terbuka %d tab + + + Riwayat peramban %d alamat situs + + Kuki dan data situs Anda\ akan keluar dari sebagian besar situs @@ -1594,9 +1588,9 @@ Anda dapat dengan mudah menambahkan situs web ini ke layar Beranda perangkat Anda untuk mendapatkan akses instan dan penjelajahan lebih cepat seperti menggunakan aplikasi. - Info masuk dan kata sandi + Info masuk dan kata sandi - Simpan info masuk dan kata sandi + Simpan info masuk dan kata sandi Minta untuk menyimpan @@ -1611,28 +1605,28 @@ Isi nama pengguna dan sandi di aplikasi lain pada perangkat Anda. - Tambahkan log masuk + Tambahkan log masuk - - Sinkronkan info masuk + + Sinkronkan info masuk - Sinkronkan log masuk antar perangkat + Sinkronkan log masuk antar perangkat - Info masuk tersimpan + Info masuk tersimpan - Info masuk yang Anda simpan atau sinkronkan ke %s akan ditampilkan di sini. + Info masuk yang Anda simpan atau sinkronkan ke %s akan ditampilkan di sini. - Pelajari lebih lanjut mengenai Sinkronisasi. + Pelajari lebih lanjut mengenai Sinkronisasi. Kekecualian - Info masuk dan kata sandi yang tidak disimpan akan ditampilkan di sini. + Info masuk dan kata sandi yang tidak disimpan akan ditampilkan di sini. - Info masuk dan kata sandi tidak akan disimpan untuk situs-situs ini. + Info masuk dan kata sandi tidak akan disimpan untuk situs-situs ini. Hapus semua pengecualian - Cari log masuk + Cari log masuk Situs @@ -1660,11 +1654,11 @@ Sembunyikan sandi - Buka kunci untuk melihat info masuk Anda yang tersimpan + Buka kunci untuk melihat info masuk Anda yang tersimpan - Amankan info masuk dan kata sandi Anda + Amankan info masuk dan kata sandi Anda - Atur pola, PIN, atau kata sandi kunci perangkat untuk melindungi info masuk dan kata sandi Anda yang tersimpan agar tidak diakses jika orang lain memiliki perangkat Anda. + Atur pola, PIN, atau kata sandi kunci perangkat untuk melindungi info masuk dan kata sandi Anda yang tersimpan agar tidak diakses jika orang lain memiliki perangkat Anda. Nanti @@ -1681,7 +1675,7 @@ Terakhir digunakan - Sortir menu info masuk + Sortir menu info masuk @@ -1689,27 +1683,27 @@ Alamat - Kartu kredit + Kartu kredit - Simpan dan isi otomatis kartu + Simpan dan isi otomatis kartu - Data terenkripsi + Data terenkripsi Sinkronisasi kartu antar perangkat Sinkronkan kartu - Tambahkan kartu kredit + Tambahkan kartu kredit - Kelola kartu tersimpan + Kelola kartu tersimpan Tambahkan alamat Kelola alamat - Simpan dan isi otomatis alamat + Simpan dan isi otomatis alamat - Sertakan informasi seperti nomor, alamat surel dan pengiriman + Sertakan informasi seperti nomor, alamat surel dan pengiriman Tambah kartu @@ -1730,7 +1724,7 @@ Hapus kartu - Apakah Anda yakin ingin menghapus kartu kredit ini? + Apakah Anda yakin ingin menghapus kartu kredit ini? Hapus @@ -1742,15 +1736,15 @@ Kartu tersimpan - Masukkan nomor kartu kredit yang sah + Masukkan nomor kartu kredit yang sah - Silahkan isi kolom ini + Silahkan isi kolom ini Buka kunci untuk melihat kartu yang Anda simpan - Amankan kartu kredit Anda + Amankan kartu kredit Anda - Atur pola, PIN, atau kata sandi kunci perangkat untuk melindungi kartu kredit Anda yang tersimpan agar tidak diakses jika orang lain memiliki perangkat Anda. + Atur pola, PIN, atau kata sandi kunci perangkat untuk melindungi kartu kredit Anda yang tersimpan agar tidak diakses jika orang lain memiliki perangkat Anda. Atur sekarang @@ -1759,7 +1753,7 @@ Buka perangkat Anda - Buka kunci untuk menggunakan informasi kartu kredit tersimpan + Buka kunci untuk menggunakan informasi kartu kredit tersimpan Tambahkan alamat @@ -1768,11 +1762,11 @@ Kelola alamat - Nama Depan + Nama Depan - Nama Tengah + Nama Tengah - Nama Belakang + Nama Belakang Jalan @@ -1797,7 +1791,7 @@ Hapus alamat - Yakin ingin menghapus alamat ini? + Yakin ingin menghapus alamat ini? Hapus @@ -1813,28 +1807,18 @@ Tambah mesin pencari baru Ubah mesin pencari - - Tambah - - Simpan Ubah Hapus - - Lainnya Nama - - Nama Nama mesin pencari URL string pencarian - String pencarian untuk digunakan - URL yang digunakan untuk pencarian Ganti kueir dengan “%s”. Contoh:\nhttps://www.google.com/search?q=%s @@ -1903,29 +1887,29 @@ Ubah - Yakin ingin menghapus info masuk ini? + Yakin ingin menghapus info masuk ini? Hapus Batal - Opsi info masuk + Opsi info masuk - Bidang teks yang dapat diubah untuk alamat web info masuk + Bidang teks yang dapat diubah untuk alamat web info masuk - Bidang teks yang dapat diubah untuk nama pengguna info masuk + Bidang teks yang dapat diubah untuk nama pengguna info masuk - Bidang teks yang dapat diubah untuk kata sandi info masuk + Bidang teks yang dapat diubah untuk kata sandi info masuk - Simpan perubahan untuk masuk + Simpan perubahan untuk masuk - Ubah + Ubah - Tambahkan log masuk baru + Tambahkan log masuk baru - Kata sandi diperlukan + Kata sandi diperlukan - Nama pengguna diperlukan + Nama pengguna diperlukan Nama host diperlukan @@ -2023,7 +2007,7 @@ Pencarian %s - + Setel tautan dari situs web, surel, dan pesan untuk secara otomatis dibuka di Firefox. @@ -2033,7 +2017,7 @@ Klik untuk lebih jelasnya - Arahkan ke atas + Arahkan ke atas Tutup @@ -2071,4 +2055,8 @@ baca artikel buka tautan untuk mempelajari lebih lanjut + + + + diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index 46dd967e5..99ef68c1f 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -253,6 +253,11 @@ Þýða síðu + + Síða þýdd úr %1$s yfir í %2$s. + Valið tungumál @@ -330,12 +335,22 @@ Meðferð persónuupplýsinga í Firefox - + + Sjáðu nánar í persónuverndaryfirlýsingu okkar Við fáum kikk út úr því að halda þér öruggum + + Sjáðu hvers vegna milljónum manns líkar við Firefox + + Öruggt vafur með fleiri valmöguleikum Vafrinn okkar, sem ekki er rekinn í hagnaðarskyni, hjálpar til við að koma í veg fyrir að fyrirtæki laumist til að fylgjast með þér á ferðum þínum um vefinn. + Meira en 100 milljónir manna vernda friðhelgi sína með því að velja vafra sem er studdur af félagasamtökum án hagnaðarmarkmiða. + + Þekktir rekjarar? Lokað sjálfkrafa á þá. Forritsaukar? Prófaðu alla þessa 700. PDF-skjöl? Innbyggði lesarinn okkar gerir auðvelt að stjórna þeim. + Vafrinn okkar, sem ekki er rekinn í hagnaðarskyni, hjálpar til við að koma í veg fyrir að fyrirtæki laumist til að fylgjast með ferðum þínum um vefinn.\n\nFrekari upplýsingar má sjá í persónuverndaryfirlýsingu okkar. @@ -690,9 +705,9 @@ Bókamerki - Innskráningar + Innskráningar - Lykilorð + Lykilorð Opnir flipar @@ -718,9 +733,9 @@ %1$s á %2$s %3$s - Greiðslukort + Greiðslukort - Greiðslumátar + Greiðslumátar Vistföng @@ -1656,13 +1671,13 @@ Þú getur á auðveldan hátt bætt þessu vefsvæði á upphafsskjáinn þinn fyrir auðveldara aðgengi og hraðara vafur. - Innskráning og lykilorð + Innskráning og lykilorð - Lykilorð + Lykilorð - Vista innskráningu og lykilorð + Vista innskráningu og lykilorð - Vista lykilorð + Vista lykilorð Biðja um að vista @@ -1677,49 +1692,49 @@ Fylltu út notendanöfn og lykilorð í öðrum forritum á tækinu þínu. - Bæta við innskráningu + Bæta við innskráningu - Bæta við lykilorði + Bæta við lykilorði - - Samstilla innskráningar - Samstilla lykilorð + Samstilla innskráningar + + Samstilla lykilorð - Samstilla innskráningar milli tækja + Samstilla innskráningar milli tækja - Samstilla lykilorð milli tækja + Samstilla lykilorð milli tækja - Vistaðar innskráningar + Vistaðar innskráningar - Vistuð lykilorð + Vistuð lykilorð - Innskráningarnar sem þú vistar eða samstillir við %s birtast hér. + Innskráningarnar sem þú vistar eða samstillir við %s birtast hér. - Lykilorðin sem þú vistar eða samstillir við %s verða skráð hér. Öll lykilorð sem þú vistar eru dulrituð. + Lykilorðin sem þú vistar eða samstillir við %s verða skráð hér. Öll lykilorð sem þú vistar eru dulrituð. - Læra meira um samstillingu. + Læra meira um samstillingu. - Frekari upplýsingar um samstillingu + Frekari upplýsingar um samstillingu Undanþágur - Innskráningar og lykilorð sem ekki eru vistuð sjást hér. + Innskráningar og lykilorð sem ekki eru vistuð sjást hér. - %s mun ekki vista lykilorð fyrir vefsvæði sem skráð eru hér. + %s mun ekki vista lykilorð fyrir vefsvæði sem skráð eru hér. - Innskráningar og lykilorð verða ekki vistuð fyrir þessi vefsvæði. + Innskráningar og lykilorð verða ekki vistuð fyrir þessi vefsvæði. - %s mun ekki vista lykilorð fyrir þessi vefsvæði. + %s mun ekki vista lykilorð fyrir þessi vefsvæði. Eyða öllum undantekningum - Leita að innskráningu + Leita að innskráningu - Leita að lykilorðum + Leita að lykilorðum Vefsvæði @@ -1747,17 +1762,17 @@ Fela lykilorð - Aflæstu til að skoða vistaðar innskráningar + Aflæstu til að skoða vistaðar innskráningar - Aflæstu til að skoða vistuð lykilorð + Aflæstu til að skoða vistuð lykilorð - Verndaðu innskráningar þínar og lykilorð + Verndaðu innskráningar þínar og lykilorð - Tryggðu öryggi vistuðu lykilorðanna þinna + Tryggðu öryggi vistuðu lykilorðanna þinna - Settu upp læsimynstur, PIN eða lykilorð til að vernda vistaðar innskráningar og lykilorð ef ske kynni að einhver annar komist yfir tækið þitt. + Settu upp læsimynstur, PIN eða lykilorð til að vernda vistaðar innskráningar og lykilorð ef ske kynni að einhver annar komist yfir tækið þitt. - Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu lykilorðin þín ef ske kynni að einhver annar komist yfir tækið þitt. + Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu lykilorðin þín ef ske kynni að einhver annar komist yfir tækið þitt. Síðar @@ -1775,7 +1790,10 @@ Síðast notað - Raða innskráningarvalmyndinni + Raða innskráningarvalmyndinni + + + Raða lykilorðavalmynd Raða lykilorðavalmynd @@ -1786,39 +1804,42 @@ Tölvupóstföng - Greiðslukort + Greiðslukort - Greiðslumátar + Greiðslumátar - Vista og fylla sjálfkrafa út í greiðslukort + Vista og fylla sjálfkrafa út í greiðslukort - Vista og fylla út greiðslumáta + Vista og fylla út greiðslumáta - Gögn eru dulrituð + Gögn eru dulrituð - %s dulritar alla greiðslumáta sem þú vistar + %s dulritar alla greiðslumáta sem þú vistar Samstilla greiðslukort milli tækja Samstilla kort - Bæta við greiðslukorti + Bæta við greiðslukorti - Bæta við korti + Bæta við korti - Sýsla með vistuð greiðslukort + Sýsla með vistuð greiðslukort - Sýsla með greiðslukort + Sýsla með greiðslukort Bæta við tölvupóstfangi Sýsla með tölvupóstföng - Vista og fylla sjálfkrafa út heimilisföng + Vista og fylla sjálfkrafa út heimilisföng - Vista og fylla út í heimilisföng + Vista og fylla út í heimilisföng - Láta upplýsingar eins og símanúmer, tölvupóstföng og heimilisföng fylgja með + Láta upplýsingar eins og símanúmer, tölvupóstföng og heimilisföng fylgja með + + + Þar með talin símanúmer og tölvupóstföng Þar með talin símanúmer og tölvupóstföng @@ -1843,9 +1864,9 @@ Eyða korti - Ertu viss um að þú viljir eyða þessu greiðslukorti? + Ertu viss um að þú viljir eyða þessu greiðslukorti? - Eyða korti? + Eyða korti? Eyða @@ -1857,23 +1878,23 @@ Vistuð greiðslukort - Settu inn gilt kortanúmer + Settu inn gilt kortanúmer - Settu inn gilt kortanúmer + Settu inn gilt kortanúmer - Fylltu út í þennan reit + Fylltu út í þennan reit - Bættu við nafni + Bættu við nafni Aflæsa til að skoða vistuð greiðslukort - Haltu kreditkortunum þínum öruggum + Haltu kreditkortunum þínum öruggum - Tryggðu öryggi vistuðu greiðslumátanna þinna + Tryggðu öryggi vistuðu greiðslumátanna þinna - Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu greiðslukortin þín ef ske kynni að einhver annar komist yfir tækið þitt. + Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu greiðslukortin þín ef ske kynni að einhver annar komist yfir tækið þitt. - Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu greiðslumátana þína ef ske kynni að einhver annar komist yfir tækið þitt. + Settu upp læsimynstur, PIN-númer eða lykilorð til að vernda vistuðu greiðslumátana þína ef ske kynni að einhver annar komist yfir tækið þitt. Setja upp núna @@ -1881,10 +1902,10 @@ Aflæstu tækinu þínu - Aflæstu til að nota geymdar kreditkortaupplýsingar + Aflæstu til að nota geymdar kreditkortaupplýsingar - Aflæstu til að nota vistaða greiðslumáta + Aflæstu til að nota vistaða greiðslumáta Bæta við tölvupóstfangi @@ -1892,11 +1913,13 @@ Sýsla með tölvupóstföng - Skírnarnafn + Skírnarnafn - Millinafn + Millinafn - Eftirnafn + Eftirnafn + + Nafn Heimilisfang @@ -1921,9 +1944,9 @@ Eyða heimilisfangi - Ertu viss um að þú viljir eyða þessu póstfangi? + Ertu viss um að þú viljir eyða þessu póstfangi? - Eyða þessu heimilisfangi? + Eyða þessu heimilisfangi? Eyða @@ -2022,49 +2045,49 @@ Breyta - Ertu viss um að þú viljir eyða þessari innskráningu? + Ertu viss um að þú viljir eyða þessari innskráningu? - Ertu viss um að þú viljir eyða þessu lykilorði? + Ertu viss um að þú viljir eyða þessu lykilorði? Eyða Hætta við - Innskráningarvalkostir + Innskráningarvalkostir - Valkostir lykilorðs + Valkostir lykilorðs - Breytilegi textareiturinn fyrir veffang þessarar innskráningarinnar. + Breytilegi textareiturinn fyrir veffang þessarar innskráningarinnar. - Breytanlegi textareiturinn fyrir vistfang vefsvæðisins. + Breytanlegi textareiturinn fyrir vistfang vefsvæðisins. - Breytilegi textareiturinn fyrir notandanafn innskráningarinnar. + Breytilegi textareiturinn fyrir notandanafn innskráningarinnar. - Breytanlegi textareiturinn fyrir notandanafnið. + Breytanlegi textareiturinn fyrir notandanafnið. - Breytilegi textareiturinn fyrir lykilorð innskráningarinnar. + Breytilegi textareiturinn fyrir lykilorð innskráningarinnar. - Breytanlegi textareiturinn fyrir lykilorðið. + Breytanlegi textareiturinn fyrir lykilorðið. - Vista breytingar á innskráningu. + Vista breytingar á innskráningu. - Vista breytingar. + Vista breytingar. - Breyta + Breyta - Breyta lykilorði + Breyta lykilorði - Bæta við nýrri innskráningu + Bæta við nýrri innskráningu - Bæta við lykilorði + Bæta við lykilorði - Lykilorðs krafist + Lykilorðs krafist - Settu inn lykilorð + Settu inn lykilorð - Notandanafn er nauðsynlegt + Notandanafn er nauðsynlegt - Settu inn notandanafn + Settu inn notandanafn Hýsingarheiti er nauðsynlegt @@ -2176,7 +2199,7 @@ Smelltu til að fá frekari upplýsingar - Flakka upp + Flakka upp Loka @@ -2217,8 +2240,6 @@ Aðlöguð einkunn - Óáreiðanlegar umsagnir fjarlægðar - Byggt á áreiðanlegum umsögnum Hápunktar úr nýlegum umsögnum @@ -2276,10 +2297,6 @@ Ef þú sérð að þessi vara er aftur komin á lager skaltu tilkynna það til okkar og við munum vinna að því að uppfæra greininguna. Tilkynna þegar vara er til á lager - - Athugar gæði umsagna - - Athugar gæði umsagna Athugar gæði umsagna (%s) @@ -2325,13 +2342,19 @@ Frekari upplýsingar - Með því að velja „Já, prófum það“ samþykkir þú %2$s og %3$s hjá %1$s frá Mozilla. + Með því að velja „Já, prófum það“ samþykkir þú %2$s og %3$s hjá %1$s frá Mozilla. Með því að velja „Já, prófa það“ samþykkir þú eftirfarandi frá %1$s: + + Með því að velja „Já, prófum það“ samþykkir þú %2$s frá %1$s og %4$s frá %3$s. + + Með því að velja „Já, prófum það“ samþykkir þú %2$s frá %1$s og %4$s frá %3$s. - persónuverndarstefnu + persónuverndarstefnu Meðferð persónuupplýsinga + + persónuverndaryfirlýsing notkunarskilmála @@ -2402,6 +2425,10 @@ Þýða þessa síðu? + + Síða þýdd úr %1$s yfir í %2$s Prófaðu einkaþýðingar í %1$s @@ -2414,6 +2441,8 @@ Þýða á Ekki núna + + Sýna upprunalegt Lokið @@ -2436,6 +2465,16 @@ Kanna nánar + + Þýðing… + + + Sækja tungumál á meðan verið er í gagnasparnaðarham (%1$s)? + + Valkostir þýðinga diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index f71d5f35d..7e87f7fab 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -98,7 +98,7 @@ - La funzione per la protezione della privacy più potente che abbiamo mai realizzato isola gli elementi traccianti tra i siti. + La funzione per la protezione della privacy più potente che abbiamo mai realizzato: isola gli elementi che ti tracciano attraverso siti diversi. Ulteriori informazioni sulla Protezione totale per i cookie @@ -258,6 +258,11 @@ Traduci pagina + + Pagina tradotta da %1$s a %2$s. + Lingua selezionata @@ -336,12 +341,22 @@ Informativa sulla privacy di Firefox - + + Ulteriori informazioni nella nostra informativa sulla privacy Ci piace mantenerti al sicuro + + Scopri perché milioni di persone amano Firefox + + Navigazione sicura con più scelta Il nostro browser, supportato da un’organizzazione senza fini di lucro, blocca automaticamente le società che, di nascosto, cercano di seguire le tue attività sul Web. + Più di 100 milioni di persone proteggono la propria privacy scegliendo un browser supportato da un’organizzazione senza fini di lucro. + + Elementi traccianti conosciuti? Bloccati automaticamente. Estensioni? Provale tutte, ce ne sono più di 700. PDF? Facili da gestire grazie al lettore integrato. + Il nostro browser, supportato da un’organizzazione senza fini di lucro, blocca automaticamente le società che, di nascosto, cercano di seguire le tue attività sul Web.\n\nScopri ulteriori informazioni nella nostra informativa sulla privacy. @@ -701,9 +716,9 @@ Segnalibri - Credenziali + Credenziali - Password + Password Schede aperte @@ -729,9 +744,9 @@ %1$s su %2$s %3$s - Carte di credito + Carte di credito - Metodi di pagamento + Metodi di pagamento Indirizzi @@ -1700,13 +1715,13 @@ È possibile aggiungere questo sito web alla schermata principale del dispositivo per accedervi più rapidamente, come se si trattasse di un’app. - Credenziali e password + Credenziali e password - Password + Password - Salva credenziali e password + Salva credenziali e password - Salva password + Salva password Chiedi prima di salvare @@ -1722,47 +1737,47 @@ Compila nomi utente e password nelle altre app del tuo dispositivo. - Aggiungi credenziali + Aggiungi credenziali - Aggiungi password + Aggiungi password - - Sincronizza le credenziali - Sincronizza password + Sincronizza le credenziali + + Sincronizza password - Sincronizza credenziali tra dispositivi + Sincronizza credenziali tra dispositivi - Sincronizza le password tra i tuoi dispositivi + Sincronizza le password tra i tuoi dispositivi - Credenziali salvate + Credenziali salvate - Password salvate + Password salvate - Le credenziali salvate o sincronizzate in %s verranno visualizzate qui. + Le credenziali salvate o sincronizzate in %s verranno visualizzate qui. - Le password salvate o sincronizzate con %s verranno visualizzate qui. Tutte le password salvate sono crittate. + Le password salvate o sincronizzate con %s verranno visualizzate qui. Tutte le password salvate sono crittate. - Ulteriori informazioni su Sync. + Ulteriori informazioni su Sync. - Ulteriori informazioni sulla sincronizzazione + Ulteriori informazioni sulla sincronizzazione Eccezioni - Le credenziali e le password non salvate verranno mostrate qui. + Le credenziali e le password non salvate verranno mostrate qui. - %s non salverà le password per i siti elencati qui. + %s non salverà le password per i siti elencati qui. - Le credenziali e le password non verranno salvate per questi siti. + Le credenziali e le password non verranno salvate per questi siti. - %s non salverà le password per questi siti. + %s non salverà le password per questi siti. Elimina tutte le eccezioni - Cerca credenziali + Cerca credenziali - Cerca nelle password + Cerca nelle password Sito @@ -1790,17 +1805,17 @@ Nascondi password - Sblocca per visualizzare le credenziali salvate + Sblocca per visualizzare le credenziali salvate - Sblocca per visualizzare le password salvate + Sblocca per visualizzare le password salvate - Proteggi le credenziali di accesso + Proteggi le credenziali di accesso - Proteggi le password salvate + Proteggi le password salvate - Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le tue credenziali. + Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le tue credenziali. - Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le password salvate. + Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le password salvate. Più tardi @@ -1818,7 +1833,10 @@ Ultimo utilizzo - Ordina il menu delle credenziali di accesso + Ordina il menu delle credenziali di accesso + + + Menu per ordinare le password Menu per ordinare le password @@ -1829,40 +1847,43 @@ Indirizzi - Carte di credito + Carte di credito - Metodi di pagamento + Metodi di pagamento - Salvare e compilare automaticamente le carte + Salvare e compilare automaticamente le carte - Salva e compila i metodi di pagamento + Salva e compila i metodi di pagamento - I dati sono crittati + I dati sono crittati - %s critta tutti i metodi di pagamento salvati + %s critta tutti i metodi di pagamento salvati Sincronizza le carte tra più dispositivi Sincronizza carte di credito - Aggiungi una carta di credito + Aggiungi una carta di credito - Aggiungi carta + Aggiungi carta - Gestione carte salvate + Gestione carte salvate - Gestisci carte + Gestisci carte Aggiungi indirizzo Gestione indirizzi - Salvare e compilare automaticamente gli indirizzi + Salvare e compilare automaticamente gli indirizzi - Salva e compila indirizzi + Salva e compila indirizzi - Includere informazioni come numeri, email e indirizzi di spedizione + Includere informazioni come numeri, email e indirizzi di spedizione + + + Include numeri di telefono e indirizzi email Include numeri di telefono e indirizzi email @@ -1887,9 +1908,9 @@ Elimina carta - Eliminare questa carta di credito? + Eliminare questa carta di credito? - Eliminare la carta? + Eliminare la carta? Elimina @@ -1903,24 +1924,24 @@ Carte salvate - Inserire un numero di carta di credito valido + Inserire un numero di carta di credito valido - Inserisci un numero di carta valido + Inserisci un numero di carta valido - Compilare questo campo + Compilare questo campo - Aggiungi un nome + Aggiungi un nome Sblocca per visualizzare le carte di credito salvate - Proteggi le tue carte di credito + Proteggi le tue carte di credito - Proteggi i metodi di pagamento salvati + Proteggi i metodi di pagamento salvati - Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le carte di credito salvate. + Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare le carte di credito salvate. - Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare i metodi di pagamento salvati. + Imposta una sequenza di blocco, PIN o password per impedire a chi si impossessa del dispositivo di visualizzare i metodi di pagamento salvati. Imposta adesso @@ -1929,10 +1950,10 @@ Sblocca il dispositivo - Sblocca per utilizzare le informazioni delle carte di credito salvate + Sblocca per utilizzare le informazioni delle carte di credito salvate - Sblocca per utilizzare i metodi di pagamento salvati + Sblocca per utilizzare i metodi di pagamento salvati Aggiungi indirizzo @@ -1940,11 +1961,13 @@ Gestione indirizzi - Nome + Nome - Secondo nome + Secondo nome - Cognome + Cognome + + Nome Indirizzo @@ -1970,9 +1993,9 @@ Elimina indirizzo - Eliminare questo indirizzo? + Eliminare questo indirizzo? - Eliminare questo indirizzo? + Eliminare questo indirizzo? Elimina @@ -2070,49 +2093,49 @@ Modifica - Rimuovere queste credenziali? + Rimuovere queste credenziali? - Eliminare questa password? + Eliminare questa password? Rimuovi Annulla - Opzioni credenziali + Opzioni credenziali - Opzioni password + Opzioni password - Il campo di testo modificabile per l’indirizzo web delle credenziali + Il campo di testo modificabile per l’indirizzo web delle credenziali - Il campo di testo modificabile per l’indirizzo del sito web. + Il campo di testo modificabile per l’indirizzo del sito web. - Il campo di testo modificabile per il nome utente delle credenziali + Il campo di testo modificabile per il nome utente delle credenziali - Il campo di testo modificabile per il nome utente. + Il campo di testo modificabile per il nome utente. - Il campo di testo modificabile per la password delle credenziali + Il campo di testo modificabile per la password delle credenziali - Il campo di testo modificabile per la password. + Il campo di testo modificabile per la password. - Salva le modifiche alle credenziali. + Salva le modifiche alle credenziali. - Salva modifiche. + Salva modifiche. - Modifica + Modifica - Modifica password + Modifica password - Aggiungi nuove credenziali + Aggiungi nuove credenziali - Aggiungi password + Aggiungi password - Password obbligatoria + Password obbligatoria - Inserisci una password + Inserisci una password - Nome utente obbligatorio + Nome utente obbligatorio - Inserisci un nome utente + Inserisci un nome utente Nome server obbligatorio @@ -2226,7 +2249,7 @@ Fare clic per ulteriori dettagli - Vai su + Vai su Chiudi @@ -2267,8 +2290,6 @@ Valutazione rettificata - Recensioni inaffidabili rimosse - Basato su recensioni affidabili In evidenza dalle recensioni recenti @@ -2295,13 +2316,13 @@ Impostazioni - Mostra annunci nella verifica recensioni + Mostra annunci in Verifica recensioni Verranno visualizzati annunci occasionali per prodotti pertinenti. Promuoviamo solo prodotti con recensioni affidabili. %s Ulteriori informazioni - Disattiva verifica recensioni + Disattiva Verifica recensioni Altri prodotti da valutare @@ -2326,10 +2347,6 @@ Segnala che il prodotto è disponibile - - Verifica qualità recensioni - - Verifica qualità recensioni Verifica qualità recensioni (%s) @@ -2377,13 +2394,19 @@ Ulteriori informazioni - Selezionando “Sì, provala” accetti l’%2$s e i %3$s di %1$s by Mozilla. + Selezionando “Sì, provala” accetti l’%2$s e i %3$s di %1$s by Mozilla. Selezionando “Sì, provalo” accetti le condizioni di %1$s: + + Selezionando “Sì, provala” accetti l’%2$s di %1$s e le %4$s di %3$s. + + Selezionando “Sì, provala” accetti l’%2$s di %1$s e le %4$s di %3$s. - informativa sulla privacy + informativa sulla privacy Informativa sulla privacy + + informativa sulla privacy condizioni di utilizzo del servizio @@ -2395,17 +2418,17 @@ Prima di acquistare, scopri se puoi fidarti delle recensioni di questo prodotto. - Prova verifica recensioni + Prova Verifica recensioni Queste recensioni sono affidabili? Controlla ora per vedere la valutazione rettificata. - Apri verifica recensioni + Apri Verifica recensioni Beta - Apri verifica recensioni + Apri Verifica recensioni - Chiudi verifica recensioni + Chiudi Verifica recensioni %1$s su 5 stelle @@ -2454,6 +2477,10 @@ Tradurre questa pagina? + + Pagina tradotta da %1$s a %2$s Prova le traduzioni riservate di %1$s @@ -2466,6 +2493,8 @@ Traduci in Non ora + + Mostra originale Fatto @@ -2488,6 +2517,16 @@ Ulteriori informazioni + + Traduzione… + + + Scaricare la lingua in modalità Risparmio dati (%1$s)? + + Opzioni di traduzione diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 58167cd3b..58bc4d662 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -253,6 +253,11 @@ תרגום הדף + + הדף תורגם מ%1$s ל%2$s. + שפה נבחרת @@ -330,12 +335,22 @@ הצהרת הפרטיות של Firefox - + + מידע נוסף בהצהרת הפרטיות שלנו אנחנו אוהבים לשמור עליך + + גלו מדוע מיליונים אוהבים את Firefox + + גלישה בטוחה עם אפשרויות נוספות הדפדפן שלנו שמגובה בקרן ללא מטרות רווח מסייע למנוע מחברות לעקוב אחריך בסתר ברחבי הרשת. + יותר מ־100 מיליון אנשים מגנים על הפרטיות שלהם על־ידי בחירה בדפדפן שמגובה על־ידי עמותה שאינה למטרות רווח. + + רכיבי מעקב ידועים? נחסמים באופן אוטומטי. הרחבות? נסו את כל ה־700 שיש לנו. קובצי PDF? עם הקורא המובנה שלנו קל לנהל אותם. + הדפדפן שלנו שמגובה בקרן ללא מטרות רווח מסייע למנוע מחברות לעקוב אחריך בסתר ברחבי הרשת.\n\nמידע נוסף בהצהרת הפרטיות שלנו. @@ -692,9 +707,9 @@ סימניות - כניסות + כניסות - ססמאות + ססמאות לשוניות פתוחות @@ -720,9 +735,9 @@ ‏%1$s על %2$s %3$s - כרטיסי אשראי + כרטיסי אשראי - אמצעי תשלום + אמצעי תשלום כתובות @@ -1613,6 +1628,9 @@ מנקה עוגיות המוגדרות על־ידי הפניות לאתרי מעקב ידועים. + + החסימה של חלק מרכיבי המעקב המסומנים למטה בוטלה באופן חלקי בדף זה מכיוון שתיקשרת איתם *. מידע נוסף @@ -1664,13 +1682,13 @@ באפשרותך להוסיף בקלות אתר זה למסך הבית של המכשיר שלך כדי לקבל גישה מיידית ולגלוש מהר יותר עם חוויה שמדמה שימוש ביישומון. - כניסות וססמאות + כניסות וססמאות - ססמאות + ססמאות - שמירת כניסות וססמאות + שמירת כניסות וססמאות - שמירת ססמאות + שמירת ססמאות לבקש לשמור @@ -1687,47 +1705,47 @@ מילוי ושמירת שמות משתמשים וססמאות ביישומונים אחרים במכשיר שלך. - הוספת כניסה + הוספת כניסה - הוספת ססמה + הוספת ססמה - - סנכרון כניסות - סנכרון ססמאות + סנכרון כניסות + + סנכרון ססמאות - סנכרון כניסות בין מכשירים + סנכרון כניסות בין מכשירים - סנכרון ססמאות בין מכשירים + סנכרון ססמאות בין מכשירים - כניסות שמורות + כניסות שמורות - ססמאות שמורות + ססמאות שמורות - הכניסות שיישמרו או יסתנכרנו אל %s יופיעו כאן. + הכניסות שיישמרו או יסתנכרנו אל %s יופיעו כאן. - הססמאות שיישמרו או יסונכרנו עם %s יופיעו כאן. כל הססמאות השמורות הינן מוצפנות. + הססמאות שיישמרו או יסונכרנו עם %s יופיעו כאן. כל הססמאות השמורות הינן מוצפנות. - מידע נוסף על Sync. + מידע נוסף על Sync. - מידע נוסף על סנכרון + מידע נוסף על סנכרון חריגות - כניסות וססמאות שאינן שמורות יופיעו כאן. + כניסות וססמאות שאינן שמורות יופיעו כאן. - ‏%s לא ישמור ססמאות לאתרים המפורטים כאן. + ‏%s לא ישמור ססמאות לאתרים המפורטים כאן. - כניסות וססמאות לא יישמרו עבור אתרים אלו. + כניסות וססמאות לא יישמרו עבור אתרים אלו. - ‏%s לא ישמור ססמאות לאתרים אלו. + ‏%s לא ישמור ססמאות לאתרים אלו. מחיקת כל החריגות - חיפוש כניסות + חיפוש כניסות - חיפוש ססמאות + חיפוש ססמאות אתר @@ -1755,17 +1773,17 @@ הסתרת ססמה - יש לבטל את הנעילה כדי להציג את הכניסות השמורות שלך + יש לבטל את הנעילה כדי להציג את הכניסות השמורות שלך - יש לבטל את הנעילה כדי להציג את הססמאות השמורות שלך + יש לבטל את הנעילה כדי להציג את הססמאות השמורות שלך - שמירה מאובטחת של הכניסות והססמאות שלך + שמירה מאובטחת של הכניסות והססמאות שלך - אבטחת הססמאות השמורות שלך + אבטחת הססמאות השמורות שלך - ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על פרטי הגישה והססמאות השמורות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על פרטי הגישה והססמאות השמורות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. - ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על הססמאות השמורות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על הססמאות השמורות שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. מאוחר יותר @@ -1783,7 +1801,10 @@ שימוש אחרון - תפריט מיון כניסות + תפריט מיון כניסות + + + תפריט מיון ססמאות תפריט מיון ססמאות @@ -1794,41 +1815,44 @@ כתובות - כרטיסי אשראי + כרטיסי אשראי - אמצעי תשלום + אמצעי תשלום - שמירה ומילוי אוטומטי של כרטיסים + שמירה ומילוי אוטומטי של כרטיסים - שמירה ומילוי אמצעי תשלום + שמירה ומילוי אמצעי תשלום - הנתונים מוצפנים + הנתונים מוצפנים - ‏%s מצפין את כל אמצעי התשלום השמורים + ‏%s מצפין את כל אמצעי התשלום השמורים סנכרון כרטיסים בין מכשירים סנכרון כרטיסים - הוספת כרטיס אשראי + הוספת כרטיס אשראי - הוספת כרטיס + הוספת כרטיס - ניהול כרטיסים שמורים + ניהול כרטיסים שמורים - ניהול כרטיסים + ניהול כרטיסים הוספת כתובת ניהול כתובות - שמירה ומילוי אוטומטי של כתובות + שמירה ומילוי אוטומטי של כתובות - שמירה ומילוי כתובות + שמירה ומילוי כתובות - לכלול מידע כמו מספרים, כתובות דוא״ל וכתובות למשלוח + לכלול מידע כמו מספרים, כתובות דוא״ל וכתובות למשלוח + + + כולל מספרי טלפון וכתובות דוא״ל כולל מספרי טלפון וכתובות דוא״ל @@ -1852,9 +1876,9 @@ מחיקת כרטיס - האם ברצונך למחוק את כרטיס האשראי הזה? + האם ברצונך למחוק את כרטיס האשראי הזה? - למחוק את הכרטיס? + למחוק את הכרטיס? מחיקה @@ -1868,24 +1892,24 @@ כרטיסים שמורים - נא להכניס מספר כרטיס אשראי תקין + נא להכניס מספר כרטיס אשראי תקין - נא להכניס מספר כרטיס תקני + נא להכניס מספר כרטיס תקני - נא למלא שדה זה + נא למלא שדה זה - הוספת שם + הוספת שם יש לבטל את הנעילה כדי להציג את הכרטיסים השמורים שלך - אבטחת כרטיסי האשראי שלך + אבטחת כרטיסי האשראי שלך - אבטחת אמצעי התשלום השמורים שלך + אבטחת אמצעי התשלום השמורים שלך - ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על כרטיסי האשראי השמורים שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על כרטיסי האשראי השמורים שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. - ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על אמצעי התשלום השמורים שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. + ניתן להגדיר תבנית נעילת מכשיר, קוד או ססמה כדי להגן על אמצעי התשלום השמורים שלך מפני גורמים בלתי מהימנים שמחזיקים במכשיר שלך. להגדיר כעת @@ -1894,10 +1918,10 @@ שחרור נעילת המכשיר שלך - יש לבטל את הנעילה כדי להשתמש בפרטי כרטיס האשראי השמור + יש לבטל את הנעילה כדי להשתמש בפרטי כרטיס האשראי השמור - יש לבטל את הנעילה כדי להשתמש באמצעי התשלום השמורים שלך + יש לבטל את הנעילה כדי להשתמש באמצעי התשלום השמורים שלך הוספת כתובת @@ -1905,11 +1929,13 @@ ניהול כתובות - שם פרטי + שם פרטי - שם אמצעי + שם אמצעי - שם משפחה + שם משפחה + + שם כתובת רחוב @@ -1932,10 +1958,10 @@ מחיקת כתובת - האם ברצונך למחוק את כתובת זו? + האם ברצונך למחוק את כתובת זו? - למחוק את הכתובת הזאת? + למחוק את הכתובת הזאת? מחיקה @@ -2034,49 +2060,49 @@ עריכה - האם ברצונך למחוק את כניסה זו? + האם ברצונך למחוק את כניסה זו? - האם ברצונך למחוק ססמה זו? + האם ברצונך למחוק ססמה זו? מחיקה ביטול - אפשרויות כניסה + אפשרויות כניסה - אפשרויות ססמה + אפשרויות ססמה - שדה הטקסט הניתן לעריכה עבור כתובת האתר של הכניסה. + שדה הטקסט הניתן לעריכה עבור כתובת האתר של הכניסה. - שדה הטקסט הניתן לעריכה עבור כתובת האתר. + שדה הטקסט הניתן לעריכה עבור כתובת האתר. - שדה הטקסט הניתן לעריכה עבור שם המשתמש של הכניסה. + שדה הטקסט הניתן לעריכה עבור שם המשתמש של הכניסה. - שדה הטקסט הניתן לעריכה עבור שם המשתמש. + שדה הטקסט הניתן לעריכה עבור שם המשתמש. - שדה הטקסט הניתן לעריכה עבור הססמה של הכניסה. + שדה הטקסט הניתן לעריכה עבור הססמה של הכניסה. - שדה הטקסט הניתן לעריכה עבור הססמה. + שדה הטקסט הניתן לעריכה עבור הססמה. - שמירת השינויים של הכניסה. + שמירת השינויים של הכניסה. - שמירת שינויים. + שמירת שינויים. - עריכה + עריכה - עריכת הססמה + עריכת הססמה - הוספת כניסה חדשה + הוספת כניסה חדשה - הוספת ססמה + הוספת ססמה - נדרשת ססמה + נדרשת ססמה - נא להכניס ססמה + נא להכניס ססמה - דרוש שם משתמש + דרוש שם משתמש - נא להכניס שם משתמש + נא להכניס שם משתמש דרוש שם מארח @@ -2190,7 +2216,7 @@ יש ללחוץ לפרטים נוספים - ניווט למעלה + ניווט למעלה סגירה @@ -2231,8 +2257,6 @@ דירוג מותאם - סקירות בלתי אמינות הוסרו - מבוסס על סקירות אמינות דגשים מהסקירות האחרונות @@ -2287,10 +2311,6 @@ אם מוצר זה חזר למלאי, נא לדווח על כך ואנו נעבוד על בדיקת הסקירות. שליחת דיווח שמוצר זה חזר למלאי - - בתהליך בדיקת איכות הסקירות - - בתהליך בדיקת איכות הסקירות בתהליך בדיקת איכות הסקירות (%s) @@ -2338,13 +2358,19 @@ מידע נוסף - בחירה באפשרות ״כן, ארצה לנסות״ מהווה הסכמה ל%2$s ול%3$s של %1$s מאת Mozilla. + בחירה באפשרות ״כן, ארצה לנסות״ מהווה הסכמה ל%2$s ול%3$s של %1$s מאת Mozilla. בחירה באפשרות ״כן, ארצה לנסות״ מהווה הסכמה לתנאים הבאים מאת %1$s: + + בחירה באפשרות ״כן, ארצה לנסות״ מהווה הסכמה ל%2$s של %1$s ול%4$s של %3$s. + + בחירה באפשרות ״כן, ארצה לנסות״ מהווה הסכמה ל%2$s של %1$s ול%4$s של %3$s. - הצהרת הפרטיות + מדיניות הפרטיות מדיניות הפרטיות + + הצהרת הפרטיות תנאי השימוש @@ -2415,6 +2441,10 @@ לתרגם את הדף הזה? + + הדף תורגם מ%1$s ל%2$s לנסות תרגומים פרטיים ב־%1$s @@ -2427,6 +2457,8 @@ שפת יעד לא כעת + + הצגת המקור סיום @@ -2449,6 +2481,16 @@ מידע נוסף + + בתהליך תרגום… + + + להוריד את השפה במצב חיסכון בנתונים (%1$s)? + + אפשרויות תרגום diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 551805b33..3f56f626b 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -259,6 +259,11 @@ ページを翻訳 + + ページを %1$s から %2$s に翻訳しました。 + 選択した言語 @@ -337,12 +342,22 @@ Firefox のプライバシー通知 - + + 詳細はプライバシー通知をご覧ください 私たちはあなたの安全を守りたいと願っています + + Firefox が選ばれる理由 + + 多くの選択肢を持つ安全なブラウジング 非営利で作られた私たちのブラウザーは、企業によるウェブ上の密かな追跡を阻止するのに役立ちます。 + 1 億人以上の人が、非営利団体が支援するブラウザーを選択してプライバシーを保護しています。 + + 既知のトラッカーが自動的にブロックされます。700 個すべての拡張機能を試せます。PDF は内蔵のリーダーで管理が簡単になります。 + 非営利で作られた私たちのブラウザーは、企業によるウェブ上の密かな追跡を阻止するのに役立ちます。\n\n詳細はプライバシー通知をご覧ください。 @@ -701,9 +716,9 @@ ブックマーク - ログイン情報 + ログイン情報 - パスワード + パスワード 開いているタブ @@ -729,9 +744,9 @@ %2$s %3$s 上の %1$s - クレジットカード情報 + クレジットカード情報 - 支払い方法 + 支払い方法 住所 @@ -1685,13 +1700,13 @@ このウェブサイトを端末のホーム画面に簡単な操作で追加できます。アプリのような感覚で素早くアクセスして閲覧しましょう。 - ログイン情報とパスワード + ログイン情報とパスワード - パスワード + パスワード - ログイン情報を保存する + ログイン情報を保存する - パスワードを保存 + パスワードを保存 保存するか確認する @@ -1707,47 +1722,47 @@ 端末上の他のアプリにユーザー名とパスワードを入力します。 - ログイン情報を追加 + ログイン情報を追加 - パスワードを追加 + パスワードを追加 - - ログイン情報を同期 - パスワードを同期 + ログイン情報を同期 + + パスワードを同期 - 端末間でログイン情報を同期します + 端末間でログイン情報を同期します - 端末間でパスワードを同期 + 端末間でパスワードを同期 - 保存されたログイン情報 + 保存されたログイン情報 - 保存されたパスワード + 保存されたパスワード - 端末に保存または %s と同期したログイン情報がここに表示されます。 + 端末に保存または %s と同期したログイン情報がここに表示されます。 - %s に保存または同期したパスワードがこのリストに表示されます。保存されたすべてのパスワードは暗号化されます。 + %s に保存または同期したパスワードがこのリストに表示されます。保存されたすべてのパスワードは暗号化されます。 - Sync についての詳細情報。 + Sync についての詳細情報。 - Sync についての詳細情報 + Sync についての詳細情報 例外 - ログイン情報が保存されないサイトがここに表示されます。 + ログイン情報が保存されないサイトがここに表示されます。 - %s は、このリストに表示されているサイトのパスワードを保存しません。 + %s は、このリストに表示されているサイトのパスワードを保存しません。 - これらのサイトではログイン情報が保存されません。 + これらのサイトではログイン情報が保存されません。 - %s はこれらのサイトのパスワードを保存しません。 + %s はこれらのサイトのパスワードを保存しません。 すべての例外を削除 - ログイン情報を検索 + ログイン情報を検索 - パスワードを検索 + パスワードを検索 サイト @@ -1775,17 +1790,17 @@ パスワードを隠す - ロック解除して保存されたログイン情報を表示します + ロック解除して保存されたログイン情報を表示します - 保存されたパスワードを表示するにはロック解除してください + 保存されたパスワードを表示するにはロック解除してください - ログイン情報とパスワードの保護 + ログイン情報とパスワードの保護 - 保存されたパスワードを保護してください + 保存されたパスワードを保護してください - 端末のロックパターンや PIN、パスワードを設定して、保存されたログイン情報とパスワードを他人の不正なアクセスから保護しましょう。 + 端末のロックパターンや PIN、パスワードを設定して、保存されたログイン情報とパスワードを他人の不正なアクセスから保護しましょう。 - 端末のロックパターンや PIN、パスワードを設定して、保存されたパスワードを他人の不正なアクセスから保護しましょう。 + 端末のロックパターンや PIN、パスワードを設定して、保存されたパスワードを他人の不正なアクセスから保護しましょう。 後で @@ -1803,7 +1818,10 @@ 最終使用日時 - ログイン情報メニューの並べ替え + ログイン情報メニューの並べ替え + + + パスワードを並べ替えます パスワードを並べ替えます @@ -1814,41 +1832,44 @@ 所在地フォーム - クレジットカード + クレジットカード - 支払い方法 + 支払い方法 - カード情報を保存して自動入力する + カード情報を保存して自動入力する - 支払い方法を保存して入力する + 支払い方法を保存して入力する - データは暗号化されています + データは暗号化されています - %s は保存したすべての支払い方法を暗号化します + %s は保存したすべての支払い方法を暗号化します 端末間でカード情報を同期する クレジットカード情報を同期 - クレジットカードを追加 + クレジットカードを追加 - カード情報を追加 + カード情報を追加 - 保存したカードを管理 + 保存したカードを管理 - カード情報を管理 + カード情報を管理 アドレスを追加 アドレスの管理 - アドレスを保存して自動入力する + アドレスを保存して自動入力する - 住所を保存して入力する + 住所を保存して入力する - カード番号、メールアドレス、配送先などの情報を含める + カード番号、メールアドレス、配送先などの情報を含める + + + 電話番号とメールアドレスを含みます 電話番号とメールアドレスを含みます @@ -1873,9 +1894,9 @@ カードを削除 - 本当にこのクレジットカード情報を削除してもよろしいですか? + 本当にこのクレジットカード情報を削除してもよろしいですか? - カード情報を削除しますか? + カード情報を削除しますか? 削除 @@ -1889,25 +1910,25 @@ 保存したカード - 有効なクレジットカード番号を入力してください + 有効なクレジットカード番号を入力してください - 正しいカード番号を入力してください + 正しいカード番号を入力してください - このフィールドは入力必須です + このフィールドは入力必須です - 名前を追加してください + 名前を追加してください 保存されたカード情報を表示するにはロック解除してください - クレジットカード情報の保護 + クレジットカード情報の保護 - 保存された支払い方法を保護してください + 保存された支払い方法を保護してください - 端末のロックパターンや PIN、パスワードを設定して、保存されたクレジットカード情報とパスワードを他人の不正なアクセスから保護しましょう。 + 端末のロックパターンや PIN、パスワードを設定して、保存されたクレジットカード情報とパスワードを他人の不正なアクセスから保護しましょう。 - 端末のロックパターンや PIN、パスワードを設定して、保存された支払い方法を他人の不正なアクセスから保護しましょう。 + 端末のロックパターンや PIN、パスワードを設定して、保存された支払い方法を他人の不正なアクセスから保護しましょう。 今すぐ設定 @@ -1916,10 +1937,10 @@ 端末のロック解除 - ロックを解除して保存したクレジットカード情報を使用します + ロックを解除して保存したクレジットカード情報を使用します - 保存された支払い方法を使用するにはロック解除してください + 保存された支払い方法を使用するにはロック解除してください アドレスを追加 @@ -1927,11 +1948,13 @@ アドレスの管理 - + - ミドルネーム + ミドルネーム - + + + 氏名 番地 @@ -1956,9 +1979,9 @@ アドレスを削除 - 本当にこの住所を削除してもよろしいですか? + 本当にこの住所を削除してもよろしいですか? - このアドレスを削除しますか? + このアドレスを削除しますか? 削除 @@ -2056,50 +2079,50 @@ 編集 - このログイン情報を削除してもよろしいですか? + このログイン情報を削除してもよろしいですか? - 本当にこのパスワードを削除してもよろしいですか? + 本当にこのパスワードを削除してもよろしいですか? 削除 キャンセル - ログインオプション + ログインオプション - パスワードのオプション + パスワードのオプション - ログイン情報のウェブアドレスの編集可能なテキストフィールド。 + ログイン情報のウェブアドレスの編集可能なテキストフィールド。 - ウェブサイトのアドレスの編集可能なテキストフィールド。 + ウェブサイトのアドレスの編集可能なテキストフィールド。 - ログイン情報のユーザー名の編集可能なテキストフィールド。 + ログイン情報のユーザー名の編集可能なテキストフィールド。 - ユーザー名の編集可能なテキストフィールド。 + ユーザー名の編集可能なテキストフィールド。 - ログイン情報のパスワードの編集可能なテキストフィールド。 + ログイン情報のパスワードの編集可能なテキストフィールド。 - パスワードの編集可能なテキストフィールド。 + パスワードの編集可能なテキストフィールド。 - 変更を保存してログインします。 + 変更を保存してログインします。 - 変更を保存します。 + 変更を保存します。 - 編集 + 編集 - パスワードを編集 + パスワードを編集 - 新しいログイン情報の追加 + 新しいログイン情報の追加 - パスワードを追加 + パスワードを追加 - パスワードが必要です + パスワードが必要です - パスワードを入力してください + パスワードを入力してください - ユーザー名は必須です + ユーザー名は必須です - ユーザー名を入力してください + ユーザー名を入力してください ホスト名は必須です @@ -2212,7 +2235,7 @@ 詳細はこちら - 上へ移動します + 上へ移動します 閉じる @@ -2254,8 +2277,6 @@ レートが調整されています - 信頼できないレビューを削除しました - 信頼できないレビューに基づきます 最近の注目レビュー @@ -2311,10 +2332,6 @@ この製品が再入荷されている場合はご報告ください。その製品レビューを確認します。 製品の在庫があることを報告する - - レビューの品質の確認 - - レビューの品質の確認 レビューの品質の確認 (%s) @@ -2363,13 +2380,19 @@ 詳細情報 - 「はい、試します」を選択すると、%1$s by Mozilla の%2$s および %3$s に同意したものとみなされます。 + 「はい、試します」を選択すると、%1$s by Mozilla の%2$s および %3$s に同意したものとみなされます。 「はい、試します」を選択すると、%1$s の以下の内容に同意したものとみなされます: + + 「はい、試します」を選択すると、%1$s の%2$sおよび %3$s の%4$sに同意したものとみなされます。 + + 「はい、試します」を選択すると、%1$s の%2$sおよび %3$s の%4$sに同意したものとみなされます。 - プライバシーポリシー + プライバシーポリシー プライバシーポリシー + + プライバシー通知 利用規約 @@ -2440,6 +2463,10 @@ このページを翻訳しますか? + + ページを %1$s から %2$s に翻訳しました %1$s でプライベート翻訳を試してください @@ -2452,6 +2479,8 @@ 翻訳先 後で + + 元の言語で表示 完了 @@ -2473,6 +2502,17 @@ 詳細情報 + + 翻訳中… + + + + データ節約モードで言語をダウンロード (%1$s) しますか? + + 翻訳オプション @@ -2620,7 +2660,7 @@ 使用中 - 未使用 + 休止中 プライベート @@ -2632,7 +2672,7 @@ 使用中のタブに追加 - 未使用のタブに追加 + 休止中のタブに追加 プライベートタブに追加 diff --git a/app/src/main/res/values-kab/strings.xml b/app/src/main/res/values-kab/strings.xml index 099ae1be7..d806ef249 100644 --- a/app/src/main/res/values-kab/strings.xml +++ b/app/src/main/res/values-kab/strings.xml @@ -338,7 +338,8 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Tasertit tabaḍnit n Firefox - + + Issin ugar deg tsertit-nneɣ n tbaḍnit Nḥemmel ad teqqimeḍ d aɣellsan @@ -693,9 +694,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ticraḍ n yisebtar - Inekcam + Inekcam - Awalen uffiren + Awalen uffiren Accaren yeldin @@ -722,9 +723,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara %1$s deg %2$s %3$s - Tikarḍiwin n usmad + Tikarḍiwin n usmad - Tarrayin n uxelleṣ + Tarrayin n uxelleṣ Tansiwin @@ -1676,13 +1677,13 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Tzemreḍ s sshal ad ternuḍ asmel-a web ɣer ugdil agejdan n yibenk-inek·inem i wakken ad tesɛuḍ anekcum askudan d tunigin taruradt s termt i icuban asnas. - Inekcam d wawalen uffiren + Inekcam d wawalen uffiren - Awalen uffiren + Awalen uffiren - Sekles inekcam d wawalen uffiren + Sekles inekcam d wawalen uffiren - Sekles awalen uffiren + Sekles awalen uffiren Suter asekles @@ -1698,39 +1699,39 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ččar ismawen n useqdac d wawalen uffiren deg yisnasen-nniḍen ɣef yibenk-ik·im. - Rnu anekcum + Rnu anekcum - Rnu awal uffir + Rnu awal uffir - - Mtawi inekcam - Mtawi awalen uffiren + Mtawi inekcam + + Mtawi awalen uffiren - Mtawi inekcam gqr yibenkan + Mtawi inekcam gqr yibenkan - Inekcam yettwakelsen + Inekcam yettwakelsen - Awalen uffiren yettwakelsen + Awalen uffiren yettwakelsen - Anekcum i tḥerzeḍ ɣer %s ad d-ittwasken da. + Anekcum i tḥerzeḍ ɣer %s ad d-ittwasken da. - Issin ugar ɣef umtawi. + Issin ugar ɣef umtawi. - Issin ugar ɣef umtawi + Issin ugar ɣef umtawi Tisuraf - Inekcam akked wawalen uffiren ur yettwaskelsen ara ad ttwaseknen dagi. + Inekcam akked wawalen uffiren ur yettwaskelsen ara ad ttwaseknen dagi. - Inekcam akked wawalen uffiren ur ttwaseklasen ara i yismal-a. + Inekcam akked wawalen uffiren ur ttwaseklasen ara i yismal-a. Kkes akk tisuraf - Nadi inekcam + Nadi inekcam - Nadi awalen uffiren + Nadi awalen uffiren Asmel web @@ -1758,13 +1759,13 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ffer awal uffir - Serreḥ akken ad tsekneḍ inekcam-ik yettwaskelsen + Serreḥ akken ad tsekneḍ inekcam-ik yettwaskelsen - Mmesten inekcam d wawalen uffiren + Mmesten inekcam d wawalen uffiren - Seɣles awalen-ik·im uffiren i yettwaskelsen + Seɣles awalen-ik·im uffiren i yettwaskelsen - Sbadu azenziɣ n usekkeṛ, tangal PIN, neɣ awal uffir akken ad temmesteneḍ inekcam-ik akked wawlen-ik uffiren yettwaskelsen ticki yella win ikecmen ɣer yibenk-ik. + Sbadu azenziɣ n usekkeṛ, tangal PIN, neɣ awal uffir akken ad temmesteneḍ inekcam-ik akked wawlen-ik uffiren yettwaskelsen ticki yella win ikecmen ɣer yibenk-ik. Ticki @@ -1783,7 +1784,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Aseqdec aneggaru - Umuɣ n usemyizwer n yinekcam + Umuɣ n usemyizwer n yinekcam @@ -1791,35 +1792,38 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Tansiwin - Tikarḍiwin n usmad + Tikarḍiwin n usmad - Tarrayin n uxelleṣ + Tarrayin n uxelleṣ - Asekles d taččart tawurmant n tkarḍiwin + Asekles d taččart tawurmant n tkarḍiwin - Isefka ttwawgelhen + Isefka ttwawgelhen Mtawi tikarḍiwin gar yibenkan Mtawi tikarḍiwin - Rnu takarḍa n usmad + Rnu takarḍa n usmad - Rnu takarḍa + Rnu takarḍa - Sefrek tikerḍiwin yettwaskelsen + Sefrek tikerḍiwin yettwaskelsen - Sefrek tikarḍiwin + Sefrek tikarḍiwin Rnu tansa Sefrek tansiwin - Asekles d taččart tawurmant n tansiwin + Asekles d taččart tawurmant n tansiwin - Sekles; teččareḍ tansiwin + Sekles; teččareḍ tansiwin - Seddu talɣut am wuṭṭunen, imayl akked tansiwin n usiweḍ + Seddu talɣut am wuṭṭunen, imayl akked tansiwin n usiweḍ + + + Seddu ula uṭṭunen n tiliɣri d tansiwin n yimayl Rnu takarḍa @@ -1840,9 +1844,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Kkes takarḍa - Tebɣiḍ s tidet ad tekkseḍ takarḍa-a n usmad? + Tebɣiḍ s tidet ad tekkseḍ takarḍa-a n usmad? - Kkes takarḍa? + Kkes takarḍa? Kkes @@ -1855,20 +1859,20 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Tikerḍiwin yettwasekles - Ma ulac aɣilif sekcem uṭṭun ameɣtu n tkarḍa n usmad + Ma ulac aɣilif sekcem uṭṭun ameɣtu n tkarḍa n usmad - Sekcem uṭṭun n tkarḍa ameɣtu + Sekcem uṭṭun n tkarḍa ameɣtu - Ttxil-k·m ččar urti-a + Ttxil-k·m ččar urti-a - Rnu isem + Rnu isem Kkes asekkeṛ i wakken ad twaliḍ tikerḍiwin-ik·im yettwaskelsen - Seɣles tikerḍiwin-ik·im n usmad + Seɣles tikerḍiwin-ik·im n usmad - Sbadu taneɣruft n usekkeṛ n yibenk, tangalt PIN neq awal uffir i ummesten n tkerḍiwin-ik·im n usmad yettwaskelsen ticki yella win ikecmen ɣer yibenk-inek·inem. + Sbadu taneɣruft n usekkeṛ n yibenk, tangalt PIN neq awal uffir i ummesten n tkerḍiwin-ik·im n usmad yettwaskelsen ticki yella win ikecmen ɣer yibenk-inek·inem. Sbadu tura @@ -1876,7 +1880,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Serreḥ i ibenk-inek·inem - Kkes asekkeṛ i wakken ad tesqedceḍ talɣut n tkarḍa n usmad + Kkes asekkeṛ i wakken ad tesqedceḍ talɣut n tkarḍa n usmad Rnu tansa @@ -1885,11 +1889,13 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Sefrek tansiwin - Aɣara + Aɣara - Isem alemmas + Isem alemmas - Isem + Isem + + Isem Tansa n taddart @@ -1914,9 +1920,9 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Kkes tansa - D tidet tebɣiḍ ad tekkseḍ tansa-a? + D tidet tebɣiḍ ad tekkseḍ tansa-a? - Kkes tansa-a? + Kkes tansa-a? Kkes @@ -2016,41 +2022,41 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Ẓreg - Tebɣiḍ ad tekseḍ anekcum-agi? + Tebɣiḍ ad tekseḍ anekcum-agi? Kkes Sefsex - Iɣewwaren n unekcum + Iɣewwaren n unekcum - Tixtiṛiyin n wawal uffir + Tixtiṛiyin n wawal uffir - Urti n uḍris yettusenfal i tansa n unekcum n web. + Urti n uḍris yettusenfal i tansa n unekcum n web. - Urti n uḍris yettusenfal i yisem n useqdac n unekcum. + Urti n uḍris yettusenfal i yisem n useqdac n unekcum. - Urti n uḍris yettusenfal i wawal uffir n unekcum. + Urti n uḍris yettusenfal i wawal uffir n unekcum. - Sekles isenfaln unekcum. + Sekles isenfaln unekcum. - Sekles isenfal. + Sekles isenfal. - Ẓreg + Ẓreg - Ẓreg awal uffir + Ẓreg awal uffir - Rnu anekcum amaynut + Rnu anekcum amaynut - Rnu awal uffir + Rnu awal uffir - Awal uffir yettusra + Awal uffir yettusra - Sekcem awal uffir + Sekcem awal uffir - Isem n useqdac yettwasra + Isem n useqdac yettwasra - Sekcem isem n useqdac + Sekcem isem n useqdac Asenneftaɣ yettwasra @@ -2165,7 +2171,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Sit i wugar n telqayt - Inig d asawen + Inig d asawen Mdel @@ -2205,8 +2211,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara D acu-tt tneflest n yilɣa-a? Aktazal yettwaseɣta - - Yir alɣu yettwakkes Tamuɣli s wazal-is seg yilɣa imaynuten @@ -2241,10 +2245,6 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Afaris ulac-it Mmel tuɣalin n ufaris deg tawsa - - Adenqed n tɣara n yilɣa - - Adenqed n tɣara n yilɣa Adenqed n tɣara n yilɣa (%s) @@ -2274,7 +2274,7 @@ Tiktiwin tigejdanin yuzzlen ur nṣeḥḥi ara Issin ugar - Tasertit n tbaḍnit + Tasertit n tbaḍnit Tasertit n tbaḍnit diff --git a/app/src/main/res/values-kk/strings.xml b/app/src/main/res/values-kk/strings.xml index acd6830c3..66b6cedbc 100644 --- a/app/src/main/res/values-kk/strings.xml +++ b/app/src/main/res/values-kk/strings.xml @@ -251,6 +251,11 @@ Парақты аудару + + Бет %1$s тілінен %2$s тіліне аударылды. + Таңдалған тіл @@ -329,12 +334,22 @@ Firefox жекелік ескертуі - + + Біздің жекелік ескертуімізден көбірек біліңіз Біз сіздің қауіпсіздігіңізді қамтамасыз етуді жақсы көреміз + + Миллиондаған адам неге Firefox-ты жақсы көретінін біліңіз + + Қосымша таңдаулары бар қауіпсіз шолу Коммерциялық емес ұйымы қолдауымен жасалатын біздің браузер компанияларды интернетте сізді жасырын түрде бақылауын автоматты түрде тоқтатуға көмектеседі. + Коммерциялық емес ұйым қолдайтын браузерді таңдау арқылы 100 миллионнан астам адам өз жекелігін қорғайды. + + Белгілі трекерлер? Автоматты түрде бұғатталған. Кеңейтулер? Барлық 700 түрін қолданып көріңіз. PDF файлдары? Құрамындағы оқу қолданбасы оларды басқаруды жеңілдетеді. + Коммерциялық емес ұйымы қолдау көрсететін браузеріміз компаниялардың сізді интернетте жасырын бақылап отыруын тоқтатуға көмектеседі.\n\nЖекелік ескертуімізден толығырақ ақпарат алыңыз. @@ -690,9 +705,9 @@ Бетбелгілер - Логиндер + Логиндер - Парольдер + Парольдер Ашық беттер @@ -717,9 +732,9 @@ %1$s, %2$s %3$s - Несиелік карталар + Несиелік карталар - Төлем әдістері + Төлем әдістері Адрестер @@ -1659,13 +1674,13 @@ Бұл веб-сайтты жылдам қатынау және қолданба тектес режимде жылдам шолу мақсатымен құрылғыңыздың үй бетіңізге қосуға болады. - Логиндер және парольдер + Логиндер және парольдер - Парольдер + Парольдер - Логиндер және парольдерді сақтау + Логиндер және парольдерді сақтау - Парольдерді сақтау + Парольдерді сақтау Сақтау алдында сұрау @@ -1682,47 +1697,47 @@ Құрылғыңыздағы басқа қолданбаларда пайдаланушы аттары мен парольдерін толтыру. - Логинді қосу + Логинді қосу - Парольді қосу + Парольді қосу - - Логиндерді синхрондау - Парольдерді синхрондау + Логиндерді синхрондау + + Парольдерді синхрондау - Логиндерді құрылғылар арасында синхрондау + Логиндерді құрылғылар арасында синхрондау - Парольдерді құрылғылар арасында синхрондау + Парольдерді құрылғылар арасында синхрондау - Сақталған логиндер + Сақталған логиндер - Сақталған парольдер + Сақталған парольдер - Сіз %s ішінде сақтаған немесе синхрондаған логиндер осында көрсетіледі. + Сіз %s ішінде сақтаған немесе синхрондаған логиндер осында көрсетіледі. - Сіз %s ішіне сақтаған немесе синхрондаған парольдер осында тізіліп көрсетіледі. Сіз сақтаған барлық парольдер шифрленген. + Сіз %s ішіне сақтаған немесе синхрондаған парольдер осында тізіліп көрсетіледі. Сіз сақтаған барлық парольдер шифрленген. - Синхрондау туралы көбірек біліңіз. + Синхрондау туралы көбірек біліңіз. - Синхрондау туралы көбірек біліңіз + Синхрондау туралы көбірек біліңіз Ережеден бөлек - Сақталмаған логиндер мен парольдер осында көрсетіледі. + Сақталмаған логиндер мен парольдер осында көрсетіледі. - %s осы жерде тізімделген сайттар үшін парольдерді сақтамайтын болады. + %s осы жерде тізімделген сайттар үшін парольдерді сақтамайтын болады. - Бұл сайттар үшін логиндер мен парольдер сақталмайды. + Бұл сайттар үшін логиндер мен парольдер сақталмайды. - %s бұл сайттар үшін парольдерді сақтамайтын болады. + %s бұл сайттар үшін парольдерді сақтамайтын болады. Барлық ережеден тыс жағдайларды өшіру - Логиндерден іздеу + Логиндерден іздеу - Парольдерді іздеу + Парольдерді іздеу Сайт @@ -1750,17 +1765,17 @@ Парольді жасыру - Сақталған логиндеріңізді көру үшін бұғаттауын ашыңыз + Сақталған логиндеріңізді көру үшін бұғаттауын ашыңыз - Сақталған парольдеріңізді көру үшін бұғаттауын ашыңыз + Сақталған парольдеріңізді көру үшін бұғаттауын ашыңыз - Логиндер және парольдерді қорғаңыз + Логиндер және парольдерді қорғаңыз - Сақталған парольдерді қорғаңыз + Сақталған парольдерді қорғаңыз - Бөтен адам сіздің құрылғыңызда болса, одан сақталған логиндер мен парольдерді қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. + Бөтен адам сіздің құрылғыңызда болса, одан сақталған логиндер мен парольдерді қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. - Бөтен адам сіздің құрылғыңызда болса, одан сақталған парольдеріңізді қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. + Бөтен адам сіздің құрылғыңызда болса, одан сақталған парольдеріңізді қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. Кейінірек @@ -1777,7 +1792,10 @@ Соңғы қолданылған - Логиндерді сұрыптау мәзірі + Логиндерді сұрыптау мәзірі + + + Парольдерді сұрыптау мәзірі Парольдерді сұрыптау мәзірі @@ -1788,40 +1806,43 @@ Адрестер - Несиелік карталар + Несиелік карталар - Төлем әдістері + Төлем әдістері - Карталарды сақтау және автотолтыру + Карталарды сақтау және автотолтыру - Төлем әдістерін сақтау және толтыру + Төлем әдістерін сақтау және толтыру - Деректер шифрленген + Деректер шифрленген - %s сіз сақтаған барлық төлем әдістерін шифрлейді + %s сіз сақтаған барлық төлем әдістерін шифрлейді Карталарды құрылғылар арасында синхрондау Карталарды синхрондау - Несиелік картаны қосу + Несиелік картаны қосу - Картаны қосу + Картаны қосу - Сақталған карталарды басқару + Сақталған карталарды басқару - Карталарды басқару + Карталарды басқару Адресті қосу Адрестерді басқару - Адрестерді сақтау және автотолтыру + Адрестерді сақтау және автотолтыру - Адрестерді сақтау және толтыру + Адрестерді сақтау және толтыру - Нөмірлер, эл. пошта және жеткізу адрестері сияқты ақпаратты қосу + Нөмірлер, эл. пошта және жеткізу адрестері сияқты ақпаратты қосу + + + Телефон нөмірлері мен электрондық пошта адрестерін қамтиды Телефон нөмірлері мен электрондық пошта адрестерін қамтиды @@ -1845,9 +1866,9 @@ Картаны өшіру - Бұл несие картасын өшіруді шынымен қалайсыз ба? + Бұл несие картасын өшіруді шынымен қалайсыз ба? - Картаны өшіру керек пе? + Картаны өшіру керек пе? Өшіру @@ -1861,24 +1882,24 @@ Сақталған карталар - Несиелік картаның жарамды нөмірін енгізіңіз + Несиелік картаның жарамды нөмірін енгізіңіз - Жарамды карта нөмірін енгізіңіз + Жарамды карта нөмірін енгізіңіз - Бұл өрісті толтырыңыз + Бұл өрісті толтырыңыз - Атын қосыңыз + Атын қосыңыз Сақталған карталарыңызды көру үшін бұғаттауын ашыңыз - Несиелік карталарыңызды қорғаңыз + Несиелік карталарыңызды қорғаңыз - Сақталған төлем әдістерін қорғаңыз + Сақталған төлем әдістерін қорғаңыз - Бөтен адам сіздің құрылғыңызда болса, одан сақталған несиелік карталарды қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. + Бөтен адам сіздің құрылғыңызда болса, одан сақталған несиелік карталарды қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. - Бөтен адам сіздің құрылғыңызда болса, одан сақталған төлем әдістерін қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. + Бөтен адам сіздің құрылғыңызда болса, одан сақталған төлем әдістерін қорғау үшін құрылғының бұғаттау үлгісін, PIN-кодын немесе парольді орнатыңыз. Қазір баптау @@ -1887,10 +1908,10 @@ Құрылғының бұғаттауын ашыңыз - Сақталған несиелік карта ақпаратын қолдану үшін бұғаттауын ашыңыз + Сақталған несиелік карта ақпаратын қолдану үшін бұғаттауын ашыңыз - Сақталған төлем әдістерін қолдану үшін құлыптан босатыңыз + Сақталған төлем әдістерін қолдану үшін құлыптан босатыңыз Адресті қосу @@ -1898,11 +1919,13 @@ Адрестерді басқару - Аты + Аты - Әкесінің аты + Әкесінің аты - Тегi + Тегi + + Аты Көше адресі @@ -1928,9 +1951,9 @@ Адресті өшіру - Бұл адресті өшіруді шынымен қалайсыз ба? + Бұл адресті өшіруді шынымен қалайсыз ба? - Бұл адресті өшіру керек пе? + Бұл адресті өшіру керек пе? Өшіру @@ -2027,50 +2050,50 @@ Түзету - Бұл логинді өшіруді қалайсыз ба? + Бұл логинді өшіруді қалайсыз ба? - Бұл парольді өшіруді шынымен қалайсыз ба? + Бұл парольді өшіруді шынымен қалайсыз ба? Өшіру Бас тарту - Логин баптаулары + Логин баптаулары - Пароль опциялары + Пароль опциялары - Логиннің веб-адресі үшін түзетуге болатын мәтіндік өрісі. + Логиннің веб-адресі үшін түзетуге болатын мәтіндік өрісі. - Веб-сайт адресі үшін түзетуге болатын мәтіндік өрісі. + Веб-сайт адресі үшін түзетуге болатын мәтіндік өрісі. - Логиннің пайдаланушы аты үшін түзетуге болатын мәтіндік өрісі. + Логиннің пайдаланушы аты үшін түзетуге болатын мәтіндік өрісі. - Пайдаланушы аты үшін түзетуге болатын мәтіндік өрісі. + Пайдаланушы аты үшін түзетуге болатын мәтіндік өрісі. - Логиннің паролі үшін түзетуге болатын мәтіндік өрісі. + Логиннің паролі үшін түзетуге болатын мәтіндік өрісі. - Пароль үшін түзетуге болатын мәтіндік өрісі. + Пароль үшін түзетуге болатын мәтіндік өрісі. - Логин өзгерістерін сақтау. + Логин өзгерістерін сақтау. - Өзгерістерді сақтау. + Өзгерістерді сақтау. - Түзету + Түзету - Парольді түзету + Парольді түзету - Жаңа логинді қосу + Жаңа логинді қосу - Парольді қосу + Парольді қосу - Пароль керек + Пароль керек - Парольді енгізіңіз + Парольді енгізіңіз - Пайдаланушы аты керек + Пайдаланушы аты керек - Пайдаланушы атын енгізіңіз + Пайдаланушы атын енгізіңіз Хост атауы керек @@ -2182,7 +2205,7 @@ Көбірек білу үшін шертіңіз - Жоғары жылжу + Жоғары жылжу Жабу @@ -2223,8 +2246,6 @@ Түзетілген рейтинг - Сенімсіз пікірлер өшірілді - Сенімді пікірлерге негізделген Соңғы пікірлердің маңызды сәттері @@ -2280,10 +2301,6 @@ Бұл өнімнің қоймаға қайта оралғанын көрсеңіз, оны бізге хабарлаңыз, біз пікірлерді тексереміз. Өнімнің қоймада бар болғанын хабарлау - - Пікір сапасын тексеру - - Пікір сапасын тексеру Пікір сапасын тексеру (%s) @@ -2329,13 +2346,19 @@ Көбірек білу - "Иә, қолданып көру" опциясын таңдау арқылы сіз Mozilla ұсынған %1$s қолданбасының %2$s және %3$s шарттарымен келісесіз. + "Иә, қолданып көру" опциясын таңдау арқылы сіз Mozilla ұсынған %1$s қолданбасының %2$s және %3$s шарттарымен келісесіз. "Иә, қолданып көру" опциясын таңдау арқылы сіз %1$s ұсынған келесімен келісесіз: + + "Иә, қолданып көру" таңдау арқылы сіз %1$s %2$s және %3$s %4$s шарттарымен келісесіз. + + "Иә, қолданып көру" таңдау арқылы сіз %1$s %2$s және %3$s %4$s шарттарымен келісесіз. - жекелік саясаты + жекелік саясаты Жекелік саясаты + + жекелік ескертуі қолдану шарттары @@ -2408,6 +2431,10 @@ Бұл парақты аудару керек пе? + + Бет %1$s тілінен %2$s тіліне аударылды %1$s ішіндегі жекелік аудармаларды қолданып көріңіз @@ -2421,6 +2448,8 @@ Мақсат тілі: Қазір емес + + Түпнұсқаны көрсету Дайын @@ -2443,6 +2472,16 @@ Көбірек білу + + Аударуда… + + + Деректерді үнемдеу режимінде (%1$s) тілді жүктеп алу керек пе? + + Аударма баптаулары diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 50dff711f..8daef6708 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -261,6 +261,11 @@ 페이지 번역 + + 페이지가 %1$s에서 %2$s로 번역되었습니다. + 선택된 언어 @@ -339,12 +344,22 @@ Firefox 개인정보처리방침 - + + 개인정보 보호정책에서 자세히 알아보기 우리는 사용자를 안전하게 지키는 것을 좋아합니다 + + 수백만 명이 Firefox를 좋아하는 이유를 알아보세요 + + 더 많은 선택으로 안전한 브라우징 당사의 비영리 지원 브라우저는 회사가 웹에서 비밀리에 사용자를 추적하는 것을 방지하는 데 도움이 됩니다. + 1억 명 이상의 사람들이 비영리 단체가 지원하는 브라우저를 선택하여 개인 정보를 보호합니다. + + 알려진 추적기? 자동으로 차단됩니다. 확장기능? 700개 모두 사용해 보세요. PDF? 내장된 리더를 사용하면 쉽게 관리할 수 있습니다. + 당사의 비영리 지원 브라우저는 회사가 웹에서 비밀리에 사용자를 추적하는 것을 방지하는 데 도움이 됩니다.\n\n개인정보처리방침에서 더 알아보세요. @@ -703,9 +718,9 @@ 북마크 - 로그인 + 로그인 - 비밀번호 + 비밀번호 열린 탭 @@ -731,9 +746,9 @@ %2$s %3$s의 %1$s - 신용 카드 + 신용 카드 - 결제 방법 + 결제 방법 주소 @@ -1710,13 +1725,13 @@ 이 웹 사이트를 기기의 홈 화면에 쉽게 추가하여 앱과 같은 경험을 통해 즉시 액세스하고 더 빠르게 탐색 할 수 있습니다. - 로그인과 비밀번호 + 로그인과 비밀번호 - 비밀번호 + 비밀번호 - 로그인과 비밀번호 저장 + 로그인과 비밀번호 저장 - 비밀번호 저장 + 비밀번호 저장 저장할지 묻기 @@ -1732,47 +1747,47 @@ 기기의 다른 앱에서 사용자 이름과 비밀번호를 채웁니다. - 로그인 추가 + 로그인 추가 - 비밀번호 추가 + 비밀번호 추가 - - Sync 로그인 - 비밀번호 동기화 + Sync 로그인 + + 비밀번호 동기화 - 기기 간에 로그인 동기화 + 기기 간에 로그인 동기화 - 기기 간에 비밀번호 동기화 + 기기 간에 비밀번호 동기화 - 저장된 로그인 + 저장된 로그인 - 저장된 비밀번호 + 저장된 비밀번호 - %s에 저장하거나 동기화한 로그인이 여기에 표시됩니다. + %s에 저장하거나 동기화한 로그인이 여기에 표시됩니다. - %s에 저장하거나 동기화한 비밀번호는 여기에 나열됩니다. 저장한 모든 비밀번호는 암호화됩니다. + %s에 저장하거나 동기화한 비밀번호는 여기에 나열됩니다. 저장한 모든 비밀번호는 암호화됩니다. - Sync에 대해 더 알아보기. + Sync에 대해 더 알아보기. - 동기화에 대해 더 알아보기 + 동기화에 대해 더 알아보기 예외 목록 - 저장되지 않은 로그인과 비밀번호가 여기에 표시됩니다. + 저장되지 않은 로그인과 비밀번호가 여기에 표시됩니다. - %s는 여기에 나열된 사이트의 비밀번호를 저장하지 않습니다. + %s는 여기에 나열된 사이트의 비밀번호를 저장하지 않습니다. - 이 사이트에 대한 로그인과 비밀번호는 저장되지 않습니다. + 이 사이트에 대한 로그인과 비밀번호는 저장되지 않습니다. - %s는 이 사이트의 비밀번호를 저장하지 않습니다. + %s는 이 사이트의 비밀번호를 저장하지 않습니다. 모든 예외 삭제 - 로그인 검색 + 로그인 검색 - 비밀번호 검색 + 비밀번호 검색 사이트 @@ -1800,17 +1815,17 @@ 비밀번호 숨기기 - 저장된 로그인을 보려면 잠금 해제하세요 + 저장된 로그인을 보려면 잠금 해제하세요 - 저장된 비밀번호를 보려면 잠금 해제하세요 + 저장된 비밀번호를 보려면 잠금 해제하세요 - 로그인과 비밀번호 보안 + 로그인과 비밀번호 보안 - 저장된 비밀번호를 보호하세요 + 저장된 비밀번호를 보호하세요 - 다른 사람이 내 기기를 가지고 있는 경우, 저장된 로그인과 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 로그인과 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. - 다른 사람이 내 기기를 가지고 있는 경우, 저장된 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 비밀번호에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. 나중에 @@ -1828,7 +1843,10 @@ 마지막 사용 - 로그인 정렬 메뉴 + 로그인 정렬 메뉴 + + + 비밀번호 정렬 메뉴 비밀번호 정렬 메뉴 @@ -1839,41 +1857,44 @@ 주소 - 신용 카드 + 신용 카드 - 결제 방법 + 결제 방법 - 카드 저장 및 자동 채우기 + 카드 저장 및 자동 채우기 - 결제 방법 저장 및 채우기 + 결제 방법 저장 및 채우기 - 데이터가 암호화됨 + 데이터가 암호화됨 - %s는 저장한 모든 결제 방법을 암호화합니다 + %s는 저장한 모든 결제 방법을 암호화합니다 기기 간에 카드 동기화 카드 동기화 - 신용 카드 추가 + 신용 카드 추가 - 카드 추가 + 카드 추가 - 저장된 카드 관리 + 저장된 카드 관리 - 카드 관리 + 카드 관리 주소 추가 주소 관리 - 주소 저장 및 자동 채우기 + 주소 저장 및 자동 채우기 - 주소 저장 및 채우기 + 주소 저장 및 채우기 - 숫자, 이메일 및 배송 주소와 같은 정보 포함 + 숫자, 이메일 및 배송 주소와 같은 정보 포함 + + + 전화번호와 이메일 주소가 포함됩니다 전화번호와 이메일 주소가 포함됩니다 @@ -1898,9 +1919,9 @@ 카드 삭제 - 이 신용 카드를 삭제하시겠습니까? + 이 신용 카드를 삭제하시겠습니까? - 카드를 삭제하시겠습니까? + 카드를 삭제하시겠습니까? 삭제 @@ -1914,24 +1935,24 @@ 저장된 카드 - 유효한 신용 카드 번호를 입력해 주세요 + 유효한 신용 카드 번호를 입력해 주세요 - 유효한 카드 번호를 입력하세요 + 유효한 카드 번호를 입력하세요 - 이 항목을 입력하세요. + 이 항목을 입력하세요. - 이름 추가 + 이름 추가 저장된 카드를 보려면 잠금 해제하세요 - 신용 카드 보안 + 신용 카드 보안 - 저장된 결제 방법을 보호하세요 + 저장된 결제 방법을 보호하세요 - 다른 사람이 내 기기를 가지고 있는 경우, 저장된 신용 카드에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 신용 카드에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. - 다른 사람이 내 기기를 가지고 있는 경우, 저장된 결제 방법에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. + 다른 사람이 내 기기를 가지고 있는 경우, 저장된 결제 방법에 접근하지 못하도록 기기 잠금 패턴, PIN 또는 비밀번호를 설정하세요. 지금 설정 @@ -1940,10 +1961,10 @@ 기기 잠금 해제 - 저장된 신용 카드 정보를 사용하려면 잠금 해제하세요 + 저장된 신용 카드 정보를 사용하려면 잠금 해제하세요 - 저장된 결제 방법을 사용하려면 잠금 해제하세요 + 저장된 결제 방법을 사용하려면 잠금 해제하세요 주소 추가 @@ -1951,11 +1972,13 @@ 주소 관리 - 이름 + 이름 - 중간 이름 + 중간 이름 - + + + 이름 도로 주소 @@ -1980,9 +2003,9 @@ 주소 삭제 - 이 주소를 삭제하시겠습니까? + 이 주소를 삭제하시겠습니까? - 이 주소를 삭제하시겠습니까? + 이 주소를 삭제하시겠습니까? 삭제 @@ -2081,49 +2104,49 @@ 편집 - 이 로그인을 삭제하시겠습니까? + 이 로그인을 삭제하시겠습니까? - 이 비밀번호를 삭제하시겠습니까? + 이 비밀번호를 삭제하시겠습니까? 삭제 취소 - 로그인 옵션 + 로그인 옵션 - 비밀번호 옵션 + 비밀번호 옵션 - 로그인 웹 주소의 편집 가능한 텍스트 필드입니다. + 로그인 웹 주소의 편집 가능한 텍스트 필드입니다. - 웹 사이트 주소에 대한 편집 가능한 텍스트 필드입니다. + 웹 사이트 주소에 대한 편집 가능한 텍스트 필드입니다. - 로그인 사용자 이름의 편집 가능한 텍스트 필드입니다. + 로그인 사용자 이름의 편집 가능한 텍스트 필드입니다. - 사용자 이름에 대한 편집 가능한 텍스트 필드입니다. + 사용자 이름에 대한 편집 가능한 텍스트 필드입니다. - 로그인 비밀번호의 편집 가능한 텍스트 필드입니다. + 로그인 비밀번호의 편집 가능한 텍스트 필드입니다. - 비밀번호에 대한 편집 가능한 텍스트 필드입니다. + 비밀번호에 대한 편집 가능한 텍스트 필드입니다. - 변경 내용을 로그인에 저장. + 변경 내용을 로그인에 저장. - 변경 내용 저장. + 변경 내용 저장. - 편집 + 편집 - 비밀번호 수정 + 비밀번호 수정 - 새 로그인 추가 + 새 로그인 추가 - 비밀번호 추가 + 비밀번호 추가 - 비밀번호 필요 + 비밀번호 필요 - 비밀번호 입력 + 비밀번호 입력 - 사용자 이름은 필수입니다 + 사용자 이름은 필수입니다 - 사용자 이름 입력 + 사용자 이름 입력 호스트 이름은 필수입니다 @@ -2237,7 +2260,7 @@ 상세 정보 - 위로 이동 + 위로 이동 닫기 @@ -2278,8 +2301,6 @@ 조정된 평점 - 신뢰할 수 없는 리뷰는 삭제됨 - 신뢰할 수 있는 리뷰에 바탕 최근 리뷰의 하이라이트 @@ -2335,10 +2356,6 @@ 이 제품이 재입고된 것을 확인하시면, 보고해 주시면 리뷰를 확인하도록 하겠습니다. 제품 재고가 있다고 보고 - - 리뷰 품질 확인 중 - - 리뷰 품질 확인 중 리뷰 품질 확인 중 (%s) @@ -2384,13 +2401,19 @@ 더 알아보기 - "사용해보기"를 선택하면 Mozilla %2$s 및 %3$s의 %1$s에 동의하게 됩니다. + "사용해보기"를 선택하면 Mozilla %2$s 및 %3$s의 %1$s에 동의하게 됩니다. "사용해보기"를 선택하면 %1$s의 다음 사항에 동의하게 됩니다: + + “사용해보기”를 선택하면 %1$s의 %2$s와 %3$s의 %4$s에 동의하게 됩니다. + + “사용해보기”를 선택하면 %1$s의 %2$s와 %3$s의 %4$s에 동의하게 됩니다. - 개인정보처리방침 + 개인정보처리방침 개인정보처리방침 + + 개인 정보 보호 정책 사용 약관 @@ -2462,6 +2485,10 @@ 이 페이지를 번역할까요? + + 페이지가 %1$s에서 %2$s로 번역되었습니다. %1$s에서 개인 정보가 보호되는 번역을 사용해 보세요 @@ -2474,6 +2501,8 @@ 대상 언어: 나중에 + + 원본 보기 완료 @@ -2496,6 +2525,16 @@ 더 알아보기 + + 번역 중… + + + 데이터 절약 모드에서 언어를 다운로드하시겠습니까 (%1$s)? + + 번역 옵션 @@ -2619,7 +2658,7 @@ This dialog will be presented when the user attempts to download a language or perform a translation without the necessary language files downloaded first when Android's data saver mode is enabled and the user is not using WiFi. The first parameter is the size in kilobytes or megabytes of the language file.--> - 데이터 절약 모드(%1$s)에 있는 동안 다운로드하시겠습니까? + 데이터 절약 모드에 있는 동안 다운로드하시겠습니까 (%1$s)? 개인 정보 보호를 위해 언어 일부분을 캐시에 다운로드합니다. diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 86347ea1a..8e63ab505 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -254,6 +254,11 @@ Oversett siden + + Siden er oversatt fra %1$s til %2$s. + Valgt språk @@ -332,12 +337,22 @@ Firefox personvernerklæring - + + Les mer i vår personvernerklæring Vi beskytter deg gjerne + + Finn ut hvorfor millioner elsker Firefox + + Sikker surfing med flere valg Vår ideelle nettleser forhindrer selskaper i å spore aktiviteten din i hemmelighet på nettet. + Mer enn 100 millioner mennesker beskytter personvernet sitt ved å velge en nettleser som er støttet av en ideell organisasjon. + + Kjente sporere? Blokkert automatisk. Utvidelser? Prøv alle 700. PDF-filer? Vår innebygde leser gjør dem enkle å administrere. + Vår ideelle nettleser forhindrer selskaper i å spore aktiviteten din i hemmelighet på nettet.\n\nLes mer i personvernerklæringen vår. @@ -691,9 +706,9 @@ Bokmerker - Innlogginger + Innlogginger - Passord + Passord Åpne faner @@ -719,9 +734,9 @@ %1$s på %2$s %3$s - Betalingskort + Betalingskort - Betalingsmetoder + Betalingsmåter Adresser @@ -1668,13 +1683,13 @@ Du kan enkelt legge til dette nettstedet på enhetens startskjerm for å få øyeblikkelig tilgang og surfe raskere med en app-lignende opplevelse. - Innlogginger og passord + Innlogginger og passord - Passord + Passord - Lagre innlogginger og passord + Lagre innlogginger og passord - Lagre passord + Lagre passord Spør om å lagre @@ -1690,48 +1705,48 @@ Fyll inn brukernavn og passord i andre apper på enheten din. - Legg til innlogging + Legg til innlogging - Legg til passord + Legg til passord - - Synkroniser innlogginger - Synkroniser passord + Synkroniser innlogginger + + Synkroniser passord - Synkroniser innlogginger på tvers av enheter + Synkroniser innlogginger på tvers av enheter - Synkroniser passord på tvers av enheter + Synkroniser passord på tvers av enheter - Lagrede innlogginger + Lagrede innlogginger - Lagrede passord + Lagrede passord - De innlogginger du lagrer eller synkroniserer til %s vil vises her. + De innlogginger du lagrer eller synkroniserer til %s vil vises her. - Passordene du lagrer eller synkroniserer med %s vil bli oppført her. Alle passord du lagrer er kryptert. + Passordene du lagrer eller synkroniserer med %s vil bli oppført her. Alle passord du lagrer er kryptert. - Les mer om Sync. + Les mer om Sync. - Les mer om synkronisering + Les mer om synkronisering Unntak - Innlogginger og passord som ikke er lagret vil vises her. + Innlogginger og passord som ikke er lagret vil vises her. - %s vil ikke lagre passord for nettsteder som er oppført her. + %s vil ikke lagre passord for nettsteder som er oppført her. - Innlogginger og passord vil ikke bli lagret for disse nettstedene. + Innlogginger og passord vil ikke bli lagret for disse nettstedene. - %s vil ikke lagre passord for disse nettstedene. + %s vil ikke lagre passord for disse nettstedene. Slett alle unntak - Søk innlogginger + Søk innlogginger - Søk etter passord + Søk etter passord Nettsted @@ -1760,15 +1775,17 @@ Skjul passord - Lås opp for å se dine lagrede innlogginger + Lås opp for å se dine lagrede innlogginger - Lås opp for å se dine lagrede passord + Lås opp for å se dine lagrede passord - Sikre dine innlogginger og passord + Sikre dine innlogginger og passord - Sikre dine lagrede passord + Sikre dine lagrede passord + + Konfigurer en PIN-kode, et passord eller et låsemønster for å forhindre at andre mennesker får tilgang de lagrede innloggingene og passordene dine, hvis de har adgang til din enhet. - Konfigurer en PIN-kode, et passord eller et låsemønster for å forhindre at andre mennesker får tilgang de lagrede innloggingene og passordene dine, hvis de har adgang til din enhet. + Konfigurer en PIN-kode, et passord eller et låsemønster for å beskytte dine lagrede passord om noen andre skulle få tak i enheten din. Senere @@ -1788,7 +1805,10 @@ Sist brukt - Sorter innlogginger-meny + Sorter innlogginger-meny + + + Sorter passord-menyen @@ -1796,28 +1816,43 @@ Adresser - Betalingskort + Betalingskort + + Betalingsmåter + + Lagre og fyll ut kort automatisk - Lagre og fyll ut kort automatisk + Lagre og fyll inn betalingsmåter - Data er kryptert + Data er kryptert + + %s krypterer alle betalingsmåter du lagrer Synkroniser kort på tvers av enheter Synkroniser kort - Legg til betalingskort + Legg til betalingskort + + Legg til kort - Behandle lagrede kort + Behandle lagrede kort + + Behandle kort Legg til adresse Behandle adresser - Lagre og autoutfyll adresser + Lagre og autoutfyll adresser + + Lagre og fyll ut adresser - Inkluderer informasjon som telefonnummer, e-post og leveringsadresser + Inkluderer informasjon som telefonnummer, e-post og leveringsadresser + + + Inkluderer telefonnumre og e-postadresser Legg til kort @@ -1838,7 +1873,9 @@ Slett kort - Er du sikker på at du vil slette dette bankkortet? + Er du sikker på at du vil slette dette bankkortet? + + Slett kort? Slett @@ -1851,16 +1888,24 @@ Lagrede kort - Oppgi et gyldig betalingskortnummer + Oppgi et gyldig betalingskortnummer + + Skriv inn et gyldig kortnummer - Fyll ut dette feltet + Fyll ut dette feltet + + Legg til et navn Lås opp for å se dine lagrede betalingskort - Sikre dine betalingskort + Sikre dine betalingskort + + Sikre dine lagrede betalingsmåter - Konfigurer en PIN-kode, et passord eller et låsemønster for å beskytte de lagrede betalingskortene dine om noen andre skulle få tak i enheten din. + Konfigurer en PIN-kode, et passord eller et låsemønster for å beskytte de lagrede betalingskortene dine om noen andre skulle få tak i enheten din. + + Konfigurer en PIN-kode, et passord eller et låsemønster for å beskytte dine lagrede betalingsmåter om noen andre skulle få tak i enheten din. Konfigurer nå @@ -1869,8 +1914,10 @@ Lås opp enheten din - Lås opp for å bruke lagret betalingskortinformasjon + Lås opp for å bruke lagret betalingskortinformasjon + + Lås opp for å bruke lagrede betalingsmåter Legg til adresse @@ -1878,11 +1925,13 @@ Behandle adresser - Fornavn + Fornavn - Mellomnavn + Mellomnavn - Etternavn + Etternavn + + Navn Gateadresse @@ -1907,7 +1956,9 @@ Slett adresse - Er du sikker på at du vil slette denne adressen? + Er du sikker på at du vil slette denne adressen? + + Slette denne adressen? Slett @@ -2007,31 +2058,53 @@ Rediger - Er du sikker på at du ønsker å slette denne innloggingen? + Er du sikker på at du ønsker å slette denne innloggingen? + + Er du sikker på at du ønsker å slette dette passordet? Slett Avbryt - Innloggingsalternativer + Innloggingsalternativer + + Passordalternativer - Det redigerbare tekstfeltet for innloggingens nettadresse. + Det redigerbare tekstfeltet for innloggingens nettadresse. + + Det redigerbare tekstfeltet for nettstedsadressen. - Det redigerbare tekstfeltet for innloggingens brukernavn. + Det redigerbare tekstfeltet for innloggingens brukernavn. + + Det redigerbare tekstfeltet for brukernavnet. + + Det redigerbare tekstfeltet for innloggingens passord. - Det redigerbare tekstfeltet for innloggingens passord. + Det redigerbare tekstfeltet for passordet. - Lagre endringer for innlogging. + Lagre endringer for innlogging. + + Lagre endringer. - Rediger + Rediger + + Rediger passord - Legg til ny innlogging + Legg til ny innlogging + + Legg til passord - Passord kreves + Passord kreves + + Skriv inn et passord - Brukernavn påkrevd + Brukernavn påkrevd + + Skriv inn et brukernavn Servernavn påkrevd + + Skriv inn en nettadresse Stemmesøk @@ -2126,6 +2199,9 @@ %s-søk + + + Endre standard nettleser Angi at lenker fra nettsteder, e-postmeldinger og meldinger skal åpnes automatisk i Firefox. @@ -2136,7 +2212,7 @@ Trykk her for mer informasjon - Naviger opp + Naviger opp Lukk @@ -2177,8 +2253,6 @@ Justert vurdering - Upålitelige vuderinger er fjernet - Basert på pålitelige vurderinger Høydepunkter fra nylige vurderinger @@ -2234,10 +2308,6 @@ Hvis du ser at dette produktet er tilbake på lager, rapporter det og vi vil jobbe med å sjekke vurderingene. Rapporter at produktet er på lager - - Kontrollerer kvaliteten på vurderingen - - Kontrollerer kvaliteten på vurderingen Kontrollerer kvaliteten på vurderingen (%s) @@ -2283,13 +2353,19 @@ Les mer - Ved å velge «Ja, prøv det» godtar du %1$s fra Mozilla sine %2$s og %3$s. + Ved å velge «Ja, prøv det» godtar du %1$s fra Mozilla sine %2$s og %3$s. Ved å velge «Ja, prøv det» godtar du følgende fra %1$s: + + Ved å velge «Ja, prøv det» godtar du %1$s sine %2$s og %3$s sine %4$s. + + Ved å velge «Ja, prøv det» godtar du %1$s sine %2$s og %3$s sine %4$s. - personvernbestemmelser + personvernbestemmelser Personvernbestemmelser + + personvernerklæring vilkår for bruk @@ -2352,8 +2428,102 @@ %s, Overskrift + + Lenker + + Lenker tilgjengelig + + + + Oversett denne siden? + + Siden er oversatt fra %1$s til %2$s + + Prøv private oversettelser i %1$s + + Av hensyn til personvernet ditt forlater aldri oversettelser enheten din. Nye språk og forbedringer kommer snart! %1$s + + Les mer + + Oversett fra + + Oversett til + + Ikke nå + + Vis original + + Ferdig + + Oversett + + Prøv igjen + + Oversetter + + Oversettelse pågår + + Velg et språk + + Det oppstod et problem med å oversette. Prøv på nytt. + + Kunne ikke laste inn språk. Sjekk Internett-tilkoblingen din og prøv igjen. + + Beklager, vi støtter ikke %1$s ennå. + + Les mer + + + Oversetter… + + + Last ned språk i datasparingsmodus (%1$s)? + + + + + Oversettelsesinnstillinger + + Tilby alltid å oversette + + Oversett alltid %1$s + + Oversett aldri %1$s + + Oversett aldri dette nettstedet + + Overstyrer alle andre innstillinger + + Overstyrer tilbud om å oversette + + Oversettelsesinnstillinger + + Om oversettelser i %1$s + + + + Oversettelser + + Tilby å oversette når det er mulig + + + Last alltid ned språk i datasparingsmodus + + Innstillinger for oversetting + + Automatisk oversettelse + + Oversett aldri disse nettstedene + + Last ned språk + Automatisk oversettelse @@ -2402,6 +2572,10 @@ Tilgjengelige språk nødvendig + + %1$s (%2$s) Last ned språk @@ -2415,4 +2589,64 @@ Valgt - + + Slette %1$s (%2$s)? + + Hvis du sletter dette språket, vil %1$s laste ned deler av språk til hurtigbufferen din mens du oversetter. + + Slette alle språk (%1$s)? + + Hvis du sletter alle språk, vil %1$s laste ned deler av språk til hurtigbufferen din mens du oversetter. + + Slett + + Avbryt + + + Laste ned mens du er i datasparingsmodus (%1$s)? + + Vi laster ned delvise språk til hurtigbufferen din for å holde oversettelser private. + + Last alltid ned i datasparingsmodus + + Last ned + + Last ned og oversett + + Avbryt + + + + Feilsøkingsverktøy + + Naviger tilbake + + Faneverktøy + + Antall faner + + Aktiv + + Inaktiv + + Privat + + Totalt + + Verktøy for å lage faner + + Antall faner som skal opprettes + + Legg til aktive faner + + Legg til inaktive faner + + Legg til private faner + diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 055898750..c2ce6165a 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -260,6 +260,11 @@ Pagina vertalen + + Pagina vertaald van het %1$s naar het %2$s. + Geselecteerde taal @@ -338,12 +343,22 @@ Firefox-privacyverklaring - + + Lees meer in onze privacyverklaring We houden u graag veilig + + Ontdek waarom miljoenen zo gek zijn op Firefox + + Veilig surfen met meer keuzes Onze door een non-profitorganisatie gesteunde browser helpt voorkomen dat bedrijven u stiekem volgen op internet. + Meer dan 100 miljoen mensen beschermen hun privacy door een browser te kiezen die wordt ondersteund door een non-profitorganisatie. + + Bekende trackers? Automatisch geblokkeerd. Extensies? Probeer ze alle 700. PDF’s? Door onze ingebouwde lezer zijn ze eenvoudig te beheren. + Onze door een non-profitorganisatie ondersteunde browser helpt voorkomen dat bedrijven u stiekem volgen op internet.\n\nMeer info in onze privacyverklaring. @@ -699,9 +714,9 @@ Bladwijzers - Aanmeldingen + Aanmeldingen - Wachtwoorden + Wachtwoorden Open tabbladen @@ -727,9 +742,9 @@ %1$s op %2$s %3$s - Creditcards + Creditcards - Betalingsmethoden + Betalingsmethoden Adressen @@ -1675,13 +1690,13 @@ U kunt deze website eenvoudig aan het startscherm van uw apparaat toevoegen, om zo direct toegang te hebben en sneller te navigeren met een app-achtige ervaring. - Aanmeldingen en wachtwoorden + Aanmeldingen en wachtwoorden - Wachtwoorden + Wachtwoorden - Aanmeldingen en wachtwoorden opslaan + Aanmeldingen en wachtwoorden opslaan - Wachtwoorden opslaan + Wachtwoorden opslaan Vragen om op te slaan @@ -1696,47 +1711,47 @@ Gebruikersnamen en wachtwoorden in andere apps op uw apparaat invullen. - Aanmelding toevoegen + Aanmelding toevoegen - Wachtwoord toevoegen + Wachtwoord toevoegen - - Aanmeldingen synchroniseren - Wachtwoorden synchroniseren + Aanmeldingen synchroniseren + + Wachtwoorden synchroniseren - Aanmeldingen op apparaten synchroniseren + Aanmeldingen op apparaten synchroniseren - Wachtwoorden synchroniseren tussen apparaten + Wachtwoorden synchroniseren tussen apparaten - Opgeslagen aanmeldingen + Opgeslagen aanmeldingen - Opgeslagen wachtwoorden + Opgeslagen wachtwoorden - De aanmeldingen die u opslaat of synchroniseert met %s worden hier getoond. + De aanmeldingen die u opslaat of synchroniseert met %s worden hier getoond. - De wachtwoorden die u opslaat of synchroniseert met %s zullen hier worden vermeld. Alle wachtwoorden die u opslaat, zijn versleuteld. + De wachtwoorden die u opslaat of synchroniseert met %s zullen hier worden vermeld. Alle wachtwoorden die u opslaat, zijn versleuteld. - Meer info over Sync. + Meer info over Sync. - Meer info over synchronisatie + Meer info over synchronisatie Uitzonderingen - Niet-opgeslagen aanmeldingen en wachtwoorden worden hier weergegeven. + Niet-opgeslagen aanmeldingen en wachtwoorden worden hier weergegeven. - %s zal geen wachtwoorden voor de hier vermelde websites opslaan. + %s zal geen wachtwoorden voor de hier vermelde websites opslaan. - Aanmeldingen en wachtwoorden worden voor deze websites niet opgeslagen. + Aanmeldingen en wachtwoorden worden voor deze websites niet opgeslagen. - %s zal geen wachtwoorden voor deze websites opslaan. + %s zal geen wachtwoorden voor deze websites opslaan. Alle uitzonderingen verwijderen - Aanmeldingen zoeken + Aanmeldingen zoeken - Wachtwoorden zoeken + Wachtwoorden zoeken Website @@ -1764,17 +1779,17 @@ Wachtwoord verbergen - Ontgrendel om uw opgeslagen aanmeldingen te bekijken + Ontgrendel om uw opgeslagen aanmeldingen te bekijken - Ontgrendel om uw opgeslagen wachtwoorden te bekijken + Ontgrendel om uw opgeslagen wachtwoorden te bekijken - Beveilig uw aanmeldingen en wachtwoorden + Beveilig uw aanmeldingen en wachtwoorden - Beveilig uw opgeslagen wachtwoorden + Beveilig uw opgeslagen wachtwoorden - Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen aanmeldingen en wachtwoorden te beschermen tegen toegang als iemand anders uw apparaat heeft. + Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen aanmeldingen en wachtwoorden te beschermen tegen toegang als iemand anders uw apparaat heeft. - Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen wachtwoorden te beschermen tegen toegang als iemand anders uw apparaat heeft. + Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen wachtwoorden te beschermen tegen toegang als iemand anders uw apparaat heeft. Later @@ -1791,7 +1806,10 @@ Laatst gebruikt - Menu Aanmeldingen sorteren + Menu Aanmeldingen sorteren + + + Wachtwoordmenu sorteren Wachtwoordmenu sorteren @@ -1802,40 +1820,43 @@ Adressen - Creditcards + Creditcards - Betalingsmethoden + Betalingsmethoden - Kaarten opslaan en automatisch invullen + Kaarten opslaan en automatisch invullen - Betalingsmethoden opslaan en invullen + Betalingsmethoden opslaan en invullen - Gegevens zijn versleuteld + Gegevens zijn versleuteld - %s versleutelt alle betalingsmethoden die u opslaat + %s versleutelt alle betalingsmethoden die u opslaat Kaarten synchroniseren tussen apparaten Kaarten synchroniseren - Creditcard toevoegen + Creditcard toevoegen - Kaart toevoegen + Kaart toevoegen - Opgeslagen kaarten beheren + Opgeslagen kaarten beheren - Kaarten beheren + Kaarten beheren Adres toevoegen Adressen beheren - Adressen opslaan en automatisch invullen + Adressen opslaan en automatisch invullen - Adressen opslaan en invullen + Adressen opslaan en invullen - Informatie zoals nummers, e-mail- en verzendadressen toevoegen + Informatie zoals nummers, e-mail- en verzendadressen toevoegen + + + Inclusief telefoonnummers en e-mailadressen Inclusief telefoonnummers en e-mailadressen @@ -1859,9 +1880,9 @@ Kaart verwijderen - Weet u zeker dat u deze creditcard wilt verwijderen? + Weet u zeker dat u deze creditcard wilt verwijderen? - Kaart verwijderen? + Kaart verwijderen? Verwijderen @@ -1875,24 +1896,24 @@ Opgeslagen kaarten - Voer een geldig creditcardnummer in + Voer een geldig creditcardnummer in - Voer een geldig kaartnummer in + Voer een geldig kaartnummer in - Vul dit veld in + Vul dit veld in - Voeg een naam toe + Voeg een naam toe Ontgrendel om uw opgeslagen kaarten te bekijken - Beveilig uw creditcards + Beveilig uw creditcards - Beveilig uw opgeslagen betalingsmethoden + Beveilig uw opgeslagen betalingsmethoden - Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen creditcards te beschermen tegen toegang als iemand anders uw apparaat heeft. + Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen creditcards te beschermen tegen toegang als iemand anders uw apparaat heeft. - Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen betalingsmethoden te beschermen tegen toegang als iemand anders uw apparaat heeft. + Stel een vergrendelingspatroon, pincode of wachtwoord voor uw apparaat in om uw opgeslagen betalingsmethoden te beschermen tegen toegang als iemand anders uw apparaat heeft. Nu instellen @@ -1901,10 +1922,10 @@ Ontgrendel uw apparaat - Ontgrendelen om opgeslagen creditcardgegevens te gebruiken + Ontgrendelen om opgeslagen creditcardgegevens te gebruiken - Ontgrendel om opgeslagen betalingsmethoden te gebruiken + Ontgrendel om opgeslagen betalingsmethoden te gebruiken Adres toevoegen @@ -1912,11 +1933,13 @@ Adressen beheren - Voornaam + Voornaam - Tweede naam + Tweede naam - Achternaam + Achternaam + + Naam Adres @@ -1941,9 +1964,9 @@ Adres verwijderen - Weet u zeker dat u dit adres wilt verwijderen? + Weet u zeker dat u dit adres wilt verwijderen? - Dit adres verwijderen? + Dit adres verwijderen? Verwijderen @@ -2041,49 +2064,49 @@ Bewerken - Weet u zeker dat u deze aanmelding wilt verwijderen? + Weet u zeker dat u deze aanmelding wilt verwijderen? - Weet u zeker dat u dit wachtwoord wilt verwijderen? + Weet u zeker dat u dit wachtwoord wilt verwijderen? Verwijderen Annuleren - Aanmeldopties + Aanmeldopties - Wachtwoordopties + Wachtwoordopties - Het bewerkbare tekstveld voor het webadres van de aanmelding. + Het bewerkbare tekstveld voor het webadres van de aanmelding. - Het bewerkbare tekstveld voor het websiteadres. + Het bewerkbare tekstveld voor het websiteadres. - Het bewerkbare tekstveld voor de gebruikersnaam van de aanmelding. + Het bewerkbare tekstveld voor de gebruikersnaam van de aanmelding. - Het bewerkbare tekstveld voor de gebruikersnaam. + Het bewerkbare tekstveld voor de gebruikersnaam. - Het bewerkbare tekstveld voor het wachtwoord van de aanmelding. + Het bewerkbare tekstveld voor het wachtwoord van de aanmelding. - Het bewerkbare tekstveld voor het wachtwoord. + Het bewerkbare tekstveld voor het wachtwoord. - Wijzigingen aan aanmelding opslaan. + Wijzigingen aan aanmelding opslaan. - Wijzigingen opslaan. + Wijzigingen opslaan. - Bewerken + Bewerken - Wachtwoord bewerken + Wachtwoord bewerken - Nieuwe aanmelding toevoegen + Nieuwe aanmelding toevoegen - Wachtwoord toevoegen + Wachtwoord toevoegen - Wachtwoord vereist + Wachtwoord vereist - Vul een wachtwoord in + Vul een wachtwoord in - Gebruikersnaam vereist + Gebruikersnaam vereist - Vul een gebruikersnaam in + Vul een gebruikersnaam in Hostnaam vereist @@ -2196,7 +2219,7 @@ Klik voor meer details - Omhoog + Omhoog Sluiten @@ -2237,8 +2260,6 @@ Aangepaste waardering - Onbetrouwbare beoordelingen verwijderd - Gebaseerd op betrouwbare beoordelingen Hoogtepunten uit recente beoordelingen @@ -2294,10 +2315,6 @@ Als u ziet dat dit product weer op voorraad is, meld dit dan aan ons en wij zullen eraan werken om de beoordelingen te controleren. Rapporteren dat product op voorraad is - - Beoordelingskwaliteit controleren - - Beoordelingskwaliteit controleren Beoordelingskwaliteit controleren (%s) @@ -2343,13 +2360,19 @@ Meer info - Door ‘Ja, proberen’ te selecteren, gaat u akkoord met het %2$s en de %3$s van %1$s door Mozilla. + Door ‘Ja, proberen’ te selecteren, gaat u akkoord met het %2$s en de %3$s van %1$s door Mozilla. Door ‘Ja, proberen’ te selecteren, gaat u akkoord met het volgende van %1$s: + + Door ‘Ja, proberen’ te selecteren, gaat u akkoord met de %2$s van %1$s en de %4$s van %3$s. + + Door ‘Ja, proberen’ te selecteren, gaat u akkoord met de %2$s van %1$s en de %4$s van %3$s. - privacybeleid + privacybeleid Privacybeleid + + privacyverklaring gebruiksvoorwaarden @@ -2423,6 +2446,10 @@ Deze pagina vertalen? + + Pagina vertaald van het %1$s naar het %2$s Probeer privévertalingen in %1$s @@ -2435,6 +2462,8 @@ Vertalen naar het Niet nu + + Origineel tonen Gereed @@ -2457,6 +2486,16 @@ Meer info + + + Vertalen… + + Taal downloaden in gegevensbesparingsmodus (%1$s)? + + Vertaalopties diff --git a/app/src/main/res/values-nn-rNO/strings.xml b/app/src/main/res/values-nn-rNO/strings.xml index ce0c47f0c..1cbbecca6 100644 --- a/app/src/main/res/values-nn-rNO/strings.xml +++ b/app/src/main/res/values-nn-rNO/strings.xml @@ -2009,6 +2009,8 @@ Avbryt Innloggingsalternativ + + Passordalternativ Det redigerbare tekstfeltet for innloggings-nettadressa. @@ -2136,7 +2138,7 @@ Søk med %s - + Vel at lenker frå nettstadar, e-postmeldingar og meldingar skal opnast automatisk i Firefox. @@ -2506,6 +2508,9 @@ Avbryt + + + Feilsøkingsverktøy Naviger tilbake @@ -2520,6 +2525,12 @@ Privat Totalt + + Verktøy for å lage faner + + Legg til i aktive faner + + Legg til i inaktive faner Legg til i private faner diff --git a/app/src/main/res/values-oc/strings.xml b/app/src/main/res/values-oc/strings.xml index 25873903b..923a215e3 100644 --- a/app/src/main/res/values-oc/strings.xml +++ b/app/src/main/res/values-oc/strings.xml @@ -2210,6 +2210,9 @@ Exemple :\nhttps://suggestqueries.google.com/complete/search?client=firefox& Recèrca %s + + Cambiatz vòstre navegador per defaut + Causir de dobrir los sites web, los corrièls e messatges automaticament dins Firefox. diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index 8abee7324..d7a238006 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -260,6 +260,11 @@ ਸਫ਼ੇ ਦਾ ਉਲੱਥਾ ਕਰੋ + + ਸਫ਼ੇ ਦਾ %1$s ਤੋਂ %2$s ਵਿੱਚ ਅਨੁਵਾਦ ਕੀਤਾ। + ਚੁਣੀ ਹੋਈ ਬੋਲੀ @@ -338,12 +343,22 @@ Firefox ਪਰਦੇਦਾਰੀ ਸੂਚਨਾ - + + ਸਾਡੀ ਪਰਦੇਦਾਰੀ ਸੂਚਨਾ ਵਿੱਚ ਹੋਰ ਜਾਣਕਾਰੀ ਲਵੋ ਅਸੀਂ ਤੁਹਾਨੂੰ ਸੁਰੱਖਿਅਤ ਰੱਖਣਾ ਚਾਹੁੰਦੇ ਹਾਂ + + ਪਤਾ ਕਰੋ ਕਿ ਲੱਖਾਂ Firefox ਨੂੰ ਪਸੰਦ ਕਿਉਂ ਕਰਦੇ ਹਨ + + ਹੋਰ ਚੋਣਾਂ ਨਾਲ ਸੁਰੱਖਿਅਤ ਬਰਾਊਜ਼ ਕਰਨਾ ਕੰਪਨੀਆਂ ਨੂੰ ਚੋਰੀ ਚੋਰੀ ਵੈੱਬ ਉੱਤੇ ਤੁਹਾਡਾ ਪਿੱਛਾ ਕਰਨ ਤੋਂ ਸਾਡਾ ਗ਼ੈਰ-ਫਾਇਦਾ ਸਮਰੱਥ ਬਰਾਊਜ਼ਰ ਆਪਣੇ-ਆਪ ਹੀ ਰੋਕਦਾ ਹੈ। + 10 ਕਰੋੜ ਤੋਂ ਵੱਧ ਲੋਕ ਨੇ ਆਪਣੀ ਪਰਦੇਦਾਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਉਸ ਬਰਾਊਜ਼ਰ ਦੀ ਚੋਣ ਕੀਤੀ ਹੈ, ਜਿਸ ਦਾ ਮਕਸਦ ਕੋਈ ਫਾਇਦਾ ਨਹੀਂ ਹੈ। + + ਜਾਣੇ-ਪਛਾਣੇ ਟਰੈਕਰ? ਆਪਣੇ ਆਪ ਪਾਬੰਦੀ ਲਾਈ। ਇਕਸਟੈਨਸ਼ਨ? 700 ਤੋਂ ਵੱਧ ਅਜ਼ਮਾਉਣ ਲਈ। PDF? ਸਾਡੇ ਬਿਲਟ-ਇਨ ਰੀਡਰ ਨਾਲ ਉਹਨਾਂ ਨੂੰ ਵਰਤਣਾ ਸੌਖਾ। + ਸਾਡਾ ਗ਼ੈਰ-ਮੁਨਾਫ਼ਾ ਸਮਰੱਥ ਬਰਾਊਜ਼ਰ ਕੰਪਨੀਆਂ ਨੂੰ ਵੈੱਬ ਉੱਤੇ ਚੋਰੀ ਛਿਪੇ ਪਿੱਛਾ ਕਰਨ ਤੋਂ ਰੋਕਣ ਲਈ ਮਦਦ ਕਰਦਾ ਹੈ।\n\nਸਾਡੇ ਪਰਦੇਦਾਰੀ ਨੋਟਿਸ ਬਾਰੇ ਹੋਰ ਸਿੱਖੋ। @@ -703,9 +718,9 @@ ਬੁੱਕਮਾਰਕ - ਲਾਗਇਨ + ਲਾਗਇਨ - ਪਾਸਵਰਡ + ਪਾਸਵਰਡ ਟੈਬਾਂ ਖੋਲ੍ਹੋ @@ -732,9 +747,9 @@ %2$s %3$s ਉੱਤੇ %1$s - ਕਰੈਡਿਟ ਕਾਰਡ + ਕਰੈਡਿਟ ਕਾਰਡ - ਭੁਗਤਾਨ ਦੇ ਢੰਗ + ਭੁਗਤਾਨ ਦੇ ਢੰਗ ਸਿਰਨਾਵੇਂ @@ -1685,13 +1700,13 @@ ਮੁੱਖ ਸਕਰੀਨ ਉੱਤੇ ਸੌਖੀ ਤਰ੍ਹਾਂ ਜੋੜ ਸਕਦੇ ਹੋ। - ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ + ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ - ਪਾਸਵਰਡ + ਪਾਸਵਰਡ - ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਸੰਭਾਲੋ + ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਸੰਭਾਲੋ - ਪਾਸਵਰਡਾਂ ਨੂੰ ਸੰਭਾਲੋ + ਪਾਸਵਰਡਾਂ ਨੂੰ ਸੰਭਾਲੋ ਸੰਭਾਲਣ ਲਈ ਪੁੱਛੋ @@ -1706,47 +1721,47 @@ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਉੱਤੇ ਹੋਰ ਐਪਾਂ ਵਿੱਚ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਅਤੇ ਪਾਸਵਰਡ ਭਰੋ। - ਲਾਗਇਨ ਜੋੜੋ + ਲਾਗਇਨ ਜੋੜੋ - ਪਾਸਵਰਡ ਜੋੜੋ + ਪਾਸਵਰਡ ਜੋੜੋ - - ਲਾਗਇਨ ਸਿੰਕ ਕਰੋ - ਪਾਸਵਰਡ ਸਿੰਕ ਕਰੋ + ਲਾਗਇਨ ਸਿੰਕ ਕਰੋ + + ਪਾਸਵਰਡ ਸਿੰਕ ਕਰੋ - ਡਿਵਾਈਸਾਂ ਵਿਚਾਲੇ ਲਾਗਇਨਾਂ ਨੂੰ ਸਿੰਕ ਕਰੋ + ਡਿਵਾਈਸਾਂ ਵਿਚਾਲੇ ਲਾਗਇਨਾਂ ਨੂੰ ਸਿੰਕ ਕਰੋ - ਪਾਸਵਰਡ ਡਿਵਾਈਸਾਂ ਵਿਚਾਲੇ ਸਿੰਕ ਕਰੋ + ਪਾਸਵਰਡ ਡਿਵਾਈਸਾਂ ਵਿਚਾਲੇ ਸਿੰਕ ਕਰੋ - ਸੰਭਾਲੇ ਹੋਏ ਲਾਗਇਨ + ਸੰਭਾਲੇ ਹੋਏ ਲਾਗਇਨ - ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ + ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ - ਤੁਹਾਡੇ ਵਲੋਂ ਸੰਭਾਲੇ ਲਾਗਇਨ ਜਾਂ %s ਨਾਲ ਸਿੰਕ ਕੀਤੇ ਇੱਥੇ ਵੇਖਾਏ ਜਾਣਗੇ। + ਤੁਹਾਡੇ ਵਲੋਂ ਸੰਭਾਲੇ ਲਾਗਇਨ ਜਾਂ %s ਨਾਲ ਸਿੰਕ ਕੀਤੇ ਇੱਥੇ ਵੇਖਾਏ ਜਾਣਗੇ। - ਤੁਹਾਡੇ ਵਲੋਂ %s ਵਿੱਚ ਸੰਭਾਲੇ ਜਾਂ ਸਿੰਕ ਕੀਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਇੱਥੇ ਦਿਖਾਇਆ ਜਾਵੇਗਾ। ਤੁਹਾਡੇ ਸਾਰੇ ਸੰਭਾਲੇ ਪਾਸਵਰਡ ਇੰਕ੍ਰਿਪਟ ਕੀਤੇ ਹੁੰਦੇ ਹਨ। + ਤੁਹਾਡੇ ਵਲੋਂ %s ਵਿੱਚ ਸੰਭਾਲੇ ਜਾਂ ਸਿੰਕ ਕੀਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਇੱਥੇ ਦਿਖਾਇਆ ਜਾਵੇਗਾ। ਤੁਹਾਡੇ ਸਾਰੇ ਸੰਭਾਲੇ ਪਾਸਵਰਡ ਇੰਕ੍ਰਿਪਟ ਕੀਤੇ ਹੁੰਦੇ ਹਨ। - ਸਿੰਕ ਬਾਰੇ ਹੋਰ ਜਾਣੋ। + ਸਿੰਕ ਬਾਰੇ ਹੋਰ ਜਾਣੋ। - ਸਿੰਕ ਬਾਰੇ ਹੋਰ ਜਾਣੋ + ਸਿੰਕ ਬਾਰੇ ਹੋਰ ਜਾਣੋ ਛੋਟਾਂ - ਨਾ ਸੰਭਾਲੇ ਹੋਏ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਇੱਥੇ ਸੰਭਾਲਿਆ ਜਾਵੇਗਾ। + ਨਾ ਸੰਭਾਲੇ ਹੋਏ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਇੱਥੇ ਸੰਭਾਲਿਆ ਜਾਵੇਗਾ। - %s ਇੱਥੇ ਦਿੱਤੀਆਂ ਹੋਈਆਂ ਸਾਈਟਾਂ ਲਈ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇਗਾ। + %s ਇੱਥੇ ਦਿੱਤੀਆਂ ਹੋਈਆਂ ਸਾਈਟਾਂ ਲਈ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇਗਾ। - ਇਹਨਾਂ ਸਾਈਟਾਂ ਲਈ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇ ਜਾਣਗੇ। + ਇਹਨਾਂ ਸਾਈਟਾਂ ਲਈ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇ ਜਾਣਗੇ। - %s ਇਹਨਾਂ ਸਾਈਟਾਂ ਲਈ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇਗਾ। + %s ਇਹਨਾਂ ਸਾਈਟਾਂ ਲਈ ਪਾਸਵਰਡ ਨਹੀਂ ਸੰਭਾਲੇਗਾ। ਸਾਰੀਆਂ ਛੋਟਾਂ ਹਟਾ ਦਿਓ - ਲਾਗਇਨ ਖੋਜੋ + ਲਾਗਇਨ ਖੋਜੋ - ਪਾਸਵਰਡ ਖੋਜੋ + ਪਾਸਵਰਡ ਖੋਜੋ ਸਾਈਟ @@ -1774,17 +1789,17 @@ ਪਾਸਵਰਡ ਲੁਕਾਓ - ਆਪਣੇ ਸੰਭਾਲੇ ਲਾਗਇਨ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + ਆਪਣੇ ਸੰਭਾਲੇ ਲਾਗਇਨ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ - ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ - ਆਪਣੇ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਕਰੋ + ਆਪਣੇ ਲਾਗਇਨ ਅਤੇ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਕਰੋ - ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ - ਆਪਣੇ ਲਾਗਇਨਾਂ ਅਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਨੂੰ ਰੱਖਣ ਵਾਲੇ ਕਿਸੇ ਦੀ ਪਹੁੰਚ ਤੋਂ ਸੁਰੱਖਿਅਤ ਰੱਖਣ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈਟ ਅੱਪ ਕਰੋ। + ਆਪਣੇ ਲਾਗਇਨਾਂ ਅਤੇ ਪਾਸਵਰਡਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਨੂੰ ਰੱਖਣ ਵਾਲੇ ਕਿਸੇ ਦੀ ਪਹੁੰਚ ਤੋਂ ਸੁਰੱਖਿਅਤ ਰੱਖਣ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈਟ ਅੱਪ ਕਰੋ। - ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਉੱਤੇ ਕਿਸੇ ਹੋਰ ਵੱਲੋਂ ਪਹੁੰਚ ਕਰਨ ਤੋਂ ਬਚਾਉਣ ਤੋਂ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ। + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਉੱਤੇ ਕਿਸੇ ਹੋਰ ਵੱਲੋਂ ਪਹੁੰਚ ਕਰਨ ਤੋਂ ਬਚਾਉਣ ਤੋਂ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ। ਬਾਅਦ \'ਚ @@ -1802,7 +1817,10 @@ ਆਖਰੀ ਵਰਤੋਂ - ਲਾਗਇਨ ਲੜੀਬਧ ਮੇਨੂ + ਲਾਗਇਨ ਲੜੀਬਧ ਮੇਨੂ + + + ਪਾਸਵਰਡ ਮੇਨੂ ਨੂੰ ਲੜੀਬੱਧ ਕਰੋ ਪਾਸਵਰਡ ਮੇਨੂ ਨੂੰ ਲੜੀਬੱਧ ਕਰੋ @@ -1813,39 +1831,42 @@ ਸਿਰਨਾਵੇਂ - ਕਰੈਡਿਟ ਕਾਰਡ + ਕਰੈਡਿਟ ਕਾਰਡ - ਭੁਗਤਾਨ ਦੇ ਢੰਗ + ਭੁਗਤਾਨ ਦੇ ਢੰਗ - ਕਾਰਡ ਸੰਭਾਲੋ ਅਤੇ ਆਪਣੇ-ਆਪ ਭਰੋ + ਕਾਰਡ ਸੰਭਾਲੋ ਅਤੇ ਆਪਣੇ-ਆਪ ਭਰੋ - ਭੁਗਤਾਨ ਦੇ ਢੰਗ ਸੰਭਾਲੋ ਅਤੇ ਭਰੋ + ਭੁਗਤਾਨ ਦੇ ਢੰਗ ਸੰਭਾਲੋ ਅਤੇ ਭਰੋ - ਡਾਟਾ ਇੰਕ੍ਰਿਪਟ ਕੀਤਾ ਹੈ + ਡਾਟਾ ਇੰਕ੍ਰਿਪਟ ਕੀਤਾ ਹੈ - %s ਤੁਹਾਡੇ ਵਲੋਂ ਸੰਭਾਲੇ ਸਾਰੇ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਇੰਕ੍ਰਿਪਟ ਕਰਦਾ ਹੈ + %s ਤੁਹਾਡੇ ਵਲੋਂ ਸੰਭਾਲੇ ਸਾਰੇ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਇੰਕ੍ਰਿਪਟ ਕਰਦਾ ਹੈ ਡਿਵਾਈਸਾਂ ਵਿਚਾਲੇ ਕਾਰਡਾਂ ਨੂੰ ਸਿੰਕ ਕਰੋ ਕਾਰਡ ਸਿੰਕ ਕਰੋ - ਕਰੈਡਿਟ ਕਾਰਡ ਜੋੜੋ + ਕਰੈਡਿਟ ਕਾਰਡ ਜੋੜੋ - ਕਾਰਡ ਜੋੜੋ + ਕਾਰਡ ਜੋੜੋ - ਸੰਭਾਲੇ ਹੋਏ ਕਾਰਡਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ + ਸੰਭਾਲੇ ਹੋਏ ਕਾਰਡਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ - ਕਾਰਡਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ + ਕਾਰਡਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ ਸਿਰਨਾਵਾਂ ਜੋੜੋ ਸਿਰਨਾਵਿਆਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ - ਸਿਰਨਾਵੇਂ ਸੰਭਾਲੋ ਅਤੇ ਆਪਣੇ-ਆਪ ਭਰੋ + ਸਿਰਨਾਵੇਂ ਸੰਭਾਲੋ ਅਤੇ ਆਪਣੇ-ਆਪ ਭਰੋ - ਸਿਰਨਾਵਿਆਂ ਨੂੰ ਸੰਭਾਲੋ ਅਤੇ ਭਰੋ + ਸਿਰਨਾਵਿਆਂ ਨੂੰ ਸੰਭਾਲੋ ਅਤੇ ਭਰੋ - ਨੰਬਰ, ਈਮੇਲ ਅਤੇ ਭੇਜਣ ਵਾਲੇ ਸਿਰਨਾਵਿਆਂ ਸਮੇਤ ਜਾਣਕਾਰੀ + ਨੰਬਰ, ਈਮੇਲ ਅਤੇ ਭੇਜਣ ਵਾਲੇ ਸਿਰਨਾਵਿਆਂ ਸਮੇਤ ਜਾਣਕਾਰੀ + + + ਫ਼ੋਨ ਨੰਬਰਾਂ ਅਤੇ ਈਮੇਲ ਸਿਰਨਾਵਿਆਂ ਸਮੇਤ ਫ਼ੋਨ ਨੰਬਰਾਂ ਅਤੇ ਈਮੇਲ ਸਿਰਨਾਵਿਆਂ ਸਮੇਤ @@ -1869,9 +1890,9 @@ ਕਾਰਡ ਨੂੰ ਹਟਾਓ - ਕੀ ਤੁਸੀਂ ਇਹ ਕਰੈਡਿਟ ਕਾਰਡ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? + ਕੀ ਤੁਸੀਂ ਇਹ ਕਰੈਡਿਟ ਕਾਰਡ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? - ਕਾਰਡ ਨੂੰ ਹਟਾਉਣਾ ਹੈ? + ਕਾਰਡ ਨੂੰ ਹਟਾਉਣਾ ਹੈ? ਹਟਾਓ @@ -1885,24 +1906,24 @@ ਸੰਭਾਲੇ ਹੋਏ ਕਾਰਡ - ਵਾਜਬ ਕਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਦਿਓ ਜੀ + ਵਾਜਬ ਕਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਦਿਓ ਜੀ - ਵਾਜਬ ਕਾਰਡ ਨੰਬਰ ਭਰੋ + ਵਾਜਬ ਕਾਰਡ ਨੰਬਰ ਭਰੋ - ਇਹ ਖੇਤਰ ਭਰੋ + ਇਹ ਖੇਤਰ ਭਰੋ - ਨਾਂ ਜੋੜੋ + ਨਾਂ ਜੋੜੋ ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਕਾਰਡ ਵੇਖਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ - ਆਪਣੇ ਕਰੈਡਿਟ ਕਾਰਡ ਸੁਰੱਖਿਅਤ ਕਰੋ + ਆਪਣੇ ਕਰੈਡਿਟ ਕਾਰਡ ਸੁਰੱਖਿਅਤ ਕਰੋ - ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਸੁਰੱਖਿਅਤ ਕਰੋ - ਆਪਣੀ ਡਿਵਾਇਸ ਲਈ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ, ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ ਤਾਂ ਜੋ ਕਿਸੇ ਹੋਰ ਹੱਥ ਤੁਹਾਡਾ ਡਿਵਾਇਸ ਹੋਣ ਉੱਤੇ ਤੁਹਾਡੇ ਸੰਭਾਲੇ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਰਹਿਣ। + ਆਪਣੀ ਡਿਵਾਇਸ ਲਈ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ, ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ ਤਾਂ ਜੋ ਕਿਸੇ ਹੋਰ ਹੱਥ ਤੁਹਾਡਾ ਡਿਵਾਇਸ ਹੋਣ ਉੱਤੇ ਤੁਹਾਡੇ ਸੰਭਾਲੇ ਪਾਸਵਰਡ ਸੁਰੱਖਿਅਤ ਰਹਿਣ। - ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ ਢੰਗਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਉੱਤੇ ਕਿਸੇ ਹੋਰ ਵੱਲੋਂ ਪਹੁੰਚ ਕਰਨ ਤੋਂ ਬਚਾਉਣ ਤੋਂ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ। + ਆਪਣੇ ਸੰਭਾਲੇ ਹੋਏ ਪਾਸਵਰਡ ਢੰਗਾਂ ਨੂੰ ਤੁਹਾਡੇ ਡਿਵਾਈਸ ਉੱਤੇ ਕਿਸੇ ਹੋਰ ਵੱਲੋਂ ਪਹੁੰਚ ਕਰਨ ਤੋਂ ਬਚਾਉਣ ਤੋਂ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਡਿਵਾਈਸ ਲਾਕ ਪੈਟਰਨ, ਪਿੰਨ ਜਾਂ ਪਾਸਵਰਡ ਸੈੱਟ ਕਰੋ। ਹੁਣੇ ਸੈਟ ਅੱਪ ਕਰੋ @@ -1910,10 +1931,10 @@ ਆਪਣਾ ਡਿਵਾਇਸ ਅਣ-ਲਾਕ ਕਰੋ - ਸੰਭਾਲੀ ਕਰੈਡਿਟ ਕਾਰਡ ਜਾਣਕਾਰੀ ਵਰਤਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + ਸੰਭਾਲੀ ਕਰੈਡਿਟ ਕਾਰਡ ਜਾਣਕਾਰੀ ਵਰਤਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ - ਸੰਭਾਲੇ ਹੋਏ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਵਰਤਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ + ਸੰਭਾਲੇ ਹੋਏ ਭੁਗਤਾਨ ਢੰਗਾਂ ਨੂੰ ਵਰਤਣ ਲਈ ਅਣ-ਲਾਕ ਕਰੋ ਸਿਰਨਾਵਾਂ ਜੋੜੋ @@ -1921,11 +1942,13 @@ ਸਿਰਨਾਵਿਆਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ - ਨਾਂ ਦਾ ਪਹਿਲਾਂ ਹਿੱਸਾ + ਨਾਂ ਦਾ ਪਹਿਲਾਂ ਹਿੱਸਾ - ਮੱਧ ਨਾਂ + ਮੱਧ ਨਾਂ - ਨਾਂ ਦਾ ਆਖਰੀ ਹਿੱਸਾ + ਨਾਂ ਦਾ ਆਖਰੀ ਹਿੱਸਾ + + ਨਾਂ ਸੜਕ ਸਿਰਨਾਵਾਂ @@ -1950,9 +1973,9 @@ ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਓ - ਕੀ ਤੁਸੀਂ ਇਹ ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? + ਕੀ ਤੁਸੀਂ ਇਹ ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? - ਇਹ ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ? + ਇਹ ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਉਣਾ ਹੈ? ਹਟਾਓ @@ -2050,50 +2073,50 @@ ਸੋਧੋ - ਕੀ ਤੁਸੀਂ ਇਹ ਲਾਗਇਨ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? + ਕੀ ਤੁਸੀਂ ਇਹ ਲਾਗਇਨ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? - ਕੀ ਤੁਸੀਂ ਇਸ ਪਾਸਵਰਡ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? + ਕੀ ਤੁਸੀਂ ਇਸ ਪਾਸਵਰਡ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ? ਹਟਾਓ ਰੱਦ ਕਰੋ - ਲਾਗਇਨ ਚੋਣਾਂ + ਲਾਗਇਨ ਚੋਣਾਂ - ਪਾਸਵਰਡ ਚੋਣਾਂ + ਪਾਸਵਰਡ ਚੋਣਾਂ - ਲਾਗਇਨ ਦੇ ਵੈੱਬ ਐਡਰੈਸ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। + ਲਾਗਇਨ ਦੇ ਵੈੱਬ ਐਡਰੈਸ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। - ਵੈੱਬਸਾਈਟ ਸਿਰਨਾਵਿਆਂ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। + ਵੈੱਬਸਾਈਟ ਸਿਰਨਾਵਿਆਂ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। - ਲਾਗਇਨ ਦੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। + ਲਾਗਇਨ ਦੇ ਵਰਤੋਂਕਾਰ-ਨਾਂ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। - ਵਰਤੋਂਕਾਰ-ਨਾਂ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। + ਵਰਤੋਂਕਾਰ-ਨਾਂ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। - ਲਾਗਇਨ ਦੇ ਪਾਸਵਰਡ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। + ਲਾਗਇਨ ਦੇ ਪਾਸਵਰਡ ਲਈ ਸੋਧਣਯੋਗ ਲਿਖਤ ਖੇਤਰ ਹੈ। - ਪਾਸਵਰਡ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। + ਪਾਸਵਰਡ ਲਈ ਸੋਧ ਕਰਨ ਯੋਗ ਲਿਖਤ ਖੇਤਰ। - ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗਇਨ ਲਈ ਸੰਭਾਲੋ। + ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗਇਨ ਲਈ ਸੰਭਾਲੋ। - ਤਬਦੀਲੀਆਂ ਨੂੰ ਸੰਭਾਲੋ। + ਤਬਦੀਲੀਆਂ ਨੂੰ ਸੰਭਾਲੋ। - ਸੋਧੋ + ਸੋਧੋ - ਪਾਸਵਰਡ ਨੂੰ ਸੋਧੋ + ਪਾਸਵਰਡ ਨੂੰ ਸੋਧੋ - ਨਵਾਂ ਲਾਗਇਨ ਜੋੜੋ + ਨਵਾਂ ਲਾਗਇਨ ਜੋੜੋ - ਪਾਸਵਰਡ ਜੋੜੋ + ਪਾਸਵਰਡ ਜੋੜੋ - ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ + ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ - ਪਾਸਵਰਡ ਦਿਓ + ਪਾਸਵਰਡ ਦਿਓ - ਵਰਤੋਂਕਾਰ-ਨਾਂ ਚਾਹੀਦਾ ਹੈ + ਵਰਤੋਂਕਾਰ-ਨਾਂ ਚਾਹੀਦਾ ਹੈ - ਵਰਤੋਂਕਾਰ-ਨਾਂ ਦਿਓ + ਵਰਤੋਂਕਾਰ-ਨਾਂ ਦਿਓ ਹੋਸਟ-ਨਾਂ ਚਾਹੀਦਾ ਹੈ @@ -2204,7 +2227,7 @@ ਹੋਰ ਵੇਰਵਿਆਂ ਲਈ ਕਲਿੱਕ ਕਰੋ - ਉੱਤੇ ਜਾਓ + ਉੱਤੇ ਜਾਓ ਬੰਦ ਕਰੋ @@ -2244,8 +2267,6 @@ ਇਹ ਰੀਵਿਊ ਕਿੰਨੇ ਭਰੋਸੇਯੋਗ ਹਨ? ਅਡਜੱਸਟ ਕੀਤੀ ਰੇਟਿੰਗ - - ਗ਼ੈਰ-ਭਰੋਸੇਯੋਗ ਰੀਵਿਊ ਹਟਾਏ ਭਰੋਸੇਯੋਗ ਰੀਵਿਊਆਂ ਉੱਤੇ ਅਧਾਰਿਤ @@ -2303,10 +2324,6 @@ ਜੇ ਤੁਹਾਨੂੰ ਉਹ ਉਤਪਾਦ ਵਾਪਸ ਸਟਾਕ ਵਿੱਚ ਮਿਲੇ ਤਾਂ ਸਾਨੂੰ ਇਸ ਬਾਰੇ ਦੱਸਿਓ ਅਤੇ ਅਸੀਂ ਰੀਵਿਊ ਦੀ ਜਾਂਚ ਕਰਾਂਗੇ। ਉਤਪਾਦ ਸਟਾਕ ਵਿੱਚ ਹੋਣ ਦੀ ਰਿਪੋਰਟ ਕਰੋ - - ਰੀਵਿਊ ਕੁਆਲਟੀ ਦੀ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ - - ਰੀਵਿਊ ਕੁਆਲਟੀ ਦੀ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ ਰੀਵਿਊ ਕੁਆਲਟੀ ਦੀ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ (%s) @@ -2352,13 +2369,19 @@ ਹੋਰ ਜਾਣੋ - “ਹਾਂ, ਇਸ ਨੂੰ ਅਜ਼ਮਾਓ” ਚੁਣ ਕੇ ਤੁਸੀਂ Mozilla ਵਲੋਂ %1$s ਦੀ %2$s ਅਤੇ %3$s ਲਈ ਸਹਿਮਤ ਹੁੰਦੇ ਹੋ। + “ਹਾਂ, ਇਸ ਨੂੰ ਅਜ਼ਮਾਓ” ਚੁਣ ਕੇ ਤੁਸੀਂ Mozilla ਵਲੋਂ %1$s ਦੀ %2$s ਅਤੇ %3$s ਲਈ ਸਹਿਮਤ ਹੁੰਦੇ ਹੋ। “ਹਾਂ, ਇਸ ਨੂੰ ਅਜ਼ਮਾਓ” ਨੂੰ ਚੁਣ ਕੇ ਤੁਸੀਂ %1$s ਤੋਂ ਹੇਠ ਦਿੱਤਿਆਂ ਨਾਲ ਸਹਿਮਤ ਹੁੰਦੇ ਹੋ: + + “ਹਾਂ, ਇਸ ਨੂੰ ਅਜ਼ਮਾਓ” ਚੁਣ ਕੇ ਤੁਸੀਂ %1$s ਦੀ %2$s ਅਤੇ %3$s ਦੀ %4$s ਨਾਲ ਸਹਿਮਤ ਹੁੰਦੇ ਹੋ। + + “ਹਾਂ, ਇਸ ਨੂੰ ਅਜ਼ਮਾਓ” ਚੁਣ ਕੇ ਤੁਸੀਂ %1$s ਦੀ %2$s ਅਤੇ %3$s ਦੀ %4$s ਨਾਲ ਸਹਿਮਤ ਹੁੰਦੇ ਹੋ। - ਪਰਦੇਦਾਰੀ ਨੀਤੀ + ਪਰਦੇਦਾਰੀ ਨੀਤੀ ਪਰਦੇਦਾਰੀ ਨੀਤੀ + + ਪਰਦੇਦਾਰੀ ਸੂਚਨਾ ਵਰਤਣ ਲਈ ਸ਼ਰਤਾਂ @@ -2430,6 +2453,10 @@ ਇਹ ਸਫ਼ੇ ਦਾ ਉਲੱਥਾ ਕਰਨਾ ਹੈ? + + ਸਫ਼ੇ ਦਾ %1$s ਤੋਂ %2$s ਵਿੱਚ ਅਨੁਵਾਦ ਕੀਤਾ %1$s ਵਿੱਚ ਪ੍ਰਾਈਵੇਟ ਉਲੱਥਾ ਅਜ਼ਮਾਓ @@ -2442,6 +2469,8 @@ ਇਸ ਵਿੱਚ ਉਲੱਥਾ ਕਰੋ ਹਾਲੇ ਨਹੀਂ + + ਅਸਲ ਵੇਖਾਓ ਮੁਕੰਮਲ @@ -2464,6 +2493,16 @@ ਹੋਰ ਜਾਣੋ + + …ਉਲੱਥਾ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ + + + ਡਾਟਾ ਬੱਚਤ ਮੋਡ ਵਿੱਚ ਭਾਸ਼ਾ ਨੂੰ ਡਾਊਨਲੋਡ ਕਰਨਾ ਹੈ (%1$s)? + + ਉਲੱਥੇ ਲਈ ਚੋਣਾਂ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c268fed78..8771d0492 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -255,6 +255,11 @@ Przetłumacz stronę + + Język oryginalnej strony: %1$s, język tłumaczenia: %2$s. + Wybrany język @@ -332,12 +337,22 @@ Zasady ochrony prywatności Firefoksa - + + Więcej informacji znajdziesz w naszych zasadach ochrony prywatności Uwielbiamy zapewniać Ci bezpieczeństwo + + Dowiedz się, dlaczego miliony kochają Firefoksa + + Bezpieczne przeglądanie i większy wybór Nasza przeglądarka wspierana przez organizację non-profit pomaga powstrzymywać firmy przed potajemnym śledzeniem Cię w Internecie. + Ponad 100 milionów osób chroni swoją prywatność, wybierając przeglądarkę wspieraną przez organizację non-profit. + + Znane elementy śledzące? Blokowane automatycznie. Rozszerzenia? Wypróbuj wszystkie 700. PDF-y? Nasz wbudowany czytnik ułatwia zarządzanie nimi. + Nasza przeglądarka wspierana przez organizację non-profit pomaga powstrzymywać firmy przed potajemnym śledzeniem Cię w Internecie.\n\nWięcej informacji znajdziesz w naszych zasadach ochrony prywatności. @@ -695,9 +710,9 @@ Zakładki - Dane logowania + Dane logowania - Hasła + Hasła Otwarte karty @@ -725,9 +740,9 @@ %1$s na urządzeniu %2$s %3$s - Karty płatnicze + Karty płatnicze - Metody płatności + Metody płatności Adresy @@ -1672,13 +1687,13 @@ Można łatwo dodać tę stronę do ekranu głównego urządzenia, aby mieć do niej bezpośredni dostęp i używać jej jak aplikację. - Dane logowania i hasła + Dane logowania i hasła - Hasła + Hasła - Zachowywanie danych logowania i haseł + Zachowywanie danych logowania i haseł - Zachowywanie haseł + Zachowywanie haseł Pytanie o zachowanie @@ -1693,47 +1708,47 @@ Wypełnia nazwy użytkowników i hasła w innych aplikacjach na urządzeniu. - Dodaj dane logowania + Dodaj dane logowania - Dodaj hasło + Dodaj hasło - - Synchronizowanie danych logowania - Synchronizowanie haseł + Synchronizowanie danych logowania + + Synchronizowanie haseł - Synchronizuj dane logowania między urządzeniami + Synchronizuj dane logowania między urządzeniami - Synchronizuj hasła między urządzeniami + Synchronizuj hasła między urządzeniami - Zachowane dane logowania + Zachowane dane logowania - Zachowane hasła + Zachowane hasła - Zachowane lub synchronizowane z przeglądarką %s dane logowania będą wyświetlane w tym miejscu. + Zachowane lub synchronizowane z przeglądarką %s dane logowania będą wyświetlane w tym miejscu. - Tutaj będą wyświetlane hasła zachowane lub synchronizowane w przeglądarce %s. Wszystkie zachowywane hasła są zaszyfrowane. + Tutaj będą wyświetlane hasła zachowane lub synchronizowane w przeglądarce %s. Wszystkie zachowywane hasła są zaszyfrowane. - Więcej informacji o synchronizacji. + Więcej informacji o synchronizacji. - Więcej informacji o synchronizacji + Więcej informacji o synchronizacji Wyjątki - Tutaj będą wyświetlane dane logowania i hasła, które nie będą zachowywane. + Tutaj będą wyświetlane dane logowania i hasła, które nie będą zachowywane. - %s nie będzie zachowywać haseł do wymienionych tutaj witryn. + %s nie będzie zachowywać haseł do wymienionych tutaj witryn. - Dane logowania i hasła dla tych witryn nie będą zachowywane. + Dane logowania i hasła dla tych witryn nie będą zachowywane. - %s nie będzie zachowywać haseł do tych witryn. + %s nie będzie zachowywać haseł do tych witryn. Usuń wszystkie wyjątki - Szukaj danych logowania + Szukaj danych logowania - Szukaj haseł + Szukaj haseł Witryna @@ -1761,17 +1776,17 @@ Ukryj hasło - Odblokuj, aby wyświetlić zachowane dane logowania + Odblokuj, aby wyświetlić zachowane dane logowania - Odblokuj, aby wyświetlić zachowane hasła + Odblokuj, aby wyświetlić zachowane hasła - Zabezpiecz dane logowania i hasła + Zabezpiecz dane logowania i hasła - Zabezpiecz zachowane hasła + Zabezpiecz zachowane hasła - Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane dane logowania i hasła w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. + Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane dane logowania i hasła w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. - Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane hasła w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. + Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane hasła w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. Później @@ -1788,7 +1803,10 @@ Ostatnie użycie - Menu sortowania danych logowania + Menu sortowania danych logowania + + + Menu sortowania haseł Menu sortowania haseł @@ -1799,42 +1817,45 @@ Adresy - Karty płatnicze + Karty płatnicze - Metody płatności + Metody płatności - Zachowywanie i automatyczne wypełnianie kart + Zachowywanie i automatyczne wypełnianie kart - Zachowywanie i wypełnianie metod płatności + Zachowywanie i wypełnianie metod płatności - Dane są zaszyfrowane + Dane są zaszyfrowane - %s szyfruje wszystkie zachowywane metody płatności + %s szyfruje wszystkie zachowywane metody płatności Synchronizuj karty między urządzeniami Synchronizuj karty - Dodaj kartę płatniczą + Dodaj kartę płatniczą - Dodaj kartę + Dodaj kartę - Zarządzaj zachowanymi kartami + Zarządzaj zachowanymi kartami - Zarządzaj kartami + Zarządzaj kartami Dodaj adres Zarządzaj adresami - Zachowywanie i automatyczne wypełnianie adresów + Zachowywanie i automatyczne wypełnianie adresów - Zachowywanie i wypełnianie adresów + Zachowywanie i wypełnianie adresów - Zawiera informacje takie jak numery, adresy e-mail i adresy wysyłki + Zawiera informacje takie jak numery, adresy e-mail i adresy wysyłki + + + W tym numery telefonów i adresy e-mail W tym numery telefonów i adresy e-mail @@ -1858,9 +1879,9 @@ Usuń kartę - Czy na pewno usunąć tę kartę płatniczą? + Czy na pewno usunąć tę kartę płatniczą? - Czy usunąć kartę? + Czy usunąć kartę? Usuń @@ -1873,24 +1894,24 @@ Zachowane karty - Wprowadź prawidłowy numer karty płatniczej + Wprowadź prawidłowy numer karty płatniczej - Podaj prawidłowy numer karty + Podaj prawidłowy numer karty - Wypełnij to pole + Wypełnij to pole - Dodaj imię i nazwisko + Dodaj imię i nazwisko Odblokuj, aby wyświetlić zachowane karty - Zabezpiecz karty płatnicze + Zabezpiecz karty płatnicze - Zabezpiecz zachowane metody płatności + Zabezpiecz zachowane metody płatności - Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane karty płatnicze w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. + Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane karty płatnicze w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. - Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane metody płatności w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. + Skonfiguruj wzór blokady, kod PIN lub hasło, aby ochronić zachowane metody płatności w przypadku, gdy ktoś inny uzyska dostęp do urządzenia. Skonfiguruj teraz @@ -1899,10 +1920,10 @@ Odblokuj urządzenie - Odblokuj, aby użyć przechowywanych informacji o kartach płatniczych + Odblokuj, aby użyć przechowywanych informacji o kartach płatniczych - Odblokuj, aby użyć zachowanych metod płatności + Odblokuj, aby użyć zachowanych metod płatności Dodaj adres @@ -1910,11 +1931,13 @@ Zarządzaj adresami - Imię + Imię - Drugie imię + Drugie imię - Nazwisko + Nazwisko + + Imię i nazwisko Adres @@ -1938,9 +1961,9 @@ Usuń adres - Czy na pewno usunąć ten adres? + Czy na pewno usunąć ten adres? - Czy usunąć ten adres? + Czy usunąć ten adres? Usuń @@ -2038,49 +2061,49 @@ Edytuj - Czy na pewno usunąć te dane logowania? + Czy na pewno usunąć te dane logowania? - Czy na pewno usunąć to hasło? + Czy na pewno usunąć to hasło? Usuń Anuluj - Opcje danych logowania + Opcje danych logowania - Opcje haseł + Opcje haseł - Edytowalne pole tekstowe dla adresu witryny danych logowania. + Edytowalne pole tekstowe dla adresu witryny danych logowania. - Edytowalne pole tekstowe dla adresu witryny. + Edytowalne pole tekstowe dla adresu witryny. - Edytowalne pole tekstowe dla nazwy użytkownika danych logowania. + Edytowalne pole tekstowe dla nazwy użytkownika danych logowania. - Edytowalne pole tekstowe dla nazwy użytkownika. + Edytowalne pole tekstowe dla nazwy użytkownika. - Edytowalne pole tekstowe dla hasła danych logowania. + Edytowalne pole tekstowe dla hasła danych logowania. - Edytowalne pole tekstowe dla hasła. + Edytowalne pole tekstowe dla hasła. - Zachowaj zmiany danych logowania. + Zachowaj zmiany danych logowania. - Zachowaj zmiany. + Zachowaj zmiany. - Edycja + Edycja - Edycja hasła + Edycja hasła - Dodanie nowych danych logowania + Dodanie nowych danych logowania - Dodanie hasła + Dodanie hasła - Hasło jest wymagane + Hasło jest wymagane - Wpisz hasło + Wpisz hasło - Nazwa użytkownika jest wymagana + Nazwa użytkownika jest wymagana - Wpisz nazwę użytkownika + Wpisz nazwę użytkownika Adres jest wymagany @@ -2192,7 +2215,7 @@ Kliknij, aby wyświetlić więcej informacji - Przejdź w górę + Przejdź w górę Zamknij @@ -2250,6 +2273,10 @@ Przetłumaczyć tę stronę? + + Język oryginalnej strony: %1$s, język tłumaczenia: %2$s Wypróbuj prywatne tłumaczenia w przeglądarce %1$s @@ -2262,6 +2289,8 @@ Język docelowy: Nie teraz + + Wyświetl w oryginale OK @@ -2283,6 +2312,16 @@ Więcej informacji + + + Tłumaczenie… + + Pobrać język w trybie oszczędzania danych (%1$s)? + + Opcje tłumaczenia diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index ad71b6832..e45199c3c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -256,6 +256,11 @@ Traduzir página + + Página traduzida de %1$s para %2$s. + Selecionar idioma @@ -334,12 +339,22 @@ Aviso de privacidade do Firefox - + + Saiba mais em nosso aviso de privacidade Adoramos manter você seguro + + Descubra por que milhões adoram o Firefox + + Navegação segura com mais opções Nosso navegador respaldado por uma entidade sem fins lucrativos ajuda a impedir que empresas sigam você secretamente pela web. + Mais de 100 milhões de pessoas protegem sua privacidade escolhendo um navegador respaldado por uma organização sem fins lucrativos. + + Rastreadores conhecidos? Bloqueados automaticamente. Extensões? Experimente todas as 700. Documentos PDF? Nosso leitor integrado facilita gerenciar. + Nosso navegador respaldado por uma entidade sem fins lucrativos ajuda a impedir que empresas sigam você secretamente pela web.\n\nSaiba mais em nosso aviso de privacidade. @@ -696,9 +711,9 @@ Favoritos - Contas de acesso + Contas de acesso - Senhas + Senhas Abas abertas @@ -724,9 +739,9 @@ %1$s no %2$s %3$s - Cartões de crédito + Cartões de crédito - Métodos de pagamento + Métodos de pagamento Endereços @@ -1670,13 +1685,13 @@ Você pode facilmente adicionar este site à tela inicial do dispositivo para ter acesso imediato e navegar mais rápido com uma experiência semelhante a um aplicativo. - Contas e senhas + Contas e senhas - Senhas + Senhas - Salvar contas e senhas + Salvar contas e senhas - Salvar senhas + Salvar senhas Perguntar se deve salvar @@ -1691,47 +1706,47 @@ Preencher nomes de usuário e senhas em outros aplicativos no dispositivo. - Adicionar conta + Adicionar conta - Adicionar senha + Adicionar senha - - Sincronizar contas - Sincronizar senhas + Sincronizar contas + + Sincronizar senhas - Sincronizar contas entre dispositivos + Sincronizar contas entre dispositivos - Sincronizar senhas entre dispositivos + Sincronizar senhas entre dispositivos - Contas salvas + Contas salvas - Senhas salvas + Senhas salvas - As contas que você salvar ou sincronizar no %s aparecem aqui. + As contas que você salvar ou sincronizar no %s aparecem aqui. - As senhas que você salva ou sincroniza no %s aparecem aqui. Todas as senhas que você salva são criptografadas. + As senhas que você salva ou sincroniza no %s aparecem aqui. Todas as senhas que você salva são criptografadas. - Saiba mais sobre sincronização. + Saiba mais sobre sincronização. - Saiba mais sobre sincronização + Saiba mais sobre sincronização Exceções - Contas e senhas que não são salvas são mostradas aqui. + Contas e senhas que não são salvas são mostradas aqui. - O %s não salva senhas dos sites desta lista. + O %s não salva senhas dos sites desta lista. - Contas e senhas desses sites não serão salvas. + Contas e senhas desses sites não serão salvas. - O %s não salva senhas desses sites. + O %s não salva senhas desses sites. Excluir todas as exceções - Pesquisar contas + Pesquisar contas - Procurar senhas + Procurar senhas Site @@ -1759,18 +1774,18 @@ Ocultar senha - Desbloqueie para ver suas contas salvas + Desbloqueie para ver suas contas salvas - Desbloqueie para ver as senhas salvas + Desbloqueie para ver as senhas salvas - Proteja suas contas e senhas + Proteja suas contas e senhas - Proteja as senhas salvas + Proteja as senhas salvas - Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a suas contas e senhas salvas, caso outras pessoas usem seu dispositivo. + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a suas contas e senhas salvas, caso outras pessoas usem seu dispositivo. - Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a suas senhas salvas, caso outras pessoas usem seu dispositivo. + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a suas senhas salvas, caso outras pessoas usem seu dispositivo. Mais tarde @@ -1787,7 +1802,10 @@ Data de uso - Menu de ordenação de contas + Menu de ordenação de contas + + + Menu de ordenação de senhas Menu de ordenação de senhas @@ -1798,40 +1816,43 @@ Endereços - Cartões de crédito + Cartões de crédito - Métodos de pagamento + Métodos de pagamento - Salvar e preencher cartões automaticamente + Salvar e preencher cartões automaticamente - Salvar e preencher métodos de pagamento + Salvar e preencher métodos de pagamento - Os dados são criptografados + Os dados são criptografados - O %s criptografa todos os métodos de pagamento que você salva + O %s criptografa todos os métodos de pagamento que você salva Sincronizar cartões entre dispositivos Sincronizar cartões - Adicionar cartão de crédito + Adicionar cartão de crédito - Adicionar cartão + Adicionar cartão - Gerenciar cartões salvos + Gerenciar cartões salvos - Gerenciar cartões + Gerenciar cartões Adicionar endereço Gerenciar endereços - Salvar e preencher endereços automaticamente + Salvar e preencher endereços automaticamente - Salvar e preencher endereços + Salvar e preencher endereços - Incluir informações como números, email e endereços de entrega + Incluir informações como números, email e endereços de entrega + + + Incluir números de telefone e endereços de email Incluir números de telefone e endereços de email @@ -1855,9 +1876,9 @@ Excluir cartão - Tem certeza que quer excluir este cartão de crédito? + Tem certeza que quer excluir este cartão de crédito? - Excluir cartão? + Excluir cartão? Excluir @@ -1871,24 +1892,24 @@ Cartões salvos - Digite um número de cartão de crédito válido + Digite um número de cartão de crédito válido - Digite um número de cartão válido + Digite um número de cartão válido - Preencha este campo + Preencha este campo - Adicionar um nome + Adicionar um nome Desbloqueie para ver seus cartões salvos - Proteja seus cartões de crédito + Proteja seus cartões de crédito - Proteja seus métodos de pagamento salvos + Proteja seus métodos de pagamento salvos - Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a seus cartões de crédito salvos, caso outras pessoas usem seu dispositivo. + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a seus cartões de crédito salvos, caso outras pessoas usem seu dispositivo. - Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a seus métodos de pagamento salvos, caso outras pessoas usem seu dispositivo. + Configure um método de bloqueio do dispositivo (desenho, código PIN ou senha) para proteger o acesso a seus métodos de pagamento salvos, caso outras pessoas usem seu dispositivo. Configurar agora @@ -1897,10 +1918,10 @@ Desbloquear dispositivo - Desbloqueie para usar informações armazenadas de cartões de crédito + Desbloqueie para usar informações armazenadas de cartões de crédito - Desbloqueie para usar formas de pagamento salvas + Desbloqueie para usar formas de pagamento salvas Adicionar endereço @@ -1909,11 +1930,13 @@ Gerenciar endereços - Primeiro nome + Primeiro nome - Nome do meio + Nome do meio - Sobrenome + Sobrenome + + Nome Endereço @@ -1938,9 +1961,9 @@ Excluir endereço - Tem certeza que quer excluir este endereço? + Tem certeza que quer excluir este endereço? - Excluir este endereço? + Excluir este endereço? Excluir @@ -2038,49 +2061,49 @@ Editar - Tem certeza que quer excluir esta conta? + Tem certeza que quer excluir esta conta? - Tem certeza que quer excluir esta senha? + Tem certeza que quer excluir esta senha? Excluir Cancelar - Opções da conta + Opções da conta - Opções de senhas + Opções de senhas - O campo de texto editável do endereço web da conta. + O campo de texto editável do endereço web da conta. - O campo de texto editável do endereço do site. + O campo de texto editável do endereço do site. - O campo de texto editável do nome de usuário da conta. + O campo de texto editável do nome de usuário da conta. - O campo de texto editável do nome de usuário. + O campo de texto editável do nome de usuário. - O campo de texto editável da senha da conta. + O campo de texto editável da senha da conta. - O campo de texto editável da senha. + O campo de texto editável da senha. - Salvar alterações na conta. + Salvar alterações na conta. - Salvar alterações. + Salvar alterações. - Editar + Editar - Editar senha + Editar senha - Adicionar conta + Adicionar conta - Adicionar senha + Adicionar senha - Senha é obrigatória + Senha é obrigatória - Digite uma senha + Digite uma senha - Nome de usuário é obrigatório + Nome de usuário é obrigatório - Digite um nome de usuário + Digite um nome de usuário Nome de servidor é obrigatório @@ -2194,7 +2217,7 @@ Clique para ver mais detalhes - Ir para o topo + Ir para o topo Fechar @@ -2235,8 +2258,6 @@ Classificação ajustada - Avaliações não confiáveis removidas - Baseado em avaliações confiáveis Destaques de avaliações recentes @@ -2294,10 +2315,6 @@ Se você perceber que tem este produto novamente em estoque, informe para nós e trabalharemos na verificação de avaliações. Informar que tem o produto em estoque - - Verificando a qualidade das avaliações - - Verificando a qualidade das avaliações Verificando a qualidade das avaliações (%s) @@ -2344,13 +2361,19 @@ Saiba mais - Ao selecionar “Sim, experimentar”, você concorda com a %2$s e os %3$s do %1$s da Mozilla. + Ao selecionar “Sim, experimentar”, você concorda com a %2$s e os %3$s do %1$s da Mozilla. Ao selecionar “Sim, experimentar” você declara que concorda com o seguinte da %1$s: + + Ao selecionar “Sim, experimentar” você declara que concorda com a %2$s do %1$s e os %4$s do %3$s. + + Ao selecionar “Sim, experimentar” você declara que concorda com a %2$s do %1$s e os %4$s do %3$s. - política de privacidade + política de privacidade Política de privacidade + + aviso de privacidade termos de uso @@ -2422,6 +2445,10 @@ Traduzir esta página? + + Página traduzida de %1$s para %2$s Experimente tradução privativa no %1$s @@ -2435,6 +2462,8 @@ Traduzir para Agora não + + Mostrar original Pronto @@ -2457,6 +2486,16 @@ Saiba mais + + Traduzindo… + + + Baixar idioma no modo de economia de dados (%1$s)? + + Opções de tradução diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 1885805a7..917e95216 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -255,6 +255,11 @@ Traduzir página + + Página traduzida de %1$s para %2$s. + Idioma selecionado @@ -333,12 +338,22 @@ Política de privacidade do Firefox - + + Saiba mais nas nossas informações de privacidade Adoramos mantê-lo(a) seguro(a) + + Descubra porque milhões adoram o Firefox + + Navegação segura, com mais opções O nosso navegador, apoiado por uma organização sem fins lucrativos, ajuda a impedir que as empresas o sigam secretamente pela Internet. + Mais de 100 milhões de pessoas protegem a sua privacidade ao escolher um navegador apoiado por uma organização sem fins lucrativos. + + Rastreadores conhecidos? Bloqueados automaticamente. Extensões? Experimente todas as 700. PDF? O nosso leitor integrado facilita a sua gestão. + O nosso navegador, apoiado por uma organização sem fins lucrativos, ajuda a impedir que as empresas o sigam secretamente pela web.\n\n Saiba mais nas nossas informações de privacidade. @@ -693,9 +708,9 @@ Marcadores - Credenciais + Credenciais - Palavras-passe + Palavras-passe Separadores abertos @@ -721,9 +736,9 @@ %1$s no %2$s %3$s - Cartões de crédito + Cartões de crédito - Métodos de pagamento + Métodos de pagamento Moradas @@ -1668,14 +1683,14 @@ Pode adicionar facilmente este site ao ecrã inicial do seu dispositivo para ter acesso instantâneo e navegar mais rápido, com uma experiência semelhante ao de uma aplicação. - Credenciais e palavras-passe + Credenciais e palavras-passe - Palavras-passe + Palavras-passe - Guardar credenciais e palavras-passe + Guardar credenciais e palavras-passe - Guardar palavras-passe + Guardar palavras-passe Pedir para guardar @@ -1690,48 +1705,48 @@ Preencher nomes de utilizador e palavras-passe noutras aplicações no seu dispositivo. - Adicionar credenciais + Adicionar credenciais - Adicionar palavra-passe + Adicionar palavra-passe - - Sincronização de credenciais - Sincronizar palavras-passe + Sincronização de credenciais + + Sincronizar palavras-passe - Sincronizar credenciais entre dispositivos + Sincronizar credenciais entre dispositivos - Sincronize palavras-passe entre dispositivos + Sincronize palavras-passe entre dispositivos - Credenciais guardadas + Credenciais guardadas - Palavras-passe guardadas + Palavras-passe guardadas - As credenciais que guardar ou sincronizar com o %s serão apresentadas aqui. + As credenciais que guardar ou sincronizar com o %s serão apresentadas aqui. - As palavras-passe que guardar ou sincronizar com o %s serão listadas aqui. Todas as palavras-passe que guarda são encriptadas. + As palavras-passe que guardar ou sincronizar com o %s serão listadas aqui. Todas as palavras-passe que guarda são encriptadas. - Saber mais sobre a sincronização. + Saber mais sobre a sincronização. - Saber mais sobre a sincronização + Saber mais sobre a sincronização Exceções - As credenciais e palavras-passe que não estão guardadas serão mostradas aqui. + As credenciais e palavras-passe que não estão guardadas serão mostradas aqui. - O %s não irá guardar palavras-passe para sites listados aqui. + O %s não irá guardar palavras-passe para sites listados aqui. - As credenciais e palavras-passe não serão guardadas para estes sites. + As credenciais e palavras-passe não serão guardadas para estes sites. - O %s não irá guardar as palavras-passe para estes sites. + O %s não irá guardar as palavras-passe para estes sites. Eliminar todas as exceções - Pesquisar credenciais + Pesquisar credenciais - Procurar palavras-passe + Procurar palavras-passe Site @@ -1760,17 +1775,17 @@ Ocultar palavra-passe - Desbloqueie para ver as credenciais guardadas + Desbloqueie para ver as credenciais guardadas - Desbloqueie para ver as palavras-passe guardadas + Desbloqueie para ver as palavras-passe guardadas - Proteja as suas credenciais e palavras-passe + Proteja as suas credenciais e palavras-passe - Proteja as suas palavras-passe guardadas + Proteja as suas palavras-passe guardadas - Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que as suas credenciais e palavras-passe guardadas sejam acedidas por outra pessoa que tenha acesso ao seu dispositivo. + Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que as suas credenciais e palavras-passe guardadas sejam acedidas por outra pessoa que tenha acesso ao seu dispositivo. - Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que as suas palavras-passe guardadas sejam acedidas por outra pessoa que tenha acesso ao seu dispositivo. + Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que as suas palavras-passe guardadas sejam acedidas por outra pessoa que tenha acesso ao seu dispositivo. Mais tarde @@ -1787,7 +1802,10 @@ Última utilização - Menu de ordenação de credenciais + Menu de ordenação de credenciais + + + Menu de ordenação de palavras-passe Menu de ordenação de palavras-passe @@ -1798,41 +1816,44 @@ Endereços - Cartões de crédito + Cartões de crédito - Métodos de pagamento + Métodos de pagamento - Guardar e preencher automaticamente cartões + Guardar e preencher automaticamente cartões - Guardar e preencher métodos de pagamento + Guardar e preencher métodos de pagamento - Os dados são encriptados + Os dados são encriptados - O %s encripta todos os métodos de pagamento que guarda + O %s encripta todos os métodos de pagamento que guarda Sincronizar cartões entre dispositivos Sincronizar cartões - Adicionar cartão de crédito + Adicionar cartão de crédito - Adicionar cartão + Adicionar cartão - Gerir cartões guardados + Gerir cartões guardados - Gerir cartões + Gerir cartões Adicionar endereço Gerir endereços - Guardar e preencher automaticamente endereços + Guardar e preencher automaticamente endereços - Guardar e preencher endereços + Guardar e preencher endereços - Incluir informações como números, e-mail e endereços de entrega + Incluir informações como números, e-mail e endereços de entrega + + + Inclui números de telefone e endereços de e-mail Inclui números de telefone e endereços de e-mail @@ -1856,9 +1877,9 @@ Eliminar cartão - Tem a certeza de que quer apagar este cartão de crédito? + Tem a certeza de que quer apagar este cartão de crédito? - Eliminar cartão? + Eliminar cartão? Apagar @@ -1872,23 +1893,23 @@ Cartões guardados - Por favor, introduza um número de cartão de crédito válido + Por favor, introduza um número de cartão de crédito válido - Insira um número de cartão válido + Insira um número de cartão válido - Por favor preencha este campo + Por favor preencha este campo - Adicionar um nome + Adicionar um nome Desbloquear para ver os cartões guardados - Proteja os seus cartões de crédito + Proteja os seus cartões de crédito - Proteja os seus métodos de pagamento guardados + Proteja os seus métodos de pagamento guardados - Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que os seus cartões de crédito guardados sejam acedidos por outra pessoa que tenha acesso ao seu dispositivo. + Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que os seus cartões de crédito guardados sejam acedidos por outra pessoa que tenha acesso ao seu dispositivo. - Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que os seus métodos de pagamento guardados sejam acedidos por outra pessoa que tenha acesso ao seu dispositivo. + Configure um padrão, PIN ou palavra-passe de bloqueio do dispositivo para impedir que os seus métodos de pagamento guardados sejam acedidos por outra pessoa que tenha acesso ao seu dispositivo. Configurar agora @@ -1896,10 +1917,10 @@ Desbloquear o seu dispositivo - Desbloquear para utilizar as informações de cartão de crédito armazenadas + Desbloquear para utilizar as informações de cartão de crédito armazenadas - Desbloquear para utilizar métodos de pagamento guardados + Desbloquear para utilizar métodos de pagamento guardados Adicionar endereço @@ -1907,11 +1928,13 @@ Gerir endereços - Primeiro nome + Primeiro nome - Nome do meio + Nome do meio - Último nome + Último nome + + Nome Endereço da rua @@ -1936,9 +1959,9 @@ Apagar endereço - Tem a certeza de que quer eliminar este endereço? + Tem a certeza de que quer eliminar este endereço? - Eliminar este endereço? + Eliminar este endereço? Apagar @@ -2037,49 +2060,49 @@ Editar - Tem a certeza que deseja eliminar esta credencial? + Tem a certeza que deseja eliminar esta credencial? - Tem a certeza que quer eliminar esta palavra-passe? + Tem a certeza que quer eliminar esta palavra-passe? Eliminar Cancelar - Opções de credenciais + Opções de credenciais - Opções de palavra-passe + Opções de palavra-passe - O campo de texto editável para o endereço de Internet da credencial. + O campo de texto editável para o endereço de Internet da credencial. - O campo de texto editável para o endereço do site. + O campo de texto editável para o endereço do site. - O campo de texto editável para o nome de utilizador da credencial. + O campo de texto editável para o nome de utilizador da credencial. - O campo de texto editável para o nome de utilizador. + O campo de texto editável para o nome de utilizador. - O campo de texto editável para a palavra-passe da credencial. + O campo de texto editável para a palavra-passe da credencial. - O campo de texto editável para a palavra-passe. + O campo de texto editável para a palavra-passe. - Guardar alterações na credencial. + Guardar alterações na credencial. - Guardar alterações. + Guardar alterações. - Editar + Editar - Editar palavra-passe + Editar palavra-passe - Adicionar nova credencial + Adicionar nova credencial - Adicionar palavra-passe + Adicionar palavra-passe - É necessária uma palavra-passe + É necessária uma palavra-passe - Introduza uma palavra-passe + Introduza uma palavra-passe - É necessário um nome de utilizador + É necessário um nome de utilizador - Introduza um nome de utilizador + Introduza um nome de utilizador É necessário um nome de servidor @@ -2192,7 +2215,7 @@ Clique para mais detalhes - Navegar para cima + Navegar para cima Fechar @@ -2233,8 +2256,6 @@ Classificação ajustada - Avaliações não confiáveis removidas - Baseado em avaliações confiáveis Destaques das avaliações recentes @@ -2290,10 +2311,6 @@ Se perceber que este produto está novamente em stock, reporte e iremos verificar as avaliações. Informar que o produto está em stock - - A verificar a qualidade da avaliação - - A verificar a qualidade da avaliação A verificar a qualidade da avaliação (%s) @@ -2339,13 +2356,19 @@ Saber mais - Ao selecionar “Sim, experimentar”, concorda com a %2$s e %3$s de %1$s da Mozilla. + Ao selecionar “Sim, experimentar”, concorda com a %2$s e %3$s de %1$s da Mozilla. Ao selecionar “Sim, experimentar”, concorda com o seguinte de %1$s: + + Ao selecionar “Sim, experimentar” concorda com a %2$s de %1$s e com a %4$s de %3$s. + + Ao selecionar “Sim, experimentar” concorda com a %2$s de %1$s e com a %4$s de %3$s. - política de privacidade + política de privacidade Política de privacidade + + informação de privacidade termos de utilização @@ -2416,6 +2439,10 @@ Traduzir esta página? + + Página traduzida de %1$s para %2$s Experimente as traduções privadas no %1$s @@ -2428,6 +2455,8 @@ Traduzir para Agora não + + Mostrar original Feito @@ -2439,7 +2468,7 @@ Tradução em curso - Escolha um idioma + Escolher um idioma Ocorreu um problema com a tradução. Por favor, tente novamente. @@ -2449,6 +2478,16 @@ Saber mais + + A traduzir… + + + Transferir idioma no modo de poupança de dados (%1$s)? + + Opções de tradução diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index b6efef041..6a482c19c 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -203,7 +203,6 @@ Motor de căutare %s - Ne place să te protejăm @@ -357,7 +356,7 @@ Marcaje - Date de autentificare + Date de autentificare File deschise @@ -382,6 +381,9 @@ and the third is the device model. --> %1$s pe %2$s %3$s + + Metode de plată + File primite @@ -1033,34 +1035,34 @@ Poți adăuga cu ușurință acest site web în ecranul de start al dispozitivului pentru acces instant și o navigare mai rapidă, ca și cum ai fi într-o aplicație. - Date de autentificare și parole + Date de autentificare și parole - Salvează datele de autentificare și parolele + Salvează datele de autentificare și parolele Întreabă pentru salvare Nu salva niciodată - - Sincronizează datele de autentificare + + Sincronizează datele de autentificare - Sincronizează datele de autentificare între dispozitive + Sincronizează datele de autentificare între dispozitive - Date de autentificare salvate + Date de autentificare salvate - Aici vor apărea datele de autentificare pe care le salvezi sau le sincronizezi în %s. + Aici vor apărea datele de autentificare pe care le salvezi sau le sincronizezi în %s. - Află mai multe despre Sync. + Află mai multe despre Sync. Excepții - Aici vor apărea datele de autentificare și parolele nesalvate. + Aici vor apărea datele de autentificare și parolele nesalvate. - Datele de autentificare și parolele nu vor fi salvate pentru aceste site-uri. + Datele de autentificare și parolele nu vor fi salvate pentru aceste site-uri. Șterge toate excepțiile - Caută date de autentificare + Caută date de autentificare Site @@ -1082,12 +1084,12 @@ Ascunde parola - Deblochează pentru a vizualiza datele de autentificare salvate + Deblochează pentru a vizualiza datele de autentificare salvate - Securizează-ți datele de autentificare și parolele + Securizează-ți datele de autentificare și parolele - Configurează un șablon de blocare a dispozitivului, un PIN sau o parolă pentru a-ți proteja datele de autentificare și parolele salvate împotriva accesării de către altcineva care are dispozitivul. + Configurează un șablon de blocare a dispozitivului, un PIN sau o parolă pentru a-ți proteja datele de autentificare și parolele salvate împotriva accesării de către altcineva care are dispozitivul. Mai târziu @@ -1104,7 +1106,12 @@ Folosite ultima dată - Meniu de sortare a datelor de autentificare + Meniu de sortare a datelor de autentificare + + + Metode de plată + + Salvează și completează metodele de plată Adaugă un motor de căutare @@ -1163,24 +1170,24 @@ Editează - Sigur vrei să ștergi aceste date de autentificare? + Sigur vrei să ștergi aceste date de autentificare? Șterge - Opțiuni de autentificare + Opțiuni de autentificare - Câmpul de text editabil pentru adresa web a datelor de autentificare. + Câmpul de text editabil pentru adresa web a datelor de autentificare. - Câmpul de text editabil pentru numele de utilizator al datelor de autentificare. + Câmpul de text editabil pentru numele de utilizator al datelor de autentificare. - Câmp de text editabil pentru parola datelor de autentificare. + Câmp de text editabil pentru parola datelor de autentificare. - Salvează modificările datelor de autentificare. + Salvează modificările datelor de autentificare. - Editează + Editează - Necesită o parolă + Necesită o parolă Căutare vocală @@ -1225,4 +1232,11 @@ + + + Oferă întotdeauna traducerea + + + Suprascrie oferirea traducerii + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 749de3588..3ece4f592 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -262,6 +262,11 @@ Перевести страницу + + Страница переведена с %1$s на %2$s. + Текущий язык @@ -340,12 +345,22 @@ Уведомление о конфиденциальности Firefox - + + Узнайте больше в нашем уведомлении о конфиденциальности Нам нравится обеспечивать вашу безопасность + + Узнайте, почему миллионы людей любят Firefox + + Безопасный веб-сёрфинг с большим выбором Наш браузер, поддерживаемый некоммерческой организацией, помогает не давать компаниям следить за вами в Интернете. + Более 100 миллионов человек защищают свою приватность, выбирая браузер, поддерживаемый некоммерческой организацией. + + Известные трекеры? Блокируются автоматически. Расширения? Попробовать все 700. PDF-файлы? Наша встроенная программа чтения позволяет легко ими управлять. + Наш браузер, поддерживаемый некоммерческой организацией, помогает ограничивать компании от слежки за вами в Интернете.\n\nПодробнее читайте в нашем уведомлении о конфиденциальности. @@ -701,9 +716,9 @@ Закладки - Пароли + Пароли - Пароли + Пароли Открытые вкладки @@ -729,9 +744,9 @@ %1$s на %2$s %3$s - Банковские карты + Банковские карты - Способы оплаты + Способы оплаты Адреса @@ -1693,13 +1708,13 @@ Вы можете легко добавить этот сайт на домашний экран вашего устройства, чтобы иметь к нему мгновенный доступ. - Пароли + Пароли - Пароли + Пароли - Сохранение паролей + Сохранение паролей - Сохранять пароли + Сохранять пароли Предлагать сохранить @@ -1714,48 +1729,48 @@ Заполнять имена пользователей и пароли в других приложениях на вашем устройстве. - Добавить логин + Добавить логин - Добавить пароль + Добавить пароль - - Синхронизация логинов - Синхронизировать пароли + Синхронизация логинов + + Синхронизировать пароли - Синхронизировать логины между устройствами + Синхронизировать логины между устройствами - Синхронизировать пароли между устройствами + Синхронизировать пароли между устройствами - Сохранённые пароли + Сохранённые пароли - Сохранённые пароли + Сохранённые пароли - Пароли, которые вы сохраняете или синхронизируете в %s, появятся тут. + Пароли, которые вы сохраняете или синхронизируете в %s, появятся тут. - Пароли, которые вы сохраните или синхронизируете в %s, будут показаны здесь. Все сохраняемые вами пароли зашифрованы. + Пароли, которые вы сохраните или синхронизируете в %s, будут показаны здесь. Все сохраняемые вами пароли зашифрованы. - Узнайте больше о синхронизации. + Узнайте больше о синхронизации. - Узнайте больше о синхронизации + Узнайте больше о синхронизации Исключения - Здесь будут показаны не сохраняемые логины и пароли. + Здесь будут показаны не сохраняемые логины и пароли. - %s не будет сохранять пароли для перечисленных здесь сайтов. + %s не будет сохранять пароли для перечисленных здесь сайтов. - Логины и пароли для этих сайтов сохраняться не будут. + Логины и пароли для этих сайтов сохраняться не будут. - %s не будет сохранять пароли для этих сайтов. + %s не будет сохранять пароли для этих сайтов. Удалить все исключения - Поиск логинов + Поиск логинов - Поиск паролей + Поиск паролей Сайт @@ -1783,17 +1798,17 @@ Скрыть пароль - Разблокируйте, чтобы просмотреть сохранённые пароли + Разблокируйте, чтобы просмотреть сохранённые пароли - Разблокируйте, чтобы просмотреть сохранённые пароли + Разблокируйте, чтобы просмотреть сохранённые пароли - Защитите свои логины и пароли + Защитите свои логины и пароли - Защитите сохранённые пароли + Защитите сохранённые пароли - Настройте графический ключ, Пин-код или пароль для блокировки устройства, чтобы защитить сохранённые пароли, если кто-либо ещё получит доступ к вашему устройству. + Настройте графический ключ, Пин-код или пароль для блокировки устройства, чтобы защитить сохранённые пароли, если кто-либо ещё получит доступ к вашему устройству. - Настройте графический ключ, пин-код или пароль для разблокировки устройства, чтобы защитить сохранённые пароли на случай, если кто-либо ещё получит доступ к вашему устройству. + Настройте графический ключ, пин-код или пароль для разблокировки устройства, чтобы защитить сохранённые пароли на случай, если кто-либо ещё получит доступ к вашему устройству. Позже @@ -1810,7 +1825,10 @@ По последнему использованию - Меню сортировки логинов + Меню сортировки логинов + + + Меню сортировки паролей Меню сортировки паролей @@ -1821,40 +1839,43 @@ Адреса - Банковские карты + Банковские карты - Способы оплаты + Способы оплаты - Сохранять и автоматически заполнять данные карт + Сохранять и автоматически заполнять данные карт - Сохранить и заполнять способы оплаты + Сохранить и заполнять способы оплаты - Данные зашифрованы + Данные зашифрованы - %s шифрует все сохраняемые вами способы оплаты + %s шифрует все сохраняемые вами способы оплаты Синхронизировать карты между различными устройствами Синхронизировать карты - Добавить банковскую карту + Добавить банковскую карту - Добавить карту + Добавить карту - Управление сохранёнными картами + Управление сохранёнными картами - Управление картами + Управление картами Добавить адрес Управление адресами - Сохранять и автоматически заполнять адреса + Сохранять и автоматически заполнять адреса - Сохранять и заполнять адреса + Сохранять и заполнять адреса - Включая такие сведения, как номера, адреса эл. почты и доставок + Включая такие сведения, как номера, адреса эл. почты и доставок + + + Включает номера телефонов и адреса электронной почты Включает номера телефонов и адреса электронной почты @@ -1878,9 +1899,9 @@ Удалить карту - Вы уверены, что хотите удалить эту банковскую карту? + Вы уверены, что хотите удалить эту банковскую карту? - Удалить карту? + Удалить карту? Удалить @@ -1893,24 +1914,24 @@ Сохранённые карты - Пожалуйста, введите правильный номер карты + Пожалуйста, введите правильный номер карты - Введите корректный номер карты + Введите корректный номер карты - Пожалуйста, заполните это поле + Пожалуйста, заполните это поле - Добавьте имя + Добавьте имя Разблокируйте, чтобы просмотреть сохранённые карты - Защитите свои банковские карты + Защитите свои банковские карты - Защитите сохранённые способы оплаты + Защитите сохранённые способы оплаты - Настройте графический ключ, Пин-код или пароль для блокировки устройства, чтобы защитить сохранённые банковские карты, если кто-либо ещё получит доступ к вашему устройству. + Настройте графический ключ, Пин-код или пароль для блокировки устройства, чтобы защитить сохранённые банковские карты, если кто-либо ещё получит доступ к вашему устройству. - Настройте графический ключ, Пин-код или пароль для разблокировки устройства, чтобы защитить сохранённые способы оплаты, на случай, если кто-либо ещё получит доступ к вашему устройству. + Настройте графический ключ, Пин-код или пароль для разблокировки устройства, чтобы защитить сохранённые способы оплаты, на случай, если кто-либо ещё получит доступ к вашему устройству. Настроить сейчас @@ -1918,10 +1939,10 @@ Разблокируйте своё устройство - Разблокируйте, чтобы использовать сохранённые данные банковской карты + Разблокируйте, чтобы использовать сохранённые данные банковской карты - Разблокируйте, чтобы использовать сохранённые способы оплаты + Разблокируйте, чтобы использовать сохранённые способы оплаты Добавить адрес @@ -1929,11 +1950,13 @@ Управление адресами - Имя + Имя - Отчество + Отчество - Фамилия + Фамилия + + Название Улица @@ -1957,9 +1980,9 @@ Удалить адрес - Вы уверены, что хотите удалить этот адрес? + Вы уверены, что хотите удалить этот адрес? - Удалить этот адрес? + Удалить этот адрес? Удалить @@ -2057,49 +2080,49 @@ Править - Вы уверены, что хотите удалить этот пароль? + Вы уверены, что хотите удалить этот пароль? - Вы уверены, что хотите удалить этот пароль? + Вы уверены, что хотите удалить этот пароль? Удалить Отмена - Настройки логина + Настройки логина - Настройки пароля + Настройки пароля - Редактируемое текстовое поле для веб-адреса логина. + Редактируемое текстовое поле для веб-адреса логина. - Редактируемое текстовое поле для адреса веб-сайта. + Редактируемое текстовое поле для адреса веб-сайта. - Редактируемое текстовое поле для имени пользователя логина. + Редактируемое текстовое поле для имени пользователя логина. - Редактируемое текстовое поле для имени пользователя. + Редактируемое текстовое поле для имени пользователя. - Редактируемое текстовое поле для пароля логина. + Редактируемое текстовое поле для пароля логина. - Редактируемое текстовое поле для пароля. + Редактируемое текстовое поле для пароля. - Сохранить изменения в логине. + Сохранить изменения в логине. - Сохранить изменения. + Сохранить изменения. - Правка + Правка - Изменить пароль + Изменить пароль - Добавить новый логин + Добавить новый логин - Добавить пароль + Добавить пароль - Требуется пароль + Требуется пароль - Введите пароль + Введите пароль - Требуется имя пользователя + Требуется имя пользователя - Введите имя пользователя + Введите имя пользователя Введите имя сервера @@ -2212,7 +2235,7 @@ Нажмите, чтобы узнать больше - Перейти наверх + Перейти наверх Закрыть @@ -2253,8 +2276,6 @@ Скорректированный рейтинг - Недостоверные отзывы удалены - На основе достоверных отзывов Основные моменты из недавних обзоров @@ -2310,10 +2331,6 @@ Если вы увидите, что этот товар снова в наличии, сообщите об этом, и мы проверим отзывы. Сообщить о наличии товара на складе - - Проверяем качество отзывов - - Проверяем качество отзывов Проверка качество отзывов (%s) @@ -2359,13 +2376,19 @@ Узнать больше - Выбрав «Да, попробовать», вы соглашаетесь с %1$s принимая %2$s и %3$s от Mozilla. + Выбрав «Да, попробовать», вы соглашаетесь с %1$s принимая %2$s и %3$s от Mozilla. Выбирая «Да, попробовать», вы соглашаетесь со следующим от %1$s: + + Выбрав «Да, попробовать», вы соглашаетесь с %2$s %1$s и %4$s %3$s. + + Выбрав «Да, попробовать», вы соглашаетесь с %2$s %1$s и %4$s %3$s. - политику приватности + политику приватности Политика конфиденциальности + + уведомление о конфиденциальности условия использования @@ -2470,6 +2493,10 @@ Перевести эту страницу? + + Страница переведена с %1$s на %2$s Попробуйте конфиденциальные переводы в %1$s @@ -2482,6 +2509,8 @@ Перевести на Не сейчас + + Показать оригинал Готово @@ -2504,6 +2533,16 @@ Узнать больше + + Перевод… + + + Загрузить язык в режиме сохранения трафика (%1$s)? + + Настройки перевода diff --git a/app/src/main/res/values-sat/strings.xml b/app/src/main/res/values-sat/strings.xml index db302a987..c172e7be8 100644 --- a/app/src/main/res/values-sat/strings.xml +++ b/app/src/main/res/values-sat/strings.xml @@ -220,6 +220,7 @@ ᱚᱲᱟᱜᱥᱟᱦᱴᱟ ᱠᱩᱥᱤᱛᱮ ᱫᱚᱦᱚᱭ ᱢᱮ + ᱚᱲᱟᱜ ᱥᱠᱨᱤᱱ @@ -235,8 +236,6 @@ ᱥᱠᱟᱱ - - ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱤᱧᱡᱤᱱ ᱥᱟᱡᱟᱣ ᱠᱚ @@ -292,56 +291,26 @@ - %s ᱮᱛᱞᱟᱤᱭᱟᱹ ᱥᱟᱞᱟᱜ ᱵᱟᱹᱲᱛᱤ ᱠᱟᱹᱢᱤ ᱠᱚᱨᱟᱣ ᱨᱮ ᱜᱚᱲᱚ ᱮᱢᱚᱜᱼᱟᱭ + %s ᱮᱛᱞᱟᱤᱭᱟᱹ ᱥᱟᱞᱟᱜ ᱵᱟᱹᱲᱛᱤ ᱠᱟᱹᱢᱤ ᱠᱚᱨᱟᱣ ᱨᱮ ᱜᱚᱲᱚ ᱮᱢᱚᱜᱼᱟᱭ - ᱟᱢᱟᱜ ᱴᱮᱵᱽ ᱠᱚ ᱥᱟᱫᱷᱚᱱ ᱠᱚ ᱢᱩᱫᱽ ᱨᱮ ᱥᱤᱱᱠᱨᱚᱱᱤᱠᱮᱥᱚᱱ ᱢᱮ, ᱰᱟᱣᱩᱱᱞᱚᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ, %s ᱦᱟᱜ ᱯᱨᱟᱭᱵᱷᱮᱥᱤ ᱨᱩᱠᱷᱤᱭᱟᱹ ᱠᱷᱚᱱ ᱡᱚᱛᱚ ᱠᱷᱚᱱ ᱰᱷᱮᱨ ᱵᱮᱵᱷᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱥ ᱧᱟᱢ ᱢᱮ, ᱟᱨᱦᱚᱸ ᱟᱭᱢᱟ ᱡᱤᱱᱤᱥ ᱵᱟᱲᱟᱭ ᱡᱚᱝ ᱢᱮ ᱾ + ᱟᱢᱟᱜ ᱴᱮᱵᱽ ᱠᱚ ᱥᱟᱫᱷᱚᱱ ᱠᱚ ᱢᱩᱫᱽ ᱨᱮ ᱥᱤᱱᱠᱨᱚᱱᱤᱠᱮᱥᱚᱱ ᱢᱮ, ᱰᱟᱣᱩᱱᱞᱚᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ, %s ᱦᱟᱜ ᱯᱨᱟᱭᱵᱷᱮᱥᱤ ᱨᱩᱠᱷᱤᱭᱟᱹ ᱠᱷᱚᱱ ᱡᱚᱛᱚ ᱠᱷᱚᱱ ᱰᱷᱮᱨ ᱵᱮᱵᱷᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱥ ᱧᱟᱢ ᱢᱮ, ᱟᱨᱦᱚᱸ ᱟᱭᱢᱟ ᱡᱤᱱᱤᱥ ᱵᱟᱲᱟᱭ ᱡᱚᱝ ᱢᱮ ᱾ - ᱞᱮᱛᱟᱲ + ᱞᱮᱛᱟᱲ - ᱱᱤᱛᱚᱜ ᱫᱚ ᱵᱟᱝᱟ + ᱱᱤᱛᱚᱜ ᱫᱚ ᱵᱟᱝᱟ - - - %s ᱟᱢᱟᱜ ᱠᱩᱥᱤ ᱵᱽᱨᱟᱣᱡᱚᱨ ᱛᱮᱭᱟᱨ ᱢᱮ - - Firefox ᱫᱚ ᱟᱢᱟᱜ ᱱᱤᱡᱚᱨᱟᱜ ᱵᱽᱨᱟᱣᱡᱚᱨ ᱦᱟᱛᱟᱣ ᱢᱮ - - %1$s ᱫᱚ ᱦᱚᱲ ᱠᱚ ᱵᱮᱯᱟᱨ ᱠᱷᱚᱱ ᱢᱩᱬᱩᱛ ᱨᱮ ᱫᱚᱦᱚᱭᱟ ᱟᱨ ᱠᱨᱚᱥ-ᱥᱟᱭᱤᱴ ᱴᱨᱮᱠᱚᱨ ᱵᱞᱚᱠ ᱠᱟᱛᱮ ᱟᱢᱟᱜ ᱯᱨᱟᱵᱷᱮᱴᱤ ᱫᱚᱦᱚᱭᱟ ᱾\n\n ᱟᱞᱮᱭᱟᱜ %2$s ᱨᱮ ᱰᱷᱮᱨ ᱵᱟᱲᱟᱭ ᱢᱮ ᱾ - - Firefox ᱫᱚ ᱦᱚᱲ ᱠᱚ ᱵᱮᱯᱟᱨ ᱠᱷᱚᱱ ᱢᱩᱬᱩᱛ ᱨᱮ ᱫᱚᱦᱚᱭᱟ ᱟᱨ ᱠᱨᱚᱥ-ᱥᱟᱭᱤᱴ ᱴᱨᱮᱠᱚᱨ ᱵᱞᱚᱠ ᱠᱟᱛᱮ ᱟᱢᱟᱜ ᱯᱨᱟᱵᱷᱮᱴᱤ ᱫᱚᱦᱚᱭᱟ ᱾\n\n ᱟᱞᱮᱭᱟᱜ ᱫᱟᱱᱟᱝ ᱠᱷᱚᱵᱚᱨ ᱨᱮ ᱰᱷᱮᱨ ᱵᱟᱲᱟᱭ ᱢᱮ ᱾ - ᱱᱤᱥᱚᱱ ᱨᱮᱭᱟᱜ ᱱᱚᱴᱤᱥ + ᱱᱤᱥᱚᱱ ᱨᱮᱭᱟᱜ ᱱᱚᱴᱤᱥ ᱢᱩᱞ ᱵᱽᱨᱟᱣᱩᱡᱟᱹᱨ ᱞᱮᱠᱷᱟ ᱥᱟᱡᱟᱣ ᱢᱮ ᱱᱤᱛᱚᱜ ᱫᱚ ᱵᱟᱝᱟ - - ᱯᱷᱚᱱ ᱠᱷᱚᱱ ᱞᱮᱯᱴᱚᱯ ᱛᱮ ᱩᱪᱟᱹᱲ ᱢᱮ ᱵᱟᱨ ᱯᱟᱦᱴᱮ ᱞᱮᱠᱟᱛᱮ - - ᱴᱮᱵᱽ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫ ᱫᱚ ᱮᱴᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱠᱷᱚᱱ ᱡᱟᱦᱟᱸ ᱨᱮ ᱟᱲᱟᱜ ᱞᱮᱫᱟᱢ ᱚᱱᱰᱮ ᱠᱷᱚᱱ ᱯᱟᱧᱡᱟ ᱫᱟᱲᱮᱭᱟᱜᱼᱟᱢ ᱾ ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱱᱤᱛᱚᱜ ᱫᱚ ᱵᱟᱝᱟ - - %s ᱮᱛᱞᱟᱤᱭᱟᱹ ᱥᱟᱞᱟᱜ ᱵᱟᱹᱲᱛᱤ ᱠᱟᱹᱢᱤ ᱠᱚᱨᱟᱣ ᱨᱮ ᱜᱚᱲᱚ ᱮᱢᱚᱜᱼᱟᱭ - - Firefox ᱮᱛᱞᱟᱤᱭᱟᱹ ᱥᱟᱞᱟᱜ ᱵᱟᱹᱲᱛᱤ ᱠᱟᱹᱢᱤ ᱠᱚᱨᱟᱣ ᱨᱮ ᱜᱚᱲᱚ ᱮᱢᱚᱜᱼᱟᱭ - - ᱥᱟᱫᱷᱚᱱ ᱠᱚ ᱛᱟᱞᱟᱨᱮ ᱴᱟᱵᱽ ᱠᱚ ᱩᱪᱟᱹᱲ ᱢᱮ, ᱰᱟᱣᱩᱱᱞᱚᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ, ᱟᱨ %s ᱠᱷᱚᱱ ᱡᱚᱛᱚ ᱠᱷᱚᱱ ᱡᱟᱹᱥᱛᱤ ᱵᱮᱵᱷᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱥ ᱧᱟᱢ ᱢᱮ ᱾ - - ᱥᱟᱫᱷᱚᱱ ᱠᱚ ᱛᱟᱞᱟᱨᱮ ᱴᱟᱵᱽ ᱠᱚ ᱩᱪᱟᱹᱲ ᱢᱮ, ᱰᱟᱣᱩᱱᱞᱚᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ, ᱟᱨ Firefox ᱠᱷᱚᱱ ᱡᱚᱛᱚ ᱠᱷᱚᱱ ᱡᱟᱹᱥᱛᱤ ᱵᱮᱵᱷᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱥ ᱧᱟᱢ ᱢᱮ ᱾ ᱠᱷᱚᱵᱚᱨ ᱠᱚ ᱦᱮᱡ ᱪᱷᱚᱭ ᱢᱮ @@ -366,8 +335,6 @@ ᱵᱟᱵᱚᱛ ᱢᱤᱫᱴᱟᱝ ᱵᱟᱪᱷᱟᱣ ᱢᱮ - - ᱥᱮᱸᱫᱽᱨᱟ ᱠᱷᱟᱴᱚᱢᱟᱪᱷᱟ ᱢᱮᱱᱮᱡᱽ ᱢᱮ ᱥᱮᱸᱫᱽᱨᱟ ᱢᱮᱱᱩ ᱨᱮ ᱧᱮᱞᱚᱜ ᱠᱟᱱ ᱤᱧᱡᱤᱱ ᱠᱚ ᱥᱟᱯᱲᱟᱣ ᱢᱮ @@ -378,8 +345,6 @@ ᱥᱮᱸᱫᱽᱨᱟ ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ - - ᱴᱷᱤᱠᱟᱹᱱᱟ ᱦᱩᱨᱠᱟᱹᱬ ᱜᱩᱜᱚᱞ ᱯᱞᱮ ᱨᱮ ᱫᱚᱨ ᱢᱮ ᱠᱷᱟᱹᱞᱤᱼHTTPS ᱢᱳᱰ - - ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱠᱷᱟᱴᱚ - - ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱠᱷᱟᱴᱚᱭ ᱢᱮ - - - ᱵᱚᱸᱫᱚ - - ᱪᱟᱹᱞᱩ - - %1$s ᱫᱚ ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱨᱮ ᱠᱩᱠᱤ ᱞᱟᱹᱱᱟᱹᱭ ᱠᱚ ᱚᱡ ᱞᱮᱠᱟᱛᱮ ᱵᱟᱭ ᱩᱫᱩᱜ ᱮᱫᱟᱭ ᱾ ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴ ᱞᱟᱹᱜᱤᱫ ᱵᱚᱱᱫ ᱜᱮᱭᱟ @@ -433,31 +387,10 @@ ᱜᱚᱲᱚ ᱱᱮᱦᱚᱨ ᱵᱷᱮᱡᱟ ᱮᱱᱟ ᱥᱟᱭᱟᱴ ᱱᱤᱛᱚᱜ ᱥᱟᱵ ᱨᱮ ᱵᱟᱹᱱᱩᱜᱼᱟ - - %1$s ᱞᱟᱹᱜᱤᱫ ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱨᱮᱰᱟᱹᱠᱥᱚᱱ ᱮᱢ ᱪᱷᱚᱭ ᱢᱮ? - - - %1$s ᱞᱟᱹᱜᱤᱫ ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱨᱮᱰᱟᱹᱠᱥᱚᱱ ᱵᱚᱱᱫᱚᱭᱟᱢ ᱥᱮ? ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴ ᱨᱮ %1$s ᱫᱚ ᱟᱡ ᱛᱮ ᱠᱩᱠᱤ ᱱᱚᱦᱚᱨ ᱵᱟᱝ ᱢᱟᱱᱟ ᱫᱟᱲᱮᱭᱟᱜ ᱠᱟᱱᱟᱭ ᱾ ᱵᱷᱚᱵᱤᱥᱚᱛ ᱨᱮ ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴ ᱜᱚᱲᱚ ᱮᱢ ᱞᱟᱹᱜᱤᱫ ᱱᱮᱦᱚᱨ ᱵᱷᱮᱡᱟ ᱫᱟᱲᱮᱭᱟᱜᱼᱟᱢ ᱾ - - %1$s ᱫᱚ ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴᱟᱜ ᱠᱩᱠᱤ ᱠᱚ ᱢᱮᱴᱟᱣᱟᱭ ᱟᱨ ᱥᱟᱦᱴᱟ ᱯᱷᱟᱨᱪᱟ ᱜᱚᱫ ᱠᱟᱜᱼᱟᱭ ᱾ ᱡᱷᱚᱛᱚ ᱠᱩᱠᱤ ᱠᱚ ᱢᱮᱴᱟᱣ ᱞᱮᱠᱷᱟᱱ ᱟᱢ ᱵᱟᱦᱨᱮ ᱛᱮ ᱚᱰᱚᱠᱚᱜᱼᱟᱢ ᱟᱨᱵᱟᱝ ᱠᱤᱨᱤᱧ ᱵᱚᱥᱛᱟ ᱫᱚ ᱠᱷᱟᱹᱞᱤᱜ ᱛᱟᱢᱟᱸ ᱾ - - - %1$s ᱫᱚ ᱥᱚᱦᱚᱫ ᱮᱢᱚᱜ ᱥᱟᱭᱤᱴ ᱠᱚ ᱞᱟᱹᱜᱤᱫ ᱟᱡ ᱛᱮ ᱡᱷᱚᱛᱚ ᱠᱩᱠᱤ ᱱᱮᱦᱚᱨ ᱵᱟᱹᱨᱜᱤᱞ ᱜᱤᱰᱤ ᱞᱟᱹᱜᱤᱫ ᱪᱮᱥᱴᱟ ᱮᱫᱟᱭ ᱾ - - - ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱵᱟᱹᱨᱜᱤᱞ ᱜᱤᱰᱤ ᱞᱟᱹᱜᱤᱫ %1$s ᱦᱚᱠ ᱮᱢᱟᱭ ᱟᱢ ᱥᱮ ? - - %1$s ᱫᱚ ᱟᱡ ᱛᱮ ᱟᱹᱰᱤᱜᱟᱱ ᱠᱩᱠᱤ ᱵᱮᱱᱚᱨ ᱱᱮᱦᱚᱨ ᱵᱟᱹᱨᱜᱤᱞ ᱜᱤᱰᱤ ᱫᱟᱲᱮᱭᱟᱜᱼᱟᱭ ᱾ - - ᱱᱤᱛᱚᱜ ᱫᱚ ᱵᱟᱝᱟ - - ᱟᱢ ᱫᱚ ᱠᱩᱠᱤ ᱱᱮᱦᱚᱨ ᱠᱚ ᱠᱚᱢ ᱜᱮ ᱧᱮᱞ ᱟᱢ - - ᱦᱮᱥᱟᱨᱤᱭᱟᱹ ᱵᱮᱰᱷᱟᱣ ᱠᱟᱱᱟ ᱨᱩᱠᱷᱤᱭᱟᱹ ᱞᱟᱹᱜᱤᱫ ᱛᱮ HTTPS ᱫᱟᱱᱟᱝ ᱵᱮᱵᱷᱟᱨ ᱛᱮ ᱥᱟᱭᱤᱴ ᱠᱚ ᱥᱟᱞᱟᱜ ᱟᱡ ᱛᱮ ᱡᱩᱲᱟᱹᱣ ᱵᱤᱲᱟᱹᱣ ᱾ @@ -481,12 +414,8 @@ ᱢᱮᱱᱠᱷᱟᱱ, ᱱᱚᱶᱟ ᱦᱚᱸ ᱦᱩᱭ ᱫᱟᱲᱮᱭᱟᱜᱼᱟ ᱡᱮ ᱢᱤᱫᱴᱟᱝ ᱢᱩᱸᱦᱟᱹ ᱤᱡ ᱦᱚᱸ ᱛᱟᱦᱮᱸ ᱠᱚᱜᱼᱟᱭ ᱾ ᱟᱢ ᱡᱩᱫᱤ ᱣᱮᱵᱽᱥᱟᱭᱤᱴ ᱥᱮᱫ ᱞᱟᱦᱟᱜ ᱠᱷᱟᱱ ᱫᱚᱢ, ᱟᱢ ᱫᱚ ᱡᱟᱦᱟᱱᱟᱜ ᱥᱚᱢᱵᱮᱫᱚᱱ ᱡᱤᱱᱤᱥ ᱟᱞᱚᱢ ᱟᱫᱮᱨ ᱛᱟᱢᱟᱸ ᱾ ᱡᱤᱫᱤ ᱟᱢ ᱞᱟᱦᱟᱜ ᱠᱷᱟᱱ, HTTPSᱼᱢᱳᱰ ᱫᱚ ᱥᱟᱭᱤᱴ ᱞᱟᱹᱜᱤᱫ ᱛᱤᱱᱟᱹᱜ ᱜᱟᱱ ᱚᱠᱛᱚ ᱞᱟᱹᱜᱤᱫ ᱵᱚᱸᱫᱚᱜᱼᱟ ᱾ ᱟᱹᱛᱩᱨ ᱫᱟᱲᱮᱭᱟᱜ - - ᱠᱟᱹᱥᱴᱚᱢ Firefox ᱠᱷᱟᱛᱟ ᱥᱟᱹᱨᱣᱟᱹᱨ ᱠᱩᱥᱤᱭᱟᱜ ᱥᱭᱝᱠ ᱥᱟᱹᱨᱣᱟᱹᱨ - - Firefox ᱠᱷᱟᱛᱟ/ ᱥᱭᱝᱠ ᱠᱟᱹᱨᱣᱟᱹᱨ ᱵᱚᱫᱚᱞᱮᱱᱟ ᱾ ᱵᱚᱫᱚᱞ ᱠᱚ ᱫᱚᱦᱚ ᱞᱟᱹᱜᱤᱫ ᱮᱯᱞᱤᱠᱮᱥᱚᱱ ᱵᱚᱸᱫᱚᱜ ᱠᱟᱱᱟ… ᱠᱷᱟᱛᱟ @@ -501,8 +430,6 @@ ᱠᱩᱥᱤᱭᱟᱜ ᱛᱮᱭᱟᱨ ᱟᱢᱟᱜ ᱴᱮᱵᱽ ᱠᱚ, ᱵᱩᱠᱢᱟᱨᱠ ᱠᱚ, ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱟᱨ ᱵᱟᱹᱲᱛᱤ ᱠᱚ ᱛᱚᱞ ᱡᱚᱠᱷᱟᱭ ᱞᱟᱹᱜᱤᱫ ᱥᱩᱦᱤ ᱮᱢ ᱢᱮ ᱾ - - Firefox ᱠᱷᱟᱛᱟ ᱥᱭᱝᱠ ᱠᱚ ᱪᱟᱹᱞᱩ ᱫᱚᱦᱚ ᱞᱟᱹᱜᱤᱫ ᱫᱩᱦᱲᱟᱹ ᱡᱩᱰᱟᱹᱣ @@ -513,8 +440,6 @@ ᱟᱸᱠᱲᱟ ᱛᱩᱢᱟᱹᱞ ᱨᱤᱢᱳᱴ ᱰᱤᱵᱚᱜᱤᱝ ᱣᱟᱭᱟ USB - - ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ ᱠᱚ ᱩᱫᱩᱜ ᱢᱮ ᱥᱮᱸᱫᱽᱨᱟ ᱦᱩᱫᱤᱥ ᱠᱚ ᱩᱫᱩᱜ @@ -614,16 +539,10 @@ ᱠᱞᱟᱥᱤᱠ %s - - ᱥᱤᱢᱤᱛ ᱮᱰᱤᱥᱚᱱ ᱟᱴᱤᱥᱴ ᱥᱤᱨᱤᱡᱽ - - ᱱᱟᱶᱟ ᱥᱟᱫᱤᱱ ᱨᱚᱲ ᱛᱩᱢᱟᱹᱞ ᱾%s ᱱᱟᱶᱟ ᱥᱟᱫᱤᱱ ᱨᱚᱲ ᱛᱩᱢᱟᱹᱞ ᱾%s - - ᱱᱟᱶᱟ ᱥᱟᱫᱤᱱ ᱨᱚᱲ ᱛᱩᱢᱟᱹᱞ ᱾ ᱱᱟᱶᱟ ᱥᱟᱫᱤᱱ ᱨᱚᱲ ᱛᱩᱢᱟᱹᱞ ᱾ @@ -633,12 +552,6 @@ ᱰᱷᱮᱨ ᱠᱟᱱᱛᱷᱪᱤᱛᱟᱹᱨ ᱠᱚ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ - - - ᱮᱰᱼᱚᱱ ᱫᱚ ᱵᱟᱭ ᱟᱠᱟᱱᱟ - - ᱮᱰᱼᱚᱱ ᱢᱟᱲᱟᱝ ᱠᱷᱚᱱ ᱵᱚᱦᱟᱞ ᱟᱠᱟᱱᱟ - ᱠᱷᱟᱛᱟ ᱢᱮᱱᱮᱡᱽ ᱢᱮ @@ -651,7 +564,7 @@ ᱵᱩᱠᱢᱟᱨᱠ ᱠᱚ - ᱵᱚᱞᱚᱱ ᱠᱚ + ᱵᱚᱞᱚᱱ ᱠᱚ ᱡᱷᱤᱡᱽ ᱠᱟᱱ ᱴᱮᱵᱽ ᱠᱚ @@ -676,7 +589,7 @@ %1$s on %2$s %3$s - ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ + ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱴᱷᱤᱠᱬᱟᱤᱭᱟᱹ @@ -945,9 +858,9 @@ ᱛᱩᱢᱟᱹᱞ ᱧᱩᱛᱩᱢ - ᱨᱤᱱᱮᱢ - - ᱚᱪᱚᱜ ᱢᱮ + ᱨᱤᱱᱮᱢ + + ᱚᱪᱚᱜ ᱢᱮ ᱱᱟᱜᱟᱢ ᱠᱷᱚᱱ ᱢᱮᱴᱟᱣ ᱢᱮ @@ -1222,8 +1135,6 @@ ᱵᱚᱸᱫ - ᱪᱷᱟᱯᱟ ᱵᱟᱭ ᱜᱟᱱ ᱞᱮᱱᱟ - ᱱᱚᱶᱟ ᱥᱟᱦᱴᱟ ᱪᱷᱟᱯᱟ ᱵᱟᱭ ᱜᱟᱱᱚᱜ ᱠᱟᱱᱟ ᱪᱷᱟᱯᱟ @@ -1268,6 +1179,7 @@ ᱯᱨᱟᱭᱣᱮᱴ ᱴᱮᱵᱽ ᱠᱚ ᱵᱚᱸᱫᱚᱭ ᱢᱮ + ᱢᱟᱨᱠᱮᱴᱤᱝ @@ -1368,14 +1280,11 @@ %d ᱴᱮᱵᱽ ᱠᱚ - ᱵᱽᱨᱟᱣᱩᱡᱤᱝ ᱱᱟᱜᱟᱢ ᱟᱨ ᱥᱟᱭᱤᱴ ᱰᱟᱴᱟ ᱱᱟᱜᱟᱢ ᱯᱟᱱᱛᱮ %d ᱴᱷᱤᱠᱬᱟᱹ ᱠᱚ - - ᱠᱩᱠᱤᱡ ᱠᱚ ᱠᱩᱠᱤᱡᱽ ᱟᱨ ᱥᱟᱭᱤᱴ ᱰᱟᱴᱟ @@ -1431,63 +1340,10 @@ ᱫᱳᱞ ᱢᱮᱴᱟᱣ ᱦᱩᱭ - - ᱢᱤᱫᱴᱟᱝ ᱵᱮᱥ ᱤᱱᱴᱚᱨᱱᱮᱴ ᱨᱮ ᱟᱢᱟᱜ ᱥᱟᱹᱜᱩᱱ ᱫᱟᱨᱟᱢ - - ᱦᱚᱲ ᱠᱚ ᱞᱟᱹᱜᱤᱫ, ᱵᱤᱱ ᱞᱟᱵᱷ ᱨᱮᱭᱟᱜ ᱢᱤᱫᱴᱟᱝ ᱵᱽᱨᱟᱣᱡᱚᱨ ᱾ - - ᱪᱟᱞᱟᱜ ᱢᱮ ᱡᱟᱦᱟᱸ ᱨᱮ ᱢᱟᱲᱟᱝ ᱛᱟᱦᱮᱸ ᱠᱟᱱᱟᱢ - - ᱟᱨᱟᱢ ᱛᱮ ᱯᱚᱨᱫᱟ ᱠᱚ ᱩᱪᱟᱹᱲ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱫᱷᱚᱱ ᱥᱟᱨᱟ ᱨᱮ ᱴᱮᱵᱽ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫ ᱠᱚᱨᱮ ᱟᱹᱭᱩᱨ ᱢᱤᱫ ᱢᱮ ᱾ - - ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱥᱭᱝᱠ ᱪᱟᱹᱞᱩ ᱢᱮᱱᱟᱜ-ᱟ - - ᱢᱩᱞ ᱞᱮᱠᱷᱟᱛᱮ ᱱᱤᱥᱚᱱ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ - - %1$s ᱫᱚ ᱵᱟᱦᱨᱮ ᱠᱚᱢᱯᱟᱱᱤ ᱠᱚ ᱣᱮᱵᱽ ᱨᱮ ᱟᱢ ᱯᱟᱸᱡᱟ ᱠᱚ ᱵᱚᱸᱫᱚᱜᱼᱟ ᱾ - - ᱡᱷᱚᱛᱚ ᱥᱟᱭᱤᱴ ᱠᱚᱨᱮ ᱠᱩᱠᱤ ᱯᱟᱧᱡᱟ ᱫᱟᱱᱟᱲ ᱠᱚ ᱵᱟᱹᱲ ᱪᱷᱚ ᱞᱟᱹᱜᱤᱫ ᱢᱩᱴ ᱠᱩᱠᱤ ᱨᱩᱠᱷᱤᱭᱟᱹ ᱫᱮᱠᱷᱟᱣᱜ ᱠᱟᱱᱟ ᱾ - - ᱵᱮᱥᱟᱜ (ᱢᱩᱞ ᱯᱷᱮᱲᱟᱛ) - - ᱯᱨᱟᱭᱣᱮᱥᱭ ᱟᱨ ᱯᱚᱨᱯᱷᱚᱨᱢᱮᱱᱥ ᱞᱟᱹᱜᱤᱫ ᱥᱚᱢᱟᱱ ᱾ ᱥᱟᱦᱴᱟ ᱢᱩᱞ ᱞᱮᱠᱷᱟᱛᱮ ᱞᱟᱫᱮᱜᱼᱟ ᱾ - - ᱱᱤᱦᱟᱹᱛ - - ᱥᱟᱦᱴᱟ ᱞᱚᱜᱚᱱ ᱞᱳᱰ ᱞᱟᱹᱜᱤᱫ ᱯᱟᱧᱡᱟ ᱫᱟᱱᱟᱲ ᱠᱚ ᱵᱞᱚᱠ ᱠᱚᱣᱟᱭ, ᱦᱮᱞᱮ ᱥᱟᱦᱴᱟ ᱞᱳᱰ ᱨᱮ ᱰᱤᱜᱟᱹᱣ ᱦᱩᱭ ᱫᱟᱲᱮᱭᱟᱜᱼᱟ ᱾ - - ᱟᱢᱟᱜ ᱴᱩᱞᱵᱟᱨ ᱯᱞᱮᱥᱢᱮᱱᱴ ᱨᱟᱠᱟᱵᱽ ᱛᱟᱢ - - - ᱞᱟᱛᱟᱨ ᱨᱮ ᱫᱚᱦᱚᱭ ᱢᱮ, ᱵᱟᱝᱠᱷᱟᱱ ᱪᱮᱛᱟᱱ ᱥᱮᱫ ᱩᱪᱟᱹᱲ ᱢᱮ ᱾ - - ᱟᱢᱟᱜ ᱰᱟᱴᱟ ᱟᱢᱟᱜ ᱠᱚᱵᱚᱡᱽ ᱨᱮ ᱛᱟᱦᱮᱱ ᱟ - - Firefox ᱴᱷᱮᱱ ᱡᱟᱦᱱᱟᱜ ᱜᱮ ᱟᱢ ᱚᱱᱞᱟᱭᱤᱱ ᱦᱟᱹᱴᱤᱧ ᱮᱫᱟᱢ ᱟᱨ ᱟᱢ ᱟᱞᱮ ᱥᱟᱶ ᱪᱮᱫ ᱮᱢ ᱦᱟᱹᱴᱤᱧ ᱮᱫᱟᱢ ᱚᱱᱟ ᱨᱮᱭᱟᱜ ᱠᱚᱵᱚᱡᱽ ᱮᱢᱟᱢ ᱠᱟᱱᱟᱭ ᱾ - - ᱟᱞᱮᱭᱟᱜ ᱱᱤᱥᱚᱱ ᱱᱚᱴᱤᱥ ᱯᱟᱲᱦᱟᱣ ᱯᱮ - - - ᱟᱹᱰᱤ ᱱᱟᱯᱟᱭ ᱤᱱᱴᱚᱨᱱᱮᱴ ᱠᱷᱩᱞᱟᱹ ᱞᱟᱹᱜᱤᱫ ᱥᱚᱡᱽ ᱜᱮᱭᱟᱢ ᱥᱮ ? - - ᱵᱽᱨᱟᱣᱩᱡᱤᱝ ᱮᱦᱚᱵᱽ ᱢᱮ - - ᱩᱭᱦᱟᱹᱨ ᱵᱟᱪᱷᱟᱣ ᱛᱟᱢ - - ᱛᱤᱱᱟᱹᱜ ᱜᱟᱱ ᱵᱮᱴᱨᱭ ᱵᱚᱪᱚᱛ ᱢᱮ ᱟᱨ ᱟᱢᱟᱜ ᱢᱮᱫ ᱵᱟᱧᱪᱟᱣ ᱛᱟᱢ ᱧᱩᱛ ᱩᱭᱦᱟᱹᱨ ᱪᱟᱹᱞᱩ ᱠᱟᱛᱮ ᱾ - - ᱟᱡ ᱛᱮ - - ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱨᱮᱭᱟᱜ ᱥᱟᱡᱟᱣ ᱦᱟᱛᱟᱣ ᱟᱭ - - ᱧᱩᱛ ᱩᱭᱦᱟᱹᱨ - - ᱢᱟᱨᱥᱟᱞ ᱩᱭᱦᱟᱹᱨ - ᱴᱮᱵᱽ ᱠᱚ ᱠᱩᱞ ᱦᱩᱭᱮᱱᱟ! @@ -1673,9 +1529,9 @@ ᱟᱢ ᱞᱚᱜᱚᱱ ᱵᱽᱨᱟᱣᱩᱡᱽ ᱟᱨ ᱮᱯ ᱞᱮᱠᱷᱟᱱ ᱢᱟᱨᱠᱷᱤ ᱤᱫᱤ ᱞᱟᱹᱜᱤᱫ ᱣᱮᱵᱥᱟᱭᱤᱴ ᱫᱚ ᱥᱟᱫᱷᱚᱱ ᱨᱮᱭᱟᱜ ᱚᱲᱟᱜ ᱥᱠᱨᱤᱱ ᱨᱮ ᱥᱮᱞᱮᱫᱽ ᱫᱟᱲᱮᱟᱜᱼᱟᱢ ᱾ - ᱵᱚᱞᱚᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ + ᱵᱚᱞᱚᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ - ᱞᱚᱜᱤᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱥᱟᱺᱪᱟᱣ ᱢᱮ + ᱞᱚᱜᱤᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱥᱟᱺᱪᱟᱣ ᱢᱮ ᱥᱟᱺᱪᱟᱣ ᱞᱟᱹᱜᱤᱫᱛᱮ ᱠᱩᱠᱞᱤ @@ -1691,28 +1547,28 @@ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱨᱮ ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱯᱩᱨᱟᱹᱣ ᱢᱮ ᱾ - ᱵᱚᱞᱚ ᱥᱮᱞᱮᱫ ᱢᱮ + ᱵᱚᱞᱚ ᱥᱮᱞᱮᱫ ᱢᱮ - - ᱞᱚᱜᱤᱱ ᱠᱚ ᱥᱭᱝᱠ ᱢᱮ + + ᱞᱚᱜᱤᱱ ᱠᱚ ᱥᱭᱝᱠ ᱢᱮ - ᱡᱷᱚᱛᱚ ᱥᱟᱫᱷᱚᱱ ᱵᱷᱤᱛᱨᱤ ᱨᱮ ᱵᱚᱞᱚ ᱠᱚ ᱥᱭᱝᱠ ᱢᱮ + ᱡᱷᱚᱛᱚ ᱥᱟᱫᱷᱚᱱ ᱵᱷᱤᱛᱨᱤ ᱨᱮ ᱵᱚᱞᱚ ᱠᱚ ᱥᱭᱝᱠ ᱢᱮ - ᱥᱟᱺᱪᱟᱣᱟᱠᱟᱱ ᱞᱚᱜᱤᱱ ᱠᱚ + ᱥᱟᱺᱪᱟᱣᱟᱠᱟᱱ ᱞᱚᱜᱤᱱ ᱠᱚ - ᱞᱚᱜᱤᱱ ᱚᱠᱟ %s ᱨᱮ ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱥᱭᱝᱠ ᱥᱟᱱᱟᱢ ᱠᱟᱱᱟ ᱚᱱᱟ ᱠᱚ ᱱᱚᱰᱮ ᱫᱮᱠᱷᱟᱣᱜᱼᱟ ᱾ + ᱞᱚᱜᱤᱱ ᱚᱠᱟ %s ᱨᱮ ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱥᱭᱝᱠ ᱥᱟᱱᱟᱢ ᱠᱟᱱᱟ ᱚᱱᱟ ᱠᱚ ᱱᱚᱰᱮ ᱫᱮᱠᱷᱟᱣᱜᱼᱟ ᱾ - ᱥᱭᱝᱠ ᱵᱟᱵᱚᱛ ᱡᱟᱹᱥᱛᱤ ᱵᱟᱰᱟᱭ ᱢᱮ ᱾ + ᱥᱭᱝᱠ ᱵᱟᱵᱚᱛ ᱡᱟᱹᱥᱛᱤ ᱵᱟᱰᱟᱭ ᱢᱮ ᱾ ᱪᱷᱟᱰᱟ ᱠᱚ - ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱡᱟ ᱵᱟᱝ ᱥᱟᱺᱪᱟᱣ ᱠᱟᱱᱟ ᱚᱱᱟᱠᱩ ᱱᱚᱰᱮ ᱩᱫᱩᱜᱚᱣᱟ ᱾ + ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱡᱟ ᱵᱟᱝ ᱥᱟᱺᱪᱟᱣ ᱠᱟᱱᱟ ᱚᱱᱟᱠᱩ ᱱᱚᱰᱮ ᱩᱫᱩᱜᱚᱣᱟ ᱾ - ᱞᱚᱜᱤᱱᱥ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱫᱚ ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴ ᱞᱟᱹᱜᱤᱫ ᱵᱟᱝ ᱥᱟᱺᱪᱟᱣᱜᱼᱟ ᱾ + ᱞᱚᱜᱤᱱᱥ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱫᱚ ᱱᱚᱶᱟ ᱥᱟᱭᱤᱴ ᱞᱟᱹᱜᱤᱫ ᱵᱟᱝ ᱥᱟᱺᱪᱟᱣᱜᱼᱟ ᱾ ᱡᱷᱚᱛᱚ ᱪᱷᱟᱰᱟᱠᱚ ᱢᱮᱴᱟᱣ ᱢᱮ - ᱞᱚᱜᱤᱱ ᱠᱚ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ + ᱞᱚᱜᱤᱱ ᱠᱚ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ ᱥᱟᱭᱤᱴ @@ -1740,11 +1596,11 @@ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱩᱠᱩ - ᱥᱟᱺᱪᱟᱣᱠᱟᱱ ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱠᱚ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ ᱛᱮ ᱚᱱᱞᱚᱠ ᱢᱮ + ᱥᱟᱺᱪᱟᱣᱠᱟᱱ ᱵᱚᱞᱚᱱ ᱥᱩᱦᱤ ᱠᱚ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ ᱛᱮ ᱚᱱᱞᱚᱠ ᱢᱮ - ᱟᱢᱟᱜ ᱞᱚᱜᱤᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱡᱟᱯᱛᱤ ᱢᱮ + ᱟᱢᱟᱜ ᱞᱚᱜᱤᱱ ᱠᱚ ᱟᱨ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱡᱟᱯᱛᱤ ᱢᱮ - ᱥᱟᱫᱷᱚᱱ ᱠᱩᱞᱩᱯ ᱪᱤᱱᱦᱟᱹ, ᱯᱤᱱ, ᱟᱨ ᱵᱟᱝ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱞᱟᱜᱟᱣᱢᱮ ᱟᱢᱟᱜ ᱥᱟᱺᱪᱟᱣ ᱞᱚᱜᱤᱱ ᱠᱚ ᱮᱢᱟᱱ ᱨᱩᱠᱷᱭᱟ ᱞᱟᱹᱜᱤᱫ ᱡᱩᱫᱤ ᱚᱞᱜᱟ ᱦᱚᱲ ᱴᱷᱮᱱ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱾ + ᱥᱟᱫᱷᱚᱱ ᱠᱩᱞᱩᱯ ᱪᱤᱱᱦᱟᱹ, ᱯᱤᱱ, ᱟᱨ ᱵᱟᱝ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱞᱟᱜᱟᱣᱢᱮ ᱟᱢᱟᱜ ᱥᱟᱺᱪᱟᱣ ᱞᱚᱜᱤᱱ ᱠᱚ ᱮᱢᱟᱱ ᱨᱩᱠᱷᱭᱟ ᱞᱟᱹᱜᱤᱫ ᱡᱩᱫᱤ ᱚᱞᱜᱟ ᱦᱚᱲ ᱴᱷᱮᱱ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱾ ᱛᱟᱭᱚᱢ ᱛᱮ @@ -1761,7 +1617,7 @@ ᱢᱟᱲᱟᱝ ᱵᱮᱵᱷᱟᱨᱟᱜ - ᱞᱚᱜᱤᱱ ᱢᱮᱱᱭᱩ ᱥᱟᱞᱟᱭ ᱢᱮ + ᱞᱚᱜᱤᱱ ᱢᱮᱱᱭᱩ ᱥᱟᱞᱟᱭ ᱢᱮ @@ -1769,30 +1625,30 @@ ᱴᱷᱤᱠᱬᱟᱤᱭᱟᱹ - ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ + ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ - ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱠᱟᱰ ᱠᱚ ᱟᱡ ᱛᱮ ᱯᱮᱨᱮᱡᱽ ᱢᱮ + ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱠᱟᱰ ᱠᱚ ᱟᱡ ᱛᱮ ᱯᱮᱨᱮᱡᱽ ᱢᱮ - ᱰᱟᱴᱟ ᱫᱚ ᱮᱱᱠᱨᱤᱯᱴᱮᱰ ᱠᱟᱱᱟ + ᱰᱟᱴᱟ ᱫᱚ ᱮᱱᱠᱨᱤᱯᱴᱮᱰ ᱠᱟᱱᱟ ᱡᱷᱚᱛᱚ ᱥᱟᱫᱷᱚᱱ ᱵᱷᱤᱛᱨᱤ ᱨᱮ ᱠᱟᱰ ᱥᱭᱝᱠ ᱢᱮ ᱠᱟᱰ ᱥᱭᱝᱠ ᱢᱮ - ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱥᱮᱞᱮᱫᱽ ᱢᱮ + ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱥᱮᱞᱮᱫᱽ ᱢᱮ - ᱥᱟᱺᱪᱟᱣ ᱠᱟᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ + ᱥᱟᱺᱪᱟᱣ ᱠᱟᱰ ᱠᱚ ᱢᱮᱱᱮᱡᱽ ᱢᱮ ᱴᱷᱤᱠᱬᱟᱹ ᱥᱮᱞᱮᱫ ᱢᱮ ᱴᱷᱤᱠᱬᱟᱹᱤᱭᱟᱹ ᱡᱚᱛᱚᱱ ᱮᱢ - ᱴᱷᱤᱬᱟᱹᱤᱭᱟᱹ ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱟᱡ ᱛᱮ ᱯᱮᱨᱮᱡ ᱢᱮ + ᱴᱷᱤᱬᱟᱹᱤᱭᱟᱹ ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱟᱡ ᱛᱮ ᱯᱮᱨᱮᱡ ᱢᱮ - ᱮᱞ, ᱤᱢᱮᱞ ᱟᱨ ᱵᱷᱮᱡᱟ ᱴᱷᱤᱠᱬᱟᱹ ᱞᱮᱠᱷᱟ ᱵᱤᱵᱨᱚᱬ ᱢᱮᱥᱟᱭ ᱢᱮ + ᱮᱞ, ᱤᱢᱮᱞ ᱟᱨ ᱵᱷᱮᱡᱟ ᱴᱷᱤᱠᱬᱟᱹ ᱞᱮᱠᱷᱟ ᱵᱤᱵᱨᱚᱬ ᱢᱮᱥᱟᱭ ᱢᱮ ᱠᱟᱰ ᱥᱮᱞᱮᱫᱽ ᱢᱮ @@ -1814,7 +1670,7 @@ ᱠᱟᱰ ᱢᱮᱴᱟᱣ ᱢᱮ - ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱛᱮ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱛ ᱛᱮ? + ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱛᱮ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱛ ᱛᱮ? ᱢᱮᱴᱟᱣ ᱢᱮ @@ -1826,15 +1682,15 @@ ᱥᱟᱺᱪᱟᱣ ᱠᱟᱱ ᱠᱟᱰ - ᱴᱷᱤᱠ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱮᱞ ᱟᱫᱮᱨ ᱢᱮ + ᱴᱷᱤᱠ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱮᱞ ᱟᱫᱮᱨ ᱢᱮ - ᱱᱚᱶᱟ ᱡᱟᱭᱜᱟ ᱯᱮᱨᱮᱡᱽ ᱢᱮ + ᱱᱚᱶᱟ ᱡᱟᱭᱜᱟ ᱯᱮᱨᱮᱡᱽ ᱢᱮ ᱥᱟᱺᱪᱟᱣᱟᱠᱟᱱ ᱠᱟᱰ ᱠᱚ ᱧᱮᱞ ᱞᱟᱹᱜᱤᱫ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ - ᱟᱢᱟᱜ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ + ᱟᱢᱟᱜ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱨᱩᱠᱷᱤᱭᱟᱹᱭ ᱢᱮ - ᱥᱟᱫᱷᱚᱱ ᱠᱩᱞᱩᱯ ᱪᱤᱱᱦᱟᱹ, ᱯᱤᱱ, ᱟᱨ ᱵᱟᱝ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱟᱢᱟᱜ ᱥᱟᱺᱪᱟᱣ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱠᱚ ᱮᱢᱟᱱ ᱨᱩᱠᱷᱭᱟ ᱞᱟᱹᱜᱤᱫ ᱡᱩᱫᱤ ᱚᱞᱜᱟ ᱦᱚᱲ ᱴᱷᱮᱱ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱾ + ᱥᱟᱫᱷᱚᱱ ᱠᱩᱞᱩᱯ ᱪᱤᱱᱦᱟᱹ, ᱯᱤᱱ, ᱟᱨ ᱵᱟᱝ ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱟᱢᱟᱜ ᱥᱟᱺᱪᱟᱣ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱠᱚ ᱮᱢᱟᱱ ᱨᱩᱠᱷᱭᱟ ᱞᱟᱹᱜᱤᱫ ᱡᱩᱫᱤ ᱚᱞᱜᱟ ᱦᱚᱲ ᱴᱷᱮᱱ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱛᱟᱦᱮᱸᱱ ᱠᱷᱟᱱ ᱾ ᱱᱤᱛᱚᱜ ᱥᱟᱡᱟᱣ ᱢᱮ @@ -1842,7 +1698,7 @@ ᱟᱢᱟᱜ ᱥᱟᱫᱷᱚᱱ ᱚᱱᱞᱚᱠ ᱢᱮ - ᱫᱚᱦᱚ ᱠᱟᱱ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱵᱤᱵᱨᱚᱬ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ + ᱫᱚᱦᱚ ᱠᱟᱱ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱵᱤᱵᱨᱚᱬ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ ᱴᱷᱤᱠᱬᱟᱹ ᱥᱮᱞᱮᱫ ᱢᱮ @@ -1851,11 +1707,11 @@ ᱴᱷᱤᱠᱬᱟᱹᱤᱭᱟᱹ ᱡᱚᱛᱚᱱ ᱮᱢ - ᱯᱩᱭᱞᱩ ᱧᱩᱛᱩᱢ + ᱯᱩᱭᱞᱩ ᱧᱩᱛᱩᱢ - ᱛᱟᱞᱟ ᱧᱩᱛᱩᱢ + ᱛᱟᱞᱟ ᱧᱩᱛᱩᱢ - ᱢᱩᱪᱟᱹᱫ ᱧᱩᱛᱩᱢ + ᱢᱩᱪᱟᱹᱫ ᱧᱩᱛᱩᱢ ᱥᱚᱰᱚᱠ ᱴᱷᱤᱠᱬᱟᱹ @@ -1881,7 +1737,7 @@ ᱴᱷᱤᱠᱬᱟᱹ ᱢᱮᱴᱟᱣ ᱢᱮ - ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱛᱮ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱴᱷᱤᱠᱬᱟᱹ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱛ ᱛᱮ? + ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱛᱮ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱴᱷᱤᱠᱬᱟᱹ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱛ ᱛᱮ? ᱢᱮᱴᱟᱣ ᱢᱮ @@ -1898,29 +1754,19 @@ ᱢᱤᱫᱴᱟᱝ ᱱᱟᱶᱟ ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ ᱥᱮᱞᱮᱫ ᱢᱮ ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ ᱥᱟᱯᱲᱟᱣ ᱢᱮ - - ᱥᱮᱞᱮᱫᱽ ᱢᱮ - - ᱥᱟᱺᱪᱟᱣ ᱥᱟᱯᱲᱟᱣ ᱢᱮᱴᱟᱣ ᱢᱮ - - ᱮᱴᱟᱜ-ᱟᱜ ᱧᱩᱛᱩᱢ - - ᱧᱩᱛᱩᱢ ᱥᱮᱸᱫᱽᱨᱟ ᱤᱧᱡᱤᱱ ᱧᱩᱛᱩᱢ ᱥᱴᱨᱤᱝ URL ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ - ᱵᱮᱵᱷᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱥᱴᱨᱭᱸᱜ ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ - ᱥᱮᱸᱫᱽᱨᱟ ᱞᱟᱹᱜᱤᱫ URL ᱵᱮᱵᱷᱟᱨ “%s” ᱥᱟᱞᱟᱜ ᱠᱣᱮᱨᱭ ᱵᱚᱫᱚᱞ ᱢᱮ ᱾ ᱡᱮᱢᱚᱱ:\nhttps://www.google.com/search?q=%s @@ -1932,8 +1778,6 @@ ᱥᱚᱞᱟᱦ ᱥᱮᱸᱫᱽᱨᱟ API URL - ᱯᱟᱱᱛᱮ ᱫᱚ “%s” ᱥᱟᱞᱟᱜ ᱛᱮ ᱵᱚᱫᱚᱞ ᱢᱮ ᱾ ᱫᱟᱹᱭᱠᱟᱹ ᱺ \nhttp://suggestqueries.google.com/complete/search?client=firefox&q=%s - ᱯᱟᱱᱛᱮ ᱫᱚ “%s” ᱥᱟᱞᱟᱜ ᱛᱮ ᱵᱚᱫᱚᱞ ᱢᱮ ᱾ ᱫᱟᱹᱭᱠᱟᱹ ᱺ \nhttps://suggestqueries.google.com/complete/search?client=firefox&q=%s ᱥᱟᱺᱪᱟᱣ ᱢᱮ @@ -1992,29 +1836,29 @@ ᱥᱟᱯᱲᱟᱣ - ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱞᱚᱜᱤᱱ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱫ ᱛᱮ? + ᱪᱮᱫ ᱟᱢ ᱜᱚᱴᱟ ᱢᱮᱱᱟᱢᱼᱟ ᱱᱚᱶᱟ ᱞᱚᱜᱤᱱ ᱢᱮᱴᱟᱣ ᱞᱟ.ᱜᱤᱫ ᱛᱮ? ᱢᱮᱴᱟᱣ ᱢᱮ ᱵᱟᱹᱰᱨᱟᱹ - ᱮᱴᱟᱜᱟᱜ ᱠᱚ ᱞᱚᱜᱤᱱ + ᱮᱴᱟᱜᱟᱜ ᱠᱚ ᱞᱚᱜᱤᱱ - ᱣᱤᱵ ᱴᱷᱤᱠᱬᱟᱹ ᱞᱚᱜᱤᱱ ᱵᱚᱞᱚ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ + ᱣᱤᱵ ᱴᱷᱤᱠᱬᱟᱹ ᱞᱚᱜᱤᱱ ᱵᱚᱞᱚ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ - ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱞᱚᱜᱤᱱ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ + ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱞᱚᱜᱤᱱ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ - ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱞᱚᱜᱤᱱ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ + ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱞᱚᱜᱤᱱ ᱞᱟᱹᱜᱤᱫ ᱥᱟᱯᱲᱟᱣ ᱚᱞ ᱡᱟᱭᱜᱟ ᱾ - ᱞᱚᱜᱤᱱ ᱵᱚᱫᱚᱞ ᱠᱚ ᱥᱟᱺᱪᱟᱣ ᱢᱮ ᱾ + ᱞᱚᱜᱤᱱ ᱵᱚᱫᱚᱞ ᱠᱚ ᱥᱟᱺᱪᱟᱣ ᱢᱮ ᱾ - ᱥᱟᱯᱲᱟᱣ + ᱥᱟᱯᱲᱟᱣ - ᱱᱟᱶᱟ ᱵᱚᱞᱚ ᱥᱮᱞᱮᱫ ᱢᱮ + ᱱᱟᱶᱟ ᱵᱚᱞᱚ ᱥᱮᱞᱮᱫ ᱢᱮ - ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱨᱮᱭᱟᱜ ᱫᱚᱨᱠᱟᱨ ᱢᱮᱱᱟᱜ-ᱟ + ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱨᱮᱭᱟᱜ ᱫᱚᱨᱠᱟᱨ ᱢᱮᱱᱟᱜ-ᱟ - ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱫᱚᱨᱠᱟᱨ + ᱵᱮᱵᱷᱟᱨᱤᱭᱟᱹ ᱧᱩᱛᱩᱢ ᱫᱚᱨᱠᱟᱨ ᱦᱚᱥᱴᱧᱩᱛᱩᱢ ᱫᱚᱨᱠᱟᱨ ᱠᱟᱱᱟ @@ -2064,14 +1908,14 @@ ᱠᱷᱟᱴᱚᱢᱟᱪᱷᱟ ᱠᱚ - - ᱧᱩᱛᱩᱢ + + ᱧᱩᱛᱩᱢ ᱠᱷᱟᱴᱚᱢᱟᱪᱷᱟ ᱧᱩᱛᱩᱢ - - ᱴᱷᱤᱠ - - ᱵᱟᱹᱰᱨᱟᱹ + + ᱴᱷᱤᱠ + + ᱵᱟᱹᱰᱨᱟᱹ ᱥᱟᱡᱟᱣ ᱠᱚ @@ -2111,7 +1955,7 @@ %s ᱥᱮᱸᱫᱽᱨᱟᱭ ᱢᱮ - + Firefox ᱟᱡ ᱛᱮ ᱠᱷᱩᱞᱟᱹ ᱪᱷᱚ ᱞᱟᱹᱜᱤᱫ ᱣᱮᱵᱥᱟᱭᱤᱴ, ᱤᱢᱮᱞ, ᱟᱨ ᱢᱮᱥᱮᱡᱽ ᱨᱮᱭᱟᱜ ᱞᱤᱝᱠ ᱥᱮᱴ ᱢᱮ ᱾ @@ -2121,7 +1965,7 @@ ᱟᱨᱦᱚᱸ ᱵᱤᱵᱨᱚᱬ ᱞᱟᱹᱜᱤᱫ ᱱᱚᱰᱮ ᱚᱛᱟᱭ ᱢᱮ - ᱪᱮᱛᱟᱱ ᱥᱮᱱ ᱱᱮᱣᱤᱜᱮᱴ ᱢᱮ + ᱪᱮᱛᱟᱱ ᱥᱮᱱ ᱱᱮᱣᱤᱜᱮᱴ ᱢᱮ ᱵᱚᱸᱫ @@ -2172,4 +2016,20 @@ ᱚᱱᱚᱞ ᱯᱟᱲᱦᱟᱣ ᱢᱮ ᱰᱷᱮᱨ ᱵᱟᱲᱟᱭ ᱞᱟᱹᱜᱤᱫ ᱞᱤᱝᱠ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ + + + + + + ᱢᱳᱴ + + ᱴᱮᱵᱽ ᱛᱮᱭᱟᱨ ᱦᱟᱹᱛᱤᱭᱟᱨ + + ᱛᱮᱭᱟᱨ ᱞᱟᱹᱜᱤᱫ ᱴᱮᱵᱽ ᱨᱮᱭᱟᱜ ᱛᱚᱲᱟᱜᱟᱱ + + ᱠᱟᱹᱢᱤ ᱠᱟᱱ ᱴᱮᱵᱽ ᱠᱚ ᱥᱮᱞᱮᱫ ᱢᱮ + + ᱵᱟᱝ ᱠᱟᱹᱢᱤ ᱴᱮᱵᱽᱠᱚᱨᱮ ᱥᱮᱞᱮᱫ ᱢᱮ + + ᱱᱤᱡᱮᱨᱟᱜ ᱴᱮᱵᱽ ᱥᱮᱞᱮᱫᱽ ᱢᱮ diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 93499e7c6..3fbccbd3d 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -247,6 +247,7 @@ Upraviť domovskú stránku + Úvodná obrazovka @@ -258,6 +259,11 @@ Preložiť stránku + + Stránka bola preložená z jazyka %1$s do jazyka %2$s. + Vybraný jazyk @@ -337,12 +343,22 @@ Vyhlásenie o ochrane osobných údajov Firefoxu - + + Ďalšie informácie nájdete v našom Vyhlásení o ochrane osobných údajov Radi vás držíme v bezpečí + + Zistite, prečo milióny ľudí milujú Firefox + + Bezpečné prehliadanie s viacerými možnosťami Náš neziskový prehliadač pomáha zabrániť spoločnostiam, aby vás tajne sledovali na webe. + Viac ako 100 miliónov ľudí chráni svoje súkromie výberom prehliadača, ktorého tvorcom je nezisková organizácia. + + Známi sledovacie prvky? Automaticky blokované. Rozšírenia? Vyskúšajte všetkých 700. Súbory PDF? Naša vstavaná čítačka uľahčuje prácu s nimi. + Náš neziskový prehliadač pomáha zabrániť spoločnostiam, aby vás tajne sledovali na webe.\n\nĎalšie informácie nájdete v našom Vyhlásení o ochrane osobných údajov. @@ -701,9 +717,9 @@ Záložky - Prihlasovacie údaje + Prihlasovacie údaje - Heslá + Heslá Otvorené karty @@ -729,9 +745,9 @@ %1$s na %2$s %3$s - Platobné karty + Platobné karty - Spôsoby platby + Spôsoby platby Adresy @@ -1675,13 +1691,13 @@ Túto webovú stránku si môžete jednoducho pridať na svoju domovskú obrazovku a mať tak okamžitý prístup k prehliadaniu. - Prihlasovacie údaje + Prihlasovacie údaje - Heslá + Heslá - Ukladanie prihlasovacích údajov + Ukladanie prihlasovacích údajov - Ukladanie hesiel + Ukladanie hesiel Pred uložením sa opýtať @@ -1696,47 +1712,47 @@ Vypĺňa používateľské mená a heslá v iných aplikáciách vo vašom zariadení. - Pridať prihlasovacie údaje + Pridať prihlasovacie údaje - Pridať heslo + Pridať heslo - - Synchronizácia prihlasovacích údajov - Synchronizácia hesiel + Synchronizácia prihlasovacích údajov + + Synchronizácia hesiel - Synchronizovať prihlasovacie údaje medzi zariadeniami + Synchronizovať prihlasovacie údaje medzi zariadeniami - Synchronizovať heslá naprieč zariadeniami + Synchronizovať heslá naprieč zariadeniami - Uložené prihlasovacie údaje + Uložené prihlasovacie údaje - Uložené heslá + Uložené heslá - Uložené alebo synchronizované údaje v aplikácii %s sa zobrazia tu. + Uložené alebo synchronizované údaje v aplikácii %s sa zobrazia tu. - Heslá, ktoré uložíte alebo synchronizujete do %su budú zobrazené tu. Všetky heslá sú šifrované. + Heslá, ktoré uložíte alebo synchronizujete do %su budú zobrazené tu. Všetky heslá sú šifrované. - Ďalšie informácie o službe Sync. + Ďalšie informácie o službe Sync. - Ďalšie informácie o synchronizácii + Ďalšie informácie o synchronizácii Výnimky - Tu sa zobrazia prihlasovacie údaje, ktoré sa nebudú ukladať. + Tu sa zobrazia prihlasovacie údaje, ktoré sa nebudú ukladať. - %s nebude ukladať heslá pre tu uvedené stránky. + %s nebude ukladať heslá pre tu uvedené stránky. - Pre nasledujúce stránky sa nebudú ukladať prihlasovacie údaje. + Pre nasledujúce stránky sa nebudú ukladať prihlasovacie údaje. - %s nebude ukladať heslá pre tieto stránky. + %s nebude ukladať heslá pre tieto stránky. Odstrániť všetky výnimky - Hľadať + Hľadať - Hľadať v heslách + Hľadať v heslách Stránka @@ -1764,17 +1780,17 @@ Skryť heslo - Pre zobrazenie prihlasovacích údajov odomknite zariadenie + Pre zobrazenie prihlasovacích údajov odomknite zariadenie - Ak chcete zobraziť uložené heslá, odomknite zariadenie + Ak chcete zobraziť uložené heslá, odomknite zariadenie - Zabezpečte svoje prihlasovacie údaje + Zabezpečte svoje prihlasovacie údaje - Zabezpečte svoje heslá + Zabezpečte svoje heslá - Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené prihlasovacie údaje v prípade, že vaše zariadenie bude používať niekto iný. + Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené prihlasovacie údaje v prípade, že vaše zariadenie bude používať niekto iný. - Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené heslá v prípade, že vaše zariadenie bude používať niekto iný. + Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené heslá v prípade, že vaše zariadenie bude používať niekto iný. Neskôr @@ -1791,7 +1807,10 @@ posledného použitia - Zoradiť ponuku prihlasovacích údajov + Zoradiť ponuku prihlasovacích údajov + + + Ponuka pre zoradenie hesiel Ponuka pre zoradenie hesiel @@ -1802,40 +1821,43 @@ Adresy - Platobné karty + Platobné karty - Spôsoby platby + Spôsoby platby - Ukladať a automaticky dopĺňať údaje o platobných kartách + Ukladať a automaticky dopĺňať údaje o platobných kartách - Ukladať a dopĺňať spôsoby platby + Ukladať a dopĺňať spôsoby platby - Údaje sú šifrované + Údaje sú šifrované - %s zašifruje všetky spôsoby platby, ktoré uložíte + %s zašifruje všetky spôsoby platby, ktoré uložíte Synchronizovať platobné karty naprieč zariadeniami Synchronizovať platobné karty - Pridať platobnú kartu + Pridať platobnú kartu - Pridať kartu + Pridať kartu - Spravovať uložené karty + Spravovať uložené karty - Spravovať karty + Spravovať karty Pridať adresu Spravovať adresy - Ukladať a automaticky dopĺňať adresy + Ukladať a automaticky dopĺňať adresy - Ukladať a dopĺňať adresy + Ukladať a dopĺňať adresy - Zahŕňa informácie ako sú čísla, e‑mailové adresy a dodacie adresy + Zahŕňa informácie ako sú čísla, e‑mailové adresy a dodacie adresy + + + Zahŕňa telefónne čísla a e‑mailové adresy Zahŕňa telefónne čísla a e‑mailové adresy @@ -1859,9 +1881,9 @@ Odstrániť kartu - Naozaj chcete odstrániť túto kreditnú kartu? + Naozaj chcete odstrániť túto kreditnú kartu? - Odstrániť kartu? + Odstrániť kartu? Odstrániť @@ -1874,24 +1896,24 @@ Uložené karty - Prosím, zadajte platné číslo platobnej karty + Prosím, zadajte platné číslo platobnej karty - Zadajte platné číslo karty + Zadajte platné číslo karty - Vyplňte toto pole + Vyplňte toto pole - Zadajte meno + Zadajte meno Odomknutím zobrazíte svoje uložené kreditné karty - Zabezpečte svoje kreditné karty + Zabezpečte svoje kreditné karty - Zabezpečte svoje uložené spôsoby platby + Zabezpečte svoje uložené spôsoby platby - Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené kreditné karty v prípade, že vaše zariadenie bude používať niekto iný. + Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené kreditné karty v prípade, že vaše zariadenie bude používať niekto iný. - Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené spôsoby platby v prípade, že vaše zariadenie bude používať niekto iný. + Nastavte si vzor, kód alebo heslo, ktorým ochránite svoje uložené spôsoby platby v prípade, že vaše zariadenie bude používať niekto iný. Nastaviť teraz @@ -1899,10 +1921,10 @@ Odomknite svoje zariadenie - Odomknutím použijete uložené informácie o kreditnej karte + Odomknutím použijete uložené informácie o kreditnej karte - Ak chcete použiť uložené spôsoby platby, odomknite zariadenie + Ak chcete použiť uložené spôsoby platby, odomknite zariadenie Pridať adresu @@ -1910,11 +1932,13 @@ Spravovať adresy - Krstné meno + Krstné meno - Stredné meno + Stredné meno - Priezvisko + Priezvisko + + Meno Ulica @@ -1939,9 +1963,9 @@ Odstrániť adresu - Naozaj chcete odstrániť túto adresu? + Naozaj chcete odstrániť túto adresu? - Chcete odstrániť túto adresu? + Chcete odstrániť túto adresu? Odstrániť @@ -2039,49 +2063,49 @@ Upraviť - Naozaj chcete odstrániť tieto prihlasovacie údaje? + Naozaj chcete odstrániť tieto prihlasovacie údaje? - Naozaj chcete odstrániť toto heslo? + Naozaj chcete odstrániť toto heslo? Odstrániť Zrušiť - Možnosti prihlásenia + Možnosti prihlásenia - Možnosti hesiel + Možnosti hesiel - Upraviteľné textové pole pre webovú adresu. + Upraviteľné textové pole pre webovú adresu. - Upraviteľné textové pole pre webovú adresu. + Upraviteľné textové pole pre webovú adresu. - Upraviteľné textové pole pre používateľské meno. + Upraviteľné textové pole pre používateľské meno. - Upraviteľné textové pole pre používateľské meno. + Upraviteľné textové pole pre používateľské meno. - Upraviteľné textové pole pre heslo. + Upraviteľné textové pole pre heslo. - Upraviteľné textové pole pre heslo. + Upraviteľné textové pole pre heslo. - Uložiť zmeny prihlasovacích údajov. + Uložiť zmeny prihlasovacích údajov. - Uložiť zmeny + Uložiť zmeny - Upraviť + Upraviť - Upraviť heslo + Upraviť heslo - Pridať nové prihlasovacie údaje + Pridať nové prihlasovacie údaje - Pridať heslo + Pridať heslo - Vyžaduje sa heslo + Vyžaduje sa heslo - Zadajte heslo + Zadajte heslo - Vyžaduje sa používateľské meno + Vyžaduje sa používateľské meno - Zadajte používateľské meno + Zadajte používateľské meno Vyžaduje sa názov hostiteľa @@ -2194,7 +2218,7 @@ Kliknutím zobrazíte viac podrobností - Prejsť nahor + Prejsť nahor Zavrieť @@ -2235,8 +2259,6 @@ Upravené hodnotenie - Nespoľahlivé recenzie boli odstránené - Na základe spoľahlivých recenzií To najlepšie z nedávnych recenzií @@ -2292,10 +2314,6 @@ Ak zistíte, že tento produkt je opäť na sklade, nahláste to a my budeme pracovať na kontrole recenzií. Oznámiť, že produkt je na sklade - - Kontroluje sa kvalita recenzií - - Kontroluje sa kvalita recenzií Kontroluje sa kvalita recenzií (%s) @@ -2342,13 +2360,19 @@ Ďalšie informácie - Výberom možnosti “Áno, vyskúšať” vyjadrujete súhlas s %1$s a %2$s služby %3$s od Mozilly. + Výberom možnosti “Áno, vyskúšať” vyjadrujete súhlas s %1$s a %2$s služby %3$s od Mozilly. Zvolením možnosti „Áno, vyskúšať“ vyjadrujete súhlas s nasledujúcim dokumentami od %1$s: + + Výberom možnosti “Áno, vyskúšať” vyjadrujete súhlas s %2$s prehliadača %1$s a %4$s spoločnosti %3$s. + + Výberom možnosti “Áno, vyskúšať” vyjadrujete súhlas s %2$s prehliadača %1$s a %4$s spoločnosti %3$s. - Zásadami ochrany osobných údajov + Zásadami ochrany osobných údajov Zásady ochrany osobných údajov + + Vyhlásení o ochrane osobných údajov Podmienkami používania @@ -2419,6 +2443,10 @@ Preložiť túto stránku? + + Stránka bola preložená z jazyka %1$s do jazyka %2$s Vyskúšajte súkromné preklady v aplikácii %1$s @@ -2431,6 +2459,8 @@ Preložiť do jazyka Teraz nie + + Zobraziť pôvodnú stránku Hotovo @@ -2453,6 +2483,16 @@ Ďalšie informácie + + Prebieha preklad… + + + Stiahnuť jazyk v režime šetrenia dát (%1$s)? + + Nastavenia prekladov diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 91d638d45..f889f99be 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -332,12 +332,22 @@ Obvestilo o zasebnosti za Firefox - + + Preberite več v obvestilu o zasebnosti Z veseljem skrbimo za vašo varnost + + Odkrijte, zakaj milijoni prisegajo na Firefox + + Varno brskanje z več izbire Naš neprofitni brskalnik preprečuje podjetjem, da bi vas skrivaj spremljala po spletu. + Več kot 100 milijonov ljudi ščiti svojo zasebnost z izbiro brskalnika, ki ga razvija neprofitna organizacija. + + Znani sledilci? Samodejno blokirani. Razširitve? Preskusite vseh 700. PDF-ji? Naš vgrajeni bralnik omogoča enostavno pregledovanje. + Naš neprofitni brskalnik pomaga podjetjem preprečiti, da bi vam na skrivaj sledila po spletu.\n\nVeč o tem v našem pravilniku o zasebnosti. @@ -693,9 +703,9 @@ Zaznamki - Prijave + Prijave - Gesla + Gesla Odprti zavihki @@ -722,9 +732,9 @@ %1$s na %2$s %3$s - Kreditne kartice + Kreditne kartice - Načini plačila + Plačilna sredstva Naslove @@ -1674,13 +1684,13 @@ To stran lahko preprosto dodate na svoj domači zaslon naprave za lažji dostop in hitrejše brskanje v načinu, podobnem aplikaciji. - Prijave in gesla + Prijave in gesla - Gesla + Gesla - Shranjevanje prijav in gesel + Shranjevanje prijav in gesel - Shranjuj gesla + Shranjuj gesla Vprašaj pred shranjevanjem @@ -1697,43 +1707,43 @@ Izpolnjuj uporabniška imena in gesla v drugih aplikacijah na napravi. - Dodaj prijavo + Dodaj prijavo - Dodaj geslo + Dodaj geslo - - Sinhronizacija prijav - Sinhroniziraj gesla + Sinhronizacija prijav + + Sinhroniziraj gesla - Sinhroniziraj prijave med napravami + Sinhroniziraj prijave med napravami - Sinhroniziraj gesla med napravami + Sinhroniziraj gesla med napravami - Shranjene prijave + Shranjene prijave - Shranjena gesla + Shranjena gesla - Tu se prikažejo prijave, ki jih shranite ali sinhronizirate v %s. + Tu se prikažejo prijave, ki jih shranite ali sinhronizirate v %s. - Več o Sync. + Več o Sync. - Več o sinhronizaciji + Več o sinhronizaciji Izjeme - Tu bodo prikazane prijave in gesla, ki niso shranjena. + Tu bodo prikazane prijave in gesla, ki niso shranjena. - Za tukaj navedena mesta %s ne bo shranjeval gesel. + Za tukaj navedena mesta %s ne bo shranjeval gesel. - Prijave in gesla za te strani ne bodo shranjene. + Prijave in gesla za te strani ne bodo shranjene. - Za ta spletna mesta %s ne bo shranjeval gesel. + Za ta spletna mesta %s ne bo shranjeval gesel. Izbriši vse izjeme - Iskanje prijav + Iskanje prijav Stran @@ -1761,15 +1771,15 @@ Skrij geslo - Odklenite za ogled shranjenih prijav + Odklenite za ogled shranjenih prijav - Zavarujte svoje prijave in gesla + Zavarujte svoje prijave in gesla - Zavarujte shranjena gesla + Zavarujte shranjena gesla - Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do shranjenih prijav in gesel, če vašo napravo uporablja še kdo. + Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do shranjenih prijav in gesel, če vašo napravo uporablja še kdo. - Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do shranjenih gesel, če vašo napravo uporablja še kdo. + Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do shranjenih gesel, če vašo napravo uporablja še kdo. Pozneje @@ -1789,7 +1799,7 @@ Času zadnje uporabe - Meni razvrščanja prijav + Meni razvrščanja prijav @@ -1797,38 +1807,43 @@ Naslovi - Kreditne kartice + Kreditne kartice + + Plačilna sredstva - Shrani in samodejno izpolni kartice + Shrani in samodejno izpolni kartice - Shranjuj in izpolnjuj načine plačila + Shranjuj in izpolnjuj plačilna sredstva - Podatki so šifrirani + Podatki so šifrirani - %s šifrira vse načine plačila, ki jih shranite + %s šifrira vsa plačilna sredstva, ki jih shranite Sinhroniziraj kartice med napravami Sinhroniziraj kartice - Dodaj kreditno kartico + Dodaj kreditno kartico - Dodaj kartico + Dodaj kartico - Upravljanje shranjenih kartic + Upravljanje shranjenih kartic - Upravljanje kartic + Upravljanje kartic Dodaj naslov Upravljanje naslovov - Shranjuj in samodejno izpolnjuj naslove + Shranjuj in samodejno izpolnjuj naslove - Shranjuj in izpolnjuj naslove + Shranjuj in izpolnjuj naslove - Vključi podatke, kot so številke, e-poštni naslovi in naslovi za dostavo + Vključi podatke, kot so številke, e-poštni naslovi in naslovi za dostavo + + + Vključuje telefonske številke in e-poštne naslove Vključuje telefonske številke in e-poštne naslove @@ -1852,7 +1867,7 @@ Izbriši kartico - Ali ste prepričani, da želite izbrisati to kreditno kartico? + Ali ste prepričani, da želite izbrisati to kreditno kartico? Izbriši @@ -1866,20 +1881,20 @@ Shranjene kartice - Vnesite veljavno številko kreditne kartice + Vnesite veljavno številko kreditne kartice - Vnesite veljavno številko kartice + Vnesite veljavno številko kartice - Izpolnite to polje + Izpolnite to polje - Dodajte ime + Dodajte ime Odklenite za ogled shranjenih kartic - Zavarujte svoje kreditne kartice + Zavarujte svoje kreditne kartice - Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do kreditnih kartic, če vašo napravo uporablja še kdo. + Nastavite vzorec za zaklepanje naprave, PIN ali geslo za zaščito pred dostopom do kreditnih kartic, če vašo napravo uporablja še kdo. Nastavi zdaj @@ -1888,7 +1903,7 @@ Odklenite svojo napravo - Odklenite za uporabo shranjenih podatkov o kreditnih karticah + Odklenite za uporabo shranjenih podatkov o kreditnih karticah Dodaj naslov @@ -1897,11 +1912,13 @@ Upravljanje naslovov - Ime + Ime - Drugo ime + Drugo ime - Priimek + Priimek + + Ime Ulica @@ -1926,7 +1943,7 @@ Izbriši naslov - Res želite izbrisati ta naslov? + Res želite izbrisati ta naslov? Izbriši @@ -2026,49 +2043,49 @@ Uredi - Ali ste prepričani, da želite izbrisati to prijavo? + Ali ste prepričani, da želite izbrisati to prijavo? - Ali ste prepričani, da želite izbrisati to geslo? + Ali ste prepričani, da želite izbrisati to geslo? Izbriši Prekliči - Možnosti prijave + Možnosti prijave - Možnosti gesel + Možnosti gesel - Besedilno polje za urejanje spletnega naslova prijave. + Besedilno polje za urejanje spletnega naslova prijave. - Besedilno polje za urejanje spletnega naslova. + Besedilno polje za urejanje spletnega naslova. - Besedilno polje za urejanje uporabniškega imena prijave. + Besedilno polje za urejanje uporabniškega imena prijave. - Besedilno polje za urejanje uporabniškega imena. + Besedilno polje za urejanje uporabniškega imena. - Besedilno polje za urejanje gesla prijave. + Besedilno polje za urejanje gesla prijave. - Besedilno polje za urejanje gesla. + Besedilno polje za urejanje gesla. - Shrani spremembe v prijavo. + Shrani spremembe v prijavo. - Shrani spremembe. + Shrani spremembe. - Urejanje + Urejanje - Uredi geslo + Uredi geslo - Dodaj novo prijavo + Dodaj novo prijavo - Dodaj geslo + Dodaj geslo - Zahtevano je geslo + Zahtevano je geslo - Vnesite geslo + Vnesite geslo - Zahtevano je uporabniško ime + Zahtevano je uporabniško ime - Vnesite uporabniško ime + Vnesite uporabniško ime Zahtevano je ime domene @@ -2170,6 +2187,9 @@ Iskalnik %s + + + Zamenjajte privzeti brskalnik Nastavite, naj se povezave s spletnih strani, e-pošte in sporočil samodejno odpirajo v Firefoxu. @@ -2180,7 +2200,7 @@ Kliknite za podrobnosti - Pojdi gor + Pojdi gor Zapri @@ -2220,8 +2240,6 @@ Kako zanesljiva so ta mnenja? Prilagojena ocena - - Nezanesljiva mnenja odstranjena Poudarki iz nedavnih mnenj @@ -2276,10 +2294,6 @@ Če opazite, da je izdelek znova na zalogi, nam to sporočite in preverili bomo mnenja. Sporoči, da je izdelek znova na zalogi - - Preverjanje kakovosti mnenj - - Preverjanje kakovosti mnenj To lahko traja približno 60 sekund. @@ -2323,11 +2337,11 @@ Več o tem - Z izbiro “Da, poskusi” se strinjate z %2$s in %3$s Mozilla %1$s. + Z izbiro “Da, poskusi” se strinjate z %2$s in %3$s Mozilla %1$s. Z izbiro “Da, poskusi” se strinjate z naslednjimi dokumenti %1$sa: - pravilnikom o zasebnosti + pravilnikom o zasebnosti Pravilnik o zasebnosti @@ -2414,6 +2428,8 @@ Ciljni jezik Ne zdaj + + Prikaži izvirnik Končano @@ -2436,6 +2452,11 @@ Več o tem + + + Prevajanje … + + Možnosti prevajanja diff --git a/app/src/main/res/values-sq/strings.xml b/app/src/main/res/values-sq/strings.xml index ea099419b..f48cffcd2 100644 --- a/app/src/main/res/values-sq/strings.xml +++ b/app/src/main/res/values-sq/strings.xml @@ -242,6 +242,7 @@ Përshtatni faqe hyrëse + Skena e kreut @@ -249,6 +250,14 @@ Fshi historik shfletimesh + + Përktheje faqen + + + Faqe e përkthyer nga %1$s në %2$s. + Gjuha e përzgjedhur @@ -324,12 +333,22 @@ Shënim mbi privatësinë në Firefox - + + Mësoni më tepër te shënimi ynë mbi privatësinë Duam fort t’ju mbajmë të parrezik + + Zbuloni pse e duan Firefox-in miliona vetë + + Shfletim i parrezik, me më tepër zgjedhje Shfletuesi ynë, me entin jofitimprurës nga pas, ndihmon të ndalen shoqëri t’ju ndjekin fshehtazi nëpër internet. + Më tepër se 100 milionë vetëm e mbrojnë privatësinë e tyre duke zgjedhur një shfletues që ka nga pas një ent jofitimprurës. + + Gjurmues të ditur? Të bllokuar automatikisht. Zgjerime? Provojini krejt të 700-ët. PDF? Lexuesi ynë i brendshëm i bën të administrohen me lehtësi. + Shfletuesi ynë, me entin jofitimprurës nga pas, ndihmon të ndalen shoqëri t’ju ndjekin fshehtazi nëpër internet.\n\nMësoni më tepër te shënimi ynë mbi privatësinë. @@ -686,9 +705,9 @@ Faqerojtës - Kredenciale Hyrjesh + Kredenciale Hyrjesh - Fjalëkalime + Fjalëkalime Skeda të hapura @@ -715,9 +734,9 @@ %1$s në %2$s %3$s - Karta krediti + Karta krediti - Metoda pagesash + Metoda pagesash Adresa @@ -1657,13 +1676,13 @@ Këtë sajt mund ta shtoni lehtë te skena Kreu e pajisjes tuaj, që ta hapni në çast dhe të shfletoni më shpejt, si të ish aplikacion. - Kredenciale hyrjesh dhe fjalëkalime + Kredenciale hyrjesh dhe fjalëkalime - Fjalëkalime + Fjalëkalime - Ruaj kredenciale hyrjesh dhe fjalëkalime + Ruaj kredenciale hyrjesh dhe fjalëkalime - Ruani fjalëkalime + Ruani fjalëkalime Pyet të ruhet a jo @@ -1679,47 +1698,47 @@ Plotësoni emra përdoruesish dhe fjalëkalime në aplikacione të tjera në pajisjen tuaj. - Shtoni kredenciale hyrjeje + Shtoni kredenciale hyrjeje - Shtoni fjalëkalim + Shtoni fjalëkalim - - Njëkohëso kredenciale hyrjeje - Njëkohësoni fjalëkalime + Njëkohëso kredenciale hyrjeje + + Njëkohësoni fjalëkalime - Njëkohëso kredenciale hyrjesh nëpër pajisje + Njëkohëso kredenciale hyrjesh nëpër pajisje - Njëkohësoni fjalëkalime mes pajisjesh + Njëkohësoni fjalëkalime mes pajisjesh - Kredenciale hyrjesh të ruajtur + Kredenciale hyrjesh të ruajtur - Fjalëkalime të ruajtur + Fjalëkalime të ruajtur - Këtu do të shfaqen kredencialet e hyrjeve që ruani ose njëkohësoni në %s. + Këtu do të shfaqen kredencialet e hyrjeve që ruani ose njëkohësoni në %s. - Këtu do të shfaqen fjalëkalimet që ruani, ose njëkohësoni në %s. Krejt fjalëkalimet që ruani, fshehtëzohen. + Këtu do të shfaqen fjalëkalimet që ruani, ose njëkohësoni në %s. Krejt fjalëkalimet që ruani, fshehtëzohen. - Mësoni më tepër mbi Sync-un. + Mësoni më tepër mbi Sync-un. - Mësoni më tepër mbi njëkohësimin + Mësoni më tepër mbi njëkohësimin Përjashtime - Këtu do të shfaqen kredenciale hyrjesh dhe fjalëkalime që nuk janë ruajtur. + Këtu do të shfaqen kredenciale hyrjesh dhe fjalëkalime që nuk janë ruajtur. - %s s’do të ruajë fjalëkalime për sajte të radhitur këtu. + %s s’do të ruajë fjalëkalime për sajte të radhitur këtu. - Për këto sajte s’do të ruhen kredenciale hyrjesh dhe fjalëkalime. + Për këto sajte s’do të ruhen kredenciale hyrjesh dhe fjalëkalime. - %s s’do të ruajë fjalëkalime për këta sajte. + %s s’do të ruajë fjalëkalime për këta sajte. Fshi krejt përjashtimet - Kërkoni te kredenciale hyrjesh + Kërkoni te kredenciale hyrjesh - Kërko te fjalëkalimet + Kërko te fjalëkalimet Sajt @@ -1747,17 +1766,17 @@ Fshihe fjalëkalimin - Që të shihni kredenciale tuajt hyrjesh të ruajtur, shkyçeni + Që të shihni kredenciale tuajt hyrjesh të ruajtur, shkyçeni - Që të shihni fjalëkalimet tuaj të ruajtura, shkyçeni + Që të shihni fjalëkalimet tuaj të ruajtura, shkyçeni - Siguroni kredenciale hyrjesh dhe fjalëkalime tuajt + Siguroni kredenciale hyrjesh dhe fjalëkalime tuajt - Siguroni fjalëkalimet tuaj të ruajtur + Siguroni fjalëkalimet tuaj të ruajtur - Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur nga hyrja në to kredencialet e hyrjes dhe fjalëkalimet tuaj të ruajtur, nëse pajisjen tuaj e ka dikush tjetër. + Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur nga hyrja në to kredencialet e hyrjes dhe fjalëkalimet tuaj të ruajtur, nëse pajisjen tuaj e ka dikush tjetër. - Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur prej hyrjes në to fjalëkalimet tuaj të ruajtur, nëse pajisjen tuaj e ka dikush tjetër. + Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur prej hyrjes në to fjalëkalimet tuaj të ruajtur, nëse pajisjen tuaj e ka dikush tjetër. Më vonë @@ -1775,7 +1794,10 @@ Përdorur së fundi - Renditni menu kredencialesh + Renditni menu kredencialesh + + + Menu renditjeje fjalëkalimesh Menu renditjeje fjalëkalimesh @@ -1786,40 +1808,43 @@ Adresa - Karta krediti + Karta krediti - Metoda pagesash + Metoda pagesash - Ruaj dhe plotëso vetvetiu të dhëna kartash + Ruaj dhe plotëso vetvetiu të dhëna kartash - Ruaj dhe plotëso metoda pagesash + Ruaj dhe plotëso metoda pagesash - Të dhënat janë të fshehtëzuara + Të dhënat janë të fshehtëzuara - %s fshehtëzon krejt metodat e pagesave që ruani + %s fshehtëzon krejt metodat e pagesave që ruani Njëkohëso të dhëna kartash mes pajisjesh Njëkohëso karta - Shtoni kartë krediti + Shtoni kartë krediti - Shtoni kartë + Shtoni kartë - Administroni karta të ruajtura + Administroni karta të ruajtura - Administroni karta + Administroni karta Shtoni adresë Administroni adresa - Ruaj dhe vetëplotëso adresa + Ruaj dhe vetëplotëso adresa - Ruaj dhe vetëplotëso adresa + Ruaj dhe vetëplotëso adresa - Përfshini hollësi të tilla si numra, email dhe adresa dërgimi + Përfshini hollësi të tilla si numra, email dhe adresa dërgimi + + + Përfshin numra telefonash dhe adresa email Përfshin numra telefonash dhe adresa email @@ -1843,9 +1868,9 @@ Fshije kartën - Jeni i sigurt se doni të fshihet kjo kartë krediti? + Jeni i sigurt se doni të fshihet kjo kartë krediti? - Të fshihet karta? + Të fshihet karta? Fshije @@ -1858,24 +1883,24 @@ Karta të ruajtura - Ju lutemi, jepni një numër të vlefshëm karte krediti + Ju lutemi, jepni një numër të vlefshëm karte krediti - Jepni një numër karte të vlefshme + Jepni një numër karte të vlefshme - Ju lutemi, plotësojeni këtë fushë + Ju lutemi, plotësojeni këtë fushë - Shtoni emër + Shtoni emër Që të shihni kartat tuaja të ruajtura, shkyçeni - Siguroni kartat tuaja të kreditit + Siguroni kartat tuaja të kreditit - Siguroni metodat tuaja të ruajtura të pagesave + Siguroni metodat tuaja të ruajtura të pagesave - Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur nga hyrja në to kartat tuaja kreditit të ruajturar, nëse pajisjen tuaj e ka dikush tjetër. + Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur nga hyrja në to kartat tuaja kreditit të ruajturar, nëse pajisjen tuaj e ka dikush tjetër. - Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur prej hyrjes në to hollësitë e ruajtura për kartat tuaja, nëse pajisjen tuaj e ka dikush tjetër. + Ujdisni një rregullsi, PIN, ose fjalëkalim kyçjeje pajisjeje për të mbrojtur prej hyrjes në to hollësitë e ruajtura për metodat tuaja të pagesave, nëse pajisjen tuaj e ka dikush tjetër. Ujdiseni tani @@ -1883,10 +1908,10 @@ Shkyçni pajisjen tuaj - Që të përdorni të dhëna karte krediti të depozituara, shkyçeni + Që të përdorni të dhëna karte krediti të depozituara, shkyçeni - Që të përdorni metoda të ruajtura pagesash, shkyçeni + Që të përdorni metoda të ruajtura pagesash, shkyçeni Shtoni adresë @@ -1894,11 +1919,13 @@ Administroni adresa - Emër + Emër - Emër i Mesit + Emër i Mesit - Mbiemër + Mbiemër + + Emër Rrugë @@ -1922,9 +1949,9 @@ Përzgjidhni adresë - Jeni i sigurt se doni të fshihet kjo adresë? + Jeni i sigurt se doni të fshihet kjo adresë? - Të fshihet kjo adresë? + Të fshihet kjo adresë? Fshije @@ -2022,50 +2049,50 @@ Përpunoni - Jeni i sigurt se doni të fshihen këto kredenciale hyrjeje? + Jeni i sigurt se doni të fshihen këto kredenciale hyrjeje? - Jeni i sigurt se doni të fshihet ky fjalëkalim? + Jeni i sigurt se doni të fshihet ky fjalëkalim? Fshije Anuloje - Mundësi hyrjesh + Mundësi hyrjesh - Mundësi fjalëkalimesh + Mundësi fjalëkalimesh - Fusha e përpunueshme e teksteve për adresën web të kredencialeve të hyrjes. - - Fusha e përpunueshme e teksteve për adresën web të fjalëkalimit. + Fusha e përpunueshme e teksteve për adresën web të kredencialeve të hyrjes. + + Fusha e përpunueshme e teksteve për adresën e sajtit. - Fusha e përpunueshme e teksteve për emrin e përdoruesit të kredencialeve të hyrjes. - - Fusha e përpunueshme e teksteve për emrin e përdoruesit të fjalëkalimit. + Fusha e përpunueshme e teksteve për emrin e përdoruesit të kredencialeve të hyrjes. + + Fusha e përpunueshme e teksteve për emrin e përdoruesit. - Fusha e përpunueshme e teksteve për fjalëkalimin e kredencialeve të hyrjes. + Fusha e përpunueshme e teksteve për fjalëkalimin e kredencialeve të hyrjes. - Fusha e përpunueshme e teksteve për fjalëkalimin. + Fusha e përpunueshme e teksteve për fjalëkalimin. - Ruani ndryshimet te kredenciale hyrjesh. + Ruani ndryshimet te kredenciale hyrjesh. - Ruaji ndryshimet. + Ruaji ndryshimet. - Përpunoni + Përpunoni - Përpunoni fjalëkalimin + Përpunoni fjalëkalimin - Shtoni kredenciale hyrjeje të re + Shtoni kredenciale hyrjeje të re - Shtoni fjalëkalim + Shtoni fjalëkalim - Lypset fjalëkalim + Lypset fjalëkalim - Jepni një fjalëkalim + Jepni një fjalëkalim - Emri i përdoruesit është i domosdoshëm + Emri i përdoruesit është i domosdoshëm - Jepni emër përdoruesi + Jepni emër përdoruesi Lypset strehëemër @@ -2165,6 +2192,9 @@ Kërkim me %s + + Ndërroni shfletuesin tuaj parazgjedhje + Caktoni lidhje prej sajtesh, email-esh dhe mesazhezh për hapje të automatizuar në Firefox. @@ -2174,7 +2204,7 @@ Klikoni për më tepër hollësi - Lëvizni për sipër + Lëvizni për sipër Mbylle @@ -2215,8 +2245,6 @@ Vlerësim i rregulluar - U hoqën shqyrtime jo të besueshme - Bazuar në shqyrtime të besueshme Gjëra në pah nga shqyrtimet së fundi @@ -2273,10 +2301,6 @@ Nëse e shihni sërish në stok këtë produkt, raportojeni dhe do të merremi me kontrollin e shqyrtimeve. Njoftoni se për produktin ka prapë stok - - Kontroll cilësie shqyrtimesh - - Po kontrollohet cilësi shqyrtimesh Po kontrollohet cilësi shqyrtimesh (%s) @@ -2322,13 +2346,19 @@ Mësoni më tepër - Duke përzgjedhur “Po, Provojeni”, pajtoheni me %1$s nga %2$s dhe %3$s të Mozilla-s. + Duke përzgjedhur “Po, Provojeni”, pajtoheni me %1$s nga %2$s dhe %3$s të Mozilla-s. Duke përzgjedhur “Po, provojeni”, pajtoheni me sa vijon prej %1$s: + + Duke përzgjedhur “Po, provojeni”, pajtoheni me %2$s e %1$s dhe %4$s të %3$s. + + Duke përzgjedhur “Po, provojeni”, pajtoheni me %2$s e %1$s dhe %4$s të %3$s. - rregulla privatësie + rregulla privatësie Rregulla privatësie + + shënim privatësie kushte përdorimi @@ -2400,6 +2430,10 @@ Të përkthehet kjo faqe? + + Faqe e përkthyer nga %1$s në %2$s Provoni përkthime private në %1$s @@ -2412,6 +2446,8 @@ Përkthe në Jo tani + + Shfaq origjinalin U bë @@ -2423,6 +2459,8 @@ Përkthim Në Kryerje e Sipër + + Zgjidhni një gjuhë Pati një problem me përkthimin. Ju lutemi, riprovoni. @@ -2432,6 +2470,15 @@ Mësoni më tepër + + Po përkthehet… + + Të shkarkohet nën mënyrën ruajtje të dhënash (%1$s)? + + Mundësi Përkthimi diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 74ab848e4..3306bab05 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -259,6 +259,11 @@ Översätt sida + + Sida översatt från %1$s till %2$s. + Valt språk @@ -337,12 +342,22 @@ Firefox sekretessmeddelande - + + Läs mer i vårt sekretessmeddelande Vi älskar att hålla dig säker + + Ta reda på varför miljoner älskar Firefox + + Säker surfning med flera val Vår icke-vinstdrivande webbläsare hjälper till att hindra företag från att i hemlighet följa dig på webben. + Mer än 100 miljoner människor skyddar sin integritet genom att välja en webbläsare som stöds av en ideell organisation. + + Kända spårare? Blockeras automatiskt. Tillägg? Prova alla 700. PDF-filer? Vår inbyggda läsare gör dem enklare att hantera. + Vår icke-vinstdrivande webbläsare hjälper till att hindra företag från att följa dig i hemlighet på webben.\n\nLäs mer i vårt sekretessmeddelande. @@ -505,7 +520,7 @@ Säker webbplats är inte tillgänglig - Troligtvis stöder webbplatsen helt enkelt inte HTTPs. + Troligtvis stöder webbplatsen helt enkelt inte HTTPS. Men det är också möjligt att en angripare är inblandad. Om du fortsätter till webbplatsen ska du inte ange någon känslig information. Om du fortsätter kommer endast HTTPS-läget att stängas av tillfälligt för webbplatsen. @@ -699,9 +714,9 @@ Bokmärken - Inloggningar + Inloggningar - Lösenord + Lösenord Öppna flikar @@ -728,9 +743,9 @@ %1$s på %2$s %3$s - Kreditkort + Kreditkort - Betalningsmetoder + Betalningsmetoder Adresser @@ -1679,13 +1694,13 @@ Du kan enkelt lägga till den här webbplatsen på enhetens startskärm för att få direktåtkomst och surfa snabbare med en appliknande upplevelse. - Inloggningar och lösenord + Inloggningar och lösenord - Lösenord + Lösenord - Spara inloggningar och lösenord + Spara inloggningar och lösenord - Spara lösenord + Spara lösenord Fråga för att spara @@ -1700,48 +1715,48 @@ Fyll i användarnamn och lösenord i andra appar på din enhet. - Lägg till inloggning + Lägg till inloggning - Lägg till lösenord + Lägg till lösenord - - Synkronisera inloggningar - Synkronisera lösenord + Synkronisera inloggningar + + Synkronisera lösenord - Synkronisera inloggningar mellan enheter + Synkronisera inloggningar mellan enheter - Synkronisera lösenord mellan enheter + Synkronisera lösenord mellan enheter - Sparade inloggningar + Sparade inloggningar - Sparade lösenord + Sparade lösenord - De inloggningar som du sparar eller synkroniserar till %s kommer att dyka upp här. + De inloggningar som du sparar eller synkroniserar till %s kommer att dyka upp här. - Lösenorden du sparar eller synkroniserar till %s kommer att listas här. Alla lösenord du sparar är krypterade. + Lösenorden du sparar eller synkroniserar till %s kommer att listas här. Alla lösenord du sparar är krypterade. - Läs mer om Sync. + Läs mer om Sync. - Läs mer om synkronisering + Läs mer om synkronisering Undantag - Inloggningar och lösenord som inte sparas visas här. + Inloggningar och lösenord som inte sparas visas här. - %s kommer inte att spara lösenord för webbplatser som listas här. + %s kommer inte att spara lösenord för webbplatser som listas här. - Inloggningar och lösenord sparas inte för dessa webbplatser. + Inloggningar och lösenord sparas inte för dessa webbplatser. - %s kommer inte att spara lösenord för dessa webbplatser. + %s kommer inte att spara lösenord för dessa webbplatser. Ta bort alla undantag - Sök inloggningar + Sök inloggningar - Sök efter lösenord + Sök efter lösenord Webbplats @@ -1769,17 +1784,17 @@ Dölj lösenord - Lås upp för att se dina sparade inloggningar + Lås upp för att se dina sparade inloggningar - Lås upp för att se dina sparade lösenord + Lås upp för att se dina sparade lösenord - Säkra dina inloggningar och lösenord + Säkra dina inloggningar och lösenord - Säkra dina sparade lösenord + Säkra dina sparade lösenord - Konfigurera enhetens låsmönster, PIN eller lösenord för att skydda dina sparade inloggningar och lösenord från åtkomst om någon annan har din enhet. + Konfigurera enhetens låsmönster, PIN eller lösenord för att skydda dina sparade inloggningar och lösenord från åtkomst om någon annan har din enhet. - Konfigurera ett enhetslåsmönster, PIN-kod eller lösenord för att skydda dina sparade lösenord från åtkomst om någon annan använder din enhet. + Konfigurera ett enhetslåsmönster, PIN-kod eller lösenord för att skydda dina sparade lösenord från åtkomst om någon annan använder din enhet. Senare @@ -1796,7 +1811,10 @@ Senast använd - Sortera inloggningsmenyn + Sortera inloggningsmenyn + + + Menyn sortera lösenord Menyn sortera lösenord @@ -1807,40 +1825,43 @@ Adresser - Kreditkort + Kreditkort - Betalningsmetoder + Betalningsmetoder - Spara och fyll i kreditkort automatiskt + Spara och fyll i kreditkort automatiskt - Spara och fyll i betalningsmetoder + Spara och fyll i betalningsmetoder - Data är krypterad + Data är krypterad - %s krypterar alla betalningsmetoder som du sparar + %s krypterar alla betalningsmetoder som du sparar Synkronisera kort mellan enheter Synkronisera kort - Lägg till kreditkort + Lägg till kreditkort - Lägg till kort + Lägg till kort - Hantera sparade kreditkort + Hantera sparade kreditkort - Hantera kort + Hantera kort Lägg till adress Hantera adresser - Spara och fyll i adresser automatiskt + Spara och fyll i adresser automatiskt - Spara och fyll i adresser + Spara och fyll i adresser - Inkludera information som nummer, e-post och leveransadresser + Inkludera information som nummer, e-post och leveransadresser + + + Inkluderar telefonnummer och e-postadresser Inkluderar telefonnummer och e-postadresser @@ -1864,9 +1885,9 @@ Ta bort kort - Är du säker på att du vill ta bort det här kreditkortet? + Är du säker på att du vill ta bort det här kreditkortet? - Ta bort kort? + Ta bort kort? Ta bort @@ -1880,24 +1901,24 @@ Sparade kreditkort - Ange ett giltigt kreditkortsnummer + Ange ett giltigt kreditkortsnummer - Ange ett giltigt kortnummer + Ange ett giltigt kortnummer - Fyll i det här fältet + Fyll i det här fältet - Lägg till ett namn + Lägg till ett namn Lås upp för att se dina sparade kreditkort - Säkra dina kreditkort + Säkra dina kreditkort - Säkra dina sparade betalningsmetoder + Säkra dina sparade betalningsmetoder - Konfigurera enhetens låsmönster, PIN eller lösenord för att skydda dina sparade kreditkort från åtkomst om någon annan har din enhet. + Konfigurera enhetens låsmönster, PIN eller lösenord för att skydda dina sparade kreditkort från åtkomst om någon annan har din enhet. - Konfigurera ett enhetslåsmönster, PIN-kod eller lösenord för att skydda dina sparade betalningsmetoder från att användas om någon annan har din enhet. + Konfigurera ett enhetslåsmönster, PIN-kod eller lösenord för att skydda dina sparade betalningsmetoder från att användas om någon annan har din enhet. Konfigurera nu @@ -1906,10 +1927,10 @@ Lås upp din enhet - Lås upp för att använda lagrad kreditkortsinformation + Lås upp för att använda lagrad kreditkortsinformation - Lås upp för att använda sparade betalningsmetoder + Lås upp för att använda sparade betalningsmetoder Lägg till adress @@ -1917,11 +1938,13 @@ Hantera adresser - Förnamn + Förnamn - Mellannamn + Mellannamn - Efternamn + Efternamn + + Namn Gatuadress @@ -1946,9 +1969,9 @@ Ta bort adress - Är du säker på att du vill ta bort den här adressen? + Är du säker på att du vill ta bort den här adressen? - Ta bort den här adressen? + Ta bort den här adressen? Ta bort @@ -2047,49 +2070,49 @@ Redigera - Är du säker på att du vill ta bort den här inloggningen? + Är du säker på att du vill ta bort den här inloggningen? - Är du säker på att du vill ta bort det här lösenordet? + Är du säker på att du vill ta bort det här lösenordet? Ta bort Avbryt - Inloggningsalternativ + Inloggningsalternativ - Lösenordsalternativ + Lösenordsalternativ - Det redigerbara textfältet för inloggningens webbadress. + Det redigerbara textfältet för inloggningens webbadress. - Det redigerbara textfältet för webbplatsadressen. + Det redigerbara textfältet för webbplatsadressen. - Det redigerbara textfältet för inloggningens användarnamn. + Det redigerbara textfältet för inloggningens användarnamn. - Det redigerbara textfältet för användarnamnet. + Det redigerbara textfältet för användarnamnet. - Det redigerbara textfältet för inloggningens lösenord. + Det redigerbara textfältet för inloggningens lösenord. - Det redigerbara textfältet för lösenordet. + Det redigerbara textfältet för lösenordet. - Spara ändringar för inloggning. + Spara ändringar för inloggning. - Spara ändringar. + Spara ändringar. - Redigera + Redigera - Redigera lösenord + Redigera lösenord - Lägg till ny inloggning + Lägg till ny inloggning - Lägg till lösenord + Lägg till lösenord - Lösenord krävs + Lösenord krävs - Ange ett lösenord + Ange ett lösenord - Användarnamn krävs + Användarnamn krävs - Ange ett användarnamn + Ange ett användarnamn Värdnamn krävs @@ -2201,7 +2224,7 @@ Klicka för mer information - Navigera uppåt + Navigera uppåt Stäng @@ -2242,8 +2265,6 @@ Justerat betyg - Opålitliga recensioner har tagits bort - Baserat på tillförlitliga recensioner Höjdpunkter från de senaste recensionerna @@ -2299,10 +2320,6 @@ Om du ser att den här produkten finns i lager igen, rapportera det så jobbar vi med att kontrollera recensionerna. Rapportera att produkten finns i lager - - Kontrollerar recensionens kvalitet - - Kontrollerar recensionens kvalitet Kontrollerar recensionskvalitet (%s) @@ -2348,13 +2365,19 @@ Läs mer - Genom att välja "Ja, prova den" godkänner du %1$s av Mozillas %2$s och %3$s. + Genom att välja "Ja, prova den" godkänner du %1$s av Mozillas %2$s och %3$s. Genom att välja "Ja, prova den" godkänner du följande från %1$s: + + Genom att välja "Ja, prova den" godkänner du %1$s %2$s och %3$s %4$s. + + Genom att välja "Ja, prova den" godkänner du %1$s %2$s och %3$s %4$s. - sekretesspolicy + sekretesspolicy Sekretesspolicy + + sekretessmeddelande användarvillkor @@ -2425,6 +2448,10 @@ Översätt den här sidan? + + Sida översatt från %1$s till %2$s Prova privata översättningar i %1$s @@ -2437,6 +2464,8 @@ Översätt till Inte nu + + Visa original Klar @@ -2461,6 +2490,16 @@ Läs mer + + Översätter… + + + Hämta språk i datasparläge (%1$s)? + + Översättningsalternativ diff --git a/app/src/main/res/values-tg/strings.xml b/app/src/main/res/values-tg/strings.xml index 4ae0da3cf..87d7fd4ae 100644 --- a/app/src/main/res/values-tg/strings.xml +++ b/app/src/main/res/values-tg/strings.xml @@ -257,6 +257,11 @@ Тарҷума кардани саҳифа + + Саҳифа аз забони %1$s ба забони %2$s тарҷума шуд. + Забони интихобшуда @@ -334,9 +339,13 @@ Огоҳномаи махфияти «Firefox» - + + Маълумоти бештар дар «Огоҳномаи махфияти мо» Мо нигоҳдории бехатарии шуморо дӯст медорем + + Бифаҳмед, ки чаро миллионҳо одамон браузери «Firefox»-ро дӯст медоранд Браузери мо, ки аз ҷониби ташкилоти ғайритиҷоратӣ дастгирӣ мешавад, маъракаҳоеро, ки шуморо дар атрофи Интернет пинҳонӣ пайгирӣ мекунанд, қатъ мекунад. @@ -694,9 +703,9 @@ Хатбаракҳо - Воридшавиҳо + Воридшавиҳо - Ниҳонвожаҳо + Ниҳонвожаҳо Варақаҳои кушодашуда @@ -723,9 +732,9 @@ %1$s дар %2$s %3$s - Кортҳои кредитӣ + Кортҳои кредитӣ - Тарзҳои пардохт + Тарзҳои пардохт Нишониҳо @@ -1675,13 +1684,13 @@ Шумо метавонед ин сомонаро ба экрани асосии дастгоҳи худ ба осонӣ илова кунед, то ки ба он дастрасии фаврӣ дошта бошед ва бо таҷрибаи ба барнома монанд зудтар паймоиш кунед. - Воридшавиҳо ва ниҳонвожаҳо + Воридшавиҳо ва ниҳонвожаҳо - Ниҳонвожаҳо + Ниҳонвожаҳо - Нигоҳ доштани воридшавиҳо ва ниҳонвожаҳо + Нигоҳ доштани воридшавиҳо ва ниҳонвожаҳо - Нигоҳ доштани ниҳонвожаҳо + Нигоҳ доштани ниҳонвожаҳо Бо пешниҳоди нигоҳдорӣ @@ -1696,47 +1705,47 @@ Номи корбарон ва ниҳонвожаҳоро дар барномаҳои дигари дастгоҳи худ пур кунед. - Илова кардани воридшавӣ + Илова кардани воридшавӣ - Илова кардани ниҳонвожа + Илова кардани ниҳонвожа - - Воридшавиҳои ҳамоҳангшуда - Ҳамоҳанг кардани ниҳонвожаҳо + Воридшавиҳои ҳамоҳангшуда + + Ҳамоҳанг кардани ниҳонвожаҳо - Ҳамоҳанг кардани воридшавиҳо байни дастгоҳҳо + Ҳамоҳанг кардани воридшавиҳо байни дастгоҳҳо - Ҳамоҳанг кардани ниҳонвожаҳо байни дастгоҳҳо + Ҳамоҳанг кардани ниҳонвожаҳо байни дастгоҳҳо - Воридшавиҳои нигоҳдошташуда + Воридшавиҳои нигоҳдошташуда - Ниҳонвожаҳои нигоҳдошташуда + Ниҳонвожаҳои нигоҳдошташуда - Воридшавиҳое, ки шумо дар %s нигоҳ медоред ё ҳамоҳанг мекунед, дар ин ҷо нишон дода мешаванд. + Воридшавиҳое, ки шумо дар %s нигоҳ медоред ё ҳамоҳанг мекунед, дар ин ҷо нишон дода мешаванд. - Ниҳонвожаҳоеро, ки шумо нигоҳ медоред ё бо «%s» ҳамоҳанг месозед, дар ин рӯйхат нишон дода мешаванд. Ҳамаи ниҳонвожаҳое, ки шумо нигоҳ медоред, рамзгузорӣ карда мешаванд. + Ниҳонвожаҳоеро, ки шумо нигоҳ медоред ё бо «%s» ҳамоҳанг месозед, дар ин рӯйхат нишон дода мешаванд. Ҳамаи ниҳонвожаҳое, ки шумо нигоҳ медоред, рамзгузорӣ карда мешаванд. - Маълумоти бештар дар бораи ҳамоҳангсозӣ + Маълумоти бештар дар бораи ҳамоҳангсозӣ - Маълумоти бештар дар бораи ҳамоҳангсозӣ + Маълумоти бештар дар бораи ҳамоҳангсозӣ Истисноҳо - Воридшавиҳо ва ниҳонвожаҳое, ки нигоҳ дошта нашудаанд, дар ин ҷо нишон дошта мешаванд. + Воридшавиҳо ва ниҳонвожаҳое, ки нигоҳ дошта нашудаанд, дар ин ҷо нишон дошта мешаванд. - «%s» барои сомонаҳое, ки дар ин рӯйхат нишон дода шудаанд, ниҳонвожаҳоро нигоҳ намедорад. + «%s» барои сомонаҳое, ки дар ин рӯйхат нишон дода шудаанд, ниҳонвожаҳоро нигоҳ намедорад. - Воридшавиҳо ва ниҳонвожаҳо барои сомонаҳои зерин нигоҳ дошта намешаванд. + Воридшавиҳо ва ниҳонвожаҳо барои сомонаҳои зерин нигоҳ дошта намешаванд. - «%s» барои сомонаҳои зерин ниҳонвожаҳоро нигоҳ намедорад. + «%s» барои сомонаҳои зерин ниҳонвожаҳоро нигоҳ намедорад. Нест кардани ҳамаи истисноҳо - Ҷустуҷӯи воридшавиҳо + Ҷустуҷӯи воридшавиҳо - Ҷустуҷӯи ниҳонвожаҳо + Ҷустуҷӯи ниҳонвожаҳо Сомона @@ -1764,15 +1773,17 @@ Пинҳон кардани ниҳонвожа - Барои дидани воридшавиҳои нигоҳдошташуда, қулфро кушоед + Барои дидани воридшавиҳои нигоҳдошташуда, қулфро кушоед - Барои дидани ниҳонвожаҳои нигоҳдошташуда, қулфро кушоед + Барои дидани ниҳонвожаҳои нигоҳдошташуда, қулфро кушоед - Воридшавиҳо ва ниҳонвожаҳои худро муҳофизат намоед + Воридшавиҳо ва ниҳонвожаҳои худро муҳофизат намоед - Ниҳонвожаҳои нигоҳдоштаро муҳофизат намоед + Ниҳонвожаҳои нигоҳдоштаро муҳофизат намоед + + Барои муҳофизат кардани воридшавиҳо ва ниҳонвожаҳои худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. - Барои муҳофизат кардани воридшавиҳо ва ниҳонвожаҳои худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. + Барои муҳофизат кардани ниҳонвожаҳои нигоҳдошташудаи худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. Дертар @@ -1790,7 +1801,7 @@ Истифодашудаи охирин - Мураттаб кардани менюи воридшавиҳо + Мураттаб кардани менюи воридшавиҳо @@ -1798,38 +1809,38 @@ Нишониҳо - Кортҳои кредитӣ + Кортҳои кредитӣ - Тарзҳои пардохт + Тарзҳои пардохт - Нигоҳ доштан ва ба таври худкор пур кардани кортҳо + Нигоҳ доштан ва ба таври худкор пур кардани кортҳо - Нигоҳ доштан ва пур кардани тарзҳои пардохт + Нигоҳ доштан ва пур кардани тарзҳои пардохт - Маълумот рамзгузорӣ карда шуд + Маълумот рамзгузорӣ карда шуд Ҳамоҳанг кардани кортҳо байни дастгоҳҳо Ҳамоҳанг кардани кортҳо - Илова кардани корти кредитӣ + Илова кардани корти кредитӣ - Илова кардани корт + Илова кардани корт - Идора кардани кортҳои нигоҳдошташуда + Идора кардани кортҳои нигоҳдошташуда - Идоракунии кортҳо + Идоракунии кортҳо Илова кардани нишонӣ Идоракунии нишониҳо - Нигоҳ доштан ва ба таври худкор пур кардани нишониҳо + Нигоҳ доштан ва ба таври худкор пур кардани нишониҳо - Нигоҳ доштан ва пур кардани нишониҳо + Нигоҳ доштан ва пур кардани нишониҳо - Илова кардани маълумот монанди рақамҳо, нишониҳои почтаи электронӣ ва бурдарасонӣ + Илова кардани маълумот монанди рақамҳо, нишониҳои почтаи электронӣ ва бурдарасонӣ Илова кардани корт @@ -1851,9 +1862,9 @@ Нест кардани корт - Шумо мутмаин ҳастед, ки мехоҳед ин корти кредитиро нест намоед? + Шумо мутмаин ҳастед, ки мехоҳед ин корти кредитиро нест намоед? - Кортро нест мекунед? + Кортро нест мекунед? Нест кардан @@ -1867,20 +1878,20 @@ Кортҳои нигоҳдошташуда - Лутфан, рақами корти кредитии дурустро ворид намоед + Лутфан, рақами корти кредитии дурустро ворид намоед - Рақами корти дурустро ворид намоед + Рақами корти дурустро ворид намоед - Лутфан, ин майдонро пур кунед + Лутфан, ин майдонро пур кунед - Номеро ворид намоед + Номеро ворид намоед Барои дидани кортҳои нигоҳдошташуда, қулфро кушоед - Кортҳои кредитии худро муҳофизат кунед + Кортҳои кредитии худро муҳофизат кунед - Барои муҳофизат кардани кортҳои кредитии нигоҳдошташудаи худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. + Барои муҳофизат кардани кортҳои кредитии нигоҳдошташудаи худ аз дастрасии озод, агар касе дигар аз дастгоҳи шумо истифода барад, шаклвораи қулфи экран, рамзи PIN ё ниҳонвожаеро барои дастгоҳи худ танзим намоед. Ҳозир насб кунед @@ -1888,7 +1899,7 @@ Қулфи дастгоҳи худро кушоед - Барои истифодаи маълумоти кортҳои кредитии нигоҳдошташуда, қулфро кушоед + Барои истифодаи маълумоти кортҳои кредитии нигоҳдошташуда, қулфро кушоед Илова кардани нишонӣ @@ -1897,11 +1908,11 @@ Идоракунии нишониҳо - Ном + Ном - Номи падар + Номи падар - Насаб + Насаб Нишонии кӯча @@ -1926,9 +1937,9 @@ Нест кардани нишонӣ - Шумо мутмаин ҳастед, ки мехоҳед ин нишониро нест намоед? + Шумо мутмаин ҳастед, ки мехоҳед ин нишониро нест намоед? - Ин нишониро нест мекунед? + Ин нишониро нест мекунед? Нест кардан @@ -2025,44 +2036,44 @@ Таҳрир кардан - Шумо мутмаин ҳастед, ки мехоҳед ин воридшавиро нест намоед? + Шумо мутмаин ҳастед, ки мехоҳед ин воридшавиро нест намоед? - Шумо мутмаин ҳастед, ки мехоҳед ин ниҳонвожаро нест намоед? + Шумо мутмаин ҳастед, ки мехоҳед ин ниҳонвожаро нест намоед? Нест кардан Бекор кардан - Имконоти воридшавӣ + Имконоти воридшавӣ - Инконоти ниҳонвожа + Инконоти ниҳонвожа - Майдони матни таҳриршаванда барои нишонии сомонаи воридшавӣ. + Майдони матни таҳриршаванда барои нишонии сомонаи воридшавӣ. - Майдони матни таҳриршаванда барои номи корбарии воридшавӣ. + Майдони матни таҳриршаванда барои номи корбарии воридшавӣ. - Майдони матни таҳриршаванда барои ниҳонвожаи воридшавӣ. + Майдони матни таҳриршаванда барои ниҳонвожаи воридшавӣ. - Нигоҳ доштани тағйирот барои воридшавӣ + Нигоҳ доштани тағйирот барои воридшавӣ - Тағийротро нигоҳ медорад. + Тағийротро нигоҳ медорад. - Таҳрир кардан + Таҳрир кардан - Таҳрир кардани ниҳонвожа + Таҳрир кардани ниҳонвожа - Илова кардани воридшавии нав + Илова кардани воридшавии нав - Илова кардани ниҳонвожа + Илова кардани ниҳонвожа - Ниҳонвожа лозим аст + Ниҳонвожа лозим аст - Ниҳонвожаеро ворид намоед + Ниҳонвожаеро ворид намоед - Номи корбар лозим аст + Номи корбар лозим аст - Номи корбареро ворид намоед + Номи корбареро ворид намоед Номи сервер лозим аст @@ -2175,7 +2186,7 @@ Барои тафсилоти бештар зер кунед - Ба боло гузаред + Ба боло гузаред Пӯшидан @@ -2216,8 +2227,6 @@ Баҳодиҳии санҷида дурустшуда - Тақризҳои беэътимод тоза карда шудаанд - Дар асоси тақризҳои беэътимод Нуқтаҳои асосӣ аз тақризҳои охирин @@ -2273,10 +2282,6 @@ Агар шумо бинед, ки ин маҳсул аз нав дастрас бошад, гузориш диҳед ва мо тақризҳои онро тафтиш мекунем. Огоҳ кунед, ки маҳсул дастрас аст - - Дар ҳоли санҷиши сифати тақризҳо - - Дар ҳоли санҷиши сифати тақризҳо Дар ҳоли санҷиши сифати тақризҳо (%s) @@ -2322,11 +2327,11 @@ Маълумоти бештар - Бо интихоби «Ҳа, озмоед», шумо ба «%1$s» бо қабули «%2$s» ва «%3$s» аз ҷониби «Mozilla» розӣ мешавед. + Бо интихоби «Ҳа, озмоед», шумо ба «%1$s» бо қабули «%2$s» ва «%3$s» аз ҷониби «Mozilla» розӣ мешавед. Бо интихоби «Ҳа, озмоед», шумо бо зерин мувофиқи «%1$s» розӣ мешавед: - сиёсати махфият + сиёсати махфият Сиёсати махфият @@ -2434,6 +2439,7 @@ Маълумоти бештар + Имконоти тарҷума diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 152ab7fc3..b1ca3fc2b 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -250,6 +250,14 @@ history and go back to the home screen. --> ล้างประวัติการเรียกดู + + แปลหน้า + + + แปลหน้าจาก%1$sเป็น%2$sแล้ว + ภาษาที่เลือก @@ -328,12 +336,22 @@ ประกาศความเป็นส่วนตัวของ Firefox - + + เรียนรู้เพิ่มเติมในประกาศความเป็นส่วนตัวของเรา เรารักที่จะดูแลคุณให้ปลอดภัย + + ค้นพบว่าทำไมผู้คนนับล้านถึงรัก Firefox + + ท่องเว็บอย่างปลอดภัยพร้อมตัวเลือกที่มากขึ้น เบราว์เซอร์ที่สนับสนุนโดยองค์กรไม่แสวงหาผลกำไรของเราจะช่วยหยุดบริษัทต่างๆ ไม่ให้แอบติดตามคุณทางเว็บได้ + ผู้คนมากกว่า 100 ล้านคนปกป้องความเป็นส่วนตัวของตัวเองด้วยการเลือกเบราว์เซอร์ที่ได้รับการสนับสนุนจากองค์กรไม่แสวงหาผลกำไร + + เครื่องมือติดตามที่รู้จักล่ะ? จะปิดกั้นให้โดยอัตโนมัติเลย ส่วนขยายล่ะ? ลองดูส่วนขยายทั้งหมดกว่า 700 อันเลย ไฟล์ PDF ล่ะ? ใช้ตัวอ่านภายในตัวของเราเลยเพื่อให้จัดการไฟล์เหล่านั้นได้ง่าย + เบราว์เซอร์ที่ได้รับการสนับสนุนจากองค์กรไม่แสวงหาผลกำไรของเราช่วยหยุดบริษัทต่าง ๆ ไม่ให้แอบติดตามคุณทางเว็บได้\n\nเรียนรู้เพิ่มเติมในประกาศความเป็นส่วนตัวของเรา @@ -692,9 +710,9 @@ ที่คั่นหน้า - การเข้าสู่ระบบ + การเข้าสู่ระบบ - รหัสผ่าน + รหัสผ่าน แท็บที่เปิดอยู่ @@ -720,9 +738,9 @@ %1$s บน %2$s %3$s - บัตรเครดิต + บัตรเครดิต - วิธีการชำระเงิน + วิธีการชำระเงิน ที่อยู่ @@ -1662,14 +1680,14 @@ คุณสามารถเพิ่มเว็บไซต์นี้ลงในหน้าจอหลักของอุปกรณ์ของคุณเพื่อเข้าถึงและเรียกดูได้เร็วขึ้นด้วยประสบการณ์ที่เหมือนแอป - การเข้าสู่ระบบและรหัสผ่าน + การเข้าสู่ระบบและรหัสผ่าน - รหัสผ่าน + รหัสผ่าน - บันทึกการเข้าสู่ระบบและรหัสผ่าน + บันทึกการเข้าสู่ระบบและรหัสผ่าน - บันทึกรหัสผ่าน + บันทึกรหัสผ่าน ถามเพื่อบันทึก @@ -1685,43 +1703,47 @@ เติมชื่อผู้ใช้และรหัสผ่านในแอปอื่น ๆ บนอุปกรณ์ของคุณ - เพิ่มการเข้าสู่ระบบ + เพิ่มการเข้าสู่ระบบ - เพิ่มรหัสผ่าน + เพิ่มรหัสผ่าน - - ซิงค์การเข้าสู่ระบบ - ซิงค์รหัสผ่าน + ซิงค์การเข้าสู่ระบบ + + ซิงค์รหัสผ่าน - ซิงค์การเข้าสู่ระบบระหว่างอุปกรณ์ + ซิงค์การเข้าสู่ระบบระหว่างอุปกรณ์ - ซิงค์รหัสผ่านระหว่างอุปกรณ์ + ซิงค์รหัสผ่านระหว่างอุปกรณ์ - การเข้าสู่ระบบที่บันทึกไว้ + การเข้าสู่ระบบที่บันทึกไว้ - รหัสผ่านที่บันทึกไว้ + รหัสผ่านที่บันทึกไว้ - การเข้าสู่ระบบที่คุณบันทึกหรือซิงค์กับ %s จะปรากฏที่นี่ + การเข้าสู่ระบบที่คุณบันทึกหรือซิงค์กับ %s จะปรากฏที่นี่ - รหัสผ่านที่คุณบันทึกหรือซิงค์กับ %s จะแสดงอยู่ที่นี่ รหัสผ่านทั้งหมดที่คุณบันทึกจะถูกเข้ารหัสไว้ + รหัสผ่านที่คุณบันทึกหรือซิงค์กับ %s จะแสดงอยู่ที่นี่ รหัสผ่านทั้งหมดที่คุณบันทึกจะถูกเข้ารหัสไว้ - เรียนรู้เพิ่มเติมเกี่ยวกับ Sync + เรียนรู้เพิ่มเติมเกี่ยวกับ Sync - เรียนรู้เพิ่มเติมเกี่ยวกับซิงค์ + เรียนรู้เพิ่มเติมเกี่ยวกับซิงค์ ข้อยกเว้น - การเข้าสู่ระบบและรหัสผ่านที่ไม่ได้บันทึกจะถูกแสดงที่นี่ + การเข้าสู่ระบบและรหัสผ่านที่ไม่ได้บันทึกจะถูกแสดงที่นี่ + + %s จะไม่บันทึกรหัสผ่านสำหรับไซต์ที่แสดงอยู่ที่นี่ - การเข้าสู่ระบบและรหัสผ่านจะไม่ถูกบันทึกสำหรับไซต์เหล่านี้ + การเข้าสู่ระบบและรหัสผ่านจะไม่ถูกบันทึกสำหรับไซต์เหล่านี้ + + %s จะไม่บันทึกรหัสผ่านสำหรับไซต์เหล่านี้ ลบข้อยกเว้นทั้งหมด - ค้นหาการเข้าสู่ระบบ + ค้นหาการเข้าสู่ระบบ - ค้นหารหัสผ่าน + ค้นหารหัสผ่าน ไซต์ @@ -1749,13 +1771,17 @@ ซ่อนรหัสผ่าน - ปลดล็อกเพื่อดูการเข้าสู่ระบบที่บันทึกไว้ของคุณ + ปลดล็อกเพื่อดูการเข้าสู่ระบบที่บันทึกไว้ของคุณ - ปลดล็อกเพื่อดูรหัสผ่านที่บันทึกไว้ของคุณ + ปลดล็อกเพื่อดูรหัสผ่านที่บันทึกไว้ของคุณ + + รักษาความปลอดภัยการเข้าสู่ระบบและรหัสผ่านของคุณ - รักษาความปลอดภัยการเข้าสู่ระบบและรหัสผ่านของคุณ + รักษาความปลอดภัยให้กับรหัสผ่านที่บันทึกไว้ของคุณ - ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงการเข้าสู่ระบบและรหัสผ่านที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงการเข้าสู่ระบบและรหัสผ่านที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ + + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงรหัสผ่านที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ ภายหลัง @@ -1773,7 +1799,10 @@ ใช้งานครั้งสุดท้าย - เรียงเมนูเข้าสู่ระบบ + เรียงเมนูเข้าสู่ระบบ + + + เมนูเรียงลำดับรหัสผ่าน @@ -1781,39 +1810,44 @@ ที่อยู่ - บัตรเครดิต + บัตรเครดิต - วิธีการชำระเงิน + วิธีการชำระเงิน - บันทึกและเติมข้อมูลบัตรอัตโนมัติ + บันทึกและเติมข้อมูลบัตรอัตโนมัติ - บันทึกและเติมวิธีการชำระเงิน + บันทึกและเติมวิธีการชำระเงิน - ข้อมูลถูกเข้ารหัส + ข้อมูลถูกเข้ารหัส + + %s จะเข้ารหัสลับวิธีการชำระเงินทั้งหมดที่คุณบันทึกไว้ ซิงค์บัตรระหว่างอุปกรณ์ ซิงค์บัตร - เพิ่มบัตรเครดิต + เพิ่มบัตรเครดิต - เพิ่มบัตร + เพิ่มบัตร - จัดการบัตรที่บันทึกไว้ + จัดการบัตรที่บันทึกไว้ - จัดการบัตร + จัดการบัตร เพิ่มที่อยู่ จัดการที่อยู่ - บันทึกและป้อนที่อยู่อัตโนมัติ + บันทึกและป้อนที่อยู่อัตโนมัติ - บันทึกและเติมที่อยู่อัตโนมัติ + บันทึกและเติมที่อยู่อัตโนมัติ - รวมข้อมูลเช่นหมายเลข อีเมล และที่อยู่ในการจัดส่ง + รวมข้อมูลเช่นหมายเลข อีเมล และที่อยู่ในการจัดส่ง + + + รวมหมายเลขโทรศัพท์และที่อยู่อีเมล รวมหมายเลขโทรศัพท์และที่อยู่อีเมล @@ -1837,9 +1871,9 @@ ลบบัตร - คุณแน่ใจหรือไม่ว่าต้องการลบบัตรเครดิตนี้? + คุณแน่ใจหรือไม่ว่าต้องการลบบัตรเครดิตนี้? - ลบบัตร? + ลบบัตร? ลบ @@ -1853,19 +1887,23 @@ บัตรที่บันทึกไว้ - โปรดป้อนหมายเลขบัตรเครดิตที่ถูกต้อง + โปรดป้อนหมายเลขบัตรเครดิตที่ถูกต้อง - ใส่หมายเลขบัตรที่ถูกต้อง + ใส่หมายเลขบัตรที่ถูกต้อง - โปรดกรอกช่องนี้ + โปรดกรอกช่องนี้ - เพิ่มชื่อ + เพิ่มชื่อ ปลดล็อกเพื่อดูบัตรเครดิตที่บันทึกไว้ของคุณ - รักษาความปลอดภัยให้กับบัตรเครดิตของคุณ + รักษาความปลอดภัยให้กับบัตรเครดิตของคุณ + + รักษาความปลอดภัยให้กับวิธีการชำระเงินที่บันทึกไว้ของคุณ + + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงบัตรเครดิตที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ - ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงบัตรเครดิตที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ + ตั้งค่ารูปแบบการล็อกอุปกรณ์, PIN, หรือรหัสผ่านเพื่อปกป้องไม่ให้ใครเข้าถึงวิธีการชำระเงินที่บันทึกไว้ของคุณหากคนอื่นมีอุปกรณ์ของคุณ ตั้งค่าตอนนี้ @@ -1873,8 +1911,10 @@ ปลดล็อกอุปกรณ์ของคุณ - ปลดล็อกเพื่อใช้ข้อมูลบัตรเครดิตที่เก็บไว้ + ปลดล็อกเพื่อใช้ข้อมูลบัตรเครดิตที่เก็บไว้ + + ปลดล็อกเพื่อใช้วิธีการชำระเงินที่บันทึกไว้ เพิ่มที่อยู่ @@ -1882,11 +1922,13 @@ จัดการที่อยู่ - ชื่อจริง + ชื่อจริง - ชื่อกลาง + ชื่อกลาง - นามสกุล + นามสกุล + + ชื่อ ที่อยู่ถนน @@ -1911,7 +1953,9 @@ ลบที่อยู่ - คุณแน่ใจหรือไม่ว่าต้องการลบที่อยู่นี้? + คุณแน่ใจหรือไม่ว่าต้องการลบที่อยู่นี้? + + ลบที่อยู่นี้หรือไม่? ลบ @@ -2009,37 +2053,49 @@ แก้ไข - คุณแน่ใจหรือไม่ที่ต้องการจะลบการเข้าสู่ระบบนี้? + คุณแน่ใจหรือไม่ที่ต้องการจะลบการเข้าสู่ระบบนี้? + + คุณแน่ใจหรือไม่ว่าต้องการลบรหัสผ่านนี้? ลบ ยกเลิก - ตัวเลือกการเข้าสู่ระบบ + ตัวเลือกการเข้าสู่ระบบ + + ตัวเลือกรหัสผ่าน - ช่องข้อความที่แก้ไขได้สำหรับที่อยู่เว็บของการเข้าสู่ระบบ + ช่องข้อความที่แก้ไขได้สำหรับที่อยู่เว็บของการเข้าสู่ระบบ + + ช่องข้อความที่แก้ไขได้สำหรับที่อยู่เว็บไซต์ - ช่องข้อความที่แก้ไขได้สำหรับชื่อผู้ใช้ของการเข้าสู่ระบบ + ช่องข้อความที่แก้ไขได้สำหรับชื่อผู้ใช้ของการเข้าสู่ระบบ + + ช่องข้อความที่แก้ไขได้สำหรับชื่อผู้ใช้ + + ช่องข้อความที่แก้ไขได้สำหรับรหัสผ่านของการเข้าสู่ระบบ - ช่องข้อความที่แก้ไขได้สำหรับรหัสผ่านของการเข้าสู่ระบบ + ช่องข้อความที่แก้ไขได้สำหรับรหัสผ่าน - บันทึกการเปลี่ยนแปลงเพื่อเข้าสู่ระบบ + บันทึกการเปลี่ยนแปลงเพื่อเข้าสู่ระบบ - บันทึกการเปลี่ยนแปลง + บันทึกการเปลี่ยนแปลง - แก้ไข + แก้ไข - แก้ไขรหัสผ่าน + แก้ไขรหัสผ่าน - เพิ่มการเข้าสู่ระบบใหม่ + เพิ่มการเข้าสู่ระบบใหม่ - เพิ่มรหัสผ่าน + เพิ่มรหัสผ่าน - ต้องการรหัสผ่าน + ต้องการรหัสผ่าน - ใส่รหัสผ่าน + ใส่รหัสผ่าน + + ต้องการชื่อผู้ใช้ - ต้องการชื่อผู้ใช้ + ป้อนชื่อผู้ใช้ ต้องการชื่อโฮสต์ @@ -2140,6 +2196,9 @@ ค้นหาด้วย %s + + เปลี่ยนเบราว์เซอร์เริ่มต้นของคุณ + ตั้งลิงก์จากเว็บไซต์ อีเมล และข้อความให้เปิดโดยอัตโนมัติใน Firefox @@ -2149,7 +2208,7 @@ คลิกเพื่อดูรายละเอียดเพิ่มเติม - นำทางขึ้นไปด้านบน + นำทางขึ้นไปด้านบน ปิด @@ -2190,8 +2249,6 @@ คะแนนที่ปรับแล้ว - เอาบทวิจารณ์ที่ไม่น่าเชื่อถือออกแล้ว - อ้างอิงจากบทวิจารณ์ที่เชื่อถือได้ ไฮไลต์จากบทวิจารณ์ล่าสุด @@ -2247,10 +2304,6 @@ หากคุณเห็นว่าสินค้านี้มีอยู่ในสต็อกแล้ว โปรดรายงานแล้วเราจะทำการตรวจสอบบทวิจารณ์ รายงานสินค้ามีในสต็อก - - กำลังตรวจสอบคุณภาพบทวิจารณ์ - - กำลังตรวจสอบคุณภาพบทวิจารณ์ กำลังตรวจสอบคุณภาพบทวิจารณ์ (%s) @@ -2296,13 +2349,19 @@ เรียนรู้เพิ่มเติม - การเลือก “ใช่ ลองใช้เลย” ถือว่าคุณยอมรับ%2$sและ%3$sของ %1$s โดย Mozilla + การเลือก “ใช่ ลองใช้เลย” ถือว่าคุณยอมรับ%2$sและ%3$sของ %1$s โดย Mozilla การเลือก “ใช่ ลองใช้เลย” ถือว่าคุณยอมรับข้อตกลงต่อไปนี้จาก %1$s: + + การเลือก “ใช่ ลองใช้เลย” ถือว่าคุณยอมรับ%2$sของ %1$s และ%4$sของ %3$s + + การเลือก “ใช่ ลองใช้เลย” ถือว่าคุณยอมรับ%2$sของ %1$s และ%4$sของ %3$s - นโยบายความเป็นส่วนตัว + นโยบายความเป็นส่วนตัว นโยบายความเป็นส่วนตัว + + ประกาศความเป็นส่วนตัว เงื่อนไขการใช้งาน @@ -2373,6 +2432,10 @@ แปลหน้านี้? + + แปลหน้าจาก%1$sเป็น%2$sแล้ว ลองใช้การแปลแบบส่วนตัวใน %1$s @@ -2385,6 +2448,8 @@ แปลเป็น ไม่ใช่ตอนนี้ + + แสดงต้นฉบับ เสร็จสิ้น @@ -2395,6 +2460,8 @@ กำลังแปล อยู่ระหว่างการแปล + + เลือกภาษา เกิดปัญหาในการแปล โปรดลองอีกครั้ง @@ -2405,6 +2472,16 @@ เรียนรู้เพิ่มเติม + + กำลังแปล… + + + ดาวน์โหลดภาษาในโหมดประหยัดข้อมูล (%1$s) หรือไม่? + + ตัวเลือกการแปล @@ -2416,6 +2493,10 @@ ไม่ต้องแปล %1$s เลย ไม่ต้องแปลไซต์นี้เลย + + แทนที่การตั้งค่าอื่นๆ ทั้งหมด + + แทนที่การเสนอให้แปล การตั้งค่าการแปล diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 1784c728d..bcf93bf63 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -255,6 +255,11 @@ Sayfayı çevir + + Sayfa %1$s dilinden %2$s diline çevrildi. + Seçili dil @@ -333,12 +338,22 @@ Firefox gizlilik bildirimi - + + Ayrıntıları gizlilik bildirimimizde bulabilirsiniz Sizi güvende tutmayı seviyoruz + + Milyonların Firefox’u neden sevdiğini öğrenin + + Daha fazla seçenekle güvenli gezinti Kâr amacı gütmeyen tarayıcımız, şirketlerin sizi web’de gizlice takip etmesini engelliyor. + 100 milyondan fazla insan, kâr amacı gütmeyen bir kuruluş tarafından desteklenen bu tarayıcıyla gizliliğini koruyor. + + Takip kodları mı dediniz? Otomatik olarak engelliyoruz. Uzantı desteği mi? 700 uzantıyı deneyebilirsiniz. Ya PDF desteği? Yerleşik okuyucumuzla PDF’leri yönetmek çok daha kolay. + Kâr amacı gütmeyen tarayıcımız, şirketlerin sizi web’de gizlice takip etmesini engelliyor.\n\nAyrıntıları gizlilik bildirimimizde bulabilirsiniz. @@ -694,9 +709,9 @@ Yer imleri - Hesaplar + Hesaplar - Parolalar + Parolalar Açık sekmeler @@ -714,7 +729,7 @@ Son eşitleme: %s - Son eşitleme: hiç + Son eşitleme: yok - Kredi kartları + Kredi kartları - Ödeme yöntemleri + Ödeme yöntemleri Adresler @@ -1503,7 +1518,7 @@ %s artık hesabınızla eşitlenmeyecek ama bu cihazdaki gezinti geçmişiniz silinmeyecek. - Bağlatıyı kes + Bağlantıyı kes İptal @@ -1668,13 +1683,13 @@ Bu siteyi cihazınızın ana ekranına ekleyerek ona hızlıca erişebilir, site bir uygulamaymış gibi daha hızlı gezinti yapabilirsiniz. - Hesaplar ve parolalar + Hesaplar ve parolalar - Parolalar + Parolalar - Kullanıcı adı ve parolaları kaydet + Kullanıcı adı ve parolaları kaydet - Parolaları kaydet + Parolaları kaydet Kaydetmeyi sor @@ -1689,47 +1704,47 @@ Cihazınızdaki diğer uygulamalarda kullanıcı adı ve parolalar doldurulsun. - Hesap ekle + Hesap ekle - Parola ekle + Parola ekle - - Hesapları eşitle - Parolaları eşitle + Hesapları eşitle + + Parolaları eşitle - Hesapları cihazlar arasında eşitle + Hesapları cihazlar arasında eşitle - Parolaları cihazlar arasında eşitle + Parolaları cihazlar arasında eşitle - Kayıtlı hesaplar + Kayıtlı hesaplar - Kayıtlı parolalar + Kayıtlı parolalar - Kaydettiğiniz veya %s ile eşitlediğiniz hesaplar burada görünecektir. + Kaydettiğiniz veya %s ile eşitlediğiniz hesaplar burada görünecektir. - %s tarayıcısına kaydettiğiniz veya eşitlediğiniz parolalar burada listelenecektir. Kaydettiğiniz tüm parolalar şifrelenir. + %s tarayıcısına kaydettiğiniz veya eşitlediğiniz parolalar burada listelenecektir. Kaydettiğiniz tüm parolalar şifrelenir. - Sync hakkında bilgi alın. + Sync hakkında bilgi alın. - Eşitlemeyle ilgili bilgi al + Eşitlemeyle ilgili bilgi al İstisnalar - Kaydedilmeyen hesaplar ve parolalar burada görünecektir. + Kaydedilmeyen hesaplar ve parolalar burada görünecektir. - %s, burada listelenen sitelerin parolalarını kaydetmeyecektir. + %s, burada listelenen sitelerin parolalarını kaydetmeyecektir. - Bu sitelere ait hesaplar ve parolalar kaydedilmeyecektir. + Bu sitelere ait hesaplar ve parolalar kaydedilmeyecektir. - %s bu sitelerin parolalarını kaydetmeyecektir. + %s bu sitelerin parolalarını kaydetmeyecektir. Tüm istisnaları sil - Hesaplarda ara + Hesaplarda ara - Parolalarda ara + Parolalarda ara Site @@ -1757,17 +1772,17 @@ Parolayı gizle - Kayıtlı hesaplarınızı görmek için kilidi açın + Kayıtlı hesaplarınızı görmek için kilidi açın - Kayıtlı parolalarınızı görmek için kilidi açın + Kayıtlı parolalarınızı görmek için kilidi açın - Hesaplarınızı güvence altına alın + Hesaplarınızı güvence altına alın - Kayıtlı parolalarınızı güvence altına alın + Kayıtlı parolalarınızı güvence altına alın - Cihazınız başka birinin eline geçerse kayıtlı hesaplarına erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. + Cihazınız başka birinin eline geçerse kayıtlı hesaplarına erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. - Cihazınız başka birinin eline geçerse kayıtlı parolalarınıza erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. + Cihazınız başka birinin eline geçerse kayıtlı parolalarınıza erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. Daha sonra @@ -1785,7 +1800,10 @@ Son kullanım - Hesapları sırala menüsü + Hesapları sırala menüsü + + + Parolaları sırala menüsü Parolaları sırala menüsü @@ -1796,40 +1814,43 @@ Adresler - Kredi kartları + Kredi kartları - Ödeme yöntemleri + Ödeme yöntemleri - Kartları kaydedip otomatik doldur + Kartları kaydedip otomatik doldur - Ödeme yöntemlerini kaydet ve doldur + Ödeme yöntemlerini kaydet ve doldur - Veriler şifrelenir + Veriler şifrelenir - %s kaydettiğiniz tüm ödeme yöntemlerini şifreler + %s kaydettiğiniz tüm ödeme yöntemlerini şifreler Kartları cihazlar arasında eşitle Kartları eşitle - Kredi kartı ekle + Kredi kartı ekle - Kart ekle + Kart ekle - Kayıtlı kartları yönet + Kayıtlı kartları yönet - Kartları yönet + Kartları yönet Adres ekle Adresleri yönet - Adresleri kaydedip otomatik doldur + Adresleri kaydedip otomatik doldur - Adresleri kaydet ve doldur + Adresleri kaydet ve doldur - Numaralar, e-posta ve gönderim adresleri gibi bilgileri dahil et + Numaralar, e-posta ve gönderim adresleri gibi bilgileri dahil et + + + Telefon numaraları ve e-posta adresleri de dahildir Telefon numaraları ve e-posta adresleri de dahildir @@ -1853,9 +1874,9 @@ Kartı sil - Bu kredi kartını silmek istediğinizden emin misiniz? + Bu kredi kartını silmek istediğinizden emin misiniz? - Kart silinsin mi? + Kart silinsin mi? Sil @@ -1869,24 +1890,24 @@ Kayıtlı kartlar - Lütfen geçerli bir kredi kartı numarası girin + Lütfen geçerli bir kredi kartı numarası girin - Geçerli bir kart numarası girin + Geçerli bir kart numarası girin - Lütfen bu alanı doldurun + Lütfen bu alanı doldurun - Adınızı yazın + Adınızı yazın Kayıtlı kartlarınızı görmek için kilidi açın - Kredi kartlarını güvence altına al + Kredi kartlarını güvence altına al - Kayıtlı ödeme yöntemlerinizi güvence altına alın + Kayıtlı ödeme yöntemlerinizi güvence altına alın - Cihazınız başka birinin eline geçerse kayıtlı kartlarınıza erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. + Cihazınız başka birinin eline geçerse kayıtlı kartlarınıza erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. - Cihazınız başka birinin eline geçerse kayıtlı ödeme yöntemlerinize erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. + Cihazınız başka birinin eline geçerse kayıtlı ödeme yöntemlerinize erişilmesini önlemek için cihaz kilidi deseni, PIN veya parola ayarlayın. Hemen ayarla @@ -1895,10 +1916,10 @@ Cihazınızın kilidini açın - Depolanan kredi kartı bilgilerini kullanmak için kilidi açın + Depolanan kredi kartı bilgilerini kullanmak için kilidi açın - Kayıtlı ödeme yöntemlerinizi kullanmak için kilidi açın + Kayıtlı ödeme yöntemlerinizi kullanmak için kilidi açın Adres ekle @@ -1906,11 +1927,13 @@ Adresleri yönet - Ad + Ad - İkinci ad + İkinci ad - Soyadı + Soyadı + + Ad Sokak adresi @@ -1935,9 +1958,9 @@ Adresi sil - Bu adresi silmek istediğinizden emin misiniz? + Bu adresi silmek istediğinizden emin misiniz? - Bu adres silinsin mi? + Bu adres silinsin mi? Sil @@ -2035,49 +2058,49 @@ Düzenle - Bu hesabı silmek istediğinizden emin misiniz? + Bu hesabı silmek istediğinizden emin misiniz? - Bu parolayı silmek istediğinizden emin misiniz? + Bu parolayı silmek istediğinizden emin misiniz? Sil Vazgeç - Hesap seçenekleri + Hesap seçenekleri - Parola seçenekleri + Parola seçenekleri - Hesabın web adresi için düzenlenebilir metin alanı. + Hesabın web adresi için düzenlenebilir metin alanı. - Web sitesi adresi için düzenlenebilir metin alanı. + Web sitesi adresi için düzenlenebilir metin alanı. - Hesabın kullanıcı adı için düzenlenebilir metin alanı. + Hesabın kullanıcı adı için düzenlenebilir metin alanı. - Kullanıcı adı için düzenlenebilir metin alanı. + Kullanıcı adı için düzenlenebilir metin alanı. - Hesabın parolası için düzenlenebilir metin alanı. + Hesabın parolası için düzenlenebilir metin alanı. - Parola için düzenlenebilir metin alanı. + Parola için düzenlenebilir metin alanı. - Değişiklikleri hesaba kaydet. + Değişiklikleri hesaba kaydet. - Değişiklikleri kaydet. + Değişiklikleri kaydet. - Düzenle + Düzenle - Parola düzenle + Parola düzenle - Yeni hesap ekle + Yeni hesap ekle - Parola ekle + Parola ekle - Parola gerekli + Parola gerekli - Parolayı girin + Parolayı girin - Kullanıcı adı gereklidir + Kullanıcı adı gereklidir - Kullanıcı adını girin + Kullanıcı adını girin Sunucu gereklidir @@ -2189,7 +2212,7 @@ Ayrıntılar için tıklayın - Yukarı + Yukarı Kapat @@ -2230,8 +2253,6 @@ Düzeltilmiş puan - Güvenilmez değerlendirmeler kaldırıldı - Güvenilir değerlendirmelere dayanarak Öne çıkan son değerlendirmeler @@ -2258,7 +2279,7 @@ Ayarlar - Değerlendirme denetleyicisinde reklamları göster + Değerlendirme kontrolcüsünde reklamları göster Ara sıra ilgili ürünlerin reklamlarını görebilirsiniz. Yalnızca güvenilir değerlendirmeleri olan ürünlerin reklamlarını kabul ediyoruz. %s @@ -2284,13 +2305,9 @@ Ürün mevcut değil - Bu ürünün yeniden stoğa girdiğini görürseniz bize bildirin, biz de değerlendirmeleri kontrol etmeye çalışalım. + Bu ürünün yeniden stoka girdiğini görürseniz bize bildirin, biz de değerlendirmeleri kontrol etmeye çalışalım. Ürünün stokta olduğunu bildir - - Değerlendirme kalitesi kontrol ediliyor - - Değerlendirme kalitesi kontrol ediliyor Değerlendirme kalitesi kontrol ediliyor (%s) @@ -2336,13 +2353,19 @@ Daha fazla bilgi alın - “Evet, deneyeceğim”i seçtiğinizde Mozilla %1$s %2$s ve %3$snı kabul etmiş olursunuz. + “Evet, deneyeceğim”i seçtiğinizde Mozilla %1$s %2$s ve %3$snı kabul etmiş olursunuz. “Evet, deneyeceğim”i seçtiğinizde %1$s için şunları kabul etmiş olursunuz: + + “Evet, deneyeceğim”i seçtiğinizde %1$s %2$s ve %3$s %4$snı kabul etmiş olursunuz. + + “Evet, deneyeceğim”i seçtiğinizde %1$s %2$s ve %3$s %4$snı kabul etmiş olursunuz. - gizlilik politikası + gizlilik politikası Gizlilik politikası + + gizlilik bildirimi kullanım koşulları @@ -2416,6 +2439,10 @@ Bu sayfa çevrilsin mi? + + Sayfa %1$s dilinden %2$s diline çevrildi %1$s ile gizli çevirileri deneyin @@ -2428,6 +2455,8 @@ Bu dile Şimdi değil + + Orijinalini göster Tamam @@ -2450,6 +2479,17 @@ Daha fazla bilgi al + + Çevriliyor… + + + + Dil, veri tasarrufu modunda indirilsin mi? (%1$s) + + Çeviri Seçenekleri diff --git a/app/src/main/res/values-ug/strings.xml b/app/src/main/res/values-ug/strings.xml index d0b0e1fdf..0071ba6ba 100644 --- a/app/src/main/res/values-ug/strings.xml +++ b/app/src/main/res/values-ug/strings.xml @@ -251,6 +251,11 @@ بەت تەرجىمىسى + + بەت %1$s دىن %2$s غا تەرجىمە قىلىندى. + تاللانغان تىل @@ -325,12 +330,22 @@ Firefox شەخسىيەت ئۇقتۇرۇشى - + + شەخسىيەت ئۇقتۇرۇشىنىڭ تەپسىلاتىنى ئوقۇڭ بىخەتەرلىكىڭىزنى ساقلاشنى ياخشى كۆرىمىز + + مىليونلىغان كىشىنىڭ نېمىشقا Firefox نى ياقتۇرىدىغانلىقىنى تېپىڭ + + بىخەتەر تور زىيارىتىنىڭ تېخىمۇ كۆپ تاللىشى پايدا تاپمايدىغان توركۆرگۈمىز شىركەتلەرنىڭ سىزگە تور بېكەتلەردە مەخپىي ھالدا ئەگىشىشىنى توسىدۇ. + 100 مىليوندىن ئارتۇق كىشى پايدا تاپمايدىغان ئورگان قوللىغان توركۆرگۈنى تاللاپ ئىشلىتىپ ئۆزلىرىنىڭ شەخسىيىتىنى قوغداۋاتىدۇ. + + بىلىنگەن ئىزلىغۇچ؟ ئۆزلۈكىدىن توسۇلىدۇ. كېڭەيتمە؟ 700 دىن ئارتۇقنى سىناڭ. PDF نى ئاچامدۇ؟ توركۆرگۈ ئىچىدىكى ئوقۇغۇچ ئۇلارنى باشقۇرۇشنى قۇلايلاشتۇرىدۇ. + پايدا تاپمايدىغان ئورگان قوللايدىغان توركۆرگۈمىز شىركەتلەرنىڭ سىزنى مەخپىي ھالدا توردىن ئىزلىشىنى توختىتىشىغا ياردەم بېرىدۇ.\n\nشەخسىيەت ئۇقتۇرۇشى ھەققىدىكى تەپسىلات بىلدۈرگۈسى. @@ -685,9 +700,9 @@ خەتكۈچ - كىرىش + كىرىش - ئىم + ئىم بەتكۈچ ئاچ @@ -711,9 +726,9 @@ and the third is the device model. --> %2$s %3$s دىكى %1$s - ئىناۋەتلىك كارتا + ئىناۋەتلىك كارتا - چىقىم قىلىش ئۇسۇلى + چىقىم قىلىش ئۇسۇلى ئادرېس @@ -1653,13 +1668,13 @@ تېز سۈرئەتتە زىيارەت قىلىش ۋە ئەپكە ئوخشاش زىيارەت تۇيغۇسىغا ئېرىشىش ئۈچۈن، مەزكۇر تور بېكەتنى باش ئېكرانغا ئاسانلا قوشالايسىز. - كىرىش ۋە ئىم + كىرىش ۋە ئىم - ئىم + ئىم - كىرىش ۋە ئىم ساقلا + كىرىش ۋە ئىم ساقلا - ئىم ساقلا + ئىم ساقلا ساقلاشنى سورا @@ -1673,47 +1688,47 @@ ئۈسكۈنىڭىزدىكى باشقا ئەپلەردە ئىشلەتكۈچى ئىسمى ۋە ئىمنى تولدۇرىدۇ. - كىرىشنى قوش + كىرىشنى قوش - ئىم قوش + ئىم قوش - - كىرىشنى قەدەمداشلا - ئىم قەدەمداشلا + كىرىشنى قەدەمداشلا + + ئىم قەدەمداشلا - ئۈسكۈنىلەر ئارا قەدەمداشلا + ئۈسكۈنىلەر ئارا قەدەمداشلا - ئىمنى ئۈسكۈنىلەر ئارا قەدەمداشلايدۇ + ئىمنى ئۈسكۈنىلەر ئارا قەدەمداشلايدۇ - ساقلانغان كىرىش + ساقلانغان كىرىش - ساقلانغان ئىم + ساقلانغان ئىم - سىز ساقلىغان كىرىش ياكى %s بىلەن بولغان قەدەمداش بۇ جايدا كۆرۈنىدۇ. + سىز ساقلىغان كىرىش ياكى %s بىلەن بولغان قەدەمداش بۇ جايدا كۆرۈنىدۇ. - سىز ساقلىغان ياكى %s غا قەدەمداشلىغان ئىم بۇ يەردە كۆرسىتىلىدۇ. سىز ساقلىغان بارلىق ئىم مەخپىيلەشتۈرۈلگەن. + سىز ساقلىغان ياكى %s غا قەدەمداشلىغان ئىم بۇ يەردە كۆرسىتىلىدۇ. سىز ساقلىغان بارلىق ئىم مەخپىيلەشتۈرۈلگەن. - قەدەمداش ھەققىدىكى تەپسىلاتلار. + قەدەمداش ھەققىدىكى تەپسىلاتلار. - قەدەمداش ھەققىدىكى تەپسىلاتلار + قەدەمداش ھەققىدىكى تەپسىلاتلار مۇستەسنا - ساقلانمىغان كىرىش ۋە ئىم بۇ يەردە كۆرسىتىلىدۇ. + ساقلانمىغان كىرىش ۋە ئىم بۇ يەردە كۆرسىتىلىدۇ. - بۇ جايدا كۆرسىتىلگەن تور بېكەتلەر ئۈچۈن %s ئىم ساقلىمايدۇ. + بۇ جايدا كۆرسىتىلگەن تور بېكەتلەر ئۈچۈن %s ئىم ساقلىمايدۇ. - بۇ تور بېكەتلەرنىڭ كىرىش ۋە ئىم ئۇچۇرلىرى ساقلانمايدۇ. + بۇ تور بېكەتلەرنىڭ كىرىش ۋە ئىم ئۇچۇرلىرى ساقلانمايدۇ. - بۇ تور بېكەتلەر ئۈچۈن %s ئىم ساقلىمايدۇ. + بۇ تور بېكەتلەر ئۈچۈن %s ئىم ساقلىمايدۇ. ھەممە مۇستەسنالارنى ئۆچۈرىدۇ - كىرىش خاتىرىسىنى ئىزدە + كىرىش خاتىرىسىنى ئىزدە - پارول ئىزدەش + پارول ئىزدەش بېكەت @@ -1742,17 +1757,17 @@ ئىم يوشۇر - ساقلانغان كىرىشلىرىڭىزنى كۆرۈش ئۈچۈن قۇلۇپ ئېچىڭ + ساقلانغان كىرىشلىرىڭىزنى كۆرۈش ئۈچۈن قۇلۇپ ئېچىڭ - ساقلانغان پارولىڭىزنى كۆرۈش ئۈچۈن قۇلۇپ ئېچىڭ + ساقلانغان پارولىڭىزنى كۆرۈش ئۈچۈن قۇلۇپ ئېچىڭ - كىرىش ۋە ئىمنى قوغدايدۇ + كىرىش ۋە ئىمنى قوغدايدۇ - ساقلانغان ئىملىرىڭىز شىفىرلىنىدۇ + ساقلانغان ئىملىرىڭىز شىفىرلىنىدۇ - ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان تىزىمغا كىرىش ئۇچۇرى ۋە ئىمنى زىيارەت قىلالمايدۇ. + ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان تىزىمغا كىرىش ئۇچۇرى ۋە ئىمنى زىيارەت قىلالمايدۇ. - ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان ئىملىرىڭىزنى زىيارەت قىلالمايدۇ. + ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان ئىملىرىڭىزنى زىيارەت قىلالمايدۇ. كېيىنچە @@ -1770,7 +1785,10 @@ ئاخىرقى قېتىم ئىشلىتىلگەن - كىرىش تىزىملىكىنى تەرتىپلەيدۇ + كىرىش تىزىملىكىنى تەرتىپلەيدۇ + + + ئىم تىزىملىكىنى تەرتىپلە ئىم تىزىملىكىنى تەرتىپلە @@ -1781,39 +1799,42 @@ ئادرېس - ئىناۋەتلىك كارتا + ئىناۋەتلىك كارتا - چىقىم قىلىش ئۇسۇلى + چىقىم قىلىش ئۇسۇلى - كارتا ساقلاش ۋە ئاپتوماتىك تولدۇرۇش + كارتا ساقلاش ۋە ئاپتوماتىك تولدۇرۇش - چىقىم قىلىش ئۇسۇلىنى ساقلاپ ۋە تولدۇرىدۇ + چىقىم قىلىش ئۇسۇلىنى ساقلاپ ۋە تولدۇرىدۇ - سانلىق مەلۇمات شىفىرلانغان + سانلىق مەلۇمات شىفىرلانغان - سىز ساقلىغان بارلىق چىقىم قىلىش ئۇسۇللىرىنى %s شىفىرلايدۇ + سىز ساقلىغان بارلىق چىقىم قىلىش ئۇسۇللىرىنى %s شىفىرلايدۇ كارتىنى ئۈسكۈنىلەر ئارا قەدەمداشلايدۇ كارتا قەدەمداشلا - ئىناۋەتلىك كارتا قوش + ئىناۋەتلىك كارتا قوش - كارتا قوش + كارتا قوش - ساقلانغان كارتا باشقۇرۇش + ساقلانغان كارتا باشقۇرۇش - كارتا باشقۇرۇش + كارتا باشقۇرۇش ئادرېس قوش ئادرېس باشقۇرۇش - ئادرېسلارنى ساقلاش ۋە ئاپتوماتىك تولدۇرۇش + ئادرېسلارنى ساقلاش ۋە ئاپتوماتىك تولدۇرۇش - ئادرېس ساقلاپ تولدۇرىدۇ + ئادرېس ساقلاپ تولدۇرىدۇ - سان، ئېلخەت ۋە توشۇش ئادرېسى قاتارلىق ئۇچۇرلارنى ئۆز ئىچىگە ئالىدۇ + سان، ئېلخەت ۋە توشۇش ئادرېسى قاتارلىق ئۇچۇرلارنى ئۆز ئىچىگە ئالىدۇ + + + تېلېفون نومۇرى ۋە ئېلخەت ئادرېسىنى ئۆز ئىچىگە ئالىدۇ تېلېفون نومۇرى ۋە ئېلخەت ئادرېسىنى ئۆز ئىچىگە ئالىدۇ @@ -1837,9 +1858,9 @@ كارتىنى ئۆچۈر - بۇ ئىناۋەتلىك كارتىنى راستىنلا ئۆچۈرەمسىز؟ + بۇ ئىناۋەتلىك كارتىنى راستىنلا ئۆچۈرەمسىز؟ - كارتىنى ئۆچۈرەمدۇ؟ + كارتىنى ئۆچۈرەمدۇ؟ ئۆچۈر @@ -1851,24 +1872,24 @@ ساقلانغان كارتا - ئىناۋەتلىك كارتا نومۇرىنى كىرگۈزۈڭ + ئىناۋەتلىك كارتا نومۇرىنى كىرگۈزۈڭ - ئىناۋەتلىك كارتا نومۇرى كىرگۈزۈلىدۇ + ئىناۋەتلىك كارتا نومۇرى كىرگۈزۈلىدۇ - بۇ بۆلەكنى تولدۇرۇڭ + بۇ بۆلەكنى تولدۇرۇڭ - ئات قوش + ئات قوش ساقلانغان كارتىلىرىڭىزنى كۆرۈش ئۈچۈن قۇلۇپ ئېچىڭ - ئىناۋەتلىك كارتىڭىزنى شىفىرلايدۇ + ئىناۋەتلىك كارتىڭىزنى شىفىرلايدۇ - ساقلانغان چىقىم قىلىش ئۇسۇللىرىڭىز شىفىرلىنىدۇ + ساقلانغان چىقىم قىلىش ئۇسۇللىرىڭىز شىفىرلىنىدۇ - ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان ئىناۋەتلىك كارتىڭىزنى زىيارەت قىلالمايدۇ. + ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان ئىناۋەتلىك كارتىڭىزنى زىيارەت قىلالمايدۇ. - ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان چىقىم قىلىش ئۇسۇلىڭىزنى زىيارەت قىلالمايدۇ. + ئۈسكۈنە قۇلۇپلاش ئەندىزىسى، PIN ياكى ئىم ئورنىتىشنى تەڭشىسىڭىز، ئۈسكۈنىڭىز باشقىلارنىڭ قولىدا بولسىمۇ ساقلانغان چىقىم قىلىش ئۇسۇلىڭىزنى زىيارەت قىلالمايدۇ. ھازىر تەڭشە @@ -1876,9 +1897,9 @@ ئۈسكۈنىڭىزنىڭ قۇلۇپىنى ئېچىڭ - ساقلانغان ئىناۋەتلىك كارتا ئۇچۇرلىرىنى ئىشلىتىش ئۈچۈن قۇلۇپ ئېچىڭ + ساقلانغان ئىناۋەتلىك كارتا ئۇچۇرلىرىنى ئىشلىتىش ئۈچۈن قۇلۇپ ئېچىڭ - ساقلانغان چىقىم قىلىش ئۇسۇلىنى ئىشلىتىش ئۈچۈن قۇلۇپ ئېچىڭ + ساقلانغان چىقىم قىلىش ئۇسۇلىنى ئىشلىتىش ئۈچۈن قۇلۇپ ئېچىڭ ئادرېس قوش @@ -1886,11 +1907,13 @@ ئادرېس باشقۇرۇش - ئىسمى + ئىسمى - ئوتتۇرا ئىسمى + ئوتتۇرا ئىسمى - تەگئات + تەگئات + + ئىسمى كوچا ئادرېسى @@ -1914,9 +1937,9 @@ ئادرېس ئۆچۈر - بۇ ئادرېسنى راستىنلا ئۆچۈرەمسىز؟ + بۇ ئادرېسنى راستىنلا ئۆچۈرەمسىز؟ - بۇ ئادرېسنى ئۆچۈرەمدۇ؟ + بۇ ئادرېسنى ئۆچۈرەمدۇ؟ ئۆچۈر @@ -2014,50 +2037,50 @@ تەھرىر - بۇ كىرىشنى راستىنلا ئۆچۈرەمسىز؟ + بۇ كىرىشنى راستىنلا ئۆچۈرەمسىز؟ - بۇ ئىمنى راستىنلا ئۆچۈرەمسىز؟ + بۇ ئىمنى راستىنلا ئۆچۈرەمسىز؟ ئۆچۈر ۋاز كەچ - كىرىش تاللانمىلىرى + كىرىش تاللانمىلىرى - ئىم تاللانمىسى + ئىم تاللانمىسى - كىرىشنىڭ تور ئادرېسىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + كىرىشنىڭ تور ئادرېسىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - تور بېكەت ئادرېسىنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + تور بېكەت ئادرېسىنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - كىرىشنىڭ ئىشلەتكۈچى ئىسمىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + كىرىشنىڭ ئىشلەتكۈچى ئىسمىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - ئىشلەتكۈچى ئاتىنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + ئىشلەتكۈچى ئاتىنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - كىرىشنىڭ ئىمىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + كىرىشنىڭ ئىمىنى تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - ئىمنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. + ئىمنىڭ تەھرىرلىگىلى بولىدىغان تېكىست بۆلىكى. - كىرىش ئۆزگەرتىشلىرىنى ساقلايدۇ. + كىرىش ئۆزگەرتىشلىرىنى ساقلايدۇ. - ئۆزگەرتىشلەرنى ساقلايدۇ. + ئۆزگەرتىشلەرنى ساقلايدۇ. - تەھرىر + تەھرىر - ئىم تەھرىر + ئىم تەھرىر - يېڭى كىرىش قوش + يېڭى كىرىش قوش - ئىم قوش + ئىم قوش - ئىم زۆرۈر + ئىم زۆرۈر - ئىم كىرگۈزۈلىدۇ + ئىم كىرگۈزۈلىدۇ - ئىشلەتكۈچى ئىسمى زۆرۈر + ئىشلەتكۈچى ئىسمى زۆرۈر - ئىشلەتكۈچى ئاتى كىرگۈزۈلىدۇ + ئىشلەتكۈچى ئاتى كىرگۈزۈلىدۇ مۇلازىم ئىسمى زۆرۈر @@ -2162,7 +2185,7 @@ تەپسىلات ئۈچۈن چېكىڭ - ئۈستىگە يول باشلا + ئۈستىگە يول باشلا تاقاش @@ -2204,8 +2227,6 @@ تەڭشەلگەن باھا - ئىشەنچسىز باھا چىقىرىۋېتىلدى - ئىشەنچلىك باھالار ئاساس قىلىندى يېقىنقى باھالاردىن يارقىن نۇقتىلار @@ -2265,10 +2286,6 @@ ئەگەر بۇ مەھسۇلاتتىن مال بارلىقىنى بايقىسىڭىز، دوكلات قىلسىڭىز، بىز باھالاشنى تەكشۈرەلەيمىز. مەھسۇلاتنىڭ تىزىلغانلىقىنى دوكلات قىلىڭ - - باھالاش سۈپىتىنى تەكشۈرۈۋاتىدۇ - - باھالاش سۈپىتىنى تەكشۈرۈۋاتىدۇ باھالاش سۈپىتىنى تەكشۈرۈۋاتىدۇ(%s) @@ -2317,13 +2334,19 @@ تەپسىلاتى - «ھەئە، سىناپ باقاي» تاللانسا سىز Mozilla نىڭ %2$s ۋە %3$s دىكى %1$s غا قوشۇلغان بولىسىز. + «ھەئە، سىناپ باقاي» تاللانسا سىز Mozilla نىڭ %2$s ۋە %3$s دىكى %1$s غا قوشۇلغان بولىسىز. «ھەئە، سىناپ باقاي» تاللانسا تۆۋەندىكى %1$s غا قوشۇلغان بولىسىز: + + «ھەئە، سىناپ باقاي» تاللانسا %1$s نىڭ %2$s ۋە %3$s نىڭ %4$s غا قوشۇلغان بولىسىز. + + «ھەئە، سىناپ باقاي» تاللانسا %1$s نىڭ %2$s ۋە %3$s نىڭ %4$s غا قوشۇلغان بولىسىز. - شەخسىيەت تۈزۈمى + شەخسىيەت تۈزۈمى شەخسىيەت تۈزۈمى + + شەخسىيەت ئۇقتۇرۇشى ئىشلىتىش شەرتلىرى @@ -2396,6 +2419,10 @@ بۇ بەتنى تەرجىمە قىلامدۇ؟ + + بەت %1$s دىن %2$s غا تەرجىمە قىلىندى %1$s دىكى شەخسىي تەرجىمىلەرنى سىناپ بېقىڭ @@ -2408,6 +2435,8 @@ نىشان تىل ھازىر ئەمەس + + ئەسلىنى كۆرسەت تامام @@ -2431,6 +2460,9 @@ تەپسىلاتى + + تەرجىمە قىلىۋاتىدۇ… + تەرجىمە تاللانمىلىرى diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index b9f1506f0..b0e5c88db 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -255,6 +255,11 @@ Перекласти сторінку + + Сторінку перекладено з %1$s на %2$s. + Обрана мова @@ -267,7 +272,7 @@ Сканувати - Налаштування пошукових засобів + Налаштування пошукових систем Заповнити посилання з буфера обміну @@ -278,7 +283,7 @@ Дозволяти пошукові пропозиції у приватних сеансах? - %s відправлятиме все, що ви вводите в адресному рядку, вашому типовому провайдеру пошуку. + %s відправлятиме все, що ви вводите в адресному рядку, вашій типовій пошуковій системі. Пошук в %s @@ -292,7 +297,7 @@ Шукати в: - Засіб пошуку %s + Пошукова система %s @@ -333,16 +338,26 @@ Положення про приватність Firefox - + + Докладніше в нашому положенні про приватність Ми дбаємо про вашу безпеку + + Дізнайтеся, чому мільйони користувачів люблять Firefox + + Безпечний перегляд із більшим вибором Наш некомерційний браузер допомагає блокувати таємне стеження компаній за вами в інтернеті. + Понад 100 мільйонів людей захищають свою приватність, обравши браузер від некомерційної організація. + + Автоблокування відомих елементів стеження. 700 розширень для будь-яких завдань. Вбудований засіб читання файлів PDF і керування ними. + Наш некомерційний браузер не дозволяє компаніям таємно стежити за вами в інтернеті.\n\nДокладніше в нашому Положенні про приватність. - політиці приватності + положенні про приватність Встановити типовим браузером @@ -401,19 +416,19 @@ Оберіть - Керуйте альтернативними засобами пошуку + Альтернативні пошукові системи - Редагувати засоби пошуку, доступні в меню + Редагувати системи, доступні в меню пошуку - Засоби пошуку, доступні в меню + Системи, доступні в меню пошуку - Типовий засіб пошуку + Типова пошукова система Пошук - Засоби пошуку + Пошукові системи - Пропозиції засобів пошуку + Пропозиції від пошукових систем Налаштування панелі адреси @@ -603,7 +618,7 @@ Власна збірка додатків - Гаразд + OK Скасувати @@ -697,9 +712,9 @@ Закладки - Паролі + Паролі - Паролі + Паролі Вкладки @@ -725,9 +740,9 @@ %1$s на %2$s %3$s - Кредитні картки + Кредитні картки - Способи оплати + Способи оплати Адреси @@ -926,7 +941,7 @@ Програма припинить застосовувати зміни - Гаразд + OK Скасувати @@ -1135,13 +1150,13 @@ Очистити дозволи - Гаразд + OK Скасувати Очистити дозвіл - Гаразд + OK Скасувати @@ -1249,7 +1264,7 @@ Переглянути - Гаразд + OK Скасувати @@ -1385,7 +1400,7 @@ Вебадреса недійсна. - Гаразд + OK Ви дійсно хочете видалити %1$s? @@ -1670,13 +1685,13 @@ Ви можете легко додати цей вебсайт на головний екран вашого пристрою, щоб мати миттєвий доступ до нього і працювати швидше. - Паролі + Паролі - Паролі + Паролі - Зберігати паролі + Зберігати паролі - Зберігати паролі + Зберігати паролі Питати про збереження @@ -1691,49 +1706,49 @@ Заповнювати імена користувачів і паролі в інших програмах на цьому пристрої. - Додати пароль + Додати пароль - Додати пароль + Додати пароль - - Синхронізація паролів - Синхронізувати паролі + Синхронізація паролів + + Синхронізувати паролі - Синхронізувати паролі між пристроями + Синхронізувати паролі між пристроями - Синхронізація паролів між пристроями + Синхронізація паролів між пристроями - Збережені паролі + Збережені паролі - Збережені паролі + Збережені паролі - Тут з’являтимуться ваші збережені та синхронізовані з %s паролі. + Тут з’являтимуться ваші збережені та синхронізовані з %s паролі. - Тут з\'являтимуться паролі, які ви зберігаєте чи синхронізуєте в %s. Усі паролі зашифровано. + Тут з\'являтимуться паролі, які ви зберігаєте чи синхронізуєте в %s. Усі паролі зашифровано. - Докладніше про синхронізацію. + Докладніше про синхронізацію. - Докладніше про синхронізацію + Докладніше про синхронізацію Винятки - Не збережені паролі з’являтимуться тут. + Не збережені паролі з’являтимуться тут. - %s не зберігатиме паролі для вказаних тут сайтів. + %s не зберігатиме паролі для вказаних тут сайтів. - Паролі для цих сайтів не зберігатимуться. + Паролі для цих сайтів не зберігатимуться. - %s не зберігатиме паролі для цих сайтів. + %s не зберігатиме паролі для цих сайтів. Видалити всі винятки - Шукати паролі + Шукати паролі - Пошук паролів + Пошук паролів Сайт @@ -1762,17 +1777,17 @@ Приховати пароль - Розблокуйте для перегляду збережених паролів + Розблокуйте для перегляду збережених паролів - Розблокуйте, щоб переглянути збережені паролі + Розблокуйте, щоб переглянути збережені паролі - Захистіть свої паролі + Захистіть свої паролі - Захистіть збережені паролі + Захистіть збережені паролі - Встановіть графічний ключ, PIN-код чи пароль для захисту збережених паролів від інших, хто може отримати доступ до вашого пристрою. + Встановіть графічний ключ, PIN-код чи пароль для захисту збережених паролів від інших, хто може отримати доступ до вашого пристрою. - Встановіть графічний ключ, PIN-код чи пароль для захисту збережених паролів від інших, хто може отримати доступ до вашого пристрою. + Встановіть графічний ключ, PIN-код чи пароль для захисту збережених паролів від інших, хто може отримати доступ до вашого пристрою. Пізніше @@ -1790,7 +1805,10 @@ Востаннє використано - Меню впорядкування паролів + Меню впорядкування паролів + + + Меню сортування паролів Меню сортування паролів @@ -1801,40 +1819,43 @@ Адреси - Кредитні картки + Кредитні картки - Способи оплати + Способи оплати - Зберігати та автоматично заповнювати дані карток + Зберігати та автоматично заповнювати дані карток - Зберігати й заповнювати способи оплати + Зберігати й заповнювати способи оплати - Дані зашифровано + Дані зашифровано - %s шифрує всі збережені способи оплати + %s шифрує всі збережені способи оплати Синхронізувати картки між пристроями Синхронізувати картки - Додати кредитну картку + Додати кредитну картку - Додати картку + Додати картку - Керувати збереженими картками + Керувати збереженими картками - Керувати картками + Керувати картками Додати адресу Керувати адресами - Зберігати та автоматично заповнювати адреси + Зберігати та автоматично заповнювати адреси - Зберігати й заповнювати адреси + Зберігати й заповнювати адреси - Включити дані, як-от номери, електронні адреси та адреси доставлення + Включити дані, як-от номери, електронні адреси та адреси доставлення + + + Містить номери телефонів і адреси електронної пошти Містить номери телефонів і адреси електронної пошти @@ -1858,9 +1879,9 @@ Видалити картку - Ви впевнені, що хочете видалити цю кредитну картку? + Ви впевнені, що хочете видалити цю кредитну картку? - Видалити картку? + Видалити картку? Видалити @@ -1874,24 +1895,24 @@ Збережені картки - Введіть дійсний номер кредитної картки + Введіть дійсний номер кредитної картки - Введіть дійсний номер картки + Введіть дійсний номер картки - Будь ласка, заповніть це поле + Будь ласка, заповніть це поле - Додайте назву + Додайте назву Розблокуйте для перегляду збережених карток - Захистіть свої банківські картки + Захистіть свої банківські картки - Захистіть свої збережені способи оплати + Захистіть свої збережені способи оплати - Встановіть графічний ключ, PIN-код чи пароль для захисту збережених банківських карток від інших, хто може отримати доступ до вашого пристрою. + Встановіть графічний ключ, PIN-код чи пароль для захисту збережених банківських карток від інших, хто може отримати доступ до вашого пристрою. - Встановіть графічний ключ, PIN-код чи пароль для захисту збережених способів оплати від інших, хто може отримати доступ до вашого пристрою. + Встановіть графічний ключ, PIN-код чи пароль для захисту збережених способів оплати від інших, хто може отримати доступ до вашого пристрою. Встановити @@ -1900,10 +1921,10 @@ Розблокуйте свій пристрій - Розблокуйте, щоб використовувати збережену інформацію про кредитну картку + Розблокуйте, щоб використовувати збережену інформацію про кредитну картку - Розблокуйте, щоб використати збережені способи оплати + Розблокуйте, щоб використати збережені способи оплати Додати адресу @@ -1911,11 +1932,13 @@ Керувати адресами - Ім’я + Ім’я - По батькові + По батькові - Прізвище + Прізвище + + Ім’я Вулиця @@ -1940,9 +1963,9 @@ Видалити адресу - Ви дійсно хочете видалити цю адресу? + Ви дійсно хочете видалити цю адресу? - Видалити цю адресу? + Видалити цю адресу? Видалити @@ -1953,11 +1976,11 @@ Видалити адресу - Додати засіб пошуку + Додати пошукову систему - Додати новий засіб пошуку + Додати нову пошукову систему - Змінити засіб пошуку + Змінити пошукову систему Змінити @@ -1966,7 +1989,7 @@ Назва - Назва засобу пошуку + Назва пошукової системи URL рядка пошуку @@ -1975,7 +1998,7 @@ Змініть запит на “%s”. Зразок:\nhttps://www.google.com/search?q=%s - Подробиці власного засобу пошуку + Подробиці власної пошукової системи API пошукових пропозицій (необов’язково) @@ -1987,7 +2010,7 @@ Зберегти - Введіть назву засобу пошуку + Введіть назву пошукової системи Введіть пошуковий запит @@ -2041,49 +2064,49 @@ Змінити - Ви дійсно хочете видалити цей запис? + Ви дійсно хочете видалити цей запис? - Ви дійсно хочете видалити цей пароль? + Ви дійсно хочете видалити цей пароль? Видалити Скасувати - Опції запису + Опції запису - Параметри пароля + Параметри пароля - Текстове поле для редагування вебадреси запису. + Текстове поле для редагування вебадреси запису. - Текстове поле для редагування адреси вебсайту. + Текстове поле для редагування адреси вебсайту. - Текстове поле для редагування імені користувача запису. + Текстове поле для редагування імені користувача запису. - Текстове поле для редагування імені користувача. + Текстове поле для редагування імені користувача. - Текстове поле для редагування пароля запису. + Текстове поле для редагування пароля запису. - Текстове поле для редагування пароля. + Текстове поле для редагування пароля. - Зберегти зміни. + Зберегти зміни. - Зберегти зміни. + Зберегти зміни. - Змінити + Змінити - Редагувати пароль + Редагувати пароль - Додати новий пароль + Додати новий пароль - Додати пароль + Додати пароль - Потрібен пароль + Потрібен пароль - Введіть пароль + Введіть пароль - Необхідно вказати ім’я користувача + Необхідно вказати ім’я користувача - Введіть ім’я користувача + Введіть ім’я користувача Необхідно вказати назву вузла @@ -2140,7 +2163,7 @@ Назва ярлика - Гаразд + OK Скасувати @@ -2195,7 +2218,7 @@ Показати подробиці - Вгору + Вгору Закрити @@ -2236,8 +2259,6 @@ Скоригований рейтинг - Сумнівні відгуки прибрано - На основі надійних відгуків Обране з недавніх відгуків @@ -2293,10 +2314,6 @@ Якщо цей товар знову з’явиться, повідомте про це нам, і ми його проаналізуємо. Повідомити про наявність товару - - Перевірка якості відгуку - - Перевірка якості відгуку Перевірка якості відгуку (%s) @@ -2342,13 +2359,19 @@ Докладніше - Вибравши “Так, спробувати”, ви погоджуєтеся з %1$s %2$s і %3$s від Mozilla. + Вибравши “Так, спробувати”, ви погоджуєтеся з %1$s %2$s і %3$s від Mozilla. Вибираючи “Спробувати”, ви погоджуєтеся з такими умовами від %1$s: + + Вибравши “Так, спробувати”, ви погоджуєтеся з %2$s %1$s і %4$s %3$s. + + Вибравши “Так, спробувати”, ви погоджуєтеся з %2$s %1$s і %4$s %3$s. - політикою приватності + політикою приватності Політика приватності + + положенням про приватність умовами користування @@ -2420,6 +2443,10 @@ Перекласти цю сторінку? + + Сторінку перекладено з %1$s на %2$s Спробуйте приватні переклади у %1$s @@ -2432,6 +2459,8 @@ Перекласти мовою Не зараз + + Показати оригінал Готово @@ -2454,6 +2483,16 @@ Докладніше + + Переклад… + + + Завантажити мову в режимі заощадження даних (%1$s)? + + Параметри перекладу diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 3dc25d14d..19aeaf695 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -242,6 +242,7 @@ Tùy biến trang chủ + Màn hình chính @@ -252,6 +253,11 @@ Dịch trang + + Đã dịch trang từ %1$s sang %2$s. + Ngôn ngữ được chọn @@ -329,12 +335,22 @@ Thông báo về quyền riêng tư Firefox - + + Tìm hiểu thêm trong thông báo bảo mật của chúng tôi Chúng tôi thích giữ an toàn cho bạn + + Tìm hiểu lý do tại sao hàng triệu người thích Firefox + + Duyệt web an toàn với nhiều lựa chọn hơn Trình duyệt được hỗ trợ phi lợi nhuận của chúng tôi giúp ngăn các công ty bí mật theo dõi bạn trên web. + Hơn 100 triệu người bảo vệ quyền riêng tư của mình bằng cách chọn trình duyệt được hỗ trợ bởi tổ chức phi lợi nhuận. + + Trình theo dõi được biết đến? Sẽ bị chặn tự động. Tiện ích mở rộng? Hãy thử tất cả 700 cái. Đọc PDF? Trình đọc tích hợp của chúng tôi giúp bạn dễ dàng quản lý chúng. + Trình duyệt được tài trợ bởi tổ chức phi lợi nhuận của chúng tôi giúp ngăn các công ty bí mật theo dõi bạn trên web.\n\nTìm hiểu thêm về thông báo quyền riêng tư của chúng tôi. Trang web an toàn không khả dụng - Rất có thể, trang web chỉ đơn giản là không hỗ trợ HTTPs. + Rất có thể, trang web chỉ đơn giản là không hỗ trợ HTTPS. Tuy nhiên, cũng có thể có kẻ tấn công tham gia. Nếu bạn tiếp tục vào trang web, bạn không nên nhập bất kỳ thông tin nhạy cảm nào. Nếu bạn tiếp tục, chế độ chỉ HTTPS sẽ tạm thời bị tắt cho trang web. @@ -688,9 +704,9 @@ Dấu trang - Đăng nhập + Đăng nhập - Mật khẩu + Mật khẩu Các thẻ đang mở @@ -716,9 +732,9 @@ %1$s trên %2$s %3$s - Thẻ tín dụng + Thẻ tín dụng - Phương thức thanh toán + Phương thức thanh toán Địa chỉ @@ -1652,13 +1668,13 @@ Bạn có thể dễ dàng thêm trang web vào màn hình chính thiết bị của bạn để có thể truy cập và duyệt web nhanh hơn với trải nghiệm giống như trên ứng dụng. - Thông tin đăng nhập và mật khẩu + Thông tin đăng nhập và mật khẩu - Mật khẩu + Mật khẩu - Lưu thông tin đăng nhập và mật khẩu + Lưu thông tin đăng nhập và mật khẩu - Lưu mật khẩu + Lưu mật khẩu Yêu cầu để lưu @@ -1673,48 +1689,48 @@ Điền tên người dùng và mật khẩu vào các ứng dụng khác trên thiết bị của bạn. - Thêm thông tin đăng nhập + Thêm thông tin đăng nhập - Thêm mật khẩu + Thêm mật khẩu - - Đồng bộ hóa thông tin đăng nhập - Đồng bộ mật khẩu + Đồng bộ hóa thông tin đăng nhập + + Đồng bộ mật khẩu - Đồng bộ hóa thông tin đăng nhập trên các thiết bị + Đồng bộ hóa thông tin đăng nhập trên các thiết bị - Đồng bộ hóa mật khẩu giữa các thiết bị + Đồng bộ hóa mật khẩu giữa các thiết bị - Thông tin đăng nhập đã lưu + Thông tin đăng nhập đã lưu - Mật khẩu đã lưu + Mật khẩu đã lưu - Thông tin đăng nhập bạn lưu hoặc đồng bộ hóa với %s sẽ hiển thị tại đây. + Thông tin đăng nhập bạn lưu hoặc đồng bộ hóa với %s sẽ hiển thị tại đây. - Mật khẩu bạn lưu hoặc đồng bộ hóa với %s sẽ được liệt kê ở đây. Tất cả mật khẩu bạn lưu đều được mã hóa. + Mật khẩu bạn lưu hoặc đồng bộ hóa với %s sẽ được liệt kê ở đây. Tất cả mật khẩu bạn lưu đều được mã hóa. - Tìm hiểu thêm về đồng bộ hóa. + Tìm hiểu thêm về đồng bộ hóa. - Tìm hiểu thêm về đồng bộ hoá + Tìm hiểu thêm về đồng bộ hoá Ngoại lệ - Thông tin đăng nhập và mật khẩu không được lưu sẽ được hiển thị ở đây. + Thông tin đăng nhập và mật khẩu không được lưu sẽ được hiển thị ở đây. - %s sẽ không lưu mật khẩu cho các trang được liệt kê ở đây. + %s sẽ không lưu mật khẩu cho các trang được liệt kê ở đây. - Thông tin đăng nhập và mật khẩu sẽ không được lưu cho các trang web này. + Thông tin đăng nhập và mật khẩu sẽ không được lưu cho các trang web này. - %s sẽ không lưu mật khẩu cho các trang web này. + %s sẽ không lưu mật khẩu cho các trang web này. Xóa tất cả ngoại lệ - Tìm thông tin đăng nhập + Tìm thông tin đăng nhập - Tìm kiếm mật khẩu + Tìm kiếm mật khẩu Trang @@ -1742,17 +1758,17 @@ Ẩn mật khẩu - Mở khóa để xem thông tin đăng nhập đã lưu của bạn + Mở khóa để xem thông tin đăng nhập đã lưu của bạn - Mở khóa để xem mật khẩu đã lưu của bạn + Mở khóa để xem mật khẩu đã lưu của bạn - Bảo mật thông tin đăng nhập và mật khẩu của bạn + Bảo mật thông tin đăng nhập và mật khẩu của bạn - Giữ mật khẩu đã lưu của bạn một cách an toàn + Giữ mật khẩu đã lưu của bạn một cách an toàn - Thiết lập mẫu khóa thiết bị, mã PIN hoặc mật khẩu để bảo vệ thông tin đăng nhập và mật khẩu đã lưu của bạn khỏi bị truy cập nếu người khác lấy được thiết bị của bạn. + Thiết lập mẫu khóa thiết bị, mã PIN hoặc mật khẩu để bảo vệ thông tin đăng nhập và mật khẩu đã lưu của bạn khỏi bị truy cập nếu người khác lấy được thiết bị của bạn. - Đặt mật khẩu thiết bị dạng mẫu hình, mã PIN hoặc mật khẩu để bảo vệ mật khẩu đã lưu của bạn không bị truy cập nếu người khác lấy được thiết bị của bạn. + Đặt mật khẩu thiết bị dạng mẫu hình, mã PIN hoặc mật khẩu để bảo vệ mật khẩu đã lưu của bạn không bị truy cập nếu người khác lấy được thiết bị của bạn. Để sau @@ -1769,7 +1785,10 @@ Sử dụng lần cuối - Sắp xếp menu đăng nhập + Sắp xếp menu đăng nhập + + + Menu sắp xếp mật khẩu Menu sắp xếp mật khẩu @@ -1780,40 +1799,43 @@ Địa chỉ - Thẻ tín dụng + Thẻ tín dụng - Phương thức thanh toán + Phương thức thanh toán - Lưu và tự động điền thẻ tín dụng + Lưu và tự động điền thẻ tín dụng - Lưu và điền phương thức thanh toán + Lưu và điền phương thức thanh toán - Dữ liệu được mã hóa + Dữ liệu được mã hóa - %s mã hóa tất cả các phương thức thanh toán bạn lưu + %s mã hóa tất cả các phương thức thanh toán bạn lưu Đồng bộ thông tin thẻ tín dụng trên các thiết bị Đồng bộ hóa thẻ tín dụng - Thêm thẻ tín dụng + Thêm thẻ tín dụng - Thêm thẻ + Thêm thẻ - Quản lý thẻ tín dụng đã lưu + Quản lý thẻ tín dụng đã lưu - Quản lý thẻ tín dụng + Quản lý thẻ tín dụng Thêm địa chỉ Quản lý địa chỉ - Lưu và tự động điền địa chỉ + Lưu và tự động điền địa chỉ - Lưu và điền địa chỉ + Lưu và điền địa chỉ - Bao gồm thông tin như số, email và địa chỉ giao hàng + Bao gồm thông tin như số, email và địa chỉ giao hàng + + + Bao gồm số điện thoại và địa chỉ email Bao gồm số điện thoại và địa chỉ email @@ -1837,9 +1859,9 @@ Xóa thẻ - Bạn có chắc chắn muốn xóa thẻ tín dụng này không? + Bạn có chắc chắn muốn xóa thẻ tín dụng này không? - Xoá thẻ? + Xoá thẻ? Xóa @@ -1853,24 +1875,24 @@ Thẻ tín dụng đã lưu - Vui lòng nhập số thẻ tín dụng hợp lệ + Vui lòng nhập số thẻ tín dụng hợp lệ - Nhập số thẻ hợp lệ + Nhập số thẻ hợp lệ - Vui lòng điền vào trường này + Vui lòng điền vào trường này - Thêm tên + Thêm tên Mở khóa để xem các thẻ tín dụng đã lưu của bạn - Bảo mật thẻ tín dụng của bạn + Bảo mật thẻ tín dụng của bạn - Giữ các phương thức thanh toán đã lưu của bạn một cách an toàn + Giữ các phương thức thanh toán đã lưu của bạn một cách an toàn - Thiết lập màn hình khóa thiết bị với mẫu hình, mã PIN hoặc mật khẩu để bảo vệ thẻ tín dụng đã lưu của bạn không bị truy cập nếu người khác có thiết bị của bạn. + Thiết lập màn hình khóa thiết bị với mẫu hình, mã PIN hoặc mật khẩu để bảo vệ thẻ tín dụng đã lưu của bạn không bị truy cập nếu người khác có thiết bị của bạn. - Đặt mật khẩu thiết bị dạng mẫu hình, mã PIN hoặc mật khẩu để bảo vệ phương thức thanh toán đã lưu của bạn không bị truy cập nếu người khác lấy đuọc thiết bị của bạn. + Đặt mật khẩu thiết bị dạng mẫu hình, mã PIN hoặc mật khẩu để bảo vệ phương thức thanh toán đã lưu của bạn không bị truy cập nếu người khác lấy đuọc thiết bị của bạn. Thiết lập ngay @@ -1878,10 +1900,10 @@ Mở khóa thiết bị của bạn - Mở khóa để sử dụng thông tin thẻ tín dụng được lưu trữ + Mở khóa để sử dụng thông tin thẻ tín dụng được lưu trữ - Mở khóa để sử dụng các phương thức thanh toán đã lưu + Mở khóa để sử dụng các phương thức thanh toán đã lưu Thêm địa chỉ @@ -1889,11 +1911,13 @@ Quản lý địa chỉ - Tên + Tên - Tên đệm + Tên đệm - Họ + Họ + + Tên Địa chỉ đường phố @@ -1918,9 +1942,9 @@ Xóa địa chỉ - Bạn có chắc chắn muốn xóa địa chỉ này không? + Bạn có chắc chắn muốn xóa địa chỉ này không? - Xoá địa chỉ này? + Xoá địa chỉ này? Xóa @@ -2018,49 +2042,49 @@ Chỉnh sửa - Bạn có chắc chắn muốn xóa thông tin đăng nhập này không? + Bạn có chắc chắn muốn xóa thông tin đăng nhập này không? - Bạn có chắc chắn muốn xóa mật khẩu này? + Bạn có chắc chắn muốn xóa mật khẩu này? Xóa Hủy bỏ - Tùy chọn thông tin đăng nhập + Tùy chọn thông tin đăng nhập - Cài đặt mật khẩu + Cài đặt mật khẩu - Trường văn bản có thể chỉnh sửa cho địa chỉ web của thông tin đăng nhập. + Trường văn bản có thể chỉnh sửa cho địa chỉ web của thông tin đăng nhập. - Trường văn bản có thể chỉnh sửa cho địa chỉ trang web. + Trường văn bản có thể chỉnh sửa cho địa chỉ trang web. - Trường văn bản có thể chỉnh sửa cho tên người dùng của thông tin đăng nhập. + Trường văn bản có thể chỉnh sửa cho tên người dùng của thông tin đăng nhập. - Trường văn bản có thể chỉnh sửa cho tên người dùng. + Trường văn bản có thể chỉnh sửa cho tên người dùng. - Trường văn bản có thể chỉnh sửa cho mật khẩu của thông tin đăng nhập. + Trường văn bản có thể chỉnh sửa cho mật khẩu của thông tin đăng nhập. - Trường văn bản có thể chỉnh sửa cho mật khẩu. + Trường văn bản có thể chỉnh sửa cho mật khẩu. - Lưu các thay đổi vào thông tin đăng nhập. + Lưu các thay đổi vào thông tin đăng nhập. - Lưu thay đổi. + Lưu thay đổi. - Chỉnh sửa + Chỉnh sửa - Chỉnh sửa mật khẩu + Chỉnh sửa mật khẩu - Thêm thông tin đăng nhập mới + Thêm thông tin đăng nhập mới - Thêm mật khẩu + Thêm mật khẩu - Yêu cầu mật khẩu + Yêu cầu mật khẩu - Nhập mật khẩu + Nhập mật khẩu - Yêu cầu tên đăng nhập + Yêu cầu tên đăng nhập - Nhập tên người dùng + Nhập tên người dùng Yêu cầu tên máy chủ @@ -2172,7 +2196,7 @@ Chạm để biết thêm chi tiết - Điều hướng lên + Điều hướng lên Đóng @@ -2213,8 +2237,6 @@ Đánh giá đã được điều chỉnh - Đã xóa các đánh giá không đáng tin cậy - Dựa trên những đánh giá đáng tin cậy Điểm nổi bật từ các đánh giá gần đây @@ -2270,10 +2292,6 @@ Nếu bạn thấy sản phẩm này đã có hàng trở lại, hãy báo cáo và chúng tôi sẽ kiểm tra đánh giá. Báo sản phẩm còn hàng - - Đang kiểm tra chất lượng đánh giá - - Đang kiểm tra chất lượng đánh giá Kiểm tra chất lượng đánh giá (%s) @@ -2319,13 +2337,19 @@ Tìm hiểu thêm - Bằng cách chọn “Có, hãy thử nó” bạn đã đồng ý với %2$s và %3$s của %1$s bởi Mozilla. + Bằng cách chọn “Có, hãy thử nó” bạn đã đồng ý với %2$s và %3$s của %1$s bởi Mozilla. Bằng cách chọn “Có, dùng thử nó”, bạn đồng ý với những điều sau từ %1$s: + + Bằng cách chọn “Có, hãy thử nó” bạn đồng ý với %2$s của %1$s và %4$s của %3$s. + + Bằng cách chọn “Có, hãy thử nó” bạn đồng ý với %2$s của %1$s và %4$s của %3$s. - chính sách riêng tư + chính sách riêng tư Chính sách riêng tư + + thông báo bảo mật điều khoản sử dụng @@ -2397,6 +2421,10 @@ Dịch trang này? + + Đã dịch trang từ %1$s sang %2$s Hãy thử bản dịch riêng tư trong %1$s @@ -2409,6 +2437,8 @@ Dịch sang Không phải bây giờ + + Hiển thị bản gốc Xong @@ -2431,6 +2461,16 @@ Tìm hiểu thêm + + Đang dịch… + + + Tải xuống ngôn ngữ ở chế độ tiết kiệm dữ liệu (%1$s)? + + Tuỳ chọn dịch diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e8d1625a3..9d1182c54 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -261,6 +261,11 @@ 翻译页面 + + 已将页面从%1$s翻译成%2$s。 + 选择的语言 @@ -341,12 +346,22 @@ Firefox 隐私声明 - + + 阅读我们的隐私声明详细了解 我们乐于为您护航 + + 探究 Firefox 何以受亿万用户青睐 + + 更多保障上网安全的选项 这款由非营利组织支持的浏览器会自动阻止大公司在网上偷偷跟踪您。 + 这款由非营利组织支持的浏览器,是超过一亿用户的隐私保护之选。 + + 已知跟踪器?自动拦截!好用扩展?足足 700 款任您选!PDF 文档?内置阅读器轻松满足您的需求。 + 这款由非营利组织支持的浏览器会自动阻止大公司在网上偷偷跟踪您。\n\n请阅读我们的隐私声明详细了解。 @@ -707,9 +722,9 @@ 书签 - 登录信息 + 登录信息 - 密码 + 密码 打开的标签页 @@ -735,10 +750,10 @@ %2$s %3$s 上的 %1$s - 信用卡 + 信用卡 - 付款方式 + 付款方式 邮政地址 @@ -1711,13 +1726,13 @@ 您可以轻松将此网站添加到设备主屏幕,以便迅捷访问并以类似应用的体验畅享浏览。 - 密码 + 密码 - 密码 + 密码 - 保存登录名和密码 + 保存登录名和密码 - 保存密码 + 保存密码 询问是否保存 @@ -1734,48 +1749,48 @@ 在您设备上的其他应用程序中填充用户名和密码。 - 添加登录信息 + 添加登录信息 - 添加密码 + 添加密码 - - 同步登录信息 - 同步密码 + 同步登录信息 + + 同步密码 - 跨设备同步登录信息 + 跨设备同步登录信息 - 跨设备同步密码 + 跨设备同步密码 - 保存的登录信息 + 保存的登录信息 - 保存的密码 + 保存的密码 - 您保存或同步到 %s 的登录信息将显示于此处。 + 您保存或同步到 %s 的登录信息将显示于此处。 - 保存和同步到 %s 的密码会显示在这里,所有密码均已加密保存。 + 保存和同步到 %s 的密码会显示在这里,所有密码均已加密保存。 - 详细了解“同步”。 + 详细了解“同步”。 - 详细了解同步功能 + 详细了解同步功能 例外 - 不保存登录名和密码的网站将显示于此处。 + 不保存登录名和密码的网站将显示于此处。 - %s 将不会保存此处所列网站的密码。 + %s 将不会保存此处所列网站的密码。 - 将不保存这些网站的登录名和密码。 + 将不保存这些网站的登录名和密码。 - %s 将不会保存这些网站的密码。 + %s 将不会保存这些网站的密码。 删除所有例外 - 搜索登录信息 + 搜索登录信息 - 搜索密码 + 搜索密码 网站 @@ -1803,17 +1818,17 @@ 隐藏密码 - 解锁以查看您保存的登录信息 + 解锁以查看您保存的登录信息 - 解锁以查看保存的密码 + 解锁以查看保存的密码 - 保护您的登录名和密码 + 保护您的登录名和密码 - 保护您保存的密码 + 保护您保存的密码 - 设置设备锁定图案、PIN 或密码以保护您保存的登录名与密码,避免他人盗用。 + 设置设备锁定图案、PIN 或密码以保护您保存的登录名与密码,避免他人盗用。 - 设置设备锁定图案、PIN 或密码以保护您保存的密码,避免他人盗用。 + 设置设备锁定图案、PIN 或密码以保护您保存的密码,避免他人盗用。 稍后 @@ -1830,7 +1845,10 @@ 上次使用 - 排序登录信息菜单 + 排序登录信息菜单 + + + 密码排序菜单 密码排序菜单 @@ -1841,40 +1859,43 @@ 地址 - 信用卡 + 信用卡 - 付款方式 + 付款方式 - 保存并自动填充信用卡信息 + 保存并自动填充信用卡信息 - 保存和填写付款方式 + 保存和填写付款方式 - 数据已加密 + 数据已加密 - %s 会加密您保存的所有付款方式 + %s 会加密您保存的所有付款方式 跨设备同步信用卡信息 同步卡片信息 - 添加信用卡 + 添加信用卡 - 添加信用卡 + 添加信用卡 - 管理保存的卡片 + 管理保存的卡片 - 管理信用卡 + 管理信用卡 添加地址 管理地址 - 保存并自动填充地址 + 保存并自动填充地址 - 保存和填充地址 + 保存和填充地址 - 包含号码、邮箱和收货地址等信息 + 包含号码、邮箱和收货地址等信息 + + + 包括电话号码和邮箱地址 包括电话号码和邮箱地址 @@ -1898,9 +1919,9 @@ 删除卡片 - 您确定要删除此信用卡吗? + 您确定要删除此信用卡吗? - 确定删除信用卡吗? + 确定删除信用卡吗? 删除 @@ -1914,25 +1935,25 @@ 保存的卡片 - 请输入有效的信用卡卡号 + 请输入有效的信用卡卡号 - 请输入有效卡号 + 请输入有效卡号 - 请填写此栏 + 请填写此栏 - 请输入持卡人姓名 + 请输入持卡人姓名 解锁后即可查看保存的卡片信息 - 保护您的卡片信息 + 保护您的卡片信息 - 保护您保存的付款方式 + 保护您保存的付款方式 - 设置设备锁定图案、PIN 或密码以保护您保存的卡片信息,避免他人盗用。 + 设置设备锁定图案、PIN 或密码以保护您保存的卡片信息,避免他人盗用。 - 设置设备锁定图案、PIN 或密码以保护您保存的付款方式,避免他人盗用。 + 设置设备锁定图案、PIN 或密码以保护您保存的付款方式,避免他人盗用。 立即设置 @@ -1941,10 +1962,10 @@ 解锁设备 - 解锁以使用存储的卡片信息 + 解锁以使用存储的卡片信息 - 解锁以使用保存的付款方式 + 解锁以使用保存的付款方式 添加地址 @@ -1952,11 +1973,13 @@ 管理地址 - + - 中间名 + 中间名 - + + + 姓名 街道地址 @@ -1981,9 +2004,9 @@ 删除地址 - 您确定要删除此地址吗? + 您确定要删除此地址吗? - 确定删除此地址吗? + 确定删除此地址吗? 删除 @@ -2081,49 +2104,49 @@ 编辑 - 您确定要删除此登录信息吗? + 您确定要删除此登录信息吗? - 您确定要删除此密码吗? + 您确定要删除此密码吗? 删除 取消 - 登录选项 + 登录选项 - 密码选项 + 密码选项 - 登录信息中的网址输入框。 + 登录信息中的网址输入框。 - 网址输入框。 + 网址输入框。 - 登录信息中的用户名输入框。 + 登录信息中的用户名输入框。 - 用户名输入框。 + 用户名输入框。 - 登录信息中的密码输入框。 + 登录信息中的密码输入框。 - 密码输入框。 + 密码输入框。 - 保存编辑过的登录信息。 + 保存编辑过的登录信息。 - 保存更改。 + 保存更改。 - 编辑 + 编辑 - 编辑密码 + 编辑密码 - 新建登录信息 + 新建登录信息 - 添加密码 + 添加密码 - 需要密码 + 需要密码 - 请输入密码 + 请输入密码 - 用户名不能为空 + 用户名不能为空 - 请输入用户名 + 请输入用户名 主机名不能为空 @@ -2223,6 +2246,9 @@ %s · 搜索 + + 切换默认浏览器 + 将网站、电子邮件及聊天工具中的链接设为在 Firefox 中自动打开。 @@ -2232,7 +2258,7 @@ 点击了解更多信息 - 向上导航 + 向上导航 关闭 @@ -2273,8 +2299,6 @@ 调整后的评分 - 已排除不可信的评价 - 基于可信评价调整 最有帮助的近期评价 @@ -2335,10 +2359,6 @@ 报告商品有货 - - 正在核查评价质量 - - 正在核查评价质量 正在检查评价质量(%s) @@ -2388,13 +2408,19 @@ 详细了解 - 选择“试试看”,即代表您同意由 Mozilla 支持的 %1$s 的%2$s和%3$s。 + 选择“试试看”,即代表您同意由 Mozilla 支持的 %1$s 的%2$s和%3$s。 选择“试试看”,即代表您同意 %1$s 的: + + 选择“试试看”,即代表您同意 %1$s 的 %2$s 和 %3$s 的 %4$s。 + + 选择“试试看”,即代表您同意 %1$s 的 %2$s 和 %3$s 的 %4$s。 - 隐私政策 + 隐私政策 隐私政策 + + 隐私声明 使用条款 @@ -2501,6 +2527,10 @@ 要翻译此页面吗? + + 已将页面从%1$s翻译成%2$s 试试 %1$s 注重隐私的翻译功能 @@ -2514,6 +2544,8 @@ 目标语言: 暂时不要 + + 显示原文 完成 @@ -2536,6 +2568,16 @@ 详细了解 + + 正在翻译… + + + 确定在流量节省模式开启时下载吗(%1$s)? + + 翻译设置 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 05ac104d5..a61ab0e4b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -259,6 +259,11 @@ 翻譯頁面 + + 已將頁面從 %1$s 翻譯為 %2$s。 + 選擇的語言 @@ -337,12 +342,22 @@ Firefox 隱私權公告 - + + 可以到我們的隱私權公告了解更多資訊 我們希望確保您上網安全 + + 看看為什麼有數百萬人愛用 Firefox + + 更多讓您上網更安全的選擇 我們這套由非營利組織所開發的瀏覽器,會自動封鎖讓大企業在網路上偷偷跟蹤您的程式。 + 有超過一億人選用由非營利組織全力相挺的瀏覽器,來保護他們的隱私。 + + 遇到已知的追蹤器?會自動封鎖。想要使用擴充套件?全部有 700 套任君選用。要開啟 PDF 檔案?我們直接內建閱讀器讓您輕鬆好管理。 + 這套由非營利組織打造的瀏覽器,可幫助防止企業在網路上偷偷追蹤您。\n\n到我們的隱私權公告了解更多資訊。 @@ -699,9 +714,9 @@ 書籤 - 登入資訊 + 登入資訊 - 密碼 + 密碼 開啟分頁 @@ -727,9 +742,9 @@ 在 %2$s %3$s 上的 %1$s - 信用卡 + 信用卡 - 付款方式 + 付款方式 地址 @@ -1696,13 +1711,13 @@ 您可將此網站加到裝置主畫面,方便快速開啟,或是以類似 App 的方式使用。 - 登入資訊與密碼 + 登入資訊與密碼 - 密碼 + 密碼 - 儲存登入資訊與密碼 + 儲存登入資訊與密碼 - 已存密碼 + 已存密碼 詢問我是否儲存 @@ -1717,47 +1732,47 @@ 使用其他裝置中的其他應用程式時也自動填寫使用者名稱與密碼。 - 新增登入資訊 + 新增登入資訊 - 新增密碼 + 新增密碼 - - 同步登入資訊 - 同步密碼 + 同步登入資訊 + + 同步密碼 - 在不同裝置間同步登入資訊 + 在不同裝置間同步登入資訊 - 在不同裝置間同步密碼 + 在不同裝置間同步密碼 - 儲存的登入資訊 + 儲存的登入資訊 - 已存密碼 + 已存密碼 - 您儲存或同步到 %s 的登入資訊將顯示於此處。 + 您儲存或同步到 %s 的登入資訊將顯示於此處。 - 您儲存或同步到 %s 的密碼將顯示於此處,所有儲存的密碼資訊都會被加密。 + 您儲存或同步到 %s 的密碼將顯示於此處,所有儲存的密碼資訊都會被加密。 - 了解 Sync 的更多資訊。 + 了解 Sync 的更多資訊。 - 瞭解同步功能的更多資訊 + 瞭解同步功能的更多資訊 例外網站 - 不儲存登入資訊與密碼的網站將顯示於此處。 + 不儲存登入資訊與密碼的網站將顯示於此處。 - %s 不會儲存下列網站的密碼。 + %s 不會儲存下列網站的密碼。 - 將不儲存這些網站的登入資訊與密碼。 + 將不儲存這些網站的登入資訊與密碼。 - %s 不會儲存下列網站的密碼。 + %s 不會儲存下列網站的密碼。 刪除所有例外 - 搜尋登入資訊 + 搜尋登入資訊 - 搜尋密碼 + 搜尋密碼 網站 @@ -1785,17 +1800,17 @@ 隱藏密碼 - 解鎖後即可檢視儲存的登入資訊 + 解鎖後即可檢視儲存的登入資訊 - 解鎖後即可檢視儲存的密碼 + 解鎖後即可檢視儲存的密碼 - 保護您的登入資訊與密碼 + 保護您的登入資訊與密碼 - 保護您儲存的密碼 + 保護您儲存的密碼 - 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存下來的登入資訊與密碼,避免別人盜用。 + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存下來的登入資訊與密碼,避免別人盜用。 - 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的密碼,避免別人盜用。 + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的密碼,避免別人盜用。 稍後處理 @@ -1812,7 +1827,10 @@ 上次使用 - 排序登入資訊選單 + 排序登入資訊選單 + + + 排序密碼選單 排序密碼選單 @@ -1823,41 +1841,44 @@ 地址 - 信用卡 + 信用卡 - 付款方式 + 付款方式 - 儲存並自動填寫卡片 + 儲存並自動填寫卡片 - 儲存並自動填寫付款方式 + 儲存並自動填寫付款方式 - 資料有加密 + 資料有加密 - %s 會加密您儲存的所有付款方式資料 + %s 會加密您儲存的所有付款方式資料 在不同裝置間同步卡片資料 同步信用卡資訊 - 新增信用卡 + 新增信用卡 - 新增付款卡片 + 新增付款卡片 - 管理已儲存的卡片 + 管理已儲存的卡片 - 管理卡片 + 管理卡片 新增地址 管理已存地址 - 儲存並自動填寫地址 + 儲存並自動填寫地址 - 儲存並自動填寫地址 + 儲存並自動填寫地址 - 包含電話號碼、E-Mail、收件地址等資訊 + 包含電話號碼、E-Mail、收件地址等資訊 + + + 包含電話號碼與電子郵件地址 包含電話號碼與電子郵件地址 @@ -1881,9 +1902,9 @@ 刪除卡片 - 你確定要刪除這張信用卡嗎? + 你確定要刪除這張信用卡嗎? - 要刪除卡片嗎? + 要刪除卡片嗎? 刪除 @@ -1897,24 +1918,24 @@ 已儲存的卡片 - 請輸入有效的信用卡號 + 請輸入有效的信用卡號 - 請輸入有效卡號 + 請輸入有效卡號 - 請填寫此欄位 + 請填寫此欄位 - 請輸入持卡人姓名 + 請輸入持卡人姓名 解鎖後即可檢視儲存的卡片資訊 - 保護您的信用卡資訊 + 保護您的信用卡資訊 - 保護您儲存的付款方式 + 保護您儲存的付款方式 - 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的信用卡資訊,避免別人盜用。 + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的信用卡資訊,避免別人盜用。 - 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的付款方式資訊,避免別人盜用。 + 設定裝置解鎖圖形、PIN 碼或密碼來保護您儲存的付款方式資訊,避免別人盜用。 立即設定 @@ -1923,10 +1944,10 @@ 裝置解鎖 - 解鎖後,即可使用儲存的信用卡資訊 + 解鎖後,即可使用儲存的信用卡資訊 - 解鎖後即可使用儲存的付款方式 + 解鎖後即可使用儲存的付款方式 新增地址 @@ -1934,11 +1955,13 @@ 管理已存地址 - 名字 + 名字 - 中間名 + 中間名 - 姓氏 + 姓氏 + + 姓名 街道地址 @@ -1963,9 +1986,9 @@ 刪除地址 - 您確定要刪除這筆地址嗎? + 您確定要刪除這筆地址嗎? - 要刪除這個地址嗎? + 要刪除這個地址嗎? 刪除 @@ -2063,49 +2086,49 @@ 編輯 - 您確定要刪除這筆登入資訊嗎? + 您確定要刪除這筆登入資訊嗎? - 你確定要刪除這筆密碼嗎? + 你確定要刪除這筆密碼嗎? 刪除 取消 - 登入選項 + 登入選項 - 密碼選項 + 密碼選項 - 登入資訊當中,網址的輸入欄位。 + 登入資訊當中,網址的輸入欄位。 - 網址的輸入欄位。 + 網址的輸入欄位。 - 登入資訊當中,使用者名稱的輸入欄位。 + 登入資訊當中,使用者名稱的輸入欄位。 - 使用者名稱的輸入欄位。 + 使用者名稱的輸入欄位。 - 登入資訊當中,密碼的輸入欄位。 + 登入資訊當中,密碼的輸入欄位。 - 密碼的輸入欄位。 + 密碼的輸入欄位。 - 儲存編輯過的登入資訊。 + 儲存編輯過的登入資訊。 - 儲存變更。 + 儲存變更。 - 編輯 + 編輯 - 編輯密碼 + 編輯密碼 - 新增登入資訊 + 新增登入資訊 - 新增密碼 + 新增密碼 - 需要密碼 + 需要密碼 - 輸入密碼 + 輸入密碼 - 必須輸入使用者名稱 + 必須輸入使用者名稱 - 輸入使用者名稱 + 輸入使用者名稱 必須輸入主機名稱 @@ -2217,7 +2240,7 @@ 點這裡取得詳細資訊 - 向上導航 + 向上導航 關閉 @@ -2258,8 +2281,6 @@ 調整後評分 - 已移除不可靠的評論 - 根據可靠評論調整 近期評論的重點資訊 @@ -2315,10 +2336,6 @@ 若您發現此產品又上架了,請回報給我們,我們將盡快檢查評論內容。 回報產品已有庫存 - - 正在檢查評論品質 - - 正在檢查評論品質 正在檢查評論品質(%s) @@ -2364,13 +2381,19 @@ 了解更多 - 選擇「好,試用看看」,代表您同意 %1$s by Mozilla 的 %2$s 與 %3$s 。 + 選擇「好,試用看看」,代表您同意 %1$s by Mozilla 的 %2$s 與 %3$s 。 選擇「好,試試看」,代表您同意 %1$s: + + 選擇「好,試用看看」,代表您同意 %1$s 的 %2$s 與 %3$s 的 %4$s。 + + 選擇「好,試用看看」,代表您同意 %1$s 的 %2$s 與 %3$s 的 %4$s。 - 隱私權保護政策 + 隱私權保護政策 隱私權保護政策 + + 隱私權公告 使用條款 @@ -2476,6 +2499,10 @@ 要翻譯此頁面嗎? + + 已將頁面從 %1$s 翻譯為 %2$s 在 %1$s 試用保護隱私的翻譯功能 @@ -2488,6 +2515,8 @@ 翻譯語言: 現在不要 + + 顯示原始內容 完成 @@ -2510,6 +2539,16 @@ 更多資訊 + + 翻譯中… + + + 裝置處於資料節省模式時,也下載翻譯語言檔(%1$s)嗎? + + 翻譯選項 diff --git a/app/src/main/res/values/preference_keys.xml b/app/src/main/res/values/preference_keys.xml index 66eac0ec8..4e73353aa 100644 --- a/app/src/main/res/values/preference_keys.xml +++ b/app/src/main/res/values/preference_keys.xml @@ -18,7 +18,6 @@ pref_key_advanced pref_key_language pref_key_data_choices - pref_key_privacy_link pref_key_delete_browsing_data pref_key_delete_browsing_data_on_quit_preference pref_key_notifications @@ -42,10 +41,8 @@ pref_key_override_amo_user pref_key_override_amo_collection pref_key_enable_gecko_logs - pref_key_help pref_key_rate pref_key_about - pref_key_your_rights pref_key_account pref_key_sign_in pref_key_account_auth_error @@ -148,6 +145,9 @@ pref_key_privacy_pop_window + + pref_key_remote_server_prod + pref_key_light_theme pref_key_dark_theme diff --git a/app/src/main/res/values/static_strings.xml b/app/src/main/res/values/static_strings.xml index 1dfb15c33..8f8e4688c 100644 --- a/app/src/main/res/values/static_strings.xml +++ b/app/src/main/res/values/static_strings.xml @@ -34,6 +34,8 @@ Secret Settings Secret Debug Info + + Use Remote Settings Production server \n(Staging will be used when disabled) \n(requires restart) Use third party CA certificates diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c7fc9088d..36601eab8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -233,12 +233,16 @@ Edit Customize homepage + Home screen Erase browsing history + + Translate page + Selected language @@ -250,8 +254,6 @@ Scan - - Search engine Search engine settings @@ -300,24 +302,34 @@ - Notifications help you do more with %s + Notifications help you do more with %s - Sync your tabs between devices, manage downloads, get tips about making the most of %s’s privacy protection, and more. + Sync your tabs between devices, manage downloads, get tips about making the most of %s’s privacy protection, and more. - Continue + Continue - Not now + Not now Firefox privacy notice - + + Learn more in our privacy notice We love keeping you safe + + Find out why millions love Firefox + + Safe browsing with more choices Our non-profit backed browser helps stop companies from secretly following you around the web. + More than 100 million people protect their privacy by choosing a browser that’s backed by a nonprofit. + + Known trackers? Blocked automatically. Extensions? Try all 700. PDFs? Our built-in reader makes them easy to manage. + Our non-profit backed browser helps stop companies from secretly following you around the web.\n\nLearn more in our privacy notice. @@ -422,20 +434,10 @@ HTTPS-Only Mode - - Cookie banner reduction Cookie Banner Blocker Cookie Banner Blocker in private browsing - - Reduce cookie banners - - Off - - On - - %1$s automatically tries to reject cookie requests on cookie banners. Off for this site @@ -453,33 +455,15 @@ Site currently not supported - Turn on Cookie banner reduction for %1$s? - Turn on Cookie Banner Blocker for %1$s? - Turn off Cookie banner reduction for %1$s? - Turn off Cookie Banner Blocker for %1$s? %1$s can’t automatically reject cookie requests on this site. You can send a request to support this site in the future. - %1$s will clear this site’s cookies and refresh the page. Clearing all cookies may sign you out or empty shopping carts. - Turn off and %1$s will clear cookies and reload this site. This may sign you out or empty shopping carts. - %1$s tries to automatically reject all cookie requests on supported sites. - Turn on and %1$s will try to automatically refuse all cookie banners on this site. - - Allow %1$s to reject cookie banners? - - %1$s can automatically reject many cookie banner requests. - - Not Now - - You’ll see fewer cookie requests - - Allow %1$s just refused cookies for you @@ -1239,8 +1223,6 @@ Dismiss - Unable to print - Unable to print this page Print @@ -1840,7 +1822,7 @@ Set up a device lock pattern, PIN, or password to protect your saved credit cards from being accessed if someone else has your device. - Set up a device lock pattern, PIN, or password to protect your saved cards from being accessed if someone else has your device. + Set up a device lock pattern, PIN, or password to protect your saved payment methods from being accessed if someone else has your device. Set up now @@ -1997,12 +1979,12 @@ Password options The editable text field for the web address of the login. - - The editable text field for the website address of the password. + + The editable text field for the website address. The editable text field for the username of the login. - - The editable text field for the username of the password. + + The editable text field for the username. The editable text field for the password of the login. @@ -2117,6 +2099,9 @@ %s search + + Switch your default browser + Set links from websites, emails, and messages to open automatically in Firefox. @@ -2126,7 +2111,7 @@ Click for more details - Navigate up + Navigate up Close @@ -2189,8 +2174,6 @@ Highlights are from %s reviews within the last 80 days that we believe to be reliable.]]> Learn more about %s. - - how %s by Mozilla determines review quality how %s determines review quality @@ -2274,13 +2257,19 @@ Learn more - By selecting “Yes, try it” you agree to %1$s by Mozilla’s %2$s and %3$s. + By selecting “Yes, try it” you agree to %1$s by Mozilla’s %2$s and %3$s. By selecting “Yes, try it” you agree to the following from %1$s: + + By selecting “Yes, try it” you agree to %1$s\'s %2$s and %3$s\'s %4$s. + + By selecting “Yes, try it” you agree to %1$s\’s %2$s and %3$s\’s %4$s. - privacy policy + privacy policy Privacy policy + + privacy notice terms of use @@ -2407,6 +2396,8 @@ Translating Translating in Progress + + Choose a language There was a problem translating. Please try again. diff --git a/app/src/main/res/xml/secret_settings_preferences.xml b/app/src/main/res/xml/secret_settings_preferences.xml index 48148593f..0a74701ce 100644 --- a/app/src/main/res/xml/secret_settings_preferences.xml +++ b/app/src/main/res/xml/secret_settings_preferences.xml @@ -61,4 +61,9 @@ app:iconSpaceReserved="false" android:title="@string/preferences_debug_settings_custom_sponsored_stories_parameters" /> + diff --git a/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt b/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt index f364a2b4b..ca27f28c9 100644 --- a/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt +++ b/app/src/test/java/org/mozilla/fenix/addons/AddonDetailsBindingDelegateTest.kt @@ -8,6 +8,7 @@ import android.net.Uri import android.text.method.LinkMovementMethod import android.view.LayoutInflater import android.view.View +import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO import androidx.core.view.isVisible import io.mockk.mockk import io.mockk.verify @@ -66,9 +67,17 @@ class AddonDetailsBindingDelegateTest { ), ), ) - assertEquals("4.30/5", binding.ratingView.contentDescription) assertEquals(4.5f, binding.ratingView.rating) assertEquals("100", binding.reviewCount.text) + + val ratingContentDescription = testContext.getString(R.string.mozac_feature_addons_rating_content_description_2) + var formattedRatting = String.format(ratingContentDescription, 4.3f) + assertEquals(formattedRatting, binding.ratingLabel.contentDescription) + assertEquals(IMPORTANT_FOR_ACCESSIBILITY_NO, binding.ratingView.importantForAccessibility) + + val reviewContentDescription = testContext.getString(R.string.mozac_feature_addons_user_rating_count_2) + formattedRatting = String.format(reviewContentDescription, 100) + assertEquals(formattedRatting, binding.reviewCount.contentDescription) } @Test @@ -79,7 +88,7 @@ class AddonDetailsBindingDelegateTest { ratingUrl = "https://example.org/", ), ) - assertEquals("100", binding.reviewCount.text) + assertEquals("100", binding.reviewCount.text.toString()) binding.reviewCount.performClick() @@ -104,6 +113,9 @@ class AddonDetailsBindingDelegateTest { detailsBindingDelegate.bind(baseAddon) assertEquals("Nov 23, 2020", binding.lastUpdatedText.text) + val expectedContentDescription = binding.lastUpdatedLabel.text.toString() + " " + "Nov 23, 2020" + assertEquals(expectedContentDescription, binding.lastUpdatedLabel.contentDescription) + assertEquals(IMPORTANT_FOR_ACCESSIBILITY_NO, binding.lastUpdatedText.importantForAccessibility) } @Test @@ -130,6 +142,9 @@ class AddonDetailsBindingDelegateTest { assertEquals("2.0.0", binding.versionText.text) binding.versionText.performLongClick() verify { interactor.showUpdaterDialog(addon2) } + val expectedContentDescription = binding.versionLabel.text.toString() + " 2.0.0" + assertEquals(expectedContentDescription, binding.versionLabel.contentDescription) + assertEquals(IMPORTANT_FOR_ACCESSIBILITY_NO, binding.versionText.importantForAccessibility) } @Test @@ -140,6 +155,9 @@ class AddonDetailsBindingDelegateTest { assertEquals("Sarah Jane", binding.authorText.text) assertNotEquals(testContext.getColorFromAttr(R.attr.textAccent), binding.authorText.currentTextColor) + val expectedContentDescription = binding.authorLabel.text.toString() + " Sarah Jane" + assertEquals(expectedContentDescription, binding.authorLabel.contentDescription) + assertEquals(IMPORTANT_FOR_ACCESSIBILITY_NO, binding.authorText.importantForAccessibility) } @Test @@ -148,7 +166,7 @@ class AddonDetailsBindingDelegateTest { baseAddon.copy(author = Addon.Author(name = "Sarah Jane", url = "https://example.org/")), ) - assertEquals("Sarah Jane", binding.authorText.text) + assertEquals("Sarah Jane", binding.authorText.text.toString()) assertEquals(testContext.getColorFromAttr(R.attr.textAccent), binding.authorText.currentTextColor) binding.authorText.performClick() diff --git a/app/src/test/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragmentTest.kt b/app/src/test/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragmentTest.kt index 6d8871228..2f88c0817 100644 --- a/app/src/test/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragmentTest.kt +++ b/app/src/test/java/org/mozilla/fenix/addons/InstalledAddonDetailsFragmentTest.kt @@ -76,7 +76,7 @@ class InstalledAddonDetailsFragmentTest { } @Test - fun `GIVEN blocklisted addon WHEN biding the enable switch THEN disable the switch`() { + fun `GIVEN blocklisted addon WHEN binding the enable switch THEN disable the switch`() { val addon = mockk() val enableSwitch = mockk(relaxed = true) val privateBrowsingSwitch = mockk(relaxed = true) @@ -93,7 +93,7 @@ class InstalledAddonDetailsFragmentTest { } @Test - fun `GIVEN enabled addon WHEN biding the enable switch THEN do not disable the switch`() { + fun `GIVEN enabled addon WHEN binding the enable switch THEN do not disable the switch`() { val addon = mockk() val enableSwitch = mockk(relaxed = true) val privateBrowsingSwitch = mockk(relaxed = true) @@ -112,7 +112,7 @@ class InstalledAddonDetailsFragmentTest { } @Test - fun `GIVEN addon not correctly signed WHEN biding the enable switch THEN disable the switch`() { + fun `GIVEN addon not correctly signed WHEN binding the enable switch THEN disable the switch`() { val addon = mockk() val enableSwitch = mockk(relaxed = true) val privateBrowsingSwitch = mockk(relaxed = true) @@ -130,7 +130,7 @@ class InstalledAddonDetailsFragmentTest { } @Test - fun `GIVEN incompatible addon WHEN biding the enable switch THEN disable the switch`() { + fun `GIVEN incompatible addon WHEN binding the enable switch THEN disable the switch`() { val addon = mockk() val enableSwitch = mockk(relaxed = true) val privateBrowsingSwitch = mockk(relaxed = true) @@ -228,9 +228,27 @@ class InstalledAddonDetailsFragmentTest { } } + @Test + fun `GIVEN addon does not allow private browsing WHEN binding THEN update switch`() { + val addon = mockAddon() + val privateBrowsingSwitch = mockk(relaxed = true) + + every { fragment.providePrivateBrowsingSwitch() } returns privateBrowsingSwitch + every { addon.incognito } returns Addon.Incognito.NOT_ALLOWED + every { fragment.addon } returns addon + every { fragment.context } returns testContext + + fragment.bindAllowInPrivateBrowsingSwitch() + + verify { privateBrowsingSwitch.isEnabled = false } + verify { privateBrowsingSwitch.isChecked = false } + verify { privateBrowsingSwitch.text = "Not allowed in private windows" } + } + private fun mockAddon(): Addon { val addon: Addon = mockk() every { addon.id } returns "some-addon-id" + every { addon.incognito } returns Addon.Incognito.SPANNING every { addon.isEnabled() } returns true every { addon.isDisabledAsBlocklisted() } returns false every { addon.isDisabledAsNotCorrectlySigned() } returns false diff --git a/app/src/test/java/org/mozilla/fenix/bindings/BrowserStoreBindingTest.kt b/app/src/test/java/org/mozilla/fenix/bindings/BrowserStoreBindingTest.kt new file mode 100644 index 000000000..0aaf57ca0 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/bindings/BrowserStoreBindingTest.kt @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.bindings + +import mozilla.components.browser.state.action.TabListAction +import mozilla.components.browser.state.state.BrowserState +import mozilla.components.browser.state.state.createTab +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.support.test.ext.joinBlocking +import mozilla.components.support.test.rule.MainCoroutineRule +import mozilla.components.support.test.rule.runTestOnMain +import org.junit.Rule +import org.junit.Test +import org.mockito.Mockito.never +import org.mockito.Mockito.spy +import org.mockito.Mockito.verify +import org.mozilla.fenix.components.AppStore +import org.mozilla.fenix.components.appstate.AppAction +import org.mozilla.fenix.components.appstate.AppState + +class BrowserStoreBindingTest { + + @get:Rule + val coroutineRule = MainCoroutineRule() + + lateinit var browserStore: BrowserStore + lateinit var appStore: AppStore + + private val tabId1 = "1" + private val tabId2 = "2" + private val tab1 = createTab(url = tabId1, id = tabId1) + private val tab2 = createTab(url = tabId2, id = tabId2) + + @Test + fun `WHEN selected tab changes THEN app action dispatched with update`() = runTestOnMain { + appStore = spy(AppStore()) + browserStore = BrowserStore( + BrowserState( + tabs = listOf(tab1, tab2), + selectedTabId = tabId1, + ), + ) + + val binding = BrowserStoreBinding(browserStore, appStore) + binding.start() + browserStore.dispatch(TabListAction.SelectTabAction(tabId2)).joinBlocking() + + // consume initial state + verify(appStore).dispatch(AppAction.SelectedTabChanged(tab1)) + // verify response to Browser Store dispatch + verify(appStore).dispatch(AppAction.SelectedTabChanged(tab2)) + } + + @Test + fun `GIVEN selected tab id is set WHEN update is observed with same id THEN update is ignored`() { + appStore = spy( + AppStore( + AppState( + selectedTabId = tabId2, + ), + ), + ) + browserStore = BrowserStore( + BrowserState( + tabs = listOf(tab1, tab2), + selectedTabId = tabId2, + ), + ) + + val binding = BrowserStoreBinding(browserStore, appStore) + binding.start() + browserStore.dispatch(TabListAction.SelectTabAction(tabId2)).joinBlocking() + + // the selected tab should only be dispatched on initialization + verify(appStore, never()).dispatch(AppAction.SelectedTabChanged(tab2)) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt b/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt index 4670b824b..ac0a109f9 100644 --- a/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt +++ b/app/src/test/java/org/mozilla/fenix/browser/BaseBrowserFragmentTest.kt @@ -20,8 +20,8 @@ import mozilla.components.browser.state.state.createTab import mozilla.components.concept.engine.EngineView import mozilla.components.concept.engine.permission.SitePermissions import mozilla.components.feature.contextmenu.ContextMenuCandidate -import mozilla.components.feature.session.behavior.EngineViewBrowserToolbarBehavior import mozilla.components.ui.widgets.VerticalSwipeRefreshLayout +import mozilla.components.ui.widgets.behavior.EngineViewClippingBehavior import org.junit.Before import org.junit.Test import org.mozilla.fenix.ext.components @@ -92,17 +92,17 @@ class BaseBrowserFragmentTest { } @Test - fun `initializeEngineView should set EngineViewBrowserToolbarBehavior when dynamic toolbar is enabled`() { + fun `initializeEngineView should set EngineViewClippingBehavior when dynamic toolbar is enabled`() { every { settings.shouldUseFixedTopToolbar } returns false every { settings.isDynamicToolbarEnabled } returns true val params: CoordinatorLayout.LayoutParams = mockk(relaxed = true) every { params.behavior } returns mockk(relaxed = true) every { swipeRefreshLayout.layoutParams } returns params - val behavior = slot() + val behavior = slot() fragment.initializeEngineView(13) - // EngineViewBrowserToolbarBehavior constructor parameters are not properties, we cannot check them. + // EngineViewClippingBehavior constructor parameters are not properties, we cannot check them. // Ensure just that the right behavior is set. verify { params.behavior = capture(behavior) } } diff --git a/app/src/test/java/org/mozilla/fenix/components/UrlRequestInterceptorTest.kt b/app/src/test/java/org/mozilla/fenix/components/UrlRequestInterceptorTest.kt index 058c47e24..f323adb3c 100644 --- a/app/src/test/java/org/mozilla/fenix/components/UrlRequestInterceptorTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/UrlRequestInterceptorTest.kt @@ -8,6 +8,7 @@ import io.mockk.mockk import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineSession.LoadUrlFlags import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.ALLOW_ADDITIONAL_HEADERS +import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.BYPASS_CACHE import mozilla.components.concept.engine.EngineSession.LoadUrlFlags.Companion.LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE import mozilla.components.concept.engine.request.RequestInterceptor import org.junit.Assert.assertEquals @@ -61,13 +62,19 @@ class UrlRequestInterceptorTest { assertFalse( urlRequestInterceptor.shouldInterceptRequest( - uri = "https://getpocket.com", + uri = "https://www.google.com", isSubframeRequest = false, ), ) - assertFalse( + assertTrue( urlRequestInterceptor.shouldInterceptRequest( - uri = "https://www.google.com", + uri = "https://www.google.com/webhp", + isSubframeRequest = false, + ), + ) + assertTrue( + urlRequestInterceptor.shouldInterceptRequest( + uri = "https://www.google.com/preferences", isSubframeRequest = false, ), ) @@ -89,6 +96,13 @@ class UrlRequestInterceptorTest { isSubframeRequest = false, ), ) + + assertFalse( + urlRequestInterceptor.shouldInterceptRequest( + uri = "https://getpocket.com", + isSubframeRequest = false, + ), + ) assertFalse( urlRequestInterceptor.shouldInterceptRequest( uri = "https://www.google.com/search?q=blue", @@ -114,13 +128,45 @@ class UrlRequestInterceptorTest { } @Test - fun `WHEN a Google request is loaded THEN request is not intercepted`() { - val uri = "https://www.google.com" - val response = getUrlRequestInterceptor().onLoadRequest( - uri = uri, + fun `WHEN a Google preferences request is loaded THEN request is intercepted`() { + val uri = "https://www.google.com/preferences" + + assertEquals( + RequestInterceptor.InterceptionResponse.Url( + url = uri, + flags = LoadUrlFlags.select( + LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE, + ALLOW_ADDITIONAL_HEADERS, + ), + additionalHeaders = mapOf( + "X-Search-Subdivision" to "0", + ), + ), + getUrlRequestInterceptor().onLoadRequest( + uri = uri, + ), ) + } - assertNull(response) + @Test + fun `WHEN a Google request end in #ip=1 is loaded THEN request bypass cache`() { + val uri = "https://www.google.com/search?q=test&ie=utf-8#ip=1" + assertEquals( + RequestInterceptor.InterceptionResponse.Url( + url = uri, + flags = LoadUrlFlags.select( + BYPASS_CACHE, + LOAD_FLAGS_BYPASS_LOAD_URI_DELEGATE, + ALLOW_ADDITIONAL_HEADERS, + ), + additionalHeaders = mapOf( + "X-Search-Subdivision" to "0", + ), + ), + getUrlRequestInterceptor().onLoadRequest( + uri = uri, + ), + ) } @Test diff --git a/app/src/test/java/org/mozilla/fenix/components/appstate/AppStoreReducerTest.kt b/app/src/test/java/org/mozilla/fenix/components/appstate/AppStoreReducerTest.kt index 7be038c02..2997e14c0 100644 --- a/app/src/test/java/org/mozilla/fenix/components/appstate/AppStoreReducerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/appstate/AppStoreReducerTest.kt @@ -5,10 +5,12 @@ package org.mozilla.fenix.components.appstate import io.mockk.mockk +import mozilla.components.browser.state.state.createTab import mozilla.components.lib.crash.Crash.NativeCodeCrash import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test +import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.components.appstate.AppAction.AddNonFatalCrash import org.mozilla.fenix.components.appstate.AppAction.RemoveAllNonFatalCrashes import org.mozilla.fenix.components.appstate.AppAction.RemoveNonFatalCrash @@ -69,4 +71,49 @@ class AppStoreReducerTest { assertTrue(updatedState.nonFatalCrashes.isEmpty()) } + + @Test + fun `GIVEN mode is private WHEN selected tab changes to normal mode THEN state is updated to normal mode`() { + val initialState = AppState( + selectedTabId = null, + mode = BrowsingMode.Private, + ) + + val updatedState = AppStoreReducer.reduce( + initialState, + AppAction.SelectedTabChanged(createTab("", private = false)), + ) + + assertFalse(updatedState.mode.isPrivate) + } + + @Test + fun `GIVEN mode is normal WHEN selected tab changes to private mode THEN state is updated to private mode`() { + val initialState = AppState( + selectedTabId = null, + mode = BrowsingMode.Normal, + ) + + val updatedState = AppStoreReducer.reduce( + initialState, + AppAction.SelectedTabChanged(createTab("", private = true)), + ) + + assertTrue(updatedState.mode.isPrivate) + } + + @Test + fun `WHEN selected tab changes to a tab in the same mode THEN mode is unchanged`() { + val initialState = AppState( + selectedTabId = null, + mode = BrowsingMode.Normal, + ) + + val updatedState = AppStoreReducer.reduce( + initialState, + AppAction.SelectedTabChanged(createTab("", private = false)), + ) + + assertFalse(updatedState.mode.isPrivate) + } } diff --git a/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarViewTest.kt b/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarViewTest.kt index 8ad2f6854..2fad1a270 100644 --- a/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarViewTest.kt +++ b/app/src/test/java/org/mozilla/fenix/components/toolbar/BrowserToolbarViewTest.kt @@ -11,9 +11,9 @@ import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import mozilla.components.browser.toolbar.BrowserToolbar -import mozilla.components.browser.toolbar.behavior.BrowserToolbarBehavior import mozilla.components.lib.publicsuffixlist.PublicSuffixList import mozilla.components.support.test.robolectric.testContext +import mozilla.components.ui.widgets.behavior.EngineViewScrollingBehavior import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Before @@ -22,20 +22,20 @@ import org.junit.runner.RunWith import org.mozilla.fenix.ext.components import org.mozilla.fenix.helpers.FenixRobolectricTestRunner import org.mozilla.fenix.utils.Settings -import mozilla.components.browser.toolbar.behavior.ToolbarPosition as MozacToolbarPosition +import mozilla.components.ui.widgets.behavior.ViewPosition as MozacToolbarPosition @RunWith(FenixRobolectricTestRunner::class) class BrowserToolbarViewTest { private lateinit var toolbarView: BrowserToolbarView private lateinit var toolbar: BrowserToolbar - private lateinit var behavior: BrowserToolbarBehavior + private lateinit var behavior: EngineViewScrollingBehavior private lateinit var settings: Settings @Before fun setup() { toolbar = BrowserToolbar(testContext) toolbar.layoutParams = CoordinatorLayout.LayoutParams(100, 100) - behavior = spyk(BrowserToolbarBehavior(testContext, null, MozacToolbarPosition.BOTTOM)) + behavior = spyk(EngineViewScrollingBehavior(testContext, null, MozacToolbarPosition.BOTTOM)) (toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = behavior settings = mockk(relaxed = true) every { testContext.components.useCases } returns mockk(relaxed = true) @@ -217,7 +217,7 @@ class BrowserToolbarViewTest { } @Test - fun `setDynamicToolbarBehavior should set a BrowserToolbarBehavior for the bottom toolbar`() { + fun `setDynamicToolbarBehavior should set a ViewHideOnScrollBehavior for the bottom toolbar`() { val toolbarViewSpy = spyk(toolbarView) (toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = null @@ -227,7 +227,7 @@ class BrowserToolbarViewTest { } @Test - fun `setDynamicToolbarBehavior should set a BrowserToolbarBehavior for the top toolbar`() { + fun `setDynamicToolbarBehavior should set a ViewHideOnScrollBehavior for the top toolbar`() { val toolbarViewSpy = spyk(toolbarView) (toolbar.layoutParams as CoordinatorLayout.LayoutParams).behavior = null diff --git a/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsControllerTest.kt b/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsControllerTest.kt deleted file mode 100644 index a9b580061..000000000 --- a/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsControllerTest.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.components.translations - -import mozilla.components.browser.state.selector.findTab -import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.state.TabSessionState -import mozilla.components.browser.state.state.TranslationsState -import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.concept.engine.translate.DetectedLanguages -import mozilla.components.concept.engine.translate.TranslationEngineState -import mozilla.components.concept.engine.translate.TranslationOptions -import mozilla.components.feature.session.SessionUseCases -import mozilla.components.support.test.mock -import mozilla.components.support.test.whenever -import org.junit.Assert.assertNotNull -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.spy -import org.mockito.Mockito.verify -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner -import org.mozilla.fenix.translations.TranslationsController - -@RunWith(FenixRobolectricTestRunner::class) -class TranslationsControllerTest { - - val tab: TabSessionState = spy( - createTab( - url = "https://www.firefox.com", - title = "Firefox", - id = "1", - ), - ) - private val tabs = spy(listOf(tab)) - private val browserState = spy(BrowserState(tabs = tabs)) - private val browserStore = spy(BrowserStore(browserState)) - - private val translationsUseCase: SessionUseCases.TranslateUseCase = mock() - private val translationsController = spy(TranslationsController(translationUseCase = translationsUseCase, browserStore = browserStore, tabId = tab.id)) - - @Test - fun `Controller translate called the translate use case as expected`() { - val from = "en" - val to = "es" - val options = TranslationOptions(false) - translationsController.translate(tab.id, from, to, options) - verify(translationsUseCase).invoke(tab.id, from, to, options) - } - - @Test - fun `Controller translate called the translate use case as expected when languages were null`() { - val mockFrom = "es" - val mockTo = "en" - val mockDetectedLanguages = DetectedLanguages( - documentLangTag = mockFrom, - supportedDocumentLang = true, - userPreferredLangTag = mockTo, - ) - whenever(translationsController.getDetectedLanguages()).thenReturn(mockDetectedLanguages) - - val from = null - val to = null - val options = TranslationOptions(false) - translationsController.translate(tab.id, from, to, options) - - verify(translationsUseCase).invoke(tab.id, mockFrom, mockTo, options) - } - - @Test - fun `Controller detectedLanguages retrieved the languages as expected`() { - val mockFrom = "es" - val mockTo = "en" - val mockDetectedLanguages = DetectedLanguages( - documentLangTag = mockFrom, - supportedDocumentLang = true, - userPreferredLangTag = mockTo, - ) - val mockState = TranslationsState( - translationEngineState = TranslationEngineState(mockDetectedLanguages), - ) - - whenever(browserState.findTab(tab.id)?.translationsState).thenReturn(mockState) - - val test = translationsController.getDetectedLanguages() - - assertNotNull(test) - assertTrue(test?.documentLangTag == mockDetectedLanguages.documentLangTag) - assertTrue(test?.userPreferredLangTag == mockDetectedLanguages.userPreferredLangTag) - } -} diff --git a/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsInteractorTest.kt b/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsInteractorTest.kt deleted file mode 100644 index e367aa056..000000000 --- a/app/src/test/java/org/mozilla/fenix/components/translations/TranslationsInteractorTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.fenix.components.translations - -import mozilla.components.browser.state.state.BrowserState -import mozilla.components.browser.state.state.TabSessionState -import mozilla.components.browser.state.state.createTab -import mozilla.components.browser.state.store.BrowserStore -import mozilla.components.concept.engine.translate.DetectedLanguages -import mozilla.components.concept.engine.translate.TranslationOptions -import mozilla.components.feature.session.SessionUseCases -import mozilla.components.support.test.mock -import mozilla.components.support.test.whenever -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.never -import org.mockito.Mockito.spy -import org.mockito.Mockito.verify -import org.mozilla.fenix.helpers.FenixRobolectricTestRunner -import org.mozilla.fenix.translations.TranslationsController -import org.mozilla.fenix.translations.TranslationsInteractor - -@RunWith(FenixRobolectricTestRunner::class) -class TranslationsInteractorTest { - - val tab: TabSessionState = spy( - createTab( - url = "https://www.firefox.com", - title = "Firefox", - id = "1", - ), - ) - private val tabs = spy(listOf(tab)) - private val browserState = spy(BrowserState(tabs = tabs)) - private val browserStore = spy(BrowserStore(browserState)) - - private val translationsUseCase: SessionUseCases.TranslateUseCase = mock() - private val translationsController = spy(TranslationsController(translationUseCase = translationsUseCase, browserStore = browserStore, tabId = tab.id)) - private val interactor = TranslationsInteractor(translationsController) - - @Test - fun `Interactor onTranslate called the translate controller as expected`() { - val from = "en" - val to = "es" - val options = TranslationOptions(false) - interactor.onTranslate(tab.id, from, to, options) - verify(translationsController).translate(tab.id, from, to, options) - verify(translationsController, never()).getDetectedLanguages() - } - - @Test - fun `Interactor onTranslate called the translate controller as expected when languages are null`() { - val mockFrom = "es" - val mockTo = "en" - val mockDetectedLanguages = DetectedLanguages( - documentLangTag = mockFrom, - supportedDocumentLang = true, - userPreferredLangTag = mockTo, - ) - whenever(translationsController.getDetectedLanguages()).thenReturn(mockDetectedLanguages) - - val from = null - val to = null - val options = TranslationOptions(false) - interactor.onTranslate(tab.id, from, to, options) - verify(translationsController).translate(tab.id, from, to, options) - verify(translationsController).getDetectedLanguages() - verify(translationsUseCase).invoke(tab.id, mockFrom, mockTo, options) - } - - @Test - fun `Interactor detectedLanguages called the controller to pull detected languages`() { - interactor.detectedLanguages() - verify(translationsController).getDetectedLanguages() - } -} diff --git a/app/src/test/java/org/mozilla/fenix/compose/ext/IntTest.kt b/app/src/test/java/org/mozilla/fenix/compose/ext/IntTest.kt new file mode 100644 index 000000000..c7c68f7eb --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/compose/ext/IntTest.kt @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.compose.ext + +import org.junit.Assert.assertEquals +import org.junit.Test +import java.util.Locale as JavaLocale + +class IntTest { + + @Test + fun `WHEN the language is Arabic THEN translate the number to the proper symbol of that locale`() { + val expected = "٥" + val numberUnderTest = 5 + + JavaLocale.setDefault(JavaLocale("ar")) + + assertEquals(expected, numberUnderTest.toLocaleString()) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/perf/StartupPathProviderTest.kt b/app/src/test/java/org/mozilla/fenix/perf/StartupPathProviderTest.kt index 8d22d86d3..ad14ebc0c 100644 --- a/app/src/test/java/org/mozilla/fenix/perf/StartupPathProviderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/perf/StartupPathProviderTest.kt @@ -108,12 +108,12 @@ class StartupPathProviderTest { } @Test - fun `GIVEN the app is launched to the homescreen and stopped WHEN getting the start up path THEN it is not set`() { + fun `GIVEN the app is launched to the homescreen with MAIN and stopped WHEN getting the start up path THEN it set to MAIN`() { every { intent.action } returns Intent.ACTION_MAIN launchApp(intent) stopLaunchedApp() - assertEquals(StartupPath.NOT_SET, provider.startupPathForActivity) + assertEquals(StartupPath.MAIN, provider.startupPathForActivity) } @Test @@ -129,13 +129,13 @@ class StartupPathProviderTest { } @Test - fun `GIVEN the app is launched to the homescreen, stopped, and relaunched warm from the app switcher WHEN getting the start up path THEN it is not set`() { + fun `GIVEN the app is launched to the homescreen with MAIN, stopped, and relaunched warm from the app switcher WHEN getting the start up path THEN it set to MAIN'`() { every { intent.action } returns Intent.ACTION_MAIN launchApp(intent) stopLaunchedApp() startStoppedAppFromAppSwitcher() - assertEquals(StartupPath.NOT_SET, provider.startupPathForActivity) + assertEquals(StartupPath.MAIN, provider.startupPathForActivity) } @Test @@ -159,7 +159,7 @@ class StartupPathProviderTest { } @Test - fun `GIVEN the app is launched, stopped, started from the app switcher and receives an intent in the foreground WHEN getting the start up path THEN it returns not set`() { + fun `GIVEN the app is launched with MAIN, stopped, started from the app switcher and receives an intent in the foreground WHEN getting the start up path THEN it returns MAIN`() { every { intent.action } returns Intent.ACTION_MAIN launchApp(intent) stopLaunchedApp() @@ -167,7 +167,7 @@ class StartupPathProviderTest { every { intent.action } returns Intent.ACTION_VIEW receiveIntentInForeground(intent) - assertEquals(StartupPath.NOT_SET, provider.startupPathForActivity) + assertEquals(StartupPath.MAIN, provider.startupPathForActivity) } private fun launchApp(intent: Intent) { diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt index 0cff849d0..3de461972 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogControllerTest.kt @@ -313,6 +313,10 @@ class SearchDialogControllerTest { assertTrue(clearToolbarFocusInvoked) assertTrue(dismissAndGoBack) + + middleware.assertLastAction(AwesomeBarAction.EngagementFinished::class) { action -> + assertTrue(action.abandoned) + } } @Test diff --git a/app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt b/app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt index c7aa3e72b..ff71df0ff 100644 --- a/app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt +++ b/app/src/test/java/org/mozilla/fenix/search/SearchDialogFragmentTest.kt @@ -50,14 +50,14 @@ internal class SearchDialogFragmentTest { @Test fun `GIVEN this is the only visible fragment WHEN asking for the previous destination THEN return null`() { - every { navController.backQueue } returns ArrayDeque(listOf(getDestination(fragmentName))) + every { navController.currentBackStack.value } returns ArrayDeque(listOf(getDestination(fragmentName))) assertNull(fragment.getPreviousDestination()) } @Test fun `GIVEN this and FragmentB on top of this are visible WHEN asking for the previous destination THEN return null`() { - every { navController.backQueue } returns ArrayDeque( + every { navController.currentBackStack.value } returns ArrayDeque( listOf( getDestination(fragmentName), getDestination("FragmentB"), @@ -70,7 +70,7 @@ internal class SearchDialogFragmentTest { @Test fun `GIVEN FragmentA, this and FragmentB are visible WHEN asking for the previous destination THEN return FragmentA`() { val fragmentADestination = getDestination("FragmentA") - every { navController.backQueue } returns ArrayDeque( + every { navController.currentBackStack.value } returns ArrayDeque( listOf( fragmentADestination, getDestination(fragmentName), @@ -84,7 +84,7 @@ internal class SearchDialogFragmentTest { @Test fun `GIVEN FragmentA and this on top of it are visible WHEN asking for the previous destination THEN return FragmentA`() { val fragmentADestination = getDestination("FragmentA") - every { navController.backQueue } returns ArrayDeque( + every { navController.currentBackStack.value } returns ArrayDeque( listOf( fragmentADestination, getDestination(fragmentName), diff --git a/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedDeviceTabsTest.kt b/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedDeviceTabsTest.kt index f99f36893..acf66374b 100644 --- a/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedDeviceTabsTest.kt +++ b/app/src/test/java/org/mozilla/fenix/sync/ext/SyncedDeviceTabsTest.kt @@ -43,6 +43,7 @@ class SyncedDeviceTabsTest { ), active = 0, lastUsed = 0L, + inactive = false, ), ), ) @@ -64,6 +65,7 @@ class SyncedDeviceTabsTest { ), active = 0, lastUsed = 0L, + inactive = false, ), Tab( history = listOf( @@ -75,6 +77,7 @@ class SyncedDeviceTabsTest { ), active = 0, lastUsed = 0L, + inactive = false, ), ), ) diff --git a/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt b/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt index 4c8eace86..dfbb1ba68 100644 --- a/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt +++ b/app/src/test/java/org/mozilla/fenix/telemetry/TelemetryMiddlewareTest.kt @@ -86,6 +86,7 @@ class TelemetryMiddlewareTest { val engine: Engine = mockk() every { engine.enableExtensionProcessSpawning() } just runs every { engine.disableExtensionProcessSpawning() } just runs + every { engine.isTranslationsEngineSupported(any(), any()) } just runs store = BrowserStore( middleware = listOf(telemetryMiddleware) + EngineMiddleware.create(engine), initialState = BrowserState(), diff --git a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperDownloaderTest.kt b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperDownloaderTest.kt index 821f523b8..2736ca062 100644 --- a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperDownloaderTest.kt +++ b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperDownloaderTest.kt @@ -141,5 +141,6 @@ class WallpaperDownloaderTest { private fun Wallpaper.generateRequest(type: String) = Request( url = "$remoteHost/${collection.name}/$name/$type.png", method = Request.Method.GET, + conservative = true, ) } diff --git a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcherTest.kt b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcherTest.kt index ff1ad66ff..35fcd694e 100644 --- a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcherTest.kt +++ b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpaperMetadataFetcherTest.kt @@ -29,6 +29,7 @@ class WallpaperMetadataFetcherTest { url = BuildConfig.WALLPAPER_URL.substringBefore("android") + "metadata/v$currentJsonVersion/wallpapers.json", method = Request.Method.GET, + conservative = true, ) private val mockResponse = mockk() private val mockClient = mockk { diff --git a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpapersUseCasesTest.kt b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpapersUseCasesTest.kt index e2716f300..858f2c2db 100644 --- a/app/src/test/java/org/mozilla/fenix/wallpapers/WallpapersUseCasesTest.kt +++ b/app/src/test/java/org/mozilla/fenix/wallpapers/WallpapersUseCasesTest.kt @@ -4,7 +4,7 @@ package org.mozilla.fenix.wallpapers -import android.content.Context +import android.content.res.Configuration import io.mockk.Runs import io.mockk.coEvery import io.mockk.coVerify @@ -31,7 +31,8 @@ import org.mozilla.fenix.wallpapers.LegacyWallpaperMigration.Companion.TURNING_R import org.mozilla.fenix.wallpapers.LegacyWallpaperMigration.Companion.TURNING_RED_PANDA_WALLPAPER_NAME import org.mozilla.fenix.wallpapers.LegacyWallpaperMigration.Companion.TURNING_RED_WALLPAPER_TEXT_COLOR import java.io.File -import java.util.* +import java.util.Calendar +import java.util.Date import kotlin.random.Random class WallpapersUseCasesTest { @@ -496,18 +497,33 @@ class WallpapersUseCasesTest { } @Test - fun `GIVEN the context WHEN bitmap is loaded THEN loadWallpaperFromDisk method is called with the correct context and wallpaper`() = + fun `GIVEN the portrait orientation WHEN bitmap is loaded THEN loadWallpaperFromDisk method is called with the correct wallpaper and orientation`() = runTest { val wallpaper: Wallpaper = mockk { every { name } returns "test" } - val context = mockk(relaxed = true) + val orientation = Configuration.ORIENTATION_PORTRAIT val defaultLoadBitmapUseCase = spyk(WallpapersUseCases.DefaultLoadBitmapUseCase { mockFolder }) - coEvery { defaultLoadBitmapUseCase.loadWallpaperFromDisk(context, wallpaper) } returns mockk() + coEvery { defaultLoadBitmapUseCase.loadWallpaperFromDisk(wallpaper, orientation) } returns mockk() - defaultLoadBitmapUseCase.invoke(context, wallpaper) + defaultLoadBitmapUseCase.invoke(wallpaper, orientation) - coVerify { defaultLoadBitmapUseCase.loadWallpaperFromDisk(context, wallpaper) } + coVerify { defaultLoadBitmapUseCase.loadWallpaperFromDisk(wallpaper, orientation) } + } + + @Test + fun `GIVEN the landscape orientation WHEN bitmap is loaded THEN loadWallpaperFromDisk method is called with the correct wallpaper and orientation`() = + runTest { + val wallpaper: Wallpaper = mockk { + every { name } returns "test" + } + val orientation = Configuration.ORIENTATION_LANDSCAPE + val defaultLoadBitmapUseCase = spyk(WallpapersUseCases.DefaultLoadBitmapUseCase { mockFolder }) + coEvery { defaultLoadBitmapUseCase.loadWallpaperFromDisk(wallpaper, orientation) } returns mockk() + + defaultLoadBitmapUseCase.invoke(wallpaper, orientation) + + coVerify { defaultLoadBitmapUseCase.loadWallpaperFromDisk(wallpaper, orientation) } } private enum class TimeRelation { diff --git a/automation/taskcluster/androidTest/flank-arm-start-test-robo.yml b/automation/taskcluster/androidTest/flank-arm-start-test-robo.yml new file mode 100644 index 000000000..503eae25f --- /dev/null +++ b/automation/taskcluster/androidTest/flank-arm-start-test-robo.yml @@ -0,0 +1,27 @@ +# Google Cloud Documentation: https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run +# Flank Documentation: https://flank.github.io/flank/ +gcloud: + results-bucket: fenix_test_artifacts + record-video: false + timeout: 5m + async: false + + app: /app/path + + auto-google-login: false + use-orchestrator: true + environment-variables: + clearPackageData: true + + device: + - model: MediumPhone.arm + version: 30 + locale: en_US + + type: robo + +flank: + project: GOOGLE_PROJECT + num-test-runs: 1 + output-style: compact + full-junit-result: true diff --git a/automation/taskcluster/androidTest/lib/testrail_conn.py b/automation/taskcluster/androidTest/lib/testrail_conn.py deleted file mode 100644 index 41d1f2667..000000000 --- a/automation/taskcluster/androidTest/lib/testrail_conn.py +++ /dev/null @@ -1,102 +0,0 @@ -# flake8: noqa -"""TestRail API binding for Python 3.x. - -(API v2, available since TestRail 3.0) - -Compatible with TestRail 3.0 and later. - -Learn more: - -http://docs.gurock.com/testrail-api2/start -http://docs.gurock.com/testrail-api2/accessing - -Copyright Gurock Software GmbH. See license.md for details. -""" - -import base64 -import json - -import requests - - -class APIClient: - def __init__(self, base_url): - self.user = '' - self.password = '' - if not base_url.endswith('/'): - base_url += '/' - self.__url = base_url + 'index.php?/api/v2/' - - def send_get(self, uri, filepath=None): - """Issue a GET request (read) against the API. - - Args: - uri: The API method to call including parameters, e.g. get_case/1. - filepath: The path and file name for attachment download; used only - for 'get_attachment/:attachment_id'. - - Returns: - A dict containing the result of the request. - """ - return self.__send_request('GET', uri, filepath) - - def send_post(self, uri, data): - """Issue a POST request (write) against the API. - - Args: - uri: The API method to call, including parameters, e.g. add_case/1. - data: The data to submit as part of the request as a dict; strings - must be UTF-8 encoded. If adding an attachment, must be the - path to the file. - - Returns: - A dict containing the result of the request. - """ - return self.__send_request('POST', uri, data) - - def __send_request(self, method, uri, data): - url = self.__url + uri - - auth = str( - base64.b64encode( - bytes('%s:%s' % (self.user, self.password), 'utf-8') - ), - 'ascii' - ).strip() - headers = {'Authorization': 'Basic ' + auth} - - if method == 'POST': - if uri[:14] == 'add_attachment': # add_attachment API method - files = {'attachment': (open(data, 'rb'))} - response = requests.post(url, headers=headers, files=files) - files['attachment'].close() - else: - headers['Content-Type'] = 'application/json' - payload = bytes(json.dumps(data), 'utf-8') - response = requests.post(url, headers=headers, data=payload) - else: - headers['Content-Type'] = 'application/json' - response = requests.get(url, headers=headers) - - if response.status_code > 201: - try: - error = response.json() - except requests.exceptions.HTTPError: # response.content not formatted as JSON - error = str(response.content) - raise APIError('TestRail API returned HTTP %s (%s)' % (response.status_code, error)) - else: - if uri[:15] == 'get_attachment/': # Expecting file, not JSON - try: - open(data, 'wb').write(response.content) - return (data) - except FileNotFoundError: - return ("Error saving attachment.") - else: - try: - return response.json() - except requests.exceptions.HTTPError: - return {} - - -class APIError(Exception): - pass diff --git a/automation/taskcluster/androidTest/testrail.py b/automation/taskcluster/androidTest/testrail.py deleted file mode 100644 index b75efa7c3..000000000 --- a/automation/taskcluster/androidTest/testrail.py +++ /dev/null @@ -1,154 +0,0 @@ -""" -This Python script is designed to automate the process of creating milestones -and test runs in TestRail, and updating test cases based on the results of -automated smoke tests for different product releases. - -Below is a summary of its functionality in order of execution: - -1. Environment and Credentials Setup: - - Imports necessary libraries and modules. - - Loads environmental variables from "execution_metadata.env". - - Reads and processes TestRail credentials from '.testrail_credentials.json'. - -2. Environment Variables Validation: - - Retrieves and validates several environment variables like `PRODUCT_TYPE`, - `RELEASE_TYPE`, `VERSION_NUMBER`, and `TEST_STATUS`. - - Ensures `TEST_STATUS` is either 'PASS' or 'FAIL'. - -3. Utility Functions: - - `parse_release_number()`: Parses the version number to extract a specific part. - - `build_milestone_name()`: Constructs a milestone name based on product type, - release type, and version number. - - `build_milestone_description()`: Creates a detailed description for the milestone - including the current date and placeholders for various testing statuses. - -4. TestRail Integration: - - Defines a `TestRail` class that handles interactions with the TestRail API. - - Includes methods to create milestones, create test runs, and update test cases. - -5. Main Execution: - - Checks if `TEST_STATUS` is 'PASS'. If not, it raises an error to trigger a Slack notification. - - Sets parameters for a demo TestRail project. - - Instantiates the `TestRail` class. - - Creates a milestone in TestRail and retrieves its ID. - - Creates test runs for each device/API combination (currently hardcoded for phase 1 testing) - and updates test cases to 'passed' status. - -6. Phase 1 and Phase 2 Notes: - - The script is currently in Phase 1, where certain values are hardcoded for testing. - - In Phase 2, these hardcoded values will be parameterized for broader usage. -""" - - -import json -import os -import textwrap -from lib.testrail_conn import APIClient -from dotenv import load_dotenv -from datetime import datetime - -try: - load_dotenv("execution_metadata.env") # Attempt to load .env file -except FileNotFoundError: - raise FileNotFoundError("The .env file was not found.") -except Exception as e: - raise Exception(f"An error occurred while loading the .env file: {e}") - -try: - with open('.testrail_credentials.json', 'r') as file: - secret = json.load(file) - TESTRAIL_HOST = secret['host'] - TESTRAIL_USERNAME = secret['username'] - TESTRAIL_PASSWORD = secret['password'] -except json.JSONDecodeError as e: - raise ValueError("Failed to load testrail credentials : {e}") - -try: - PRODUCT_TYPE = os.environ["PRODUCT_TYPE"] - RELEASE_TYPE = os.environ["RELEASE_TYPE"] - VERSION_NUMBER = os.environ["MOBILE_HEAD_REF"] - TEST_STATUS = os.environ["TEST_STATUS"] - - if TEST_STATUS not in ('PASS', 'FAIL'): - raise ValueError(f"ERROR: Invalid TEST_STATUS value: {TEST_STATUS}") -except KeyError as e: - raise ValueError(f"ERROR: Missing Environment Variable: {e}") - -def parse_release_number(VERSION_NUMBER): - parts = VERSION_NUMBER.split('_') - return parts[1] - -def build_milestone_name(product_type, release_type, version_number): - return f"Automated smoke testing sign-off - {product_type} {release_type} {version_number}" - -def build_milestone_description(milestone_name): - current_date = datetime.now() - formatted_date = current_date = current_date.strftime("%B %d, %Y") - return textwrap.dedent(f""" - RELEASE: {milestone_name}\n\n\ - RELEASE_TAG_URL: https://github.com/mozilla-mobile/firefox-android/releases\n\n\ - RELEASE_DATE: {formatted_date}\n\n\ - TESTING_STATUS: [ TBD ]\n\n\ - QA_RECOMMENDATION:[ TBD ]\n\n\ - QA_RECOMENTATION_VERBOSE: \n\n\ - TESTING_SUMMARY\n\n\ - Known issues: n/a\n\ - New issue: n/a\n\ - Verified issue: - """) - -class TestRail(): - - def __init__(self): - try: - self.client = APIClient(TESTRAIL_HOST) - self.client.user = TESTRAIL_USERNAME - self.client.password = TESTRAIL_PASSWORD - except KeyError as e: - raise ValueError(f"ERROR: Missing Testrail Env Var: {e}") - - # Public Methods - - def create_milestone(self, testrail_project_id, title, description): - data = {"name": title, "description": description} - return self.client.send_post(f'add_milestone/{testrail_project_id}', data) - - def create_test_run(self, testrail_project_id, testrail_milestone_id, name_run, testrail_suite_id): - data = {"name": name_run, "milestone_id": testrail_milestone_id, "suite_id": testrail_suite_id} - return self.client.send_post(f'add_run/{testrail_project_id}', data) - - def update_test_cases_to_passed(self, testrail_project_id, testrail_run_id, testrail_suite_id): - test_cases = self._get_test_cases(testrail_project_id, testrail_suite_id) - data = { "results": [{"case_id": test_case['id'], "status_id": 1} for test_case in test_cases]} - return testrail._update_test_run_results(testrail_run_id, data) - - # Private Methods - - def _get_test_cases(self, testrail_project_id, testrail_test_suite_id): - return self.client.send_get(f'get_cases/{testrail_project_id}&suite_id={testrail_test_suite_id}') - - def _update_test_run_results(self, testrail_run_id, data): - return self.client.send_post(f'add_results_for_cases/{testrail_run_id}', data) - -if __name__ == "__main__": - if TEST_STATUS != 'PASS': - raise ValueError("Tests failed. Sending Slack Notification....") - - # There are for a dummy Testrail project used for Phase 1 testing of this script - # They will be parameterized during Phase 2 of script hardening - PROJECT_ID = 53 # Firefox for FireTV - TEST_SUITE_ID = 45442 # Demo Test Suite - - testrail = TestRail() - milestone_name = build_milestone_name(PRODUCT_TYPE, RELEASE_TYPE, parse_release_number(VERSION_NUMBER)) - milestone_description = build_milestone_description(milestone_name) - - # Create milestone for 'Firefox for FireTV' and store the ID - milestone_id = testrail.create_milestone(PROJECT_ID, milestone_name, milestone_description)['id'] - - # Create test run for each Device/API and update test cases to 'passed' - # The Firebase Test devices are temporarily hard-coded during testing - # and will be parameterized in Phase 2 of hardening - for test_run_name in ['Google Pixel 32(Android11)', 'Google Pixel2(Android9)']: - test_run_id = testrail.create_test_run(PROJECT_ID, milestone_id, test_run_name, TEST_SUITE_ID)['id'] - testrail.update_test_cases_to_passed(PROJECT_ID, test_run_id, TEST_SUITE_ID) diff --git a/automation/taskcluster/androidTest/ui-test.sh b/automation/taskcluster/androidTest/ui-test.sh index a4df3971b..3c5b29c17 100755 --- a/automation/taskcluster/androidTest/ui-test.sh +++ b/automation/taskcluster/androidTest/ui-test.sh @@ -102,18 +102,9 @@ function failure_check() { echo if [[ $exitcode -ne 0 ]]; then echo "FAILURE: UI test run failed, please check above URL" - TEST_STATUS="FAIL" else echo "All UI test(s) have passed!" - TEST_STATUS="PASS" fi - - { - echo "TEST_STATUS=${TEST_STATUS}" - echo "PRODUCT_TYPE=${PRODUCT_TYPE}" - echo "RELEASE_TYPE=${RELEASE_TYPE}" - } >> execution_metadata.env - echo echo "RESULTS" echo diff --git a/build.gradle b/build.gradle index cb9ff542e..bd002d017 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,7 @@ buildscript { classpath ComponentsDependencies.tools_androidgradle classpath ComponentsDependencies.tools_kotlingradle classpath FenixDependencies.tools_benchmarkgradle - classpath FenixDependencies.androidx_safeargs + classpath ComponentsDependencies.androidx_safeargs classpath FenixDependencies.osslicenses_plugin classpath "org.mozilla.telemetry:glean-gradle-plugin:${Versions.mozilla_glean}" classpath "${ApplicationServicesConfig.groupId}:tooling-nimbus-gradle:${ApplicationServicesConfig.version}" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e0930..a80b22ce5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/plugins/apksize/build.gradle b/plugins/apksize/build.gradle index 77b077a8b..5a38f6a8b 100644 --- a/plugins/apksize/build.gradle +++ b/plugins/apksize/build.gradle @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ plugins { - id "org.gradle.kotlin.kotlin-dsl" version "4.1.2" + id "org.gradle.kotlin.kotlin-dsl" version "4.2.1" } repositories { diff --git a/plugins/fenixdependencies/build.gradle b/plugins/fenixdependencies/build.gradle index 7e8043a2a..f74423c7a 100644 --- a/plugins/fenixdependencies/build.gradle +++ b/plugins/fenixdependencies/build.gradle @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ plugins { - id "org.gradle.kotlin.kotlin-dsl" version "4.1.2" + id "org.gradle.kotlin.kotlin-dsl" version "4.2.1" } repositories { diff --git a/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt b/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt index e7f73234e..a2a385a22 100644 --- a/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt +++ b/plugins/fenixdependencies/src/main/java/FenixDependenciesPlugin.kt @@ -19,20 +19,21 @@ object FenixVersions { const val fastlane = "2.1.1" const val androidx_activity = "1.7.2" - const val androidx_benchmark = "1.2.2" + const val androidx_benchmark = "1.2.3" const val androidx_profileinstaller = "1.3.1" const val androidx_legacy = "1.0.0" + const val androidx_lifecycle = "2.6.1" const val androidx_navigation = "2.5.3" const val androidx_splash_screen = "1.0.1" const val androidx_transition = "1.4.1" const val androidx_datastore = "1.0.0" - const val google_accompanist = "0.30.1" + const val google_accompanist = "0.32.0" - const val adjust = "4.35.1" + const val adjust = "4.38.1" const val installreferrer = "2.2" - const val junit = "5.9.3" - const val mockk = "1.13.8" + const val junit = "5.10.2" + const val mockk = "1.13.9" // keep in sync with the versions used in AS. const val protobuf = "3.21.10" @@ -51,6 +52,7 @@ object FenixDependencies { const val androidx_profileinstaller = "androidx.profileinstaller:profileinstaller:${FenixVersions.androidx_profileinstaller}" const val androidx_activity_ktx = "androidx.activity:activity-ktx:${FenixVersions.androidx_activity}" const val androidx_legacy = "androidx.legacy:legacy-support-v4:${FenixVersions.androidx_legacy}" + const val androidx_lifecycle_common = "androidx.lifecycle:lifecycle-common:${FenixVersions.androidx_lifecycle}" const val androidx_safeargs = "androidx.navigation:navigation-safe-args-gradle-plugin:${FenixVersions.androidx_navigation}" const val androidx_navigation_fragment = "androidx.navigation:navigation-fragment-ktx:${FenixVersions.androidx_navigation}" const val androidx_navigation_ui = "androidx.navigation:navigation-ui:${FenixVersions.androidx_navigation}"