mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-07-30 18:04:08 +01:00
Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eff0e973aa | |||
| 34f336c2a2 | |||
| b0f71c8613 | |||
| 95019407c2 | |||
| 0101d41cf9 | |||
| 75c18806d5 | |||
| 7a07a96fba | |||
| 4f6c1c4647 | |||
| df4afe4e92 | |||
| 6a18bcc915 | |||
| 06e7b79e3d | |||
| 31f0945db4 | |||
| edc629e7fa | |||
| bdfe06ed74 | |||
| 1d11e29e94 | |||
| f70ae10067 | |||
| 7ca57e5531 | |||
| adad1425d8 | |||
| 693b208fe2 | |||
| e975084b8e | |||
| 3bc693961d | |||
| 2dde0b43b8 | |||
| 88366cd416 | |||
| 4ee2b71b13 | |||
| 86aae39141 | |||
| e71ec7c6d9 | |||
| 20d24d177d | |||
| cfc1ed8d5c | |||
| 25f7c31e75 | |||
| 929a391d50 | |||
| 76f2543308 | |||
| 5eebaa3528 | |||
| 673324f46a | |||
| ea9cd4251e | |||
| ac7d54331a | |||
| 5e3a34e1bc | |||
| fe6a74eb56 | |||
| 6a6b7a1924 | |||
| f50e970b5d | |||
| 32961106e1 | |||
| 8d3728b32a | |||
| 2f3b25c787 | |||
| 5cc7266a9e | |||
| 90cba056f1 | |||
| 07ca23ceae | |||
| 0d0b9d345c | |||
| 7f63af659d | |||
| 66390b4fe4 | |||
| b60f53f4df | |||
| 8bc31386a5 | |||
| 8f4b4aa160 | |||
| 12af41174a | |||
| e7c5af7ea5 | |||
| 51b1dbd470 | |||
| dd38f72f60 | |||
| db8a705704 | |||
| ba43403009 | |||
| 417b9eb50a | |||
| 76c9b4a7dc | |||
| d1b916d61c | |||
| 908bb8dbe6 | |||
| 31216592de | |||
| bcc9f17e41 | |||
| d9dd15eff3 | |||
| 1a12eb992d | |||
| 7c1e010482 | |||
| 8a5826555c | |||
| 8ffbfb4000 | |||
| 16fe25a38a | |||
| c47a74ba09 | |||
| 24287a15e2 | |||
| 77bef0b101 | |||
| e2ef8c2805 | |||
| a52799e069 |
@@ -23,7 +23,7 @@ jobs:
|
||||
lfs: true
|
||||
|
||||
- name: set up JDK 21
|
||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5
|
||||
# gh api repos/actions/setup-java/commits/v5 --jq '.sha'
|
||||
with:
|
||||
distribution: temurin
|
||||
@@ -42,15 +42,16 @@ jobs:
|
||||
# Required to persist the Gradle configuration cache across runs.
|
||||
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
|
||||
|
||||
# Pull requests run the fast custom linter (ci); pushes to main / 8.x branches run the full
|
||||
# Android lint (qa).
|
||||
# Pull requests run the fast custom linter (ciRemote); pushes to main / 8.x branches run the
|
||||
# full Android lint (qaRemote). Both include screenshot validation, which is deliberately kept
|
||||
# out of the local qa/ci tasks because screenshot rendering is host-OS dependent.
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
SIGNAL_BUILD_CACHE_URL: ${{ secrets.SIGNAL_BUILD_CACHE_URL }}
|
||||
SIGNAL_BUILD_CACHE_USER: ${{ secrets.SIGNAL_BUILD_CACHE_USER }}
|
||||
SIGNAL_BUILD_CACHE_PASSWORD: ${{ secrets.SIGNAL_BUILD_CACHE_PASSWORD }}
|
||||
SIGNAL_BUILD_CACHE_PUSH: ${{ startsWith(github.ref, 'refs/heads/8.') }}
|
||||
run: ./gradlew ${{ github.event_name == 'pull_request' && 'ci' || 'qa' }}
|
||||
run: ./gradlew ${{ github.event_name == 'pull_request' && 'ciRemote' || 'qaRemote' }}
|
||||
|
||||
- name: Archive reports for failed build
|
||||
if: ${{ failure() }}
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
|
||||
- name: set up JDK 21
|
||||
uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5
|
||||
uses: actions/setup-java@0f481fcb613427c0f801b606911222b5b6f3083a # v5
|
||||
# gh api repos/actions/setup-java/commits/v5 --jq '.sha'
|
||||
with:
|
||||
distribution: temurin
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
actions: write
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10
|
||||
- uses: actions/stale@1e223db275d687790206a7acac4d1a11bd6fe629 # v10
|
||||
# gh api repos/actions/stale/commits/v10 --jq '.sha'
|
||||
with:
|
||||
days-before-stale: 60
|
||||
|
||||
+14
-2
@@ -32,8 +32,8 @@ plugins {
|
||||
val staticIps = Properties().apply { file("static-ips.properties").reader().use { load(it) } }
|
||||
staticIps.stringPropertyNames().forEach { rootProject.extra[it] = staticIps.getProperty(it) }
|
||||
|
||||
val canonicalVersionCode = 1718
|
||||
val canonicalVersionName = "8.19.1"
|
||||
val canonicalVersionCode = 1720
|
||||
val canonicalVersionName = "8.20.0"
|
||||
val currentHotfixVersion = 0
|
||||
val maxHotfixVersions = 100
|
||||
|
||||
@@ -132,6 +132,17 @@ ktlint {
|
||||
version.set("1.5.0")
|
||||
}
|
||||
|
||||
// ktlint only scans convention source dirs, so the shared dirs added to the compile tasks are
|
||||
// otherwise skipped. Add them to the base test/androidTest ktlint tasks so ktlintCheck/format cover them.
|
||||
tasks.withType(org.jlleitschuh.gradle.ktlint.tasks.BaseKtLintCheckTask::class.java).configureEach {
|
||||
if (name.endsWith("OverTestSourceSet") || name.endsWith("OverAndroidTestSourceSet")) {
|
||||
source("$projectDir/src/testShared")
|
||||
}
|
||||
if (name.endsWith("OverAndroidTestSourceSet")) {
|
||||
source("$projectDir/src/benchmarkShared/java")
|
||||
}
|
||||
}
|
||||
|
||||
screenshotTests {
|
||||
// Fraction of differing pixels tolerated before a screenshot test fails (0.0001 = 0.01%).
|
||||
imageDifferenceThreshold = 0.0001f
|
||||
@@ -831,6 +842,7 @@ dependencies {
|
||||
|
||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
|
||||
androidTestImplementation(libs.androidx.compose.ui.test.manifest)
|
||||
androidTestImplementation(testLibs.androidx.test.ext.junit)
|
||||
androidTestImplementation(testLibs.espresso.core)
|
||||
androidTestImplementation(testLibs.espresso.contrib) {
|
||||
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions.click
|
||||
import androidx.test.espresso.action.ViewActions.scrollTo
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions
|
||||
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isNull
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.util.getParcelableExtraCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.badges.self.none.BecomeASustainerFragment
|
||||
import org.thoughtcrime.securesms.badges.self.overview.BadgesOverviewFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.routes.AppSettingsRoute
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.profiles.manage.EditProfileActivity
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Entry-path coverage for the "become a subscriber" upsell.
|
||||
*
|
||||
* The upsell surface is [BecomeASustainerFragment], reached from the profile screen's badges row. The
|
||||
* handoff test asserts the sheet's button launches the recurring-donation checkout route; the gating
|
||||
* tests assert the "user might be a sustainer" rule in [org.thoughtcrime.securesms.profiles.manage.EditProfileFragment]:
|
||||
* a non-donor sees the upsell, an existing donor is routed to badge management instead.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class BecomeASustainerUpsellTest {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule()
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
private val context: Context get() = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
setSelfBadges(emptyList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nonDonor_badgeTap_showsUpsellSheet() {
|
||||
ActivityScenario.launch(EditProfileActivity::class.java).use { scenario ->
|
||||
onView(withId(R.id.manage_profile_badges_container)).perform(scrollTo(), click())
|
||||
|
||||
val sheet = awaitNavHostFragment(scenario) { it.filterIsInstance<BecomeASustainerFragment>().firstOrNull() }
|
||||
assertThat(sheet).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun becomeASustainer_launchesRecurringCheckoutRoute() {
|
||||
LaunchedActivityRecorder(AppSettingsActivity::class.java).use { recorder ->
|
||||
ActivityScenario.launch(EditProfileActivity::class.java).use { scenario ->
|
||||
onView(withId(R.id.manage_profile_badges_container)).perform(scrollTo(), click())
|
||||
awaitNavHostFragment(scenario) { it.filterIsInstance<BecomeASustainerFragment>().firstOrNull() }
|
||||
|
||||
val becomeASustainer = withText(R.string.BecomeASustainerMegaphone__become_a_sustainer)
|
||||
onView(withId(R.id.recycler)).perform(RecyclerViewActions.scrollTo<RecyclerView.ViewHolder>(hasDescendant(becomeASustainer)))
|
||||
onView(becomeASustainer).perform(click())
|
||||
|
||||
val intent = recorder.awaitLaunch()
|
||||
val route = intent.extras!!.keySet().firstNotNullOfOrNull { intent.getParcelableExtraCompat(it, AppSettingsRoute::class.java) }
|
||||
assertThat(route).isEqualTo(AppSettingsRoute.DonationsRoute.Donations(directToCheckoutType = InAppPaymentType.RECURRING_DONATION))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun donor_badgeTap_opensBadgeManagement() {
|
||||
setSelfBadges(listOf(donorBadge()))
|
||||
|
||||
ActivityScenario.launch(EditProfileActivity::class.java).use { scenario ->
|
||||
onView(withId(R.id.manage_profile_badges_container)).perform(scrollTo(), click())
|
||||
|
||||
val badgeManagement = awaitNavHostFragment(scenario) { it.filterIsInstance<BadgesOverviewFragment>().firstOrNull() }
|
||||
assertThat(badgeManagement).isNotNull()
|
||||
|
||||
val upsell = navHostFragments(scenario).filterIsInstance<BecomeASustainerFragment>().firstOrNull()
|
||||
assertThat(upsell).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
private fun awaitNavHostFragment(scenario: ActivityScenario<EditProfileActivity>, selector: (List<Fragment>) -> Fragment?): Fragment {
|
||||
return await(description = "nav host fragment") { selector(navHostFragments(scenario)) }
|
||||
}
|
||||
|
||||
private fun navHostFragments(scenario: ActivityScenario<EditProfileActivity>): List<Fragment> {
|
||||
var fragments: List<Fragment> = emptyList()
|
||||
scenario.onActivity { activity ->
|
||||
val navHost = activity.supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment
|
||||
fragments = navHost?.childFragmentManager?.fragments ?: emptyList()
|
||||
}
|
||||
return fragments
|
||||
}
|
||||
|
||||
private fun setSelfBadges(badges: List<Badge>) {
|
||||
SignalDatabase.recipients.setBadges(Recipient.self().id, badges)
|
||||
Recipient.self().fresh()
|
||||
}
|
||||
|
||||
private fun donorBadge(): Badge {
|
||||
return Badge(
|
||||
id = "test-donor-badge",
|
||||
category = Badge.Category.Donor,
|
||||
name = "Signal Sustainer",
|
||||
description = "",
|
||||
imageUrl = Uri.EMPTY,
|
||||
imageDensity = "xxhdpi",
|
||||
expirationTimestamp = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30),
|
||||
visible = true,
|
||||
duration = TimeUnit.DAYS.toMillis(30)
|
||||
)
|
||||
}
|
||||
|
||||
private fun <T> await(timeoutMs: Long = 10_000, pollMs: Long = 50, description: String, supplier: () -> T?): T {
|
||||
val deadline = System.currentTimeMillis() + timeoutMs
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
supplier()?.let { return it }
|
||||
Thread.sleep(pollMs)
|
||||
}
|
||||
error("Timed out after ${timeoutMs}ms waiting for $description")
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures the first launched activity of [activityClass] and finishes it immediately so its own
|
||||
* downstream launches (e.g. the auto-launched checkout) don't cascade during the test.
|
||||
*/
|
||||
private inner class LaunchedActivityRecorder(private val activityClass: Class<out Activity>) : AutoCloseable {
|
||||
@Volatile
|
||||
private var launched: Intent? = null
|
||||
|
||||
private val app = context.applicationContext as Application
|
||||
private val callbacks = object : Application.ActivityLifecycleCallbacks {
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
if (activityClass.isInstance(activity) && launched == null) {
|
||||
launched = activity.intent
|
||||
activity.finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) = Unit
|
||||
override fun onActivityResumed(activity: Activity) = Unit
|
||||
override fun onActivityPaused(activity: Activity) = Unit
|
||||
override fun onActivityStopped(activity: Activity) = Unit
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
|
||||
override fun onActivityDestroyed(activity: Activity) = Unit
|
||||
}
|
||||
|
||||
init {
|
||||
app.registerActivityLifecycleCallbacks(callbacks)
|
||||
}
|
||||
|
||||
fun awaitLaunch(): Intent = await(description = "${activityClass.simpleName} launch") { launched }
|
||||
|
||||
override fun close() = app.unregisterActivityLifecycleCallbacks(callbacks)
|
||||
}
|
||||
}
|
||||
+8
@@ -17,7 +17,9 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import io.mockk.unmockkObject
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@@ -25,6 +27,7 @@ import org.junit.runner.RunWith
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.testing.GooglePayTestRule
|
||||
@@ -59,6 +62,11 @@ class CheckoutFlowActivityTest__OneTimeDonations {
|
||||
startJobLoopForTests()
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkObject(DonationPermits)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenPermitAcquisitionFails_whenIDonateOnce_thenIExpectPaymentSetupErrorDialog() {
|
||||
failDonationPermitAcquisition()
|
||||
|
||||
+21
-68
@@ -13,8 +13,6 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.unmockkObject
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -23,9 +21,6 @@ import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.signal.libsignal.net.RequestResult
|
||||
import org.signal.network.NetworkResult
|
||||
import org.signal.network.exceptions.NonSuccessfulResponseCodeException
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits
|
||||
@@ -33,19 +28,18 @@ import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.testing.GooglePayTestRule
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.RxTestSchedulerRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.testing.actions.scrollToDescendant
|
||||
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
||||
import org.thoughtcrime.securesms.testing.endpoints.DonationResponses
|
||||
import org.thoughtcrime.securesms.testing.endpoints.MockEndpoints
|
||||
import org.thoughtcrime.securesms.testing.endpoints.failure
|
||||
import org.thoughtcrime.securesms.testing.endpoints.ok
|
||||
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
||||
import java.math.BigDecimal
|
||||
import java.util.Currency
|
||||
import kotlin.time.Duration.Companion.days
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@Suppress("ClassName")
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@@ -153,10 +147,10 @@ class CheckoutFlowActivityTest__RecurringDonations {
|
||||
|
||||
@Test
|
||||
fun givenSubscriptionPaymentMethodPermitRejected_whenISubscribe_thenIExpectPaymentSetupErrorDialog() {
|
||||
AppDependencies.donationPermitsRepository.clearPermits()
|
||||
mockkObject(DonationPermits)
|
||||
every { DonationPermits.getDonationPermit() } returns RequestResult.Success("permit")
|
||||
every { AppDependencies.donationsApi.createStripeSubscriptionPaymentMethod(any(), any(), any()) } returns NetworkResult.StatusCodeError(NonSuccessfulResponseCodeException(402))
|
||||
succeedDonationPermitAcquisition()
|
||||
MockEndpoints.responder.register({ it.method == "POST" && it.path.contains("/create_payment_method") }) {
|
||||
failure(402)
|
||||
}
|
||||
|
||||
val scenario = ActivityScenario.launch<CheckoutFlowActivity>(intent)
|
||||
rxRule.defaultTestScheduler.triggerActions()
|
||||
@@ -172,44 +166,22 @@ class CheckoutFlowActivityTest__RecurringDonations {
|
||||
}
|
||||
|
||||
private fun initialiseActiveSubscription() {
|
||||
val currency = Currency.getInstance("USD")
|
||||
val subscriber = InAppPaymentSubscriberRecord(
|
||||
subscriberId = SubscriberId.generate(),
|
||||
currency = currency,
|
||||
type = InAppPaymentSubscriberRecord.Type.DONATION,
|
||||
requiresCancel = false,
|
||||
paymentMethodType = InAppPaymentData.PaymentMethodType.CARD,
|
||||
iapSubscriptionId = null
|
||||
)
|
||||
|
||||
InAppPaymentsRepository.setSubscriber(subscriber)
|
||||
SignalStore.inAppPayments.setRecurringDonationCurrency(currency)
|
||||
|
||||
AppDependencies.donationsApi.apply {
|
||||
every { getSubscription(subscriber.subscriberId) } returns NetworkResult.Success(
|
||||
ActiveSubscription(
|
||||
ActiveSubscription.Subscription(
|
||||
200,
|
||||
currency.currencyCode,
|
||||
BigDecimal.ONE,
|
||||
System.currentTimeMillis().milliseconds.inWholeSeconds + 30.days.inWholeSeconds,
|
||||
true,
|
||||
System.currentTimeMillis().milliseconds.inWholeSeconds + 30.days.inWholeSeconds,
|
||||
false,
|
||||
"active",
|
||||
"STRIPE",
|
||||
"CARD",
|
||||
false
|
||||
),
|
||||
null
|
||||
)
|
||||
)
|
||||
|
||||
every { deleteSubscription(subscriber.subscriberId) } returns NetworkResult.Success(Unit)
|
||||
val subscriber = registerSubscriber()
|
||||
val serialized = subscriber.subscriberId.serialize()
|
||||
MockEndpoints.responder.register({ it.method == "GET" && it.path.contains(serialized) }) {
|
||||
ok(DonationResponses.activeSubscription(status = "active", active = true))
|
||||
}
|
||||
}
|
||||
|
||||
private fun initialisePendingSubscription() {
|
||||
val subscriber = registerSubscriber()
|
||||
val serialized = subscriber.subscriberId.serialize()
|
||||
MockEndpoints.responder.register({ it.method == "GET" && it.path.contains(serialized) }) {
|
||||
ok(DonationResponses.activeSubscription(status = "incomplete", active = false))
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerSubscriber(): InAppPaymentSubscriberRecord {
|
||||
val currency = Currency.getInstance("USD")
|
||||
val subscriber = InAppPaymentSubscriberRecord(
|
||||
subscriberId = SubscriberId.generate(),
|
||||
@@ -223,25 +195,6 @@ class CheckoutFlowActivityTest__RecurringDonations {
|
||||
InAppPaymentsRepository.setSubscriber(subscriber)
|
||||
SignalStore.inAppPayments.setRecurringDonationCurrency(currency)
|
||||
|
||||
AppDependencies.donationsApi.apply {
|
||||
every { getSubscription(subscriber.subscriberId) } returns NetworkResult.Success(
|
||||
ActiveSubscription(
|
||||
ActiveSubscription.Subscription(
|
||||
200,
|
||||
currency.currencyCode,
|
||||
BigDecimal.ONE,
|
||||
System.currentTimeMillis().milliseconds.inWholeSeconds + 30.days.inWholeSeconds,
|
||||
false,
|
||||
System.currentTimeMillis().milliseconds.inWholeSeconds + 30.days.inWholeSeconds,
|
||||
false,
|
||||
"incomplete",
|
||||
"STRIPE",
|
||||
"CARD",
|
||||
false
|
||||
),
|
||||
null
|
||||
)
|
||||
)
|
||||
}
|
||||
return subscriber
|
||||
}
|
||||
}
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import androidx.compose.ui.test.junit4.v2.createEmptyComposeRule
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isClickable
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isNotEmpty
|
||||
import io.mockk.unmockkObject
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits
|
||||
import org.thoughtcrime.securesms.database.DonationReceiptTable
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord
|
||||
import org.thoughtcrime.securesms.testing.GooglePayTestRule
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.RxTestSchedulerRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.testing.actions.scrollToDescendant
|
||||
import org.thoughtcrime.securesms.testing.endpoints.MockEndpoints
|
||||
import org.thoughtcrime.securesms.testing.endpoints.registerStripeHappyPath
|
||||
import org.thoughtcrime.securesms.testing.flushUntil
|
||||
|
||||
/**
|
||||
* Milestone integration test: drives a Google Pay one-time donation through the entire lifecycle to
|
||||
* receipt redemption, exercising all three outer boundaries at once — the Signal-service websocket
|
||||
* responder (boost intent + receipt credential + redeem), the Stripe HTTP interceptor (payment
|
||||
* method + confirm + intent status), and the test zk server (real client-side credential validation).
|
||||
*/
|
||||
@Suppress("ClassName")
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CheckoutFlowActivityTest__Redemption {
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule(othersCount = 10)
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
@get:Rule
|
||||
val rxRule = RxTestSchedulerRule()
|
||||
|
||||
@get:Rule
|
||||
val googlePayRule = GooglePayTestRule()
|
||||
|
||||
@get:Rule
|
||||
val composeRule = createEmptyComposeRule()
|
||||
|
||||
private val intent = CheckoutFlowActivity.createIntent(InstrumentationRegistry.getInstrumentation().targetContext, InAppPaymentType.ONE_TIME_DONATION)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
SignalDatabase.inAppPayments.writableDatabase.deleteAll(InAppPaymentTable.TABLE_NAME)
|
||||
SignalDatabase.donationReceipts.writableDatabase.deleteAll(DonationReceiptTable.TABLE_NAME)
|
||||
startJobLoopForTests()
|
||||
succeedDonationPermitAcquisition()
|
||||
MockEndpoints.responder.registerStripeHappyPath()
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkObject(DonationPermits)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAllEndpointsSucceed_whenIDonateOnceWithGooglePay_thenIExpectAReceipt() {
|
||||
val scenario = ActivityScenario.launch<CheckoutFlowActivity>(intent)
|
||||
rxRule.defaultTestScheduler.triggerActions()
|
||||
|
||||
scrollToDescendant(R.id.recycler, withId(R.id.boost_1), rxRule.defaultTestScheduler)
|
||||
onView(allOf(withId(R.id.boost_1), isClickable())).perform(ViewActions.click())
|
||||
rxRule.defaultTestScheduler.triggerActions()
|
||||
|
||||
scrollToDescendant(R.id.recycler, withText(R.string.DonateToSignalFragment__continue), rxRule.defaultTestScheduler)
|
||||
onView(withText(R.string.DonateToSignalFragment__continue)).perform(ViewActions.click())
|
||||
rxRule.defaultTestScheduler.triggerActions()
|
||||
|
||||
scenario.selectGooglePay(composeRule, rxRule.defaultTestScheduler, InAppPaymentType.ONE_TIME_DONATION)
|
||||
|
||||
rxRule.defaultTestScheduler.flushUntil {
|
||||
SignalDatabase.donationReceipts.getReceipts(InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION).isNotEmpty()
|
||||
}
|
||||
|
||||
assertThat(SignalDatabase.donationReceipts.getReceipts(InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION)).isNotEmpty()
|
||||
}
|
||||
}
|
||||
+280
@@ -0,0 +1,280 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.ui.test.hasTestTag
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollToNode
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isClickable
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isEnabled
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import io.reactivex.rxjava3.schedulers.TestScheduler
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.signal.donations.StripeIntentAccessor
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewaySelectorTestTags
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.paypal.PayPalConfirmationDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.paypal.PayPalConfirmationResult
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.Stripe3DSDialogFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
|
||||
import org.thoughtcrime.securesms.testing.actions.scrollToDescendant
|
||||
import org.thoughtcrime.securesms.testing.endpoints.StripeResponses
|
||||
import org.thoughtcrime.securesms.testing.flushUntil
|
||||
|
||||
/**
|
||||
* Drives [CheckoutFlowActivity] through the UI "as a user" for a [DonationsCheckoutTestSpec]: selects
|
||||
* an amount/tier, continues to the gateway selector, and completes the chosen payment method. Each
|
||||
* payment method is a strategy dispatched on [DonationsCheckoutTestSpec.paymentMethod].
|
||||
*
|
||||
* Webview approval steps (PayPal, Stripe 3DS) can't complete against a mocked network, so instead of
|
||||
* loading the approval URL we inject the fragment result the webview would have posted — the same
|
||||
* mechanism the production dialog uses on return.
|
||||
*/
|
||||
class CheckoutFlowDriver(
|
||||
private val composeRule: ComposeTestRule,
|
||||
private val scheduler: TestScheduler
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private const val TEST_NAME = "Test McTesterson"
|
||||
private const val TEST_EMAIL = "test@signal.org"
|
||||
|
||||
/** A structurally valid German IBAN (passes mod-97), for the SEPA form. */
|
||||
private const val TEST_IBAN = "DE89370400440532013000"
|
||||
}
|
||||
|
||||
fun drive(scenario: ActivityScenario<CheckoutFlowActivity>, spec: DonationsCheckoutTestSpec) {
|
||||
scheduler.triggerActions()
|
||||
|
||||
selectAmountOrTier(spec.inAppPaymentType)
|
||||
proceedToGateway()
|
||||
|
||||
when (spec.paymentMethod) {
|
||||
TestPaymentMethod.GOOGLE_PAY -> scenario.selectGooglePay(composeRule, scheduler, spec.inAppPaymentType)
|
||||
TestPaymentMethod.CREDIT_CARD -> completeCreditCard()
|
||||
TestPaymentMethod.PAYPAL -> completePayPal(scenario, spec.inAppPaymentType)
|
||||
TestPaymentMethod.SEPA_DEBIT -> completeSepa()
|
||||
TestPaymentMethod.IDEAL -> completeIdeal(spec.inAppPaymentType)
|
||||
}
|
||||
|
||||
if (spec.world.stripe == StripeOutcome.REQUIRES_3DS && spec.paymentMethod.usesStripe()) {
|
||||
complete3ds(scenario, spec.inAppPaymentType)
|
||||
}
|
||||
}
|
||||
|
||||
private fun selectAmountOrTier(type: InAppPaymentType) {
|
||||
if (type == InAppPaymentType.ONE_TIME_DONATION) {
|
||||
scrollToDescendant(R.id.recycler, withId(R.id.boost_1), scheduler)
|
||||
onView(allOf(withId(R.id.boost_1), isClickable())).perform(ViewActions.click())
|
||||
scheduler.triggerActions()
|
||||
}
|
||||
// Recurring: the monthly tier is selected by default, so nothing to pick here.
|
||||
}
|
||||
|
||||
private fun proceedToGateway() {
|
||||
scrollToDescendant(R.id.recycler, withText(R.string.DonateToSignalFragment__continue), scheduler)
|
||||
onView(withText(R.string.DonateToSignalFragment__continue)).perform(ViewActions.click())
|
||||
scheduler.triggerActions()
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the [org.thoughtcrime.securesms.components.settings.app.subscription.donate.card.CreditCardFragment]
|
||||
* with a valid test card and continues, driving the flow into the Stripe payment pipeline.
|
||||
*/
|
||||
private fun completeCreditCard() {
|
||||
clickGatewayButton(GatewaySelectorTestTags.CREDIT_CARD_BUTTON)
|
||||
|
||||
scheduler.flushUntil {
|
||||
onView(withId(R.id.card_number)).check(matches(isDisplayed()))
|
||||
true
|
||||
}
|
||||
|
||||
onView(withId(R.id.card_number)).perform(ViewActions.typeText("4242424242424242"), ViewActions.closeSoftKeyboard())
|
||||
onView(withId(R.id.card_expiry)).perform(ViewActions.typeText("1228"), ViewActions.closeSoftKeyboard())
|
||||
onView(withId(R.id.card_cvv)).perform(ViewActions.typeText("123"), ViewActions.closeSoftKeyboard())
|
||||
|
||||
scheduler.flushUntil {
|
||||
onView(withId(R.id.continue_button)).check(matches(isEnabled()))
|
||||
true
|
||||
}
|
||||
onView(withId(R.id.continue_button)).perform(ViewActions.click())
|
||||
scheduler.triggerActions()
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects PayPal, then injects the approval result the webview would have returned. One-time uses a
|
||||
* [PayPalConfirmationResult]; recurring posts `true`.
|
||||
*/
|
||||
private fun completePayPal(scenario: ActivityScenario<CheckoutFlowActivity>, type: InAppPaymentType) {
|
||||
clickGatewayButton(GatewaySelectorTestTags.PAYPAL_BUTTON)
|
||||
|
||||
val result: Any = if (type == InAppPaymentType.ONE_TIME_DONATION) {
|
||||
PayPalConfirmationResult(payerId = "test-payer", paymentId = null, paymentToken = "test-token")
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
||||
awaitDialogAndSetResult(
|
||||
scenario = scenario,
|
||||
dialogClass = PayPalConfirmationDialogFragment::class.java,
|
||||
resultKey = PayPalConfirmationDialogFragment.REQUEST_KEY,
|
||||
bundle = bundleOf(PayPalConfirmationDialogFragment.REQUEST_KEY to result)
|
||||
)
|
||||
}
|
||||
|
||||
/** Injects the 3DS return the Stripe webview would have posted, resuming the Stripe pipeline. */
|
||||
private fun complete3ds(scenario: ActivityScenario<CheckoutFlowActivity>, type: InAppPaymentType) {
|
||||
val accessor = if (type == InAppPaymentType.ONE_TIME_DONATION) {
|
||||
StripeIntentAccessor(StripeIntentAccessor.ObjectType.PAYMENT_INTENT, StripeResponses.DEFAULT_PAYMENT_INTENT_ID, "${StripeResponses.DEFAULT_PAYMENT_INTENT_ID}_secret_test")
|
||||
} else {
|
||||
StripeIntentAccessor(StripeIntentAccessor.ObjectType.SETUP_INTENT, StripeResponses.DEFAULT_SETUP_INTENT_ID, "${StripeResponses.DEFAULT_SETUP_INTENT_ID}_secret_test")
|
||||
}
|
||||
|
||||
awaitDialogAndSetResult(
|
||||
scenario = scenario,
|
||||
dialogClass = Stripe3DSDialogFragment::class.java,
|
||||
resultKey = Stripe3DSDialogFragment.REQUEST_KEY,
|
||||
bundle = bundleOf(Stripe3DSDialogFragment.REQUEST_KEY to accessor)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects SEPA, accepts the mandate (its button scrolls the text to the bottom before it agrees, so
|
||||
* it is clicked until the details form appears), fills the bank details, and donates. SEPA requires
|
||||
* a EUR donation currency (see [WorldState.currencyCode]).
|
||||
*/
|
||||
private fun completeSepa() {
|
||||
clickGatewayButton(GatewaySelectorTestTags.SEPA_BUTTON)
|
||||
|
||||
scheduler.flushUntil {
|
||||
val ibanPresent = runCatching {
|
||||
composeRule.onAllNodesWithTag(DonationTransferTestTags.SEPA_IBAN_FIELD).fetchSemanticsNodes().isNotEmpty()
|
||||
}.getOrDefault(false)
|
||||
if (!ibanPresent) {
|
||||
runCatching { composeRule.onNodeWithTag(DonationTransferTestTags.SEPA_MANDATE_CONTINUE_BUTTON).performClick() }
|
||||
}
|
||||
ibanPresent
|
||||
}
|
||||
|
||||
typeIntoField(DonationTransferTestTags.SEPA_DETAILS_LIST, DonationTransferTestTags.SEPA_IBAN_FIELD, TEST_IBAN)
|
||||
typeIntoField(DonationTransferTestTags.SEPA_DETAILS_LIST, DonationTransferTestTags.SEPA_NAME_FIELD, TEST_NAME)
|
||||
typeIntoField(DonationTransferTestTags.SEPA_DETAILS_LIST, DonationTransferTestTags.SEPA_EMAIL_FIELD, TEST_EMAIL)
|
||||
|
||||
clickWhenReady(DonationTransferTestTags.SEPA_DONATE_BUTTON)
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects iDEAL, fills the bank details (email is recurring-only), and donates. iDEAL requires a EUR
|
||||
* donation currency and, on success, lands in an awaiting-authorization state.
|
||||
*/
|
||||
private fun completeIdeal(type: InAppPaymentType) {
|
||||
clickGatewayButton(GatewaySelectorTestTags.IDEAL_BUTTON)
|
||||
|
||||
scheduler.flushUntil {
|
||||
runCatching {
|
||||
composeRule.onAllNodesWithTag(DonationTransferTestTags.IDEAL_NAME_FIELD).fetchSemanticsNodes().isNotEmpty()
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
|
||||
typeIntoField(DonationTransferTestTags.IDEAL_DETAILS_LIST, DonationTransferTestTags.IDEAL_NAME_FIELD, TEST_NAME)
|
||||
if (type.recurring) {
|
||||
typeIntoField(DonationTransferTestTags.IDEAL_DETAILS_LIST, DonationTransferTestTags.IDEAL_EMAIL_FIELD, TEST_EMAIL)
|
||||
}
|
||||
|
||||
clickWhenReady(DonationTransferTestTags.IDEAL_DONATE_BUTTON)
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the [listTag] lazy list until the field tagged [fieldTag] is composed and on-screen, then types
|
||||
* [text] into it. The transfer forms lay their fields out in a [androidx.compose.foundation.lazy.LazyColumn],
|
||||
* so a lower field is not composed on a short screen until scrolled to — without this, the input silently
|
||||
* matches nothing on Firebase's smaller devices.
|
||||
*/
|
||||
private fun typeIntoField(listTag: String, fieldTag: String, text: String) {
|
||||
composeRule.onNodeWithTag(listTag).performScrollToNode(hasTestTag(fieldTag))
|
||||
composeRule.onNodeWithTag(fieldTag).performTextInput(text)
|
||||
}
|
||||
|
||||
/** Retries clicking a Compose node until the click lands (e.g. once a submit button becomes enabled). */
|
||||
private fun clickWhenReady(tag: String) {
|
||||
scheduler.flushUntil {
|
||||
runCatching {
|
||||
composeRule.onNodeWithTag(tag).performClick()
|
||||
true
|
||||
}.getOrDefault(false)
|
||||
}
|
||||
scheduler.triggerActions()
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks a Compose gateway-selector button and waits for the bottom sheet to dismiss. For methods
|
||||
* other than Google Pay the checkout then navigates to the method's fragment; Google Pay instead
|
||||
* requires a result injection (see `selectGooglePay`).
|
||||
*/
|
||||
private fun clickGatewayButton(tag: String) {
|
||||
scheduler.flushUntil {
|
||||
composeRule.onAllNodesWithTag(tag).fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
|
||||
// The selector is a vertically scrolling bottom sheet; on a short screen the lower gateway buttons are
|
||||
// off-screen, so bring the target on-screen before clicking (mirrors GatewaySelectorBottomSheetContentTest).
|
||||
composeRule.onNodeWithTag(GatewaySelectorTestTags.CONTAINER).performScrollToNode(hasTestTag(tag))
|
||||
composeRule.onNodeWithTag(tag).performClick()
|
||||
|
||||
scheduler.flushUntil {
|
||||
runCatching {
|
||||
composeRule.onAllNodesWithTag(tag).fetchSemanticsNodes().isEmpty()
|
||||
}.getOrDefault(true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a navigated dialog of [dialogClass] to be present, then posts [bundle] as its fragment
|
||||
* result on the nav host's fragment manager (where the in-progress fragment registered its listener).
|
||||
*/
|
||||
private fun <T : Fragment> awaitDialogAndSetResult(
|
||||
scenario: ActivityScenario<CheckoutFlowActivity>,
|
||||
dialogClass: Class<T>,
|
||||
resultKey: String,
|
||||
bundle: Bundle
|
||||
) {
|
||||
scheduler.flushUntil {
|
||||
var delivered = false
|
||||
scenario.onActivity { activity ->
|
||||
val fragmentManager = navHostChildFragmentManager(activity)
|
||||
if (fragmentManager != null && fragmentManager.fragments.any { dialogClass.isInstance(it) }) {
|
||||
fragmentManager.setFragmentResult(resultKey, bundle)
|
||||
delivered = true
|
||||
}
|
||||
}
|
||||
delivered
|
||||
}
|
||||
scheduler.triggerActions()
|
||||
}
|
||||
|
||||
private fun navHostChildFragmentManager(activity: FragmentActivity): FragmentManager? {
|
||||
return activity.supportFragmentManager.fragments
|
||||
.filterIsInstance<NavHostFragment>()
|
||||
.firstOrNull()
|
||||
?.childFragmentManager
|
||||
}
|
||||
|
||||
private fun TestPaymentMethod.usesStripe(): Boolean {
|
||||
return this != TestPaymentMethod.PAYPAL
|
||||
}
|
||||
}
|
||||
+36
-3
@@ -7,10 +7,12 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import androidx.compose.ui.test.hasTestTag
|
||||
import androidx.compose.ui.test.junit4.ComposeTestRule
|
||||
import androidx.compose.ui.test.onAllNodesWithTag
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollToNode
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
@@ -18,6 +20,7 @@ import androidx.test.espresso.matcher.RootMatchers.isDialog
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.reactivex.rxjava3.schedulers.TestScheduler
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.signal.libsignal.net.RequestResult
|
||||
@@ -26,23 +29,52 @@ import org.thoughtcrime.securesms.SignalInstrumentationApplicationContext
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.GooglePayComponent
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaymentsRepository
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.gateway.GatewaySelectorTestTags
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.testing.flushUntil
|
||||
|
||||
/**
|
||||
* Forces real donation-permit acquisition to fail at the issuer, exercising the permit code path through
|
||||
* [org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits].
|
||||
* Forces donation-permit acquisition to fail, so the checkout surfaces a payment-setup error before
|
||||
* reaching the payment method. Stubs the [DonationPermits] object directly (the underlying
|
||||
* `createDonationPermits` call rides the websocket, which the responder does not mint valid permits
|
||||
* for). Call `unmockkObject(DonationPermits)` in teardown.
|
||||
*/
|
||||
fun failDonationPermitAcquisition(statusCode: Int = 500) {
|
||||
AppDependencies.donationPermitsRepository.clearPermits()
|
||||
every { AppDependencies.donationsApi.createDonationPermits(any()) } returns RequestResult.NonSuccess(RestStatusCodeError(statusCode, emptyMap(), null))
|
||||
mockkObject(DonationPermits)
|
||||
every { DonationPermits.getDonationPermit() } returns RequestResult.NonSuccess(RestStatusCodeError(statusCode, emptyMap(), null))
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes donation-permit acquisition succeed with a placeholder permit, letting the checkout proceed
|
||||
* past the permit gate to the payment method. Call `unmockkObject(DonationPermits)` in teardown.
|
||||
*/
|
||||
fun succeedDonationPermitAcquisition() {
|
||||
AppDependencies.donationPermitsRepository.clearPermits()
|
||||
mockkObject(DonationPermits)
|
||||
every { DonationPermits.getDonationPermit() } returns RequestResult.Success("permit")
|
||||
}
|
||||
|
||||
/**
|
||||
* The instrumentation app stubs [org.thoughtcrime.securesms.ApplicationContext.beginJobLoop] to a no-op, so enqueued
|
||||
* jobs never run. The checkout pipeline drives a real setup job through the JobManager, so the loop must be started.
|
||||
*
|
||||
* Before starting it, cancel any leftover in-app-payment jobs. A recurring setup job retries indefinitely over a
|
||||
* one-day lifespan, so a spec that fails setup leaves one persisted in the JobManager. On Firebase Test Lab the
|
||||
* orchestrator's `clearPackageData` does not reliably wipe the JobManager between parameterized specs (it does on a
|
||||
* local emulator, which is why this only surfaces on-device), so that job survives into the next spec and runs after
|
||||
* its InAppPayment row was deleted in setup — `InAppPaymentsRepository.resolveLock` then throws "Not found" from the
|
||||
* job thread and crashes the whole app. Clearing the queues here makes each test start from a clean job state.
|
||||
*/
|
||||
fun startJobLoopForTests() {
|
||||
AppDependencies.jobManager.cancelAllInQueues(
|
||||
setOf(
|
||||
InAppPaymentsRepository.getRecurringJobQueueKey(InAppPaymentType.RECURRING_DONATION),
|
||||
InAppPaymentsRepository.getRecurringJobQueueKey(InAppPaymentType.RECURRING_BACKUP)
|
||||
)
|
||||
)
|
||||
AppDependencies.jobManager.flush()
|
||||
|
||||
(AppDependencies.application as SignalInstrumentationApplicationContext).beginJobLoopForTests()
|
||||
}
|
||||
|
||||
@@ -67,6 +99,7 @@ fun ActivityScenario<CheckoutFlowActivity>.selectGooglePay(
|
||||
composeRule.onAllNodesWithTag(GatewaySelectorTestTags.GOOGLE_PAY_BUTTON).fetchSemanticsNodes().isNotEmpty()
|
||||
}
|
||||
|
||||
composeRule.onNodeWithTag(GatewaySelectorTestTags.CONTAINER).performScrollToNode(hasTestTag(GatewaySelectorTestTags.GOOGLE_PAY_BUTTON))
|
||||
composeRule.onNodeWithTag(GatewaySelectorTestTags.GOOGLE_PAY_BUTTON).performClick()
|
||||
|
||||
scheduler.flushUntil {
|
||||
|
||||
+282
@@ -0,0 +1,282 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import androidx.compose.ui.test.junit4.v2.createEmptyComposeRule
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.RootMatchers.isDialog
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isNotEmpty
|
||||
import assertk.assertions.isNotNull
|
||||
import assertk.assertions.isNull
|
||||
import io.mockk.unmockkObject
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.permits.DonationPermits
|
||||
import org.thoughtcrime.securesms.database.DonationReceiptTable
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentReceiptRecord
|
||||
import org.thoughtcrime.securesms.testing.GooglePayTestRule
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.RawFlag
|
||||
import org.thoughtcrime.securesms.testing.RemoteConfigForTest
|
||||
import org.thoughtcrime.securesms.testing.RxTestSchedulerRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.testing.flushUntil
|
||||
|
||||
/**
|
||||
* Spec-driven integration test for donation checkout. Each [DonationsCheckoutTestSpec] declares a
|
||||
* "world" (what each endpoint returns) and an expected outcome; this runner applies the world, drives
|
||||
* [CheckoutFlowActivity] through the real UI via [CheckoutFlowDriver], and asserts the outcome.
|
||||
*
|
||||
* Adding coverage is data: append a spec to [DonationsCheckoutSpecs.ALL].
|
||||
*/
|
||||
@RunWith(Parameterized::class)
|
||||
@RemoteConfigForTest(
|
||||
rawFlags = [
|
||||
RawFlag("android.sepa.debit.donations.5", "true"),
|
||||
RawFlag("android.ideal.donations.5", "true"),
|
||||
// Region codes are matched against the digit-only self E164 ("15555550101"), so no leading "+".
|
||||
RawFlag("global.donations.sepaEnabledRegions", "1"),
|
||||
RawFlag("global.donations.idealEnabledRegions", "1")
|
||||
]
|
||||
)
|
||||
class DonationsCheckoutSpecTest(private val spec: DonationsCheckoutTestSpec) {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule(othersCount = 10)
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
@get:Rule
|
||||
val rxRule = RxTestSchedulerRule()
|
||||
|
||||
@get:Rule
|
||||
val googlePayRule = GooglePayTestRule()
|
||||
|
||||
@get:Rule
|
||||
val composeRule = createEmptyComposeRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
SignalDatabase.inAppPayments.writableDatabase.deleteAll(InAppPaymentTable.TABLE_NAME)
|
||||
SignalDatabase.donationReceipts.writableDatabase.deleteAll(DonationReceiptTable.TABLE_NAME)
|
||||
startJobLoopForTests()
|
||||
spec.world.apply()
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkObject(DonationPermits)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runSpec() {
|
||||
val intent = CheckoutFlowActivity.createIntent(InstrumentationRegistry.getInstrumentation().targetContext, spec.inAppPaymentType)
|
||||
val scenario = ActivityScenario.launch<CheckoutFlowActivity>(intent)
|
||||
|
||||
CheckoutFlowDriver(composeRule, rxRule.defaultTestScheduler).drive(scenario, spec)
|
||||
|
||||
when (val expected = spec.expected) {
|
||||
is ExpectedOutcome.Redeemed -> {
|
||||
rxRule.defaultTestScheduler.flushUntil { receipts().isNotEmpty() }
|
||||
assertThat(receipts()).isNotEmpty()
|
||||
}
|
||||
|
||||
is ExpectedOutcome.ErrorDialog -> {
|
||||
awaitDialog(rxRule.defaultTestScheduler, expected.titleRes)
|
||||
if (expected.messageRes != null) {
|
||||
onView(withText(expected.messageRes)).inRoot(isDialog()).check(matches(isDisplayed()))
|
||||
}
|
||||
}
|
||||
|
||||
is ExpectedOutcome.PaymentSubmitted -> {
|
||||
rxRule.defaultTestScheduler.flushUntil { submittedPayment() != null }
|
||||
val payment = submittedPayment()
|
||||
assertThat(payment).isNotNull()
|
||||
assertThat(payment!!.data.error).isNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The latest payment once it has moved past CREATED with no error, or null if not yet there. */
|
||||
private fun submittedPayment(): InAppPaymentTable.InAppPayment? {
|
||||
return SignalDatabase.inAppPayments.getLatestInAppPaymentByType(spec.inAppPaymentType)
|
||||
?.takeIf { it.state != InAppPaymentTable.State.CREATED && it.data.error == null }
|
||||
}
|
||||
|
||||
private fun receipts(): List<InAppPaymentReceiptRecord> {
|
||||
val type = if (spec.inAppPaymentType == InAppPaymentType.ONE_TIME_DONATION) {
|
||||
InAppPaymentReceiptRecord.Type.ONE_TIME_DONATION
|
||||
} else {
|
||||
InAppPaymentReceiptRecord.Type.RECURRING_DONATION
|
||||
}
|
||||
return SignalDatabase.donationReceipts.getReceipts(type)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun specs(): Collection<DonationsCheckoutTestSpec> = DonationsCheckoutSpecs.ALL
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The enumerated donation checkout scenarios. Currently seeded with Google Pay coverage; the other
|
||||
* payment-method drivers (card, SEPA, iDEAL, PayPal) and their scenarios are added alongside their
|
||||
* [CheckoutFlowDriver] strategies.
|
||||
*/
|
||||
object DonationsCheckoutSpecs {
|
||||
|
||||
private val paymentErrorDialog = ExpectedOutcome.ErrorDialog(
|
||||
titleRes = R.string.DonationsErrors__error_processing_payment,
|
||||
messageRes = R.string.DonationsErrors__your_payment
|
||||
)
|
||||
|
||||
val ALL: List<DonationsCheckoutTestSpec> = listOf(
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_oneTime_happyPath_isRedeemed",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(),
|
||||
expected = ExpectedOutcome.Redeemed
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_oneTime_permitFailure_showsError",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(permit = PermitOutcome.FAILURE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_oneTime_stripeDecline_showsError",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(stripe = StripeOutcome.DECLINE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_oneTime_signalCreateIntent402_showsError",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(signalCreatePaymentStatus = 402),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_recurring_permitFailure_showsError",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(permit = PermitOutcome.FAILURE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_oneTime_happyPath_isRedeemed",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(),
|
||||
expected = ExpectedOutcome.Redeemed
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_oneTime_stripeDecline_showsError",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(stripe = StripeOutcome.DECLINE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_oneTime_3dsApproved_isRedeemed",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(stripe = StripeOutcome.REQUIRES_3DS),
|
||||
expected = ExpectedOutcome.Redeemed
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "payPal_oneTime_happyPath_isRedeemed",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.PAYPAL,
|
||||
world = WorldState(),
|
||||
expected = ExpectedOutcome.Redeemed
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "sepa_oneTime_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.SEPA_DEBIT,
|
||||
world = WorldState(currencyCode = "EUR"),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "ideal_oneTime_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.IDEAL,
|
||||
world = WorldState(currencyCode = "EUR"),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
|
||||
// Recurring happy paths. Asserted as "submitted": the recurring-specific work is the setup
|
||||
// pipeline (create subscriber, setup intent, set default, set level); receipt redemption is
|
||||
// shared with the one-time path already covered above.
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_recurring_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(recurringActivatesAfterSetup = true),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_recurring_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(recurringActivatesAfterSetup = true),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "payPal_recurring_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.PAYPAL,
|
||||
world = WorldState(recurringActivatesAfterSetup = true),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "sepa_recurring_happyPath_isSubmitted",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.SEPA_DEBIT,
|
||||
world = WorldState(currencyCode = "EUR"),
|
||||
expected = ExpectedOutcome.PaymentSubmitted
|
||||
),
|
||||
|
||||
// Additional error cases.
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_oneTime_permitFailure_showsError",
|
||||
inAppPaymentType = InAppPaymentType.ONE_TIME_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(permit = PermitOutcome.FAILURE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "creditCard_recurring_stripeDecline_showsError",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.CREDIT_CARD,
|
||||
world = WorldState(stripe = StripeOutcome.DECLINE),
|
||||
expected = paymentErrorDialog
|
||||
),
|
||||
DonationsCheckoutTestSpec(
|
||||
name = "googlePay_recurring_signalCreatePaymentMethod402_showsError",
|
||||
inAppPaymentType = InAppPaymentType.RECURRING_DONATION,
|
||||
paymentMethod = TestPaymentMethod.GOOGLE_PAY,
|
||||
world = WorldState(signalCreatePaymentStatus = 402),
|
||||
expected = paymentErrorDialog
|
||||
)
|
||||
)
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.testing.endpoints.DonationResponses
|
||||
import org.thoughtcrime.securesms.testing.endpoints.EndpointResponse
|
||||
import org.thoughtcrime.securesms.testing.endpoints.MockEndpoints
|
||||
import org.thoughtcrime.securesms.testing.endpoints.StripeResponses
|
||||
import org.thoughtcrime.securesms.testing.endpoints.failure
|
||||
import org.thoughtcrime.securesms.testing.endpoints.ok
|
||||
import org.thoughtcrime.securesms.testing.endpoints.registerPayPalHappyPath
|
||||
import org.thoughtcrime.securesms.testing.endpoints.registerStripeHappyPath
|
||||
import java.util.Currency
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* A declarative "state of the world" + expected outcome for one donation checkout scenario. Specs
|
||||
* are enumerated by [DonationsCheckoutSpecTest] and each one drives [CheckoutFlowActivity] end to end
|
||||
* for its [paymentMethod].
|
||||
*/
|
||||
data class DonationsCheckoutTestSpec(
|
||||
val name: String,
|
||||
val inAppPaymentType: InAppPaymentType,
|
||||
val paymentMethod: TestPaymentMethod,
|
||||
val world: WorldState = WorldState(),
|
||||
val expected: ExpectedOutcome
|
||||
) {
|
||||
/** Used as the parameterized test label. */
|
||||
override fun toString(): String = name
|
||||
}
|
||||
|
||||
enum class TestPaymentMethod {
|
||||
GOOGLE_PAY,
|
||||
CREDIT_CARD,
|
||||
SEPA_DEBIT,
|
||||
IDEAL,
|
||||
PAYPAL
|
||||
}
|
||||
|
||||
/** Whether donation-permit acquisition succeeds or fails. */
|
||||
enum class PermitOutcome { SUCCESS, FAILURE }
|
||||
|
||||
/** The Stripe HTTP edge's behavior for a scenario. */
|
||||
enum class StripeOutcome {
|
||||
SUCCESS,
|
||||
DECLINE,
|
||||
FAILURE,
|
||||
REQUIRES_3DS
|
||||
}
|
||||
|
||||
/** Pre-existing recurring subscription state (recurring scenarios only). */
|
||||
enum class SubscriptionState { NONE, ACTIVE, PENDING }
|
||||
|
||||
/**
|
||||
* The knobs that define what each endpoint returns. [apply] registers the corresponding handlers on
|
||||
* the shared responder (overriding the [org.thoughtcrime.securesms.testing.InAppPaymentsRule]
|
||||
* defaults, since later registrations win) and sets the permit outcome.
|
||||
*/
|
||||
data class WorldState(
|
||||
val permit: PermitOutcome = PermitOutcome.SUCCESS,
|
||||
val stripe: StripeOutcome = StripeOutcome.SUCCESS,
|
||||
val declineCode: String = "card_declined",
|
||||
val signalCreatePaymentStatus: Int = 200,
|
||||
val receiptCredentialStatus: Int = 200,
|
||||
val redeemStatus: Int = 200,
|
||||
val existingSubscription: SubscriptionState = SubscriptionState.NONE,
|
||||
/** Donation currency to use. SEPA/iDEAL require EUR. */
|
||||
val currencyCode: String = "USD",
|
||||
/**
|
||||
* For a new recurring donation: report no active subscription until the subscription level is set
|
||||
* during setup, then report an active one. This lets the checkout show "Continue" (new subscriber)
|
||||
* while still letting the recurring receipt-credential context job see an active subscription to redeem.
|
||||
*/
|
||||
val recurringActivatesAfterSetup: Boolean = false
|
||||
) {
|
||||
fun apply() {
|
||||
val currency = Currency.getInstance(currencyCode)
|
||||
SignalStore.inAppPayments.setOneTimeCurrency(currency)
|
||||
SignalStore.inAppPayments.setRecurringDonationCurrency(currency)
|
||||
|
||||
when (permit) {
|
||||
PermitOutcome.SUCCESS -> succeedDonationPermitAcquisition()
|
||||
PermitOutcome.FAILURE -> failDonationPermitAcquisition()
|
||||
}
|
||||
|
||||
val responder = MockEndpoints.responder
|
||||
|
||||
// Signal-service PayPal endpoints (harmless for non-PayPal specs; distinct paths).
|
||||
responder.registerPayPalHappyPath()
|
||||
|
||||
// Stripe HTTP edge.
|
||||
responder.registerStripeHappyPath()
|
||||
when (stripe) {
|
||||
StripeOutcome.SUCCESS -> Unit
|
||||
StripeOutcome.DECLINE -> responder.register({ it.method == "POST" && (it.path.endsWith("/confirm") || it.path.contains("/payment_methods")) }) {
|
||||
failure(402, StripeResponses.declineError(declineCode))
|
||||
}
|
||||
StripeOutcome.FAILURE -> responder.register({ it.method == "POST" && it.path.endsWith("/confirm") }) {
|
||||
failure(402, StripeResponses.failureError("card_not_supported"))
|
||||
}
|
||||
StripeOutcome.REQUIRES_3DS -> responder.register({ it.method == "POST" && it.path.endsWith("/confirm") }) {
|
||||
ok(StripeResponses.confirm3dsRequired())
|
||||
}
|
||||
}
|
||||
|
||||
// Signal-service edge overrides.
|
||||
if (signalCreatePaymentStatus != 200) {
|
||||
responder.register({ it.method == "POST" && (it.path.contains("/create_payment_method") || it.path.endsWith("/boost/create")) }) {
|
||||
failure(signalCreatePaymentStatus)
|
||||
}
|
||||
}
|
||||
if (receiptCredentialStatus != 200) {
|
||||
responder.register({ it.method == "POST" && it.path.contains("/receipt_credentials") }) { failure(receiptCredentialStatus) }
|
||||
}
|
||||
if (redeemStatus != 200) {
|
||||
responder.register({ it.method == "POST" && it.path.contains("/redeem-receipt") }) { failure(redeemStatus) }
|
||||
}
|
||||
|
||||
when (existingSubscription) {
|
||||
SubscriptionState.NONE -> Unit
|
||||
SubscriptionState.ACTIVE -> registerSubscription(status = "active", active = true)
|
||||
SubscriptionState.PENDING -> registerSubscription(status = "incomplete", active = false)
|
||||
}
|
||||
|
||||
if (recurringActivatesAfterSetup) {
|
||||
val activated = AtomicBoolean(false)
|
||||
responder.register({ it.method == "PUT" && it.path.contains("/level/") }) {
|
||||
activated.set(true)
|
||||
ok()
|
||||
}
|
||||
responder.register({ it.method == "GET" && it.path.contains("/v1/subscription/") && !it.path.contains("configuration") && !it.path.contains("bank_mandate") }) {
|
||||
if (activated.get()) ok(DonationResponses.activeSubscription()) else ok(DonationResponses.emptySubscription())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerSubscription(status: String, active: Boolean) {
|
||||
MockEndpoints.responder.register({ it.method == "GET" && it.path.contains("/v1/subscription/") && !it.path.contains("configuration") }) {
|
||||
EndpointResponse(status = 200, body = DonationResponses.activeSubscription(status = status, active = active))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The expected terminal result of driving a spec. */
|
||||
sealed interface ExpectedOutcome {
|
||||
/** An error dialog with [titleRes] (and optionally [messageRes]) is shown. */
|
||||
data class ErrorDialog(@StringRes val titleRes: Int, @StringRes val messageRes: Int? = null) : ExpectedOutcome
|
||||
|
||||
/** The full lifecycle completes and a donation receipt is recorded. */
|
||||
data object Redeemed : ExpectedOutcome
|
||||
|
||||
/**
|
||||
* Payment setup succeeded and the payment moved past [org.thoughtcrime.securesms.database.InAppPaymentTable.State.CREATED]
|
||||
* with no error. Used for bank-transfer methods (SEPA/iDEAL), which don't redeem immediately —
|
||||
* they land in a pending / awaiting-authorization state.
|
||||
*/
|
||||
data object PaymentSubmitted : ExpectedOutcome
|
||||
}
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isInstanceOf
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.MainActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalFragment
|
||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
* Entry-path coverage for the inline chat donation prompt: the Release-Channel "donation request"
|
||||
* conversation item that renders a "Donate" action button and opens the one-time checkout.
|
||||
*
|
||||
* The conversation is hosted by [MainActivity], so this drives it the same way
|
||||
* [org.thoughtcrime.securesms.main.MainNavigationLaunchTest] does — a manual lifecycle-callback launch
|
||||
* plus direct view interaction, since ActivityScenario/Espresso misbehave for the conversation
|
||||
* custom-action intent.
|
||||
*
|
||||
* Unlike the megaphone and subscriber-upsell paths, this prompt is intentionally NOT gated by sustainer
|
||||
* status; [sustainer_donatePromptStillShown] documents that.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class InlineDonationPromptTest {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule()
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
private val context: Context get() = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
SignalStore.inAppPayments.setLastEndOfPeriod(0L)
|
||||
SignalDatabase.recipients.setBadges(Recipient.self().id, emptyList())
|
||||
Recipient.self().fresh()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nonSustainer_donatePromptOpensOneTimeCheckout() {
|
||||
seedDonationRequest()
|
||||
|
||||
assertDonatePromptOpensCheckout()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sustainer_donatePromptStillShown() {
|
||||
SignalStore.inAppPayments.setLastEndOfPeriod(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) + TimeUnit.DAYS.toSeconds(30))
|
||||
SignalDatabase.recipients.setBadges(Recipient.self().id, listOf(donorBadge()))
|
||||
Recipient.self().fresh()
|
||||
|
||||
seedDonationRequest()
|
||||
|
||||
assertDonatePromptOpensCheckout()
|
||||
}
|
||||
|
||||
private fun assertDonatePromptOpensCheckout() {
|
||||
val activity = launchConversation()
|
||||
|
||||
val donateButton = awaitView(activity, R.id.conversation_update_action)
|
||||
runOnMainSync { donateButton.performClick() }
|
||||
|
||||
val dialog = await(description = "one-time checkout dialog") {
|
||||
activity.supportFragmentManager.findFragmentByTag(ONE_TIME_NAV_TAG)
|
||||
}
|
||||
|
||||
assertThat(dialog).isInstanceOf(DonateToSignalFragment.Dialog::class)
|
||||
val type = dialog.requireArguments().getSerializableCompat(DonateToSignalFragment.Dialog.ARG, InAppPaymentType::class.java)
|
||||
assertThat(type).isEqualTo(InAppPaymentType.ONE_TIME_DONATION)
|
||||
}
|
||||
|
||||
private fun seedDonationRequest() {
|
||||
val recipientId: RecipientId = SignalDatabase.recipients.insertReleaseChannelRecipient()
|
||||
SignalStore.releaseChannel.setReleaseChannelRecipientId(recipientId)
|
||||
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(recipientId))
|
||||
SignalDatabase.messages.insertBoostRequestMessage(recipientId, threadId)
|
||||
}
|
||||
|
||||
private fun launchConversation(): MainActivity {
|
||||
val recipientId = SignalStore.releaseChannel.releaseChannelRecipientId!!
|
||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(Recipient.resolved(recipientId))
|
||||
|
||||
val conversationIntent = ConversationIntents.createBuilder(context, recipientId, threadId).blockingGet().build()
|
||||
val launchIntent = Intent(context, MainActivity::class.java).apply {
|
||||
action = ConversationIntents.ACTION
|
||||
putExtras(conversationIntent)
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
}
|
||||
|
||||
val app = context.applicationContext as Application
|
||||
val resumed = CountDownLatch(1)
|
||||
val holder = arrayOfNulls<MainActivity>(1)
|
||||
val callbacks = object : Application.ActivityLifecycleCallbacks {
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) = Unit
|
||||
|
||||
// Capture on resume rather than create: a CLEAR_TOP|SINGLE_TOP conversation intent may be
|
||||
// delivered to an existing MainActivity via onNewIntent, which never fires onActivityCreated.
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
if (activity is MainActivity) {
|
||||
holder[0] = activity
|
||||
resumed.countDown()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) = Unit
|
||||
override fun onActivityPaused(activity: Activity) = Unit
|
||||
override fun onActivityStopped(activity: Activity) = Unit
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
|
||||
override fun onActivityDestroyed(activity: Activity) = Unit
|
||||
}
|
||||
app.registerActivityLifecycleCallbacks(callbacks)
|
||||
|
||||
app.startActivity(launchIntent)
|
||||
if (!resumed.await(15, TimeUnit.SECONDS)) {
|
||||
app.unregisterActivityLifecycleCallbacks(callbacks)
|
||||
error("MainActivity did not reach RESUMED within 15s")
|
||||
}
|
||||
app.unregisterActivityLifecycleCallbacks(callbacks)
|
||||
|
||||
return holder[0] ?: error("MainActivity was not captured")
|
||||
}
|
||||
|
||||
private fun awaitView(activity: FragmentActivity, viewId: Int): View {
|
||||
return await(description = "view $viewId") {
|
||||
activity.findViewById<View>(viewId)?.takeIf { it.isShown }
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> await(
|
||||
timeoutMs: Long = 15_000,
|
||||
pollMs: Long = 50,
|
||||
description: String,
|
||||
supplier: () -> T?
|
||||
): T {
|
||||
val deadline = System.currentTimeMillis() + timeoutMs
|
||||
while (System.currentTimeMillis() < deadline) {
|
||||
val result = runOnMainSync(supplier)
|
||||
if (result != null) return result
|
||||
Thread.sleep(pollMs)
|
||||
}
|
||||
error("Timed out after ${timeoutMs}ms waiting for $description")
|
||||
}
|
||||
|
||||
private fun <T> runOnMainSync(block: () -> T): T {
|
||||
var result: Result<T> = Result.failure(IllegalStateException("runOnMainSync produced no result"))
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync { result = runCatching(block) }
|
||||
return result.getOrThrow()
|
||||
}
|
||||
|
||||
private fun donorBadge(): Badge {
|
||||
return Badge(
|
||||
id = "test-donor-badge",
|
||||
category = Badge.Category.Donor,
|
||||
name = "Signal Sustainer",
|
||||
description = "",
|
||||
imageUrl = Uri.EMPTY,
|
||||
imageDensity = "xxhdpi",
|
||||
expirationTimestamp = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30),
|
||||
visible = true,
|
||||
duration = TimeUnit.DAYS.toMillis(30)
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ONE_TIME_NAV_TAG = "one_time_nav"
|
||||
}
|
||||
}
|
||||
+58
-3
@@ -3,19 +3,28 @@ package org.thoughtcrime.securesms.dependencies
|
||||
import android.app.Application
|
||||
import io.mockk.mockk
|
||||
import io.mockk.spyk
|
||||
import okhttp3.OkHttpClient
|
||||
import org.signal.core.util.UptimeSleepTimer
|
||||
import org.signal.core.util.billing.BillingApi
|
||||
import org.signal.libsignal.net.Network
|
||||
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations
|
||||
import org.signal.network.api.ArchiveApi
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
|
||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache
|
||||
import org.thoughtcrime.securesms.testing.endpoints.DonationTestServer
|
||||
import org.thoughtcrime.securesms.testing.endpoints.MockEndpoints
|
||||
import org.thoughtcrime.securesms.testing.endpoints.ResponderInterceptor
|
||||
import org.thoughtcrime.securesms.testing.endpoints.ResponderWebSocketConnection
|
||||
import org.whispersystems.signalservice.api.SignalServiceDataStore
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender
|
||||
import org.whispersystems.signalservice.api.account.AccountApi
|
||||
import org.whispersystems.signalservice.api.donations.DonationsApi
|
||||
import org.whispersystems.signalservice.api.keys.KeysApi
|
||||
import org.whispersystems.signalservice.api.message.MessageApi
|
||||
import org.whispersystems.signalservice.api.websocket.SignalWebSocket
|
||||
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration
|
||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket
|
||||
import java.util.function.Supplier
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Dependency provider used for instrumentation tests (aka androidTests).
|
||||
@@ -45,8 +54,54 @@ class InstrumentationApplicationDependencyProvider(val application: Application,
|
||||
return mockk()
|
||||
}
|
||||
|
||||
override fun provideDonationsApi(authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): DonationsApi {
|
||||
return mockk()
|
||||
/**
|
||||
* Adds the Stripe-matching [ResponderInterceptor] on top of the default client (which supplies the
|
||||
* user agent + DNS), so `api.stripe.com` requests made by [org.signal.donations.StripeApi] are
|
||||
* answered from the shared [MockEndpoints.responder] and never hit the real network.
|
||||
*/
|
||||
override fun provideOkHttpClient(): OkHttpClient {
|
||||
return default.provideOkHttpClient()
|
||||
.newBuilder()
|
||||
.addInterceptor(ResponderInterceptor(MockEndpoints.responder))
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Backs the real [org.whispersystems.signalservice.api.donations.DonationsApi] (and any other
|
||||
* websocket API) with a [ResponderWebSocketConnection] driven by the shared [MockEndpoints.responder],
|
||||
* so Signal-service requests are answered from the scenario's "world" and never hit the network.
|
||||
*/
|
||||
override fun provideAuthWebSocket(
|
||||
signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>,
|
||||
libSignalNetworkSupplier: Supplier<Network>
|
||||
): SignalWebSocket.AuthenticatedWebSocket {
|
||||
return SignalWebSocket.AuthenticatedWebSocket(
|
||||
connectionFactory = { ResponderWebSocketConnection(MockEndpoints.responder) },
|
||||
canConnect = { true },
|
||||
sleepTimer = UptimeSleepTimer(),
|
||||
disconnectTimeoutMs = 15.seconds.inWholeMilliseconds
|
||||
)
|
||||
}
|
||||
|
||||
override fun provideUnauthWebSocket(
|
||||
signalServiceConfigurationSupplier: Supplier<SignalServiceConfiguration>,
|
||||
libSignalNetworkSupplier: Supplier<Network>
|
||||
): SignalWebSocket.UnauthenticatedWebSocket {
|
||||
return SignalWebSocket.UnauthenticatedWebSocket(
|
||||
connectionFactory = { ResponderWebSocketConnection(MockEndpoints.responder) },
|
||||
canConnect = { true },
|
||||
sleepTimer = UptimeSleepTimer(),
|
||||
disconnectTimeoutMs = 15.seconds.inWholeMilliseconds
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the test zk server's public params so credentials minted by [MockEndpoints] validate here.
|
||||
* The real [ClientZkReceiptOperations.receiveReceiptCredential] validation still runs in the
|
||||
* receipt-credential context job — only the params are swapped for test ones.
|
||||
*/
|
||||
override fun provideClientZkReceiptOperations(signalServiceConfiguration: SignalServiceConfiguration): ClientZkReceiptOperations {
|
||||
return DonationTestServer.clientReceiptOperations
|
||||
}
|
||||
|
||||
override fun provideSignalServiceMessageSender(
|
||||
|
||||
-2
@@ -121,8 +121,6 @@ class BackupSubscriptionCheckJobTest {
|
||||
)
|
||||
)
|
||||
|
||||
every { AppDependencies.donationsApi.putSubscription(any()) } returns NetworkResult.Success(Unit)
|
||||
|
||||
insertSubscriber()
|
||||
}
|
||||
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.megaphone
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isFalse
|
||||
import assertk.assertions.isNull
|
||||
import assertk.assertions.isTrue
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkObject
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkObject
|
||||
import io.mockk.unmockkStatic
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.util.deleteAll
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.util.VersionTracker
|
||||
|
||||
/**
|
||||
* The "user might be a sustainer" rule for the donations remote megaphone: the `standard_donate`
|
||||
* conditional (via [RemoteMegaphoneRepository.getRemoteMegaphoneToShow]) suppresses the megaphone for
|
||||
* existing donors and shows it otherwise.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class DonationMegaphoneGatingTest {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule()
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
SignalDatabase.inAppPayments.writableDatabase.deleteAll(InAppPaymentTable.TABLE_NAME)
|
||||
SignalDatabase.remoteMegaphones.debugRemoveAll()
|
||||
setSelfBadges(emptyList())
|
||||
|
||||
// Freshly-installed test APKs report 0 days installed and no configured payment methods, both of
|
||||
// which independently fail shouldShowDonateMegaphone. Fix them so the donor badge is the only
|
||||
// variable across the gating tests.
|
||||
mockkStatic(VersionTracker::class)
|
||||
mockkObject(InAppDonations)
|
||||
every { VersionTracker.getDaysSinceFirstInstalled(any()) } returns 30L
|
||||
every { InAppDonations.hasAtLeastOnePaymentMethodAvailable() } returns true
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkStatic(VersionTracker::class)
|
||||
unmockkObject(InAppDonations)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nonDonor_showsStandardDonateMegaphone() {
|
||||
val record = donateMegaphoneRecord(conditionalId = "standard_donate")
|
||||
SignalDatabase.remoteMegaphones.insert(record)
|
||||
|
||||
assertThat(RemoteMegaphoneRepository.getRemoteMegaphoneToShow()?.uuid).isEqualTo(record.uuid)
|
||||
assertThat(RemoteMegaphoneRepository.hasRemoteMegaphoneToShow(canShowLocalDonate = true)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sustainer_donorBadge_suppressesStandardDonateMegaphone() {
|
||||
SignalDatabase.remoteMegaphones.insert(donateMegaphoneRecord(conditionalId = "standard_donate"))
|
||||
setSelfBadges(listOf(donorBadge()))
|
||||
|
||||
assertThat(RemoteMegaphoneRepository.getRemoteMegaphoneToShow()).isNull()
|
||||
assertThat(RemoteMegaphoneRepository.hasRemoteMegaphoneToShow(canShowLocalDonate = true)).isFalse()
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.megaphone
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import assertk.assertions.isNotNull
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.signal.core.ui.compose.theme.SignalTheme
|
||||
import org.signal.core.util.getSerializableCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.RemoteMegaphoneRecord
|
||||
import org.thoughtcrime.securesms.testing.InAppPaymentsRule
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
|
||||
/**
|
||||
* Entry-path coverage for the donations remote megaphone: the megaphone shown on the conversation list
|
||||
* that carries a "Donate" action into the one-time checkout flow.
|
||||
*
|
||||
* The megaphone renders through [MegaphoneComponent], so this renders that composable directly (rather
|
||||
* than launching the full [org.thoughtcrime.securesms.MainActivity]) and asserts that tapping Donate
|
||||
* runs the production [RemoteMegaphoneRepository] action, which navigates to [CheckoutFlowActivity]
|
||||
* with [InAppPaymentType.ONE_TIME_DONATION]. The sustainer gating is covered by [DonationMegaphoneGatingTest].
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class DonationMegaphoneTest {
|
||||
|
||||
@get:Rule
|
||||
val harness = SignalActivityRule()
|
||||
|
||||
@get:Rule
|
||||
val iapRule = InAppPaymentsRule()
|
||||
|
||||
@get:Rule
|
||||
val composeRule = createComposeRule()
|
||||
|
||||
private val context: Context get() = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
SignalDatabase.remoteMegaphones.debugRemoveAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun donateMegaphone_donateClick_opensOneTimeCheckout() {
|
||||
val record = donateMegaphoneRecord(conditionalId = null)
|
||||
SignalDatabase.remoteMegaphones.insert(record)
|
||||
|
||||
val controller = RecordingMegaphoneActionController()
|
||||
|
||||
composeRule.setContent {
|
||||
SignalTheme {
|
||||
MegaphoneComponent(buildDonateMegaphone(record), controller)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText(record.primaryActionText!!).performClick()
|
||||
|
||||
val intent = controller.navigationIntent
|
||||
assertThat(intent).isNotNull()
|
||||
assertThat(intent!!.component?.className).isEqualTo(CheckoutFlowActivity::class.java.name)
|
||||
|
||||
val type = intent.extras!!.getSerializableCompat(CheckoutFlowActivity.ARG_IN_APP_PAYMENT_TYPE, InAppPaymentType::class.java)
|
||||
assertThat(type).isEqualTo(InAppPaymentType.ONE_TIME_DONATION)
|
||||
}
|
||||
|
||||
/** Mirrors [Megaphones.buildRemoteMegaphone]: wires the primary button to the real repository action. */
|
||||
private fun buildDonateMegaphone(record: RemoteMegaphoneRecord): Megaphone {
|
||||
return Megaphone.Builder(Megaphones.Event.REMOTE_MEGAPHONE, Megaphone.Style.BASIC)
|
||||
.setTitle(record.title)
|
||||
.setBody(record.body)
|
||||
.setActionButton(record.primaryActionText!!) { _, controller ->
|
||||
RemoteMegaphoneRepository.getAction(record.primaryActionId!!).run(context, controller, record)
|
||||
}
|
||||
.build()
|
||||
}
|
||||
|
||||
private class RecordingMegaphoneActionController : MegaphoneActionController {
|
||||
var navigationIntent: Intent? = null
|
||||
private set
|
||||
|
||||
override fun onMegaphoneNavigationRequested(intent: Intent) {
|
||||
navigationIntent = intent
|
||||
}
|
||||
|
||||
override fun onMegaphoneNavigationRequested(intent: Intent, requestCode: Int) {
|
||||
navigationIntent = intent
|
||||
}
|
||||
|
||||
override fun onMegaphoneToastRequested(string: String) = Unit
|
||||
override fun getMegaphoneActivity(): Activity = throw UnsupportedOperationException("not used")
|
||||
override fun onMegaphoneSnooze(event: Megaphones.Event) = Unit
|
||||
override fun onMegaphoneCompleted(event: Megaphones.Event) = Unit
|
||||
override fun onMegaphoneDialogFragmentRequested(dialogFragment: DialogFragment) = Unit
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.megaphone
|
||||
|
||||
import android.net.Uri
|
||||
import org.thoughtcrime.securesms.badges.models.Badge
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.RemoteMegaphoneRecord
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
fun donateMegaphoneRecord(conditionalId: String?): RemoteMegaphoneRecord {
|
||||
val now = System.currentTimeMillis()
|
||||
return RemoteMegaphoneRecord(
|
||||
priority = 100,
|
||||
uuid = UUID.randomUUID().toString(),
|
||||
countries = null,
|
||||
minimumVersion = 1,
|
||||
doNotShowBefore = now - TimeUnit.DAYS.toMillis(2),
|
||||
doNotShowAfter = now + TimeUnit.DAYS.toMillis(28),
|
||||
showForNumberOfDays = 30,
|
||||
conditionalId = conditionalId,
|
||||
primaryActionId = RemoteMegaphoneRecord.ActionId.DONATE,
|
||||
secondaryActionId = RemoteMegaphoneRecord.ActionId.SNOOZE,
|
||||
imageUrl = null,
|
||||
title = "Donate Test",
|
||||
body = "Donate body test.",
|
||||
primaryActionText = "Donate",
|
||||
secondaryActionText = "Snooze"
|
||||
)
|
||||
}
|
||||
|
||||
fun donorBadge(): Badge {
|
||||
return Badge(
|
||||
id = "test-donor-badge",
|
||||
category = Badge.Category.Donor,
|
||||
name = "Signal Sustainer",
|
||||
description = "",
|
||||
imageUrl = Uri.EMPTY,
|
||||
imageDensity = "xxhdpi",
|
||||
expirationTimestamp = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(30),
|
||||
visible = true,
|
||||
duration = TimeUnit.DAYS.toMillis(30)
|
||||
)
|
||||
}
|
||||
|
||||
fun setSelfBadges(badges: List<Badge>) {
|
||||
SignalDatabase.recipients.setBadges(Recipient.self().id, badges)
|
||||
Recipient.self().fresh()
|
||||
}
|
||||
+9
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.testing.MessageContentFuzzer
|
||||
import org.thoughtcrime.securesms.testing.SignalActivityRule
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.internal.push.AddressableMessage
|
||||
import org.whispersystems.signalservice.internal.push.AttachmentPointer
|
||||
@@ -51,6 +52,14 @@ class SyncMessageProcessorTest_attachmentBackfill {
|
||||
originalDeviceId = SignalStore.account.deviceId
|
||||
// Make this device a linked device so backfill response handling activates.
|
||||
SignalStore.account.deviceId = 2
|
||||
|
||||
// Prevent AttachmentDownloadJob onAdded from async changing the attachment state.
|
||||
TextSecurePreferences.getSharedPreferences(harness.application)
|
||||
.edit()
|
||||
.putStringSet(TextSecurePreferences.MEDIA_DOWNLOAD_WIFI_PREF, emptySet())
|
||||
.putStringSet(TextSecurePreferences.MEDIA_DOWNLOAD_MOBILE_PREF, emptySet())
|
||||
.putStringSet(TextSecurePreferences.MEDIA_DOWNLOAD_ROAMING_PREF, emptySet())
|
||||
.commit()
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -7,43 +7,90 @@ package org.thoughtcrime.securesms.testing
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import io.mockk.every
|
||||
import org.json.JSONObject
|
||||
import org.junit.rules.ExternalResource
|
||||
import org.signal.core.util.JsonUtils
|
||||
import org.signal.network.NetworkResult
|
||||
import org.signal.network.exceptions.NonSuccessfulResponseCodeException
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
||||
import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration
|
||||
import org.thoughtcrime.securesms.testing.endpoints.DonationResponses
|
||||
import org.thoughtcrime.securesms.testing.endpoints.DonationTestServer
|
||||
import org.thoughtcrime.securesms.testing.endpoints.EndpointResponse
|
||||
import org.thoughtcrime.securesms.testing.endpoints.MockEndpoints
|
||||
import org.thoughtcrime.securesms.testing.endpoints.delete
|
||||
import org.thoughtcrime.securesms.testing.endpoints.get
|
||||
import org.thoughtcrime.securesms.testing.endpoints.ok
|
||||
import org.thoughtcrime.securesms.testing.endpoints.post
|
||||
import org.thoughtcrime.securesms.testing.endpoints.put
|
||||
import org.whispersystems.signalservice.internal.push.WhoAmIResponse
|
||||
|
||||
/**
|
||||
* Sets up some common infrastructure for on-device InAppPayment testing
|
||||
* Sets up common infrastructure for on-device InAppPayment testing.
|
||||
*
|
||||
* The Signal-service edge is driven through the shared [MockEndpoints.responder] (the real
|
||||
* [org.whispersystems.signalservice.api.donations.DonationsApi] runs against these handlers), while
|
||||
* account/archive lookups that are not websocket-backed here stay mocked via mockk. A scenario can
|
||||
* override any default by registering a more specific handler after this rule runs (last-registered
|
||||
* wins).
|
||||
*/
|
||||
class InAppPaymentsRule : ExternalResource() {
|
||||
|
||||
override fun before() {
|
||||
initialiseConfigurationResponse()
|
||||
initialisePutSubscription()
|
||||
MockEndpoints.responder.clear()
|
||||
registerDonationServiceDefaults()
|
||||
initialiseSetArchiveBackupId()
|
||||
initialiseSetAccountAttributes()
|
||||
initialiseAccountAndSubscriptionLookups()
|
||||
initialiseAccountLookups()
|
||||
}
|
||||
|
||||
private fun initialiseConfigurationResponse() {
|
||||
val assets = InstrumentationRegistry.getInstrumentation().context.resources.assets
|
||||
val response = assets.open("inAppPaymentsTests/configuration.json").use { stream ->
|
||||
NetworkResult.Success(JsonUtils.fromJson(stream, SubscriptionsConfiguration::class.java))
|
||||
}
|
||||
|
||||
AppDependencies.donationsApi.apply {
|
||||
every { getDonationsConfiguration(any()) } returns response
|
||||
}
|
||||
override fun after() {
|
||||
MockEndpoints.responder.clear()
|
||||
}
|
||||
|
||||
private fun initialisePutSubscription() {
|
||||
AppDependencies.donationsApi.apply {
|
||||
every { putSubscription(any()) } returns NetworkResult.Success(Unit)
|
||||
every { createSubscriber(any(), any()) } returns NetworkResult.Success(Unit)
|
||||
/**
|
||||
* Default happy-path responses for the Signal donations endpoints. Registered generic-to-specific
|
||||
* so more specific paths registered later win.
|
||||
*/
|
||||
private fun registerDonationServiceDefaults() {
|
||||
val responder = MockEndpoints.responder
|
||||
|
||||
// Subscriber lifecycle: create/put/update-level (PUT), cancel (DELETE) all succeed by default.
|
||||
responder.put("/v1/subscription/") { ok() }
|
||||
responder.delete("/v1/subscription/") { ok() }
|
||||
|
||||
// getSubscription defaults to "no active subscription".
|
||||
responder.get("/v1/subscription/") { ok(DonationResponses.emptySubscription()) }
|
||||
|
||||
// Donations configuration (registered after the generic GET so it wins for its path).
|
||||
val configuration = InstrumentationRegistry.getInstrumentation().context.resources.assets
|
||||
.open("inAppPaymentsTests/configuration.json")
|
||||
.use { it.readBytes().decodeToString() }
|
||||
responder.get("/v1/subscription/configuration") { ok(configuration) }
|
||||
|
||||
// SEPA bank-transfer mandate text (registered after the generic GET so it wins for its path).
|
||||
responder.get("/v1/subscription/bank_mandate/") { ok(DonationResponses.bankMandate()) }
|
||||
|
||||
// One-time (boost) payment intent.
|
||||
responder.post("/v1/subscription/boost/create") { ok(DonationResponses.stripeClientSecret()) }
|
||||
|
||||
// Recurring payment method setup + default payment method + level are keyed by subscriber id in
|
||||
// the middle of the path, so match on a distinctive suffix.
|
||||
responder.register({ it.method == "POST" && it.path.contains("/create_payment_method") && !it.path.contains("paypal") }) {
|
||||
ok(DonationResponses.setupIntentClientSecret())
|
||||
}
|
||||
responder.register({ it.method == "POST" && it.path.contains("/default_payment_method") }) { ok() }
|
||||
|
||||
// Receipt credential submission (boost + recurring) — mint a valid credential from the client's request.
|
||||
responder.register({ it.method == "POST" && it.path.contains("/receipt_credentials") }) { request ->
|
||||
mintReceiptCredential(request.bodyString)
|
||||
}
|
||||
|
||||
// Redemption.
|
||||
responder.post("/v1/donation/redeem-receipt") { ok() }
|
||||
}
|
||||
|
||||
private fun mintReceiptCredential(requestBody: String): EndpointResponse {
|
||||
val requestBase64 = JSONObject(requestBody).getString("receiptCredentialRequest")
|
||||
val minted = DonationTestServer.issueReceiptCredential(requestBase64)
|
||||
return ok(DonationResponses.receiptCredential(minted))
|
||||
}
|
||||
|
||||
private fun initialiseSetArchiveBackupId() {
|
||||
@@ -59,23 +106,12 @@ class InAppPaymentsRule : ExternalResource() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting the real job loop lets background jobs unrelated to the assertion under test run against the strict
|
||||
* API mocks (e.g. [org.thoughtcrime.securesms.jobs.InAppPaymentRecurringContextJob] querying whoAmI, the
|
||||
* active subscription, and then submitting receipt credentials). Stub these calls so those jobs hit a handled
|
||||
* path and terminate quietly instead of throwing [io.mockk.MockKException] on a job thread, which crashes the
|
||||
* whole app process (the test asserts nothing, so it surfaces as "Application crashed" with no failed test).
|
||||
* Tests that supply an active subscription push the job past the [getSubscription] guard to
|
||||
* [submitReceiptCredentials], so that must be stubbed too. End-to-end coverage of that pipeline is tracked
|
||||
* separately; here we only keep the process alive and the logs clean.
|
||||
* whoAmI is served by the (still mocked) account API rather than the websocket responder, so
|
||||
* background jobs that resolve the account during a test hit a handled path instead of throwing.
|
||||
*/
|
||||
private fun initialiseAccountAndSubscriptionLookups() {
|
||||
private fun initialiseAccountLookups() {
|
||||
AppDependencies.accountApi.apply {
|
||||
every { whoAmI() } returns NetworkResult.Success(WhoAmIResponse(number = "+15555550123"))
|
||||
}
|
||||
|
||||
AppDependencies.donationsApi.apply {
|
||||
every { getSubscription(any()) } returns NetworkResult.Success(ActiveSubscription.EMPTY)
|
||||
every { submitReceiptCredentials(any(), any()) } returns NetworkResult.StatusCodeError(NonSuccessfulResponseCodeException(402))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.signal.benchmark.setup.Harness
|
||||
import org.signal.benchmark.setup.OtherClient
|
||||
import org.signal.core.util.ThreadUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.network.websocket.WebSocketRequestMessage
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.TestDbUtils
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
@@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.whispersystems.signalservice.internal.push.Envelope
|
||||
import org.whispersystems.signalservice.internal.websocket.BenchmarkWebSocketConnection
|
||||
import org.signal.network.websocket.WebSocketRequestMessage
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
|
||||
@@ -78,7 +78,6 @@ class NoOpJob(parameters: Parameters) : Job(parameters) {
|
||||
StoryOnboardingDownloadJob.KEY
|
||||
)
|
||||
|
||||
fun replaceFactories(factories: Map<String, Job.Factory<*>>): Map<String, Job.Factory<*>> =
|
||||
factories.mapValues { if (it.key in STARTUP_NETWORK_JOB_KEYS) Factory() else it.value }
|
||||
fun replaceFactories(factories: Map<String, Job.Factory<*>>): Map<String, Job.Factory<*>> = factories.mapValues { if (it.key in STARTUP_NETWORK_JOB_KEYS) Factory() else it.value }
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,10 +8,10 @@ package org.whispersystems.signalservice.internal.websocket
|
||||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import org.signal.core.util.JsonUtils
|
||||
import org.signal.network.websocket.WebSocketRequestMessage
|
||||
import org.signal.network.websocket.WebSocketResponseMessage
|
||||
import org.signal.network.websocket.WebsocketResponse
|
||||
import org.signal.core.util.JsonUtils
|
||||
import org.thoughtcrime.securesms.util.SignalTrace
|
||||
import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState
|
||||
import org.whispersystems.signalservice.internal.push.SendMessageResponse
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -76,6 +76,7 @@ import androidx.lifecycle.createSavedStateHandle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
|
||||
import androidx.navigation3.ui.NavDisplay
|
||||
@@ -673,23 +674,23 @@ class MainActivity :
|
||||
primaryContent = {
|
||||
when (mainNavigationState.currentListLocation) {
|
||||
MainNavigationListLocation.CHATS, MainNavigationListLocation.ARCHIVE -> {
|
||||
NavDisplay(
|
||||
NavDisplay<NavKey>(
|
||||
backStack = mainNavigationViewModel.chatsBackStackEntries,
|
||||
onBack = { mainNavigationViewModel.popChatsDetailLocation() },
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec,
|
||||
transitionSpec = { TransitionSpecs.HorizontalSlide.transitionSpec },
|
||||
popTransitionSpec = { TransitionSpecs.HorizontalSlide.popTransitionSpec },
|
||||
predictivePopTransitionSpec = { TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec },
|
||||
entryProvider = entryProvider { chatsNavEntries(convoTransitionState) }
|
||||
)
|
||||
}
|
||||
|
||||
MainNavigationListLocation.CALLS -> {
|
||||
NavDisplay(
|
||||
NavDisplay<NavKey>(
|
||||
backStack = mainNavigationViewModel.callsBackStackEntries,
|
||||
onBack = { mainNavigationViewModel.popCallsDetailLocation() },
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec,
|
||||
transitionSpec = { TransitionSpecs.HorizontalSlide.transitionSpec },
|
||||
popTransitionSpec = { TransitionSpecs.HorizontalSlide.popTransitionSpec },
|
||||
predictivePopTransitionSpec = { TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec },
|
||||
entryDecorators = listOf(
|
||||
rememberSaveableStateHolderNavEntryDecorator(),
|
||||
rememberViewModelStoreNavEntryDecorator()
|
||||
@@ -699,12 +700,12 @@ class MainActivity :
|
||||
}
|
||||
|
||||
MainNavigationListLocation.STORIES -> {
|
||||
NavDisplay(
|
||||
NavDisplay<NavKey>(
|
||||
backStack = mainNavigationViewModel.storiesBackStackEntries,
|
||||
onBack = { mainNavigationViewModel.popStoriesDetailLocation() },
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec,
|
||||
transitionSpec = { TransitionSpecs.HorizontalSlide.transitionSpec },
|
||||
popTransitionSpec = { TransitionSpecs.HorizontalSlide.popTransitionSpec },
|
||||
predictivePopTransitionSpec = { TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec },
|
||||
entryDecorators = listOf(
|
||||
rememberSaveableStateHolderNavEntryDecorator(),
|
||||
rememberViewModelStoreNavEntryDecorator()
|
||||
|
||||
@@ -255,6 +255,9 @@ public abstract class PassphraseRequiredActivity extends BaseActivity implements
|
||||
}
|
||||
|
||||
private Intent getTransferOrRestoreIntent() {
|
||||
if (Environment.USE_NEW_REGISTRATION) {
|
||||
return org.signal.registration.RegistrationActivity.createIntent(this, MainActivity.clearTop(this));
|
||||
}
|
||||
Intent intent = RestoreActivity.getRestoreIntent(this);
|
||||
return getRoutedIntent(intent, MainActivity.clearTop(this));
|
||||
}
|
||||
|
||||
@@ -79,7 +79,13 @@ class SystemContactsEntrypointViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
private fun getDestinationForSyncAdapter(context: Context, intent: Intent): DestinationAndBody {
|
||||
context.contentResolver.query(intent.data!!, null, null, null, null).use { cursor ->
|
||||
val uri = intent.data
|
||||
if (uri == null || uri.authority != ContactsContract.AUTHORITY) {
|
||||
Log.w(TAG, "Ignoring content URI with an unexpected authority.")
|
||||
return DestinationAndBody("", "")
|
||||
}
|
||||
|
||||
context.contentResolver.query(uri, null, null, null, null).use { cursor ->
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return DestinationAndBody(cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.RawContacts.Data.DATA1)), "")
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.database.KyberPreKeyTable
|
||||
import org.thoughtcrime.securesms.database.OneTimePreKeyTable
|
||||
import org.thoughtcrime.securesms.database.SearchTable
|
||||
import org.thoughtcrime.securesms.database.SessionTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.SignedPreKeyTable
|
||||
import org.thoughtcrime.securesms.database.StickerTable
|
||||
@@ -1126,7 +1127,7 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
return frameReader.use { reader ->
|
||||
import(reader, selfData, cancellationSignal = { false })
|
||||
import(reader, selfData, backupMode = BackupMode.LOCAL, cancellationSignal = { false })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1157,7 +1158,7 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
return frameReader.use { reader ->
|
||||
import(reader, selfData, cancellationSignal)
|
||||
import(reader, selfData, backupMode = BackupMode.REMOTE, cancellationSignal = cancellationSignal)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Unable to restore signal backup", e)
|
||||
@@ -1185,7 +1186,7 @@ object BackupRepository {
|
||||
)
|
||||
|
||||
return frameReader.use { reader ->
|
||||
import(reader, selfData, cancellationSignal)
|
||||
import(reader, selfData, backupMode = BackupMode.LINK_SYNC, cancellationSignal = cancellationSignal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1211,7 +1212,7 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
return frameReader.use { reader ->
|
||||
import(reader, selfData, cancellationSignal)
|
||||
import(reader, selfData, backupMode = BackupMode.REMOTE, cancellationSignal = cancellationSignal)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1227,13 +1228,14 @@ object BackupRepository {
|
||||
val frameReader = PlainTextBackupReader(inputStreamFactory(), length)
|
||||
|
||||
return frameReader.use { reader ->
|
||||
import(reader, selfData, cancellationSignal)
|
||||
import(reader, selfData, backupMode = BackupMode.PLAINTEXT_EXPORT, cancellationSignal = cancellationSignal)
|
||||
}
|
||||
}
|
||||
|
||||
private fun import(
|
||||
frameReader: BackupImportReader,
|
||||
selfData: SelfData,
|
||||
backupMode: BackupMode,
|
||||
cancellationSignal: () -> Boolean
|
||||
): ImportResult {
|
||||
val stopwatch = Stopwatch("import")
|
||||
@@ -1291,7 +1293,16 @@ object BackupRepository {
|
||||
}
|
||||
|
||||
Log.d(TAG, "[import] --- Recreating all tables ---")
|
||||
val skipTables = setOf(KyberPreKeyTable.TABLE_NAME, OneTimePreKeyTable.TABLE_NAME, SignedPreKeyTable.TABLE_NAME)
|
||||
val skipTables = buildSet {
|
||||
add(KyberPreKeyTable.TABLE_NAME)
|
||||
add(OneTimePreKeyTable.TABLE_NAME)
|
||||
add(SignedPreKeyTable.TABLE_NAME)
|
||||
|
||||
// Preserve the session established with the primary during linking
|
||||
if (backupMode.isLinkAndSync) {
|
||||
add(SessionTable.TABLE_NAME)
|
||||
}
|
||||
}
|
||||
val tableMetadata = SignalDatabase.rawDatabase.getAllTableDefinitions().filter { !it.name.startsWith(SearchTable.FTS_TABLE_NAME + "_") }
|
||||
for (table in tableMetadata) {
|
||||
if (skipTables.contains(table.name)) {
|
||||
@@ -1664,6 +1675,19 @@ object BackupRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the remote backup's last-modified time in [BackupValues.lastBackupTime], (404/401 clear it to 0).
|
||||
*/
|
||||
fun refreshBackupFileTimestamp(): NetworkResult<ZonedDateTime> {
|
||||
return getBackupFileLastModified().also { result ->
|
||||
when (result) {
|
||||
is NetworkResult.Success -> SignalStore.backup.lastBackupTime = result.result.toMillis()
|
||||
is NetworkResult.StatusCodeError if (result.code == 404 || result.code == 401) -> SignalStore.backup.lastBackupTime = 0L
|
||||
else -> Log.w(TAG, "Failed to refresh last backup time from remote: ${result::class.simpleName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object with details about the remote backup state.
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.thoughtcrime.securesms.backup.v2
|
||||
|
||||
import org.signal.core.util.LongSerializer
|
||||
import org.signal.libsignal.zkgroup.backups.BackupLevel
|
||||
|
||||
/**
|
||||
* Serializable enum value for what we think a user's current backup tier is.
|
||||
@@ -18,6 +19,13 @@ enum class MessageBackupTier(val value: Int) {
|
||||
FREE(0),
|
||||
PAID(1);
|
||||
|
||||
fun toBackupLevel(): Long {
|
||||
return when (this) {
|
||||
FREE -> BackupLevel.FREE.value.toLong()
|
||||
PAID -> BackupLevel.PAID.value.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
companion object Serializer : LongSerializer<MessageBackupTier?> {
|
||||
override fun serialize(data: MessageBackupTier?): Long {
|
||||
return data?.value?.toLong() ?: -1
|
||||
@@ -26,5 +34,13 @@ enum class MessageBackupTier(val value: Int) {
|
||||
override fun deserialize(data: Long): MessageBackupTier? {
|
||||
return entries.firstOrNull { it.value == data.toInt() }
|
||||
}
|
||||
|
||||
fun fromBackupLevel(backupLevel: Long?): MessageBackupTier? {
|
||||
return when (backupLevel) {
|
||||
BackupLevel.FREE.value.toLong() -> FREE
|
||||
BackupLevel.PAID.value.toLong() -> PAID
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.signal.core.util.toJson
|
||||
import org.signal.libsignal.crypto.Aes256Ctr32
|
||||
import org.thoughtcrime.securesms.backup.LocalExportProgress
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportResult
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
@@ -269,13 +270,18 @@ object LocalArchiver {
|
||||
|
||||
val mainStreamLength = snapshotFileSystem.mainLength() ?: return ArchiveResult.failure(RestoreFailure.MainStream)
|
||||
|
||||
BackupRepository.importLocal(
|
||||
val importResult = BackupRepository.importLocal(
|
||||
mainStreamFactory = { snapshotFileSystem.mainInputStream()!! },
|
||||
mainStreamLength = mainStreamLength,
|
||||
selfData = selfData,
|
||||
backupId = backupId,
|
||||
messageBackupKey = messageBackupKey
|
||||
)
|
||||
|
||||
if (importResult is ImportResult.Failure) {
|
||||
Log.w(TAG, "Local backup import failed")
|
||||
return RestoreResult.failure(RestoreFailure.ImportFailed)
|
||||
}
|
||||
} finally {
|
||||
metadataStream?.close()
|
||||
}
|
||||
@@ -350,6 +356,7 @@ object LocalArchiver {
|
||||
data object MainStream : RestoreFailure
|
||||
data object Cancelled : RestoreFailure
|
||||
data object BackupIdMissing : RestoreFailure
|
||||
data object ImportFailed : RestoreFailure
|
||||
data class VersionMismatch(val backupVersion: Int, val supportedVersion: Int) : RestoreFailure
|
||||
}
|
||||
|
||||
|
||||
+2
-19
@@ -16,7 +16,6 @@ import org.signal.core.models.database.AttachmentId
|
||||
import org.signal.core.util.UuidUtil
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.toByteArray
|
||||
import org.signal.libsignal.zkgroup.backups.BackupLevel
|
||||
import org.signal.mediasend.SentMediaQuality
|
||||
import org.thoughtcrime.securesms.backup.v2.ExportState
|
||||
import org.thoughtcrime.securesms.backup.v2.ImportState
|
||||
@@ -127,7 +126,7 @@ object AccountDataArchiveProcessor {
|
||||
hasCompletedUsernameOnboarding = signalStore.uiHintValues.hasCompletedUsernameOnboarding(),
|
||||
customChatColors = db.chatColorsTable.getSavedChatColors().toRemoteChatColors().also { colors -> exportState.customChatColorIds.addAll(colors.map { it.id }) },
|
||||
optimizeOnDeviceStorage = signalStore.backupValues.optimizeStorage && signalStore.backupValues.backupTier == MessageBackupTier.PAID,
|
||||
backupTier = signalStore.backupValues.backupTier.toRemoteBackupTier(),
|
||||
backupTier = signalStore.backupValues.backupTier?.toBackupLevel(),
|
||||
defaultSentMediaQuality = signalStore.settingsValues.sentMediaQuality.toRemoteSentMediaQuality(),
|
||||
autoDownloadSettings = AccountData.AutoDownloadSettings(
|
||||
images = getRemoteAutoDownloadOption("image", mobileAutoDownload, wifiAutoDownload),
|
||||
@@ -277,7 +276,7 @@ object AccountDataArchiveProcessor {
|
||||
SignalStore.story.userHasSeenGroupStoryEducationSheet = settings.hasSeenGroupStoryEducationSheet
|
||||
SignalStore.story.viewedReceiptsEnabled = settings.storyViewReceiptsEnabled ?: settings.readReceipts
|
||||
SignalStore.backup.optimizeStorage = settings.optimizeOnDeviceStorage
|
||||
SignalStore.backup.backupTier = settings.backupTier?.toLocalBackupTier()
|
||||
SignalStore.backup.backupTier = MessageBackupTier.fromBackupLevel(settings.backupTier)
|
||||
SignalStore.settings.sentMediaQuality = settings.defaultSentMediaQuality.toLocalSentMediaQuality()
|
||||
SignalStore.settings.setTheme(settings.appTheme.toLocalTheme())
|
||||
SignalStore.settings.setCallDataMode(settings.callsUseLessDataSetting.toLocalCallDataMode())
|
||||
@@ -456,22 +455,6 @@ object AccountDataArchiveProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private fun MessageBackupTier?.toRemoteBackupTier(): Long? {
|
||||
return when (this) {
|
||||
MessageBackupTier.FREE -> BackupLevel.FREE.value.toLong()
|
||||
MessageBackupTier.PAID -> BackupLevel.PAID.value.toLong()
|
||||
null -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun Long?.toLocalBackupTier(): MessageBackupTier? {
|
||||
return when (this) {
|
||||
BackupLevel.FREE.value.toLong() -> MessageBackupTier.FREE
|
||||
BackupLevel.PAID.value.toLong() -> MessageBackupTier.PAID
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun SentMediaQuality.toRemoteSentMediaQuality(): AccountData.SentMediaQuality {
|
||||
return when (this) {
|
||||
SentMediaQuality.STANDARD -> AccountData.SentMediaQuality.STANDARD
|
||||
|
||||
@@ -110,6 +110,9 @@ object CallLinks {
|
||||
} catch (_: UnsupportedEncodingException) {
|
||||
Log.w(TAG, "Invalid url: $url")
|
||||
return null
|
||||
} catch (_: IllegalArgumentException) {
|
||||
Log.w(TAG, "Invalid url: $url")
|
||||
return null
|
||||
}
|
||||
|
||||
val key = fragmentQuery[ROOT_KEY]
|
||||
|
||||
@@ -48,11 +48,15 @@ class SignalProgressDialog private constructor(
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
dialog.hide()
|
||||
if (dialog.window?.decorView?.isAttachedToWindow == true) {
|
||||
dialog.hide()
|
||||
}
|
||||
}
|
||||
|
||||
fun dismiss() {
|
||||
dialog.dismiss()
|
||||
if (dialog.window?.decorView?.isAttachedToWindow == true) {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+5
-1
@@ -90,7 +90,11 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
|
||||
is AppSettingsRoute.BackupsRoute.Backups -> AppSettingsFragmentDirections.actionDirectToBackupsSettingsFragment().setLaunchCheckoutFlow(appSettingsRoute.launchCheckoutFlow)
|
||||
AppSettingsRoute.Invite -> AppSettingsFragmentDirections.actionDirectToInviteFragment()
|
||||
AppSettingsRoute.DataAndStorageRoute.DataAndStorage -> AppSettingsFragmentDirections.actionDirectToStoragePreferenceFragment()
|
||||
AppSettingsRoute.AccountRoute.Account -> AppSettingsFragmentDirections.actionDirectToAccountSettingsFragment()
|
||||
AppSettingsRoute.AccountRoute.Account -> if (SignalStore.account.isPrimaryDevice) {
|
||||
AppSettingsFragmentDirections.actionDirectToAccountSettingsFragment()
|
||||
} else {
|
||||
AppSettingsFragmentDirections.actionDirectToLinkedDeviceAccountSettingsFragment()
|
||||
}
|
||||
else -> error("Unsupported start location: ${appSettingsRoute?.javaClass?.name}")
|
||||
}
|
||||
}
|
||||
|
||||
+30
-25
@@ -76,6 +76,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.InAppPaym
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.completed.InAppPaymentsBottomSheetDelegate
|
||||
import org.thoughtcrime.securesms.compose.rememberStatusBarColorNestedScrollModifier
|
||||
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.profiles.ProfileName
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
@@ -96,7 +97,11 @@ class AppSettingsFragment : ComposeFragment(), Callbacks {
|
||||
appSettingsRouter.currentRoute.collect { route ->
|
||||
when (route) {
|
||||
is AppSettingsRoute.BackupsRoute.Remote -> findNavController().safeNavigate(R.id.action_appSettingsFragment_to_remoteBackupsSettingsFragment)
|
||||
is AppSettingsRoute.AccountRoute.Account -> findNavController().safeNavigate(R.id.action_appSettingsFragment_to_accountSettingsFragment)
|
||||
is AppSettingsRoute.AccountRoute.Account -> if (SignalStore.account.isPrimaryDevice) {
|
||||
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_accountSettingsFragment)
|
||||
} else {
|
||||
findNavController().safeNavigate(R.id.action_appSettingsFragment_to_linkedDeviceAccountSettingsFragment)
|
||||
}
|
||||
is AppSettingsRoute.LinkDeviceRoute.LinkDevice -> findNavController().safeNavigate(R.id.action_appSettingsFragment_to_linkDeviceFragment)
|
||||
is AppSettingsRoute.DonationsRoute.Donations -> findNavController().safeNavigate(R.id.action_appSettingsFragment_to_manageDonationsFragment)
|
||||
is AppSettingsRoute.AppearanceRoute.Appearance -> findNavController().safeNavigate(R.id.action_appSettingsFragment_to_appearanceSettingsFragment)
|
||||
@@ -292,17 +297,17 @@ private fun AppSettingsContent(
|
||||
BackupFailureState.NONE -> Unit
|
||||
}
|
||||
|
||||
if (state.isPrimaryDevice) {
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.AccountSettingsFragment__account),
|
||||
icon = painterResource(CoreUiR.drawable.symbol_person_circle_24),
|
||||
onClick = {
|
||||
callbacks.navigate(AppSettingsRoute.AccountRoute.Account)
|
||||
}
|
||||
)
|
||||
}
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.AccountSettingsFragment__account),
|
||||
icon = painterResource(CoreUiR.drawable.symbol_person_circle_24),
|
||||
onClick = {
|
||||
callbacks.navigate(AppSettingsRoute.AccountRoute.Account)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (state.isPrimaryDevice) {
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.preferences__linked_devices),
|
||||
@@ -412,20 +417,20 @@ private fun AppSettingsContent(
|
||||
)
|
||||
}
|
||||
|
||||
if (state.isPrimaryDevice) {
|
||||
item {
|
||||
Rows.TextRow(
|
||||
icon = SignalIcons.Backup.imageVector,
|
||||
text = stringResource(R.string.preferences_chats__backups),
|
||||
onClick = {
|
||||
callbacks.navigate(AppSettingsRoute.BackupsRoute.Backups())
|
||||
},
|
||||
onLongClick = {
|
||||
callbacks.copyRemoteBackupsSubscriberIdToClipboard()
|
||||
},
|
||||
enabled = isRegisteredAndUpToDate
|
||||
)
|
||||
}
|
||||
item {
|
||||
Rows.TextRow(
|
||||
icon = SignalIcons.Backup.imageVector,
|
||||
text = stringResource(R.string.preferences_chats__backups),
|
||||
onClick = {
|
||||
callbacks.navigate(AppSettingsRoute.BackupsRoute.Backups())
|
||||
},
|
||||
onLongClick = if (state.isPrimaryDevice) {
|
||||
{ callbacks.copyRemoteBackupsSubscriberIdToClipboard() }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
enabled = isRegisteredAndUpToDate
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import org.signal.core.ui.BottomSheetUtil
|
||||
import org.signal.core.ui.compose.BottomSheets
|
||||
import org.signal.core.ui.compose.ComposeBottomSheetDialogFragment
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.core.ui.compose.horizontalGutters
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
/**
|
||||
* Bottom sheet shown from the linked-device Account settings screen explaining what linked devices
|
||||
* are and that account management lives on the primary device.
|
||||
*/
|
||||
class LinkedDeviceAccountLearnMoreBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
override val peekHeightPercentage: Float = 0.75f
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun show(fragmentManager: FragmentManager) {
|
||||
LinkedDeviceAccountLearnMoreBottomSheet()
|
||||
.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
LinkedDeviceAccountLearnMoreSheet()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountLearnMoreSheet() {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.horizontalGutters()
|
||||
.padding(bottom = 48.dp)
|
||||
) {
|
||||
BottomSheets.Handle()
|
||||
|
||||
Icon(
|
||||
imageVector = SignalIcons.Devices.imageVector,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp, bottom = 24.dp)
|
||||
.clip(RoundedCornerShape(50))
|
||||
.background(MaterialTheme.colorScheme.primary.copy(alpha = 0.12f))
|
||||
.padding(horizontal = 20.dp, vertical = 6.dp)
|
||||
.size(40.dp)
|
||||
)
|
||||
|
||||
val linkedDevices = stringResource(R.string.LinkedDeviceAccountLearnMoreBottomSheet__linked_devices)
|
||||
val text = stringResource(R.string.LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access)
|
||||
val annotatedText = remember(text, linkedDevices) {
|
||||
buildAnnotatedString {
|
||||
val start = text.indexOf(linkedDevices)
|
||||
if (start >= 0) {
|
||||
append(text.substring(0, start))
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(linkedDevices)
|
||||
}
|
||||
append(text.substring(start + linkedDevices.length))
|
||||
} else {
|
||||
append(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = annotatedText,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 20.dp)
|
||||
)
|
||||
|
||||
BulletRow(stringResource(R.string.LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop))
|
||||
BulletRow(stringResource(R.string.LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages))
|
||||
BulletRow(stringResource(R.string.LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BulletRow(text: String) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 12.dp),
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
Text(
|
||||
text = "\u2022",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.padding(end = 8.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountLearnMoreSheetPreview() {
|
||||
Previews.BottomSheetContentPreview {
|
||||
LinkedDeviceAccountLearnMoreSheet()
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
sealed interface LinkedDeviceAccountSettingsEvent {
|
||||
/** The user tapped "Learn more" on the linked-device callout. */
|
||||
data object LearnMoreClicked : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The user tapped the navigation (back) icon. */
|
||||
data object NavigateBackClicked : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The user tapped the "Delete app data" row. */
|
||||
data object DeleteAppDataClicked : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The user confirmed the delete in the confirmation dialog. */
|
||||
data object DeleteConfirmed : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The user dismissed the delete confirmation dialog. */
|
||||
data object DeleteDismissed : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The fragment reported that clearing application data failed. */
|
||||
data object DataWipeFailed : LinkedDeviceAccountSettingsEvent
|
||||
|
||||
/** The fragment has handled the current [LinkedDeviceAccountSettingsState.oneTimeEvent]. */
|
||||
data object ConsumeOneTimeEvent : LinkedDeviceAccountSettingsEvent
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.ComposeFragment
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Dialogs
|
||||
import org.signal.core.ui.compose.Dividers
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.Rows
|
||||
import org.signal.core.ui.compose.Scaffolds
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.core.ui.compose.theme.SignalTheme
|
||||
import org.signal.core.util.ServiceUtil
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.account.LinkedDeviceAccountSettingsState.OneTimeEvent
|
||||
import org.thoughtcrime.securesms.compose.rememberStatusBarColorNestedScrollModifier
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
|
||||
/**
|
||||
* Account settings shown when the current device is a linked (non-primary) device. Account
|
||||
* management lives on the primary device, so this screen only surfaces an informational callout
|
||||
* and the ability to delete the Signal data stored on this device.
|
||||
*/
|
||||
class LinkedDeviceAccountSettingsFragment : ComposeFragment() {
|
||||
|
||||
private val viewModel: LinkedDeviceAccountSettingsViewModel by viewModels()
|
||||
|
||||
@Composable
|
||||
override fun FragmentContent() {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(state.oneTimeEvent) {
|
||||
viewModel.onEvent(LinkedDeviceAccountSettingsEvent.ConsumeOneTimeEvent)
|
||||
when (state.oneTimeEvent) {
|
||||
OneTimeEvent.OpenLearnMore -> LinkedDeviceAccountLearnMoreBottomSheet.show(childFragmentManager)
|
||||
OneTimeEvent.NavigateBack -> requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
OneTimeEvent.WipeData -> {
|
||||
if (!ServiceUtil.getActivityManager(AppDependencies.application).clearApplicationUserData()) {
|
||||
viewModel.onEvent(LinkedDeviceAccountSettingsEvent.DataWipeFailed)
|
||||
}
|
||||
}
|
||||
OneTimeEvent.DeleteFailed -> Toast.makeText(requireContext(), R.string.preferences_account_delete_all_data_failed, Toast.LENGTH_LONG).show()
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
LinkedDeviceAccountSettingsScreen(
|
||||
state = state,
|
||||
onEvent = viewModel::onEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountSettingsScreen(
|
||||
state: LinkedDeviceAccountSettingsState,
|
||||
onEvent: (LinkedDeviceAccountSettingsEvent) -> Unit
|
||||
) {
|
||||
Scaffolds.Settings(
|
||||
title = stringResource(R.string.AccountSettingsFragment__account),
|
||||
onNavigationClick = { onEvent(LinkedDeviceAccountSettingsEvent.NavigateBackClicked) },
|
||||
navigationIcon = SignalIcons.ArrowStart.imageVector
|
||||
) { paddingValues ->
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.padding(paddingValues)
|
||||
.then(rememberStatusBarColorNestedScrollModifier())
|
||||
) {
|
||||
item {
|
||||
LinkedDeviceCallout(onLearnMoreClick = { onEvent(LinkedDeviceAccountSettingsEvent.LearnMoreClicked) })
|
||||
}
|
||||
|
||||
item {
|
||||
Dividers.Default()
|
||||
}
|
||||
|
||||
item {
|
||||
Rows.TextRow(
|
||||
text = stringResource(R.string.LinkedDeviceAccountSettingsFragment__delete_app_data),
|
||||
label = stringResource(R.string.LinkedDeviceAccountSettingsFragment__this_will_remove_all_data),
|
||||
onClick = { onEvent(LinkedDeviceAccountSettingsEvent.DeleteAppDataClicked) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state.showDeleteConfirmationDialog) {
|
||||
DeleteAppDataConfirmationDialog(
|
||||
onConfirm = { onEvent(LinkedDeviceAccountSettingsEvent.DeleteConfirmed) },
|
||||
onDismiss = { onEvent(LinkedDeviceAccountSettingsEvent.DeleteDismissed) }
|
||||
)
|
||||
}
|
||||
|
||||
if (state.deleting) {
|
||||
Dialogs.IndeterminateProgressDialog()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LinkedDeviceCallout(
|
||||
onLearnMoreClick: () -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp, vertical = 12.dp)
|
||||
.fillMaxWidth()
|
||||
.background(color = SignalTheme.colors.colorSurface2, shape = RoundedCornerShape(12.dp))
|
||||
.padding(20.dp)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = SignalIcons.Devices.imageVector,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.width(24.dp))
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(R.string.LinkedDeviceAccountSettingsFragment__this_is_a_linked_device),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
Buttons.Small(
|
||||
onClick = onLearnMoreClick,
|
||||
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.onSecondaryContainer)
|
||||
) {
|
||||
Text(text = stringResource(R.string.LearnMoreTextView_learn_more))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DeleteAppDataConfirmationDialog(
|
||||
onConfirm: () -> Unit,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
Dialogs.SimpleAlertDialog(
|
||||
title = stringResource(R.string.LinkedDeviceAccountSettingsFragment__delete_app_data_question),
|
||||
body = stringResource(R.string.LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages),
|
||||
confirm = stringResource(R.string.delete),
|
||||
confirmColor = MaterialTheme.colorScheme.error,
|
||||
onConfirm = onConfirm,
|
||||
dismiss = stringResource(android.R.string.cancel),
|
||||
onDismiss = onDismiss
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountSettingsScreenPreview() {
|
||||
Previews.Preview {
|
||||
LinkedDeviceAccountSettingsScreen(
|
||||
state = LinkedDeviceAccountSettingsState(),
|
||||
onEvent = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountSettingsScreenDeleteConfirmationPreview() {
|
||||
Previews.Preview {
|
||||
LinkedDeviceAccountSettingsScreen(
|
||||
state = LinkedDeviceAccountSettingsState(showDeleteConfirmationDialog = true),
|
||||
onEvent = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun LinkedDeviceAccountSettingsScreenDeletingPreview() {
|
||||
Previews.Preview {
|
||||
LinkedDeviceAccountSettingsScreen(
|
||||
state = LinkedDeviceAccountSettingsState(deleting = true),
|
||||
onEvent = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
data class LinkedDeviceAccountSettingsState(
|
||||
val showDeleteConfirmationDialog: Boolean = false,
|
||||
val deleting: Boolean = false,
|
||||
val oneTimeEvent: OneTimeEvent? = null
|
||||
) {
|
||||
/** One-time side effects the fragment must carry out (they need Android/fragment context). Consumed via [LinkedDeviceAccountSettingsEvent.ConsumeOneTimeEvent]. */
|
||||
sealed interface OneTimeEvent {
|
||||
data object OpenLearnMore : OneTimeEvent
|
||||
data object NavigateBack : OneTimeEvent
|
||||
data object WipeData : OneTimeEvent
|
||||
data object DeleteFailed : OneTimeEvent
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.account
|
||||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.signal.core.ui.compose.EventDrivenViewModel
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.components.settings.app.account.LinkedDeviceAccountSettingsState.OneTimeEvent
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.linkdevice.LinkDeviceRepository
|
||||
|
||||
/**
|
||||
* Drives the account settings screen shown on a linked (non-primary) device. Owns the screen state
|
||||
* and, on delete, makes a best-effort attempt to unlink this device from the server before the
|
||||
* fragment wipes local data.
|
||||
*/
|
||||
class LinkedDeviceAccountSettingsViewModel(
|
||||
private val selfDeviceId: () -> Int = { SignalStore.account.deviceId },
|
||||
private val removeDevice: suspend (Int) -> Boolean = LinkDeviceRepository::removeDevice
|
||||
) : EventDrivenViewModel<LinkedDeviceAccountSettingsEvent>(TAG) {
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(LinkedDeviceAccountSettingsViewModel::class)
|
||||
}
|
||||
|
||||
private val _state = MutableStateFlow(LinkedDeviceAccountSettingsState())
|
||||
val state: StateFlow<LinkedDeviceAccountSettingsState> = _state.asStateFlow()
|
||||
|
||||
override suspend fun processEvent(event: LinkedDeviceAccountSettingsEvent) {
|
||||
applyEvent(_state.value, event) { _state.value = it }
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
suspend fun applyEvent(state: LinkedDeviceAccountSettingsState, event: LinkedDeviceAccountSettingsEvent, stateEmitter: (LinkedDeviceAccountSettingsState) -> Unit) {
|
||||
when (event) {
|
||||
LinkedDeviceAccountSettingsEvent.LearnMoreClicked -> stateEmitter(state.copy(oneTimeEvent = OneTimeEvent.OpenLearnMore))
|
||||
LinkedDeviceAccountSettingsEvent.NavigateBackClicked -> stateEmitter(state.copy(oneTimeEvent = OneTimeEvent.NavigateBack))
|
||||
LinkedDeviceAccountSettingsEvent.DeleteAppDataClicked -> stateEmitter(state.copy(showDeleteConfirmationDialog = true))
|
||||
LinkedDeviceAccountSettingsEvent.DeleteDismissed -> stateEmitter(state.copy(showDeleteConfirmationDialog = false))
|
||||
LinkedDeviceAccountSettingsEvent.DeleteConfirmed -> {
|
||||
val deletingState = state.copy(showDeleteConfirmationDialog = false, deleting = true)
|
||||
stateEmitter(deletingState)
|
||||
withContext(Dispatchers.IO) { removeDevice(selfDeviceId()) }
|
||||
stateEmitter(deletingState.copy(oneTimeEvent = OneTimeEvent.WipeData))
|
||||
}
|
||||
LinkedDeviceAccountSettingsEvent.DataWipeFailed -> stateEmitter(state.copy(deleting = false, oneTimeEvent = OneTimeEvent.DeleteFailed))
|
||||
LinkedDeviceAccountSettingsEvent.ConsumeOneTimeEvent -> stateEmitter(state.copy(oneTimeEvent = null))
|
||||
}
|
||||
}
|
||||
}
|
||||
+145
-44
@@ -35,6 +35,11 @@ import androidx.compose.ui.platform.LocalLocale
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.LinkAnnotation
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.withLink
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
@@ -58,6 +63,7 @@ import org.thoughtcrime.securesms.backup.v2.ui.subscription.MessageBackupsType
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.MessageBackupsCheckoutLauncher.createBackupsCheckoutLauncher
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.Environment
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
@@ -86,7 +92,7 @@ class BackupsSettingsFragment : ComposeFragment() {
|
||||
findNavController().safeNavigate(R.id.action_backupsSettingsFragment_to_remoteBackupsSettingsFragment)
|
||||
}
|
||||
|
||||
if (savedInstanceState == null && args.launchCheckoutFlow) {
|
||||
if (savedInstanceState == null && args.launchCheckoutFlow && SignalStore.account.isPrimaryDevice) {
|
||||
checkoutLauncher.launch(null)
|
||||
}
|
||||
}
|
||||
@@ -103,7 +109,9 @@ class BackupsSettingsFragment : ComposeFragment() {
|
||||
is BackupState.Error -> Unit
|
||||
|
||||
BackupState.None -> {
|
||||
checkoutLauncher.launch(null)
|
||||
if (!state.isLinkedDevice) {
|
||||
checkoutLauncher.launch(null)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
@@ -112,13 +120,14 @@ class BackupsSettingsFragment : ComposeFragment() {
|
||||
}
|
||||
},
|
||||
onOnDeviceBackupsRowClick = {
|
||||
if (SignalStore.backup.newLocalBackupsEnabled || (Environment.Backups.isNewFormatSupportedForLocalBackup() && !SignalStore.settings.isBackupEnabled)) {
|
||||
if (state.isLinkedDevice || SignalStore.backup.newLocalBackupsEnabled || (Environment.Backups.isNewFormatSupportedForLocalBackup() && !SignalStore.settings.isBackupEnabled)) {
|
||||
findNavController().safeNavigate(R.id.action_backupsSettingsFragment_to_localBackupsFragment)
|
||||
} else {
|
||||
findNavController().safeNavigate(R.id.action_backupsSettingsFragment_to_backupsPreferenceFragment)
|
||||
}
|
||||
},
|
||||
onBackupTierInternalOverrideChanged = { viewModel.onBackupTierInternalOverrideChanged(it) }
|
||||
onBackupTierInternalOverrideChanged = { viewModel.onBackupTierInternalOverrideChanged(it) },
|
||||
onLearnMoreClick = { CommunicationActions.openBrowserLink(requireContext(), "https://support.signal.org/hc/articles/360007059752") }
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -129,7 +138,8 @@ private fun BackupsSettingsContent(
|
||||
onNavigationClick: () -> Unit = {},
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
onOnDeviceBackupsRowClick: () -> Unit = {},
|
||||
onBackupTierInternalOverrideChanged: (MessageBackupTier?) -> Unit = {}
|
||||
onBackupTierInternalOverrideChanged: (MessageBackupTier?) -> Unit = {},
|
||||
onLearnMoreClick: () -> Unit = {}
|
||||
) {
|
||||
Scaffolds.Settings(
|
||||
title = stringResource(R.string.preferences_chats__backups),
|
||||
@@ -166,21 +176,29 @@ private fun BackupsSettingsContent(
|
||||
}
|
||||
|
||||
item {
|
||||
val displayActionButton = !backupsSettingsState.isLinkedDevice
|
||||
|
||||
when (backupsSettingsState.backupState) {
|
||||
is BackupState.LocalStore -> {
|
||||
LocalStoreBackupRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
lastBackupAt = backupsSettingsState.lastBackupAt,
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = displayActionButton
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
is BackupState.Inactive -> {
|
||||
InactiveBackupsRow(
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
)
|
||||
if (backupsSettingsState.isLinkedDevice) {
|
||||
BackupsOffLinkedDeviceRow(onLearnMoreClick = onLearnMoreClick)
|
||||
} else {
|
||||
InactiveBackupsRow(
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = true
|
||||
)
|
||||
}
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
@@ -189,23 +207,30 @@ private fun BackupsSettingsContent(
|
||||
ActiveBackupsRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
lastBackupAt = backupsSettingsState.lastBackupAt
|
||||
lastBackupAt = backupsSettingsState.lastBackupAt,
|
||||
displayActionButton = true
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
BackupState.None -> {
|
||||
NeverEnabledBackupsRow(
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
)
|
||||
if (backupsSettingsState.isLinkedDevice) {
|
||||
BackupsOffLinkedDeviceRow(onLearnMoreClick = onLearnMoreClick)
|
||||
} else {
|
||||
NeverEnabledBackupsRow(
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = true
|
||||
)
|
||||
}
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
}
|
||||
|
||||
is BackupState.Error -> {
|
||||
WaitingForNetworkRow(
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = displayActionButton
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
@@ -213,7 +238,8 @@ private fun BackupsSettingsContent(
|
||||
|
||||
BackupState.NotFound -> {
|
||||
NotFoundBackupRow(
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = displayActionButton
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
@@ -221,7 +247,8 @@ private fun BackupsSettingsContent(
|
||||
|
||||
is BackupState.Pending -> {
|
||||
PendingBackupRow(
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = displayActionButton
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
@@ -231,7 +258,8 @@ private fun BackupsSettingsContent(
|
||||
ActiveBackupsRow(
|
||||
backupState = backupsSettingsState.backupState,
|
||||
lastBackupAt = backupsSettingsState.lastBackupAt,
|
||||
onBackupsRowClick = onBackupsRowClick
|
||||
onBackupsRowClick = onBackupsRowClick,
|
||||
displayActionButton = displayActionButton
|
||||
)
|
||||
|
||||
OtherWaysToBackUpHeading()
|
||||
@@ -262,7 +290,8 @@ private fun OtherWaysToBackUpHeading() {
|
||||
|
||||
@Composable
|
||||
private fun NeverEnabledBackupsRow(
|
||||
onBackupsRowClick: () -> Unit = {}
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
@@ -291,13 +320,15 @@ private fun NeverEnabledBackupsRow(
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
|
||||
Buttons.MediumTonal(
|
||||
onClick = onBackupsRowClick,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.BackupsSettingsFragment_set_up)
|
||||
)
|
||||
if (displayActionButton) {
|
||||
Buttons.MediumTonal(
|
||||
onClick = onBackupsRowClick,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.BackupsSettingsFragment_set_up)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,12 +336,57 @@ private fun NeverEnabledBackupsRow(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WaitingForNetworkRow(onBackupsRowClick: () -> Unit = {}) {
|
||||
private fun BackupsOffLinkedDeviceRow(
|
||||
onLearnMoreClick: () -> Unit = {}
|
||||
) {
|
||||
val description = buildAnnotatedString {
|
||||
append(stringResource(R.string.BackupsSettingsFragment__automatic_backups_get_started_on_your_phone))
|
||||
append(" ")
|
||||
withLink(LinkAnnotation.Clickable(tag = "learn-more") { onLearnMoreClick() }) {
|
||||
withStyle(SpanStyle(color = MaterialTheme.colorScheme.primary)) {
|
||||
append(stringResource(R.string.RemoteBackupsSettingsFragment__learn_more))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
icon = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = 12.dp)
|
||||
.align(Alignment.Top)
|
||||
) {
|
||||
Icon(
|
||||
painter = SignalIcons.Backup.painter,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
},
|
||||
text = {
|
||||
Column {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__signal_backups),
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
|
||||
Text(
|
||||
text = description,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WaitingForNetworkRow(onBackupsRowClick: () -> Unit = {}, displayActionButton: Boolean = true) {
|
||||
Rows.TextRow(
|
||||
text = {
|
||||
Column {
|
||||
Text(text = stringResource(R.string.RemoteBackupsSettingsFragment__waiting_for_network))
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
@@ -321,7 +397,8 @@ private fun WaitingForNetworkRow(onBackupsRowClick: () -> Unit = {}) {
|
||||
|
||||
@Composable
|
||||
private fun InactiveBackupsRow(
|
||||
onBackupsRowClick: () -> Unit = {}
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
text = {
|
||||
@@ -336,7 +413,7 @@ private fun InactiveBackupsRow(
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
},
|
||||
icon = {
|
||||
@@ -354,7 +431,8 @@ private fun InactiveBackupsRow(
|
||||
|
||||
@Composable
|
||||
private fun NotFoundBackupRow(
|
||||
onBackupsRowClick: () -> Unit = {}
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
@@ -382,7 +460,7 @@ private fun NotFoundBackupRow(
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -390,7 +468,8 @@ private fun NotFoundBackupRow(
|
||||
|
||||
@Composable
|
||||
private fun PendingBackupRow(
|
||||
onBackupsRowClick: () -> Unit = {}
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
@@ -418,14 +497,18 @@ private fun PendingBackupRow(
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ViewSettingsButton(onClick: () -> Unit) {
|
||||
private fun ViewSettingsButton(onClick: () -> Unit, visible: Boolean = true) {
|
||||
if (!visible) {
|
||||
return
|
||||
}
|
||||
|
||||
Buttons.MediumTonal(
|
||||
onClick = onClick,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
@@ -440,7 +523,8 @@ private fun ViewSettingsButton(onClick: () -> Unit) {
|
||||
private fun LocalStoreBackupRow(
|
||||
backupState: BackupState.LocalStore,
|
||||
lastBackupAt: Duration,
|
||||
onBackupsRowClick: () -> Unit
|
||||
onBackupsRowClick: () -> Unit,
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
@@ -475,7 +559,7 @@ private fun LocalStoreBackupRow(
|
||||
)
|
||||
|
||||
LastBackedUpText(lastBackupAt)
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -485,7 +569,8 @@ private fun LocalStoreBackupRow(
|
||||
private fun ActiveBackupsRow(
|
||||
backupState: BackupState.WithTypeAndRenewalTime,
|
||||
lastBackupAt: Duration,
|
||||
onBackupsRowClick: () -> Unit = {}
|
||||
onBackupsRowClick: () -> Unit = {},
|
||||
displayActionButton: Boolean = true
|
||||
) {
|
||||
Rows.TextRow(
|
||||
modifier = Modifier.wrapContentHeight(),
|
||||
@@ -552,7 +637,7 @@ private fun ActiveBackupsRow(
|
||||
|
||||
LastBackedUpText(lastBackupAt)
|
||||
|
||||
ViewSettingsButton(onBackupsRowClick)
|
||||
ViewSettingsButton(onBackupsRowClick, displayActionButton)
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -644,7 +729,8 @@ private fun BackupsSettingsContentPreview() {
|
||||
renewalTime = 0.seconds,
|
||||
price = FiatMoney(BigDecimal.valueOf(4), Currency.getInstance("CAD"))
|
||||
),
|
||||
lastBackupAt = 0.seconds
|
||||
lastBackupAt = 0.seconds,
|
||||
isLinkedDevice = false
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -652,14 +738,21 @@ private fun BackupsSettingsContentPreview() {
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun BackupsSettingsContentBackupTierInternalOverridePreview() {
|
||||
private fun BackupsSettingsContentLinkedDevicePreview() {
|
||||
Previews.Preview {
|
||||
BackupsSettingsContent(
|
||||
backupsSettingsState = BackupsSettingsState(
|
||||
backupState = BackupState.None,
|
||||
showBackupTierInternalOverride = true,
|
||||
backupTierInternalOverride = null,
|
||||
lastBackupAt = 0.seconds
|
||||
backupState = BackupState.ActivePaid(
|
||||
messageBackupsType = MessageBackupsType.Paid(
|
||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(2.99), Currency.getInstance("USD")),
|
||||
storageAllowanceBytes = 1_000_000,
|
||||
mediaTtl = 30.days
|
||||
),
|
||||
renewalTime = 0.seconds,
|
||||
price = FiatMoney(BigDecimal.valueOf(2.99), Currency.getInstance("USD"))
|
||||
),
|
||||
lastBackupAt = 0.seconds,
|
||||
isLinkedDevice = true
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -758,3 +851,11 @@ private fun NeverEnabledBackupsRowPreview() {
|
||||
NeverEnabledBackupsRow()
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun BackupsOffLinkedDeviceRowPreview() {
|
||||
Previews.Preview {
|
||||
BackupsOffLinkedDeviceRow()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,5 +17,6 @@ data class BackupsSettingsState(
|
||||
val backupState: BackupState,
|
||||
val lastBackupAt: Duration = SignalStore.backup.lastBackupTime.milliseconds,
|
||||
val showBackupTierInternalOverride: Boolean = false,
|
||||
val backupTierInternalOverride: MessageBackupTier? = null
|
||||
val backupTierInternalOverride: MessageBackupTier? = null,
|
||||
val isLinkedDevice: Boolean = SignalStore.account.isLinkedDevice
|
||||
)
|
||||
|
||||
+8
-1
@@ -15,6 +15,7 @@ import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.concurrent.SignalDispatchers
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.backup.DeletionState
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.MessageBackupTier
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
@@ -44,7 +45,7 @@ class BackupsSettingsViewModel : ViewModel() {
|
||||
it.copy(
|
||||
backupState = enabledState,
|
||||
lastBackupAt = SignalStore.backup.lastBackupTime.milliseconds,
|
||||
showBackupTierInternalOverride = Environment.IS_STAGING,
|
||||
showBackupTierInternalOverride = Environment.IS_STAGING && SignalStore.account.isPrimaryDevice,
|
||||
backupTierInternalOverride = SignalStore.backup.backupTierInternalOverride
|
||||
)
|
||||
}
|
||||
@@ -59,6 +60,12 @@ class BackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SignalStore.account.isLinkedDevice) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
BackupRepository.refreshBackupFileTimestamp()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onBackupTierInternalOverrideChanged(tier: MessageBackupTier?) {
|
||||
|
||||
+171
-38
@@ -452,7 +452,8 @@ private fun RemoteBackupsSettingsContent(
|
||||
state = state.backupState,
|
||||
onLearnMoreClick = contentCallbacks::onLearnMoreAboutLostSubscription,
|
||||
onRenewClick = contentCallbacks::onRenewLostSubscription,
|
||||
isRenewEnabled = backupDeleteState.isIdle()
|
||||
isRenewEnabled = backupDeleteState.isIdle(),
|
||||
isLinkedDevice = state.isLinkedDevice
|
||||
)
|
||||
}
|
||||
|
||||
@@ -464,7 +465,8 @@ private fun RemoteBackupsSettingsContent(
|
||||
onBackupTypeActionButtonClicked = contentCallbacks::onBackupTypeActionClick,
|
||||
isPaidTierPricingAvailable = state.isPaidTierPricingAvailable,
|
||||
isGooglePlayServicesAvailable = state.isGooglePlayServicesAvailable,
|
||||
buttonsEnabled = backupDeleteState.isIdle()
|
||||
buttonsEnabled = backupDeleteState.isIdle(),
|
||||
isLinkedDevice = state.isLinkedDevice
|
||||
)
|
||||
}
|
||||
|
||||
@@ -473,13 +475,16 @@ private fun RemoteBackupsSettingsContent(
|
||||
title = stringResource(R.string.RemoteBackupsSettingsFragment__your_subscription_was_not_found),
|
||||
onRenewClick = contentCallbacks::onRenewLostSubscription,
|
||||
onLearnMoreClick = contentCallbacks::onLearnMoreAboutLostSubscription,
|
||||
isRenewEnabled = backupDeleteState.isIdle()
|
||||
isRenewEnabled = backupDeleteState.isIdle(),
|
||||
isLinkedDevice = state.isLinkedDevice
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (backupDeleteState != DeletionState.NONE && backupDeleteState != DeletionState.CLEAR_LOCAL_STATE) {
|
||||
if (state.isLinkedDevice) {
|
||||
appendReducedBackupDetailsItems(state)
|
||||
} else if (backupDeleteState != DeletionState.NONE && backupDeleteState != DeletionState.CLEAR_LOCAL_STATE) {
|
||||
appendBackupDeletionItems(
|
||||
backupDeleteState = backupDeleteState,
|
||||
backupRestoreState = backupRestoreState,
|
||||
@@ -973,12 +978,58 @@ private fun LazyListScope.appendBackupDetailsItems(
|
||||
}
|
||||
}
|
||||
|
||||
private fun LazyListScope.appendReducedBackupDetailsItems(
|
||||
state: RemoteBackupsSettingsState
|
||||
) {
|
||||
item {
|
||||
Dividers.Default()
|
||||
}
|
||||
|
||||
item {
|
||||
Texts.SectionHeader(text = stringResource(id = R.string.RemoteBackupsSettingsFragment__backup_details))
|
||||
}
|
||||
|
||||
item {
|
||||
ReadOnlyLastBackupRow(lastBackupTimestamp = state.lastBackupTimestamp)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ReadOnlyLastBackupRow(
|
||||
lastBackupTimestamp: Long
|
||||
) {
|
||||
val label = if (lastBackupTimestamp > 0) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val day = remember(lastBackupTimestamp) {
|
||||
DateUtils.getDayPrecisionTimeString(context, Locale.getDefault(), lastBackupTimestamp)
|
||||
}
|
||||
|
||||
val time = remember(lastBackupTimestamp) {
|
||||
DateUtils.getOnlyTimeString(context, lastBackupTimestamp)
|
||||
}
|
||||
|
||||
stringResource(
|
||||
id = R.string.RemoteBackupsSettingsFragment__your_phone_s,
|
||||
stringResource(id = R.string.RemoteBackupsSettingsFragment__s_at_s, day, time)
|
||||
)
|
||||
} else {
|
||||
stringResource(id = R.string.RemoteBackupsSettingsFragment__never)
|
||||
}
|
||||
|
||||
Rows.TextRow(
|
||||
text = stringResource(id = R.string.RemoteBackupsSettingsFragment__last_backup),
|
||||
label = label
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BackupCard(
|
||||
backupState: BackupState.WithTypeAndRenewalTime,
|
||||
isPaidTierPricingAvailable: Boolean,
|
||||
isGooglePlayServicesAvailable: Boolean,
|
||||
buttonsEnabled: Boolean,
|
||||
isLinkedDevice: Boolean = false,
|
||||
onBackupTypeActionButtonClicked: (MessageBackupTier) -> Unit = {}
|
||||
) {
|
||||
val messageBackupsType = backupState.messageBackupsType
|
||||
@@ -1070,7 +1121,21 @@ private fun BackupCard(
|
||||
)
|
||||
}
|
||||
|
||||
if (backupState.isActive() && isPaidTierPricingAvailable && isGooglePlayServicesAvailable) {
|
||||
if (isLinkedDevice) {
|
||||
val primaryDeviceText = when (backupState) {
|
||||
is BackupState.ActivePaid -> stringResource(R.string.RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device)
|
||||
is BackupState.Canceled -> stringResource(R.string.RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device)
|
||||
is BackupState.ActiveFree -> stringResource(R.string.RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device)
|
||||
else -> stringResource(R.string.RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = primaryDeviceText,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
)
|
||||
} else if (backupState.isActive() && isPaidTierPricingAvailable && isGooglePlayServicesAvailable) {
|
||||
val buttonText = when (messageBackupsType) {
|
||||
is MessageBackupsType.Paid -> stringResource(R.string.RemoteBackupsSettingsFragment__manage_or_cancel)
|
||||
is MessageBackupsType.Free -> stringResource(R.string.RemoteBackupsSettingsFragment__upgrade)
|
||||
@@ -1270,6 +1335,7 @@ private fun PendingCard(
|
||||
private fun SubscriptionNotFoundCard(
|
||||
title: String,
|
||||
isRenewEnabled: Boolean,
|
||||
isLinkedDevice: Boolean = false,
|
||||
onRenewClick: () -> Unit = {},
|
||||
onLearnMoreClick: () -> Unit = {}
|
||||
) {
|
||||
@@ -1308,38 +1374,47 @@ private fun SubscriptionNotFoundCard(
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
horizontalArrangement = spacedBy(16.dp)
|
||||
) {
|
||||
Buttons.MediumTonal(
|
||||
onClick = onRenewClick,
|
||||
colors = ButtonDefaults.filledTonalButtonColors().copy(
|
||||
containerColor = SignalTheme.colors.colorTransparent5,
|
||||
contentColor = colorResource(CoreUiR.color.signal_light_colorOnSurface)
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp)
|
||||
.weight(1f)
|
||||
if (isLinkedDevice) {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device),
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
)
|
||||
} else {
|
||||
Row(
|
||||
horizontalArrangement = spacedBy(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__renew)
|
||||
)
|
||||
}
|
||||
Buttons.MediumTonal(
|
||||
onClick = onRenewClick,
|
||||
colors = ButtonDefaults.filledTonalButtonColors().copy(
|
||||
containerColor = SignalTheme.colors.colorTransparent5,
|
||||
contentColor = colorResource(CoreUiR.color.signal_light_colorOnSurface)
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__renew)
|
||||
)
|
||||
}
|
||||
|
||||
Buttons.MediumTonal(
|
||||
onClick = onLearnMoreClick,
|
||||
enabled = isRenewEnabled,
|
||||
colors = ButtonDefaults.filledTonalButtonColors().copy(
|
||||
containerColor = SignalTheme.colors.colorTransparent5,
|
||||
contentColor = colorResource(CoreUiR.color.signal_light_colorOnSurface)
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__learn_more)
|
||||
)
|
||||
Buttons.MediumTonal(
|
||||
onClick = onLearnMoreClick,
|
||||
enabled = isRenewEnabled,
|
||||
colors = ButtonDefaults.filledTonalButtonColors().copy(
|
||||
containerColor = SignalTheme.colors.colorTransparent5,
|
||||
contentColor = colorResource(CoreUiR.color.signal_light_colorOnSurface)
|
||||
),
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.RemoteBackupsSettingsFragment__learn_more)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1349,6 +1424,7 @@ private fun SubscriptionNotFoundCard(
|
||||
private fun SubscriptionMismatchMissingGooglePlayCard(
|
||||
state: BackupState.SubscriptionMismatchMissingGooglePlay,
|
||||
isRenewEnabled: Boolean,
|
||||
isLinkedDevice: Boolean = false,
|
||||
onRenewClick: () -> Unit = {},
|
||||
onLearnMoreClick: () -> Unit = {}
|
||||
) {
|
||||
@@ -1357,6 +1433,7 @@ private fun SubscriptionMismatchMissingGooglePlayCard(
|
||||
SubscriptionNotFoundCard(
|
||||
title = pluralStringResource(R.plurals.RemoteBackupsSettingsFragment__your_subscription_on_this_device_is_valid, days.toInt(), days),
|
||||
isRenewEnabled = isRenewEnabled,
|
||||
isLinkedDevice = isLinkedDevice,
|
||||
onRenewClick = onRenewClick,
|
||||
onLearnMoreClick = onLearnMoreClick
|
||||
)
|
||||
@@ -1847,6 +1924,64 @@ private fun RemoteBackupsSettingsInternalUserContentPreview() {
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun RemoteBackupsSettingsLinkedDevicePaidContentPreview() {
|
||||
Previews.Preview {
|
||||
RemoteBackupsSettingsContent(
|
||||
state = RemoteBackupsSettingsState(
|
||||
backupsEnabled = true,
|
||||
isLinkedDevice = true,
|
||||
lastBackupTimestamp = -1,
|
||||
canBackUpUsingCellular = false,
|
||||
canRestoreUsingCellular = false,
|
||||
dialog = RemoteBackupsSettingsState.Dialog.NONE,
|
||||
snackbar = RemoteBackupsSettingsState.Snackbar.NONE,
|
||||
backupMediaSize = 2300000,
|
||||
backupState = BackupState.ActivePaid(
|
||||
messageBackupsType = MessageBackupsType.Paid(
|
||||
pricePerMonth = FiatMoney(BigDecimal.valueOf(2.99), Currency.getInstance("USD")),
|
||||
storageAllowanceBytes = 1_000_000,
|
||||
mediaTtl = 30.days
|
||||
),
|
||||
price = FiatMoney(BigDecimal.valueOf(2.99), Currency.getInstance("USD")),
|
||||
renewalTime = 1_752_710_400.seconds
|
||||
)
|
||||
),
|
||||
statusBarColorNestedScrollConnection = null,
|
||||
backupDeleteState = DeletionState.NONE,
|
||||
backupRestoreState = BackupRestoreState.None,
|
||||
contentCallbacks = ContentCallbacks.Empty,
|
||||
backupProgress = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun RemoteBackupsSettingsLinkedDeviceNotFoundContentPreview() {
|
||||
Previews.Preview {
|
||||
RemoteBackupsSettingsContent(
|
||||
state = RemoteBackupsSettingsState(
|
||||
backupsEnabled = true,
|
||||
isLinkedDevice = true,
|
||||
lastBackupTimestamp = -1,
|
||||
canBackUpUsingCellular = false,
|
||||
canRestoreUsingCellular = false,
|
||||
dialog = RemoteBackupsSettingsState.Dialog.NONE,
|
||||
snackbar = RemoteBackupsSettingsState.Snackbar.NONE,
|
||||
backupMediaSize = 2300000,
|
||||
backupState = BackupState.NotFound
|
||||
),
|
||||
statusBarColorNestedScrollConnection = null,
|
||||
backupDeleteState = DeletionState.NONE,
|
||||
backupRestoreState = BackupRestoreState.None,
|
||||
contentCallbacks = ContentCallbacks.Empty,
|
||||
backupProgress = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun RedemptionErrorAlertPreview() {
|
||||
@@ -1875,10 +2010,8 @@ private fun ErrorCardPreview() {
|
||||
@Composable
|
||||
private fun PendingCardPreview() {
|
||||
Previews.Preview {
|
||||
val locale = LocalLocale.current.platformLocale
|
||||
|
||||
PendingCard(
|
||||
price = FiatMoney(BigDecimal.TEN, Currency.getInstance(locale))
|
||||
price = FiatMoney(BigDecimal.TEN, Currency.getInstance(Locale.US))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -35,7 +35,8 @@ data class RemoteBackupsSettingsState(
|
||||
val backupCreationError: BackupValues.BackupCreationError? = null,
|
||||
val lastMessageCutoffTime: Long = 0,
|
||||
val freeTierMediaRetentionDays: Int = -1,
|
||||
val isGooglePlayServicesAvailable: Boolean = false
|
||||
val isGooglePlayServicesAvailable: Boolean = false,
|
||||
val isLinkedDevice: Boolean = false
|
||||
) {
|
||||
|
||||
data class BackupMediaDetails(
|
||||
|
||||
+37
-1
@@ -79,7 +79,8 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
internalUser = RemoteConfig.internalUser,
|
||||
includeDebuglog = SignalStore.internal.includeDebuglogInBackup.takeIf { RemoteConfig.internalUser },
|
||||
backupCreationError = SignalStore.backup.backupCreationError,
|
||||
lastMessageCutoffTime = SignalStore.backup.lastUsedMessageCutoffTime
|
||||
lastMessageCutoffTime = SignalStore.backup.lastUsedMessageCutoffTime,
|
||||
isLinkedDevice = SignalStore.account.isLinkedDevice
|
||||
)
|
||||
)
|
||||
|
||||
@@ -92,6 +93,14 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
private var forQuickRestore = false
|
||||
|
||||
init {
|
||||
if (state.value.isLinkedDevice) {
|
||||
initLinkedDevice()
|
||||
} else {
|
||||
initPrimaryDevice()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initPrimaryDevice() {
|
||||
ArchiveUploadProgress.triggerUpdate()
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
@@ -199,6 +208,29 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render remote backups as read-only and refresh the last-backup time from the CDN.
|
||||
*/
|
||||
private fun initLinkedDevice() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
BackupStateObserver(viewModelScope, useDatabaseFallbackOnNetworkError = true).backupState.collect { backupState ->
|
||||
_state.update {
|
||||
it.copy(backupState = backupState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.Default) {
|
||||
SignalStore.backup.lastBackupTimeFlow.collect { lastBackupTime ->
|
||||
_state.update { it.copy(lastBackupTimestamp = lastBackupTime) }
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
BackupRepository.refreshBackupFileTimestamp()
|
||||
}
|
||||
}
|
||||
|
||||
fun setCanBackUpUsingCellular(canBackUpUsingCellular: Boolean) {
|
||||
SignalStore.backup.backupWithCellular = canBackUpUsingCellular
|
||||
_state.update {
|
||||
@@ -259,6 +291,10 @@ class RemoteBackupsSettingsViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
if (state.value.isLinkedDevice) {
|
||||
return
|
||||
}
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val id = SignalDatabase.inAppPayments.getLatestInAppPaymentByType(InAppPaymentType.RECURRING_BACKUP)?.id
|
||||
|
||||
|
||||
-13
@@ -588,19 +588,6 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
||||
|
||||
dividerPref()
|
||||
|
||||
sectionHeaderPref(DSLSettingsText.from("Media"))
|
||||
|
||||
switchPref(
|
||||
title = DSLSettingsText.from("Enable HEVC Encoding for HD Videos"),
|
||||
summary = DSLSettingsText.from("Videos sent in \"HD\" quality will be encoded in HEVC on compatible devices."),
|
||||
isChecked = state.hevcEncoding,
|
||||
onClick = {
|
||||
viewModel.setHevcEncoding(!state.hevcEncoding)
|
||||
}
|
||||
)
|
||||
|
||||
dividerPref()
|
||||
|
||||
sectionHeaderPref(DSLSettingsText.from("Conversations and Shortcuts"))
|
||||
|
||||
clickPref(
|
||||
|
||||
-1
@@ -28,7 +28,6 @@ data class InternalSettingsState(
|
||||
val pnpInitialized: Boolean,
|
||||
val useConversationItemV2ForMedia: Boolean,
|
||||
val hasPendingOneTimeDonation: Boolean,
|
||||
val hevcEncoding: Boolean,
|
||||
val forceSplitPane: Boolean,
|
||||
val forceSinglePane: Boolean,
|
||||
val useNewMediaActivity: Boolean,
|
||||
|
||||
-6
@@ -152,11 +152,6 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun setHevcEncoding(enabled: Boolean) {
|
||||
SignalStore.internal.hevcEncoding = enabled
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun addSampleReleaseNote(callToAction: String = "action") {
|
||||
repository.addSampleReleaseNote(callToAction)
|
||||
}
|
||||
@@ -242,7 +237,6 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
|
||||
pnpInitialized = SignalStore.misc.hasPniInitializedDevices,
|
||||
useConversationItemV2ForMedia = SignalStore.internal.useConversationItemV2Media,
|
||||
hasPendingOneTimeDonation = SignalStore.inAppPayments.getPendingOneTimeDonation() != null,
|
||||
hevcEncoding = SignalStore.internal.hevcEncoding,
|
||||
forceSplitPane = SignalStore.internal.forceSplitPane,
|
||||
forceSinglePane = SignalStore.internal.forceSinglePane,
|
||||
useNewMediaActivity = SignalStore.internal.useNewMediaActivity,
|
||||
|
||||
+2
@@ -71,6 +71,8 @@ class AdvancedPrivacySettingsViewModel(
|
||||
|
||||
fun setAllowAutomaticVerification(enabled: Boolean) {
|
||||
SignalStore.settings.automaticVerificationEnabled = enabled
|
||||
SignalStore.misc.hasKeyTransparencyFailure = false
|
||||
SignalStore.misc.hasSeenKeyTransparencyFailure = false
|
||||
refresh()
|
||||
viewModelScope.launch(SignalDispatchers.Default) {
|
||||
if (!enabled) {
|
||||
|
||||
+3
-1
@@ -67,7 +67,9 @@ class ExpireTimerSettingsFragment : ComposeFragment() {
|
||||
if (state.isGroupCreate) {
|
||||
requireActivity().setResult(Activity.RESULT_OK, Intent().putExtra(FOR_RESULT_VALUE, saveState.result))
|
||||
}
|
||||
requireActivity().onNavigateUp()
|
||||
if (!NavHostFragment.findNavController(this).popBackStack()) {
|
||||
requireActivity().onNavigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
is ProcessState.Failure -> {
|
||||
|
||||
+1
@@ -133,6 +133,7 @@ class ManageStorageSettingsViewModel : ViewModel() {
|
||||
|
||||
private suspend fun getOnDeviceStorageOptimizationState(): OnDeviceStorageOptimizationState {
|
||||
return when {
|
||||
!SignalStore.account.isPrimaryDevice -> OnDeviceStorageOptimizationState.FEATURE_NOT_AVAILABLE
|
||||
!SignalStore.backup.areBackupsEnabled || !BackupUpgradeAvailabilityChecker.isUpgradeAvailable(AppDependencies.application) -> OnDeviceStorageOptimizationState.FEATURE_NOT_AVAILABLE
|
||||
SignalStore.backup.backupTier != MessageBackupTier.PAID -> OnDeviceStorageOptimizationState.REQUIRES_PAID_TIER
|
||||
SignalStore.backup.optimizeStorage -> OnDeviceStorageOptimizationState.ENABLED
|
||||
|
||||
+3
-1
@@ -9,6 +9,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Parcelable
|
||||
import androidx.activity.result.contract.ActivityResultContract
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.fragment.app.Fragment
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import io.reactivex.rxjava3.subjects.Subject
|
||||
@@ -26,7 +27,8 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.GooglePay
|
||||
class CheckoutFlowActivity : FragmentWrapperActivity(), GooglePayComponent {
|
||||
|
||||
companion object {
|
||||
private const val ARG_IN_APP_PAYMENT_TYPE = "in_app_payment_type"
|
||||
@VisibleForTesting
|
||||
const val ARG_IN_APP_PAYMENT_TYPE = "in_app_payment_type"
|
||||
const val RESULT_DATA = "result_data"
|
||||
|
||||
fun createIntent(context: Context, inAppPaymentType: InAppPaymentType): Intent {
|
||||
|
||||
+3
-1
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.donate
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
@@ -78,7 +79,8 @@ class DonateToSignalFragment :
|
||||
|
||||
companion object {
|
||||
|
||||
private const val ARG = "in_app_payment_type"
|
||||
@VisibleForTesting
|
||||
const val ARG = "in_app_payment_type"
|
||||
|
||||
@JvmStatic
|
||||
fun create(inAppPaymentType: InAppPaymentType): DialogFragment {
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer
|
||||
|
||||
/**
|
||||
* Test tags for the bank-transfer (SEPA) and iDEAL Compose entry forms, so instrumentation tests can
|
||||
* drive them reliably. Follows the central-object convention used by the registration module's
|
||||
* `TestTags`.
|
||||
*/
|
||||
object DonationTransferTestTags {
|
||||
// SEPA bank transfer mandate
|
||||
const val SEPA_MANDATE_CONTINUE_BUTTON = "sepa_mandate_continue_button"
|
||||
|
||||
// SEPA bank transfer details
|
||||
const val SEPA_DETAILS_LIST = "sepa_details_list"
|
||||
const val SEPA_IBAN_FIELD = "sepa_iban_field"
|
||||
const val SEPA_NAME_FIELD = "sepa_name_field"
|
||||
const val SEPA_EMAIL_FIELD = "sepa_email_field"
|
||||
const val SEPA_DONATE_BUTTON = "sepa_donate_button"
|
||||
|
||||
// iDEAL transfer details
|
||||
const val IDEAL_DETAILS_LIST = "ideal_details_list"
|
||||
const val IDEAL_NAME_FIELD = "ideal_name_field"
|
||||
const val IDEAL_EMAIL_FIELD = "ideal_email_field"
|
||||
const val IDEAL_DONATE_BUTTON = "ideal_donate_button"
|
||||
}
|
||||
+7
@@ -32,6 +32,7 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
@@ -63,6 +64,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.In
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressViewModel
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.BankTransferRequestKeys
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.details.BankTransferDetailsViewModel.Field
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
@@ -237,6 +239,7 @@ fun BankTransferDetailsContent(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 24.dp)
|
||||
.testTag(DonationTransferTestTags.SEPA_DETAILS_LIST)
|
||||
) {
|
||||
item {
|
||||
val learnMore = stringResource(id = R.string.BankTransferDetailsFragment__learn_more)
|
||||
@@ -292,6 +295,7 @@ fun BankTransferDetailsContent(
|
||||
.defaultMinSize(minHeight = 78.dp)
|
||||
.onFocusChanged { onFocusChanged(Field.IBAN, it.hasFocus) }
|
||||
.focusRequester(focusRequester)
|
||||
.testTag(DonationTransferTestTags.SEPA_IBAN_FIELD)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -320,6 +324,7 @@ fun BankTransferDetailsContent(
|
||||
.padding(top = 16.dp)
|
||||
.defaultMinSize(minHeight = 78.dp)
|
||||
.onFocusChanged { onFocusChanged(Field.NAME, it.hasFocus) }
|
||||
.testTag(DonationTransferTestTags.SEPA_NAME_FIELD)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -348,6 +353,7 @@ fun BankTransferDetailsContent(
|
||||
.padding(top = 16.dp)
|
||||
.defaultMinSize(minHeight = 78.dp)
|
||||
.onFocusChanged { onFocusChanged(Field.EMAIL, it.hasFocus) }
|
||||
.testTag(DonationTransferTestTags.SEPA_EMAIL_FIELD)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -373,6 +379,7 @@ fun BankTransferDetailsContent(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minWidth = 220.dp)
|
||||
.padding(vertical = 16.dp)
|
||||
.testTag(DonationTransferTestTags.SEPA_DONATE_BUTTON)
|
||||
) {
|
||||
Text(text = donateLabel)
|
||||
}
|
||||
|
||||
+6
@@ -26,6 +26,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusDirection
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
@@ -60,6 +61,7 @@ import org.thoughtcrime.securesms.components.settings.app.subscription.donate.ga
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressFragment
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.stripe.StripePaymentInProgressViewModel
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.BankTransferRequestKeys
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.ideal.IdealTransferDetailsViewModel.Field
|
||||
import org.thoughtcrime.securesms.database.InAppPaymentTable
|
||||
import org.thoughtcrime.securesms.payments.FiatMoneyUtil
|
||||
@@ -241,6 +243,7 @@ private fun IdealTransferDetailsContent(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 24.dp)
|
||||
.testTag(DonationTransferTestTags.IDEAL_DETAILS_LIST)
|
||||
) {
|
||||
item {
|
||||
val learnMore = stringResource(id = R.string.IdealTransferDetailsFragment__learn_more)
|
||||
@@ -283,6 +286,7 @@ private fun IdealTransferDetailsContent(
|
||||
.padding(top = 16.dp)
|
||||
.defaultMinSize(minHeight = 78.dp)
|
||||
.onFocusChanged { onFocusChanged(Field.NAME, it.hasFocus) }
|
||||
.testTag(DonationTransferTestTags.IDEAL_NAME_FIELD)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -316,6 +320,7 @@ private fun IdealTransferDetailsContent(
|
||||
.padding(top = 16.dp)
|
||||
.defaultMinSize(minHeight = 78.dp)
|
||||
.onFocusChanged { onFocusChanged(Field.EMAIL, it.hasFocus) }
|
||||
.testTag(DonationTransferTestTags.IDEAL_EMAIL_FIELD)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -327,6 +332,7 @@ private fun IdealTransferDetailsContent(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minWidth = 220.dp)
|
||||
.padding(bottom = 16.dp)
|
||||
.testTag(DonationTransferTestTags.IDEAL_DONATE_BUTTON)
|
||||
) {
|
||||
Text(text = donateLabel)
|
||||
}
|
||||
|
||||
+3
@@ -40,6 +40,7 @@ import androidx.compose.ui.Alignment.Companion.CenterHorizontally
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -58,6 +59,7 @@ import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.core.ui.compose.Texts
|
||||
import org.signal.core.ui.compose.theme.SignalTheme
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.transfer.DonationTransferTestTags
|
||||
import org.thoughtcrime.securesms.compose.StatusBarColorAnimator
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
@@ -267,6 +269,7 @@ fun BankTransferScreen(
|
||||
.wrapContentWidth()
|
||||
.padding(top = 16.dp, bottom = 16.dp)
|
||||
.defaultMinSize(minWidth = 220.dp)
|
||||
.testTag(DonationTransferTestTags.SEPA_MANDATE_CONTINUE_BUTTON)
|
||||
) {
|
||||
Text(text = if (listState.canScrollForward) stringResource(id = R.string.BankTransferMandateFragment__read_more) else stringResource(id = R.string.BankTransferMandateFragment__agree))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -234,6 +235,7 @@ object ContactSearchModels {
|
||||
) { model ->
|
||||
Text(
|
||||
text = if (model.empty.query.isNullOrEmpty()) stringResource(R.string.SearchFragment_no_results_empty) else stringResource(R.string.SearchFragment_no_results, model.empty.query),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
||||
+19
-1
@@ -44,6 +44,18 @@ object PlaintextExportRepository {
|
||||
private val TAG = Log.tag(PlaintextExportRepository::class.java)
|
||||
private const val BATCH_SIZE = 500
|
||||
|
||||
private val EMOJI_REGEX = Regex(
|
||||
"[" +
|
||||
"\\x{1F000}-\\x{1FAFF}" +
|
||||
"\\x{2600}-\\x{27BF}" +
|
||||
"\\x{2300}-\\x{23FF}" +
|
||||
"\\x{2B00}-\\x{2BFF}" +
|
||||
"\\x{FE00}-\\x{FE0F}" +
|
||||
"\\x{200D}" +
|
||||
"\\x{20E3}" +
|
||||
"]"
|
||||
)
|
||||
|
||||
fun export(
|
||||
context: Context,
|
||||
threadId: Long,
|
||||
@@ -435,7 +447,13 @@ object PlaintextExportRepository {
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun sanitizeFileName(name: String): String {
|
||||
return name.replace(Regex("[\\\\/:*?\"<>|]"), "_").trim().take(100)
|
||||
val sanitized = name
|
||||
.replace(EMOJI_REGEX, "")
|
||||
.replace(Regex("[\\\\/:*?\"<>|]"), "_")
|
||||
.replace(Regex("\\s+"), " ")
|
||||
.trim()
|
||||
.take(100)
|
||||
return if (sanitized.isEmpty() || sanitized.all { it == '.' }) "chat" else sanitized
|
||||
}
|
||||
|
||||
private fun <T> ExecutorService.submitTyped(callable: Callable<T>): Future<T> {
|
||||
|
||||
+15
-27
@@ -27,7 +27,6 @@ import android.graphics.Canvas;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -1224,33 +1223,22 @@ public class ConversationListFragment extends MainFragment implements Conversati
|
||||
final Set<Long> selectedConversations = new HashSet<>(ids);
|
||||
|
||||
if (!selectedConversations.isEmpty()) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
private SignalProgressDialog dialog;
|
||||
SignalProgressDialog progressDialog = SignalProgressDialog.show(requireActivity(),
|
||||
context.getString(R.string.ConversationListFragment_deleting),
|
||||
context.getResources().getQuantityString(R.plurals.ConversationListFragment_deleting_selected_conversations, conversationsCount),
|
||||
true,
|
||||
false);
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
dialog = SignalProgressDialog.show(requireActivity(),
|
||||
context.getString(R.string.ConversationListFragment_deleting),
|
||||
context.getResources().getQuantityString(R.plurals.ConversationListFragment_deleting_selected_conversations, conversationsCount),
|
||||
true,
|
||||
false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
Log.d(TAG, "[handleDelete] Deleting " + selectedConversations.size() + " chats");
|
||||
SignalDatabase.threads().deleteConversations(selectedConversations, true);
|
||||
AppDependencies.getMessageNotifier().updateNotification(AppDependencies.getApplication());
|
||||
Log.d(TAG, "[handleDelete] Delete complete");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
dialog.dismiss();
|
||||
endActionModeIfActive();
|
||||
}
|
||||
}.executeOnExecutor(SignalExecutors.BOUNDED);
|
||||
SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> {
|
||||
Log.d(TAG, "[handleDelete] Deleting " + selectedConversations.size() + " chats");
|
||||
SignalDatabase.threads().deleteConversations(selectedConversations, true);
|
||||
AppDependencies.getMessageNotifier().updateNotification(AppDependencies.getApplication());
|
||||
Log.d(TAG, "[handleDelete] Delete complete");
|
||||
return null;
|
||||
}, unused -> {
|
||||
progressDialog.dismiss();
|
||||
endActionModeIfActive();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -498,6 +498,7 @@ object AppDependencies {
|
||||
fun provideProfileService(profileOperations: ClientZkProfileOperations, authWebSocket: SignalWebSocket.AuthenticatedWebSocket, unauthWebSocket: SignalWebSocket.UnauthenticatedWebSocket): ProfileService
|
||||
fun provideDeadlockDetector(): DeadlockDetector
|
||||
fun provideClientZkReceiptOperations(signalServiceConfiguration: SignalServiceConfiguration): ClientZkReceiptOperations
|
||||
fun provideOkHttpClient(): OkHttpClient
|
||||
fun provideScheduledMessageManager(): ScheduledMessageManager
|
||||
fun providePinnedMessageManager(): PinnedMessageManager
|
||||
fun provideLibsignalNetwork(config: SignalServiceConfiguration): Network
|
||||
|
||||
+10
@@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.signal.billing.BillingFactory;
|
||||
import org.signal.core.models.ServiceId.ACI;
|
||||
@@ -209,6 +210,7 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
protocolStore.aci(),
|
||||
new SignalProtocolAddress(pushServiceSocket.getCredentialsProvider().getAci().getLibSignalServiceId(),
|
||||
pushServiceSocket.getCredentialsProvider().getDeviceId()),
|
||||
ReentrantSessionLock.INSTANCE,
|
||||
PreKeyBatcher.INSTANCE
|
||||
)
|
||||
);
|
||||
@@ -541,6 +543,14 @@ public class ApplicationDependencyProvider implements AppDependencies.Provider {
|
||||
return provideClientZkOperations(signalServiceConfiguration).getReceiptOperations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull OkHttpClient provideOkHttpClient() {
|
||||
return new OkHttpClient.Builder()
|
||||
.addInterceptor(new StandardUserAgentInterceptor())
|
||||
.dns(SignalServiceNetworkAccess.DNS)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BillingApi provideBillingApi() {
|
||||
return BillingFactory.create(GooglePlayBillingDependencies.INSTANCE, Environment.Backups.supportsGooglePlayBilling());
|
||||
|
||||
+1
-5
@@ -37,7 +37,6 @@ import org.thoughtcrime.securesms.groups.GroupsV2Authorization
|
||||
import org.thoughtcrime.securesms.groups.GroupsV2AuthorizationMemoryValueCache
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver
|
||||
import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor
|
||||
import org.thoughtcrime.securesms.payments.Payments
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
|
||||
import org.thoughtcrime.securesms.push.SignalServiceTrustStore
|
||||
@@ -244,10 +243,7 @@ class NetworkDependenciesModule(
|
||||
}
|
||||
|
||||
val okHttpClient: OkHttpClient by lazy {
|
||||
OkHttpClient.Builder()
|
||||
.addInterceptor(StandardUserAgentInterceptor())
|
||||
.dns(SignalServiceNetworkAccess.DNS)
|
||||
.build()
|
||||
provider.provideOkHttpClient()
|
||||
}
|
||||
|
||||
val signalOkHttpClient: OkHttpClient by lazy {
|
||||
|
||||
@@ -135,7 +135,7 @@ class CheckKeyTransparencyJob private constructor(
|
||||
keyTransparencyStore = KeyTransparencyStore
|
||||
)
|
||||
|
||||
Log.i(TAG, "Key transparency complete, result: $result. Included username in check: ${Recipient.self().usernameSyncMessagesCapability.isSupported}, next check time: ${SignalStore.misc.nextKeyTransparencyTime}")
|
||||
Log.i(TAG, "Key transparency complete, result: $result. Included username in check: ${Recipient.self().usernameSyncMessagesCapability.isSupported}, discoverability: ${SignalStore.phoneNumberPrivacy.phoneNumberDiscoverabilityMode}, next check time: ${SignalStore.misc.nextKeyTransparencyTime}")
|
||||
return when (result) {
|
||||
is RequestResult.Success -> {
|
||||
SignalStore.misc.hasKeyTransparencyFailure = false
|
||||
@@ -144,9 +144,10 @@ class CheckKeyTransparencyJob private constructor(
|
||||
}
|
||||
|
||||
is RequestResult.NonSuccess -> {
|
||||
if (!showFailure) {
|
||||
if (!showFailure && !SignalStore.misc.hasKeyTransparencyFailure) {
|
||||
Log.w(TAG, "Verification failure. Enqueuing this job again to run again a day.")
|
||||
StorageSyncJob.forRemoteChange()
|
||||
AppDependencies.jobManager.add(StorageSyncJob.forRemoteChange())
|
||||
AppDependencies.jobManager.add(RefreshAttributesJob())
|
||||
enqueueFollowingFailure()
|
||||
} else {
|
||||
Log.w(TAG, "Second verification failure. Showing failure sheet.")
|
||||
|
||||
@@ -186,6 +186,10 @@ class RestoreLocalAttachmentJob private constructor(
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Experienced an exception while trying to read attachment.", e)
|
||||
return Result.retry(defaultBackoff())
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Lost access to the backup directory. Unable to restore attachment.", e)
|
||||
SignalStore.backup.localRestoreDirectoryError = true
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
|
||||
@@ -30,7 +30,6 @@ class InternalValues internal constructor(store: KeyValueStore) : SignalStoreVal
|
||||
const val LAST_SCROLL_POSITION: String = "internal.last_scroll_position"
|
||||
const val CONVERSATION_ITEM_V2_MEDIA: String = "internal.conversation_item_v2_media"
|
||||
const val WEB_SOCKET_SHADOWING_STATS: String = "internal.web_socket_shadowing_stats"
|
||||
const val ENCODE_HEVC: String = "internal.hevc_encoding"
|
||||
const val FORCE_SPLIT_PANE_ON_COMPACT_LANDSCAPE: String = "internal.force.split.pane.on.compact.landscape.ui"
|
||||
const val FORCE_SINGLE_PANE_ON_ALL_DEVICES: String = "internal.force_single_pane_on_all_devices"
|
||||
const val SHOW_ARCHIVE_STATE_HINT: String = "internal.show_archive_state_hint"
|
||||
@@ -171,8 +170,6 @@ class InternalValues internal constructor(store: KeyValueStore) : SignalStoreVal
|
||||
*/
|
||||
var callingUseInputVoiceComm by booleanValue(CALLING_USE_INPUT_VOICE_COMM, true).defaultForExternalUsers()
|
||||
|
||||
var hevcEncoding by booleanValue(ENCODE_HEVC, false).defaultForExternalUsers()
|
||||
|
||||
var lastScrollPosition: Int by integerValue(LAST_SCROLL_POSITION, 0).defaultForExternalUsers()
|
||||
|
||||
var useConversationItemV2Media by booleanValue(CONVERSATION_ITEM_V2_MEDIA, false).defaultForExternalUsers()
|
||||
|
||||
@@ -133,6 +133,14 @@ class SignalStore(context: Application, private val store: KeyValueStore) {
|
||||
instance!!.store.resetCache()
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps out the singleton for a test instance. Pass null to clear it. Should only be used for testing!
|
||||
*/
|
||||
@VisibleForTesting
|
||||
fun testInject(instance: SignalStore?) {
|
||||
Companion.instance = instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Restoring a backup changes the underlying disk values, so the cache needs to be reset.
|
||||
*/
|
||||
|
||||
@@ -51,7 +51,7 @@ object LinkDeviceRepository {
|
||||
private val TAG = Log.tag(LinkDeviceRepository::class)
|
||||
private const val DECRYPTION_INFO = "deviceCreatedAt"
|
||||
|
||||
fun removeDevice(deviceId: Int): Boolean {
|
||||
suspend fun removeDevice(deviceId: Int): Boolean {
|
||||
return when (val result = AppDependencies.linkDeviceApi.removeDevice(deviceId)) {
|
||||
is NetworkResult.Success -> {
|
||||
LinkedDeviceInactiveCheckJob.enqueue()
|
||||
|
||||
@@ -7,12 +7,13 @@ import org.signal.mediasend.SentMediaQuality
|
||||
import org.signal.mediasend.edit.video.VideoTrimData
|
||||
import org.thoughtcrime.securesms.conversation.MessageSendType
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.mms.PushMediaConstraints
|
||||
import org.thoughtcrime.securesms.mms.TranscodingConfigProvider
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.video.TranscodingPreset
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
data class MediaSelectionState(
|
||||
@@ -31,13 +32,12 @@ data class MediaSelectionState(
|
||||
val cameraFirstCapture: Media? = null,
|
||||
val isStory: Boolean,
|
||||
val storySendRequirements: Stories.MediaTransform.SendRequirements = Stories.MediaTransform.SendRequirements.CAN_NOT_SEND,
|
||||
val suppressEmptyError: Boolean = true
|
||||
val suppressEmptyError: Boolean = true,
|
||||
val transcodingConfigs: List<TranscodingConfig.QualityTier> = TranscodingConfigProvider.getConfigsForMediaQuality(SentMediaQuality.fromCode(quality.code))
|
||||
) {
|
||||
|
||||
val isVideoTrimmingVisible: Boolean = focusedMedia != null && MediaUtil.isVideoType(focusedMedia.contentType) && MediaConstraints.isVideoTranscodeAvailable() && !focusedMedia.isVideoGif
|
||||
|
||||
val transcodingPreset: TranscodingPreset = PushMediaConstraints(SentMediaQuality.fromCode(quality.code)).videoTranscodingSettings
|
||||
|
||||
val maxSelection = RemoteConfig.maxAttachmentCount
|
||||
|
||||
val canSend = !isSent && selectedMedia.isNotEmpty()
|
||||
@@ -46,11 +46,11 @@ data class MediaSelectionState(
|
||||
return editorStateMap[uri] as? VideoTrimData ?: VideoTrimData()
|
||||
}
|
||||
|
||||
fun calculateMaxVideoDurationUs(maxFileSize: Long): Long {
|
||||
fun calculateMaxVideoDurationUs(maxFileSize: Long, videoDuration: Duration): Long {
|
||||
return if (isStory && !MediaConstraints.isVideoTranscodeAvailable()) {
|
||||
Stories.MAX_VIDEO_DURATION_MILLIS
|
||||
} else {
|
||||
transcodingPreset.calculateMaxVideoUploadDurationInSeconds(maxFileSize).seconds.inWholeMicroseconds
|
||||
TranscodingConfig.calculateMaxVideoUploadDurationInSeconds(transcodingConfigs, videoDuration, maxFileSize).seconds.inWholeMicroseconds
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.conversation.MessageStyler
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivityResult
|
||||
import org.thoughtcrime.securesms.mms.PushMediaConstraints
|
||||
import org.thoughtcrime.securesms.mms.TranscodingConfigProvider
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.scribbles.ImageEditorFragment
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
@@ -42,6 +43,7 @@ import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
import java.util.Collections
|
||||
import kotlin.math.max
|
||||
import kotlin.time.Duration.Companion.microseconds
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
/**
|
||||
@@ -166,11 +168,11 @@ class MediaSelectionViewModel(
|
||||
.subscribe { filterResult ->
|
||||
if (filterResult.filteredMedia.isNotEmpty()) {
|
||||
store.update {
|
||||
val maxDuration = it.calculateMaxVideoDurationUs(getMediaConstraints().getEditorVideoMaxSize())
|
||||
val initializedVideoEditorStates = filterResult.filteredMedia.filterNot { media -> it.editorStateMap.containsKey(media.uri) }
|
||||
.filter { media -> MediaUtil.isNonGifVideo(media) }
|
||||
.associate { video: Media ->
|
||||
val duration = video.duration.milliseconds.inWholeMicroseconds
|
||||
val maxDuration = it.calculateMaxVideoDurationUs(getMediaConstraints().getEditorVideoMaxSize(), video.duration.milliseconds)
|
||||
if (duration < maxDuration) {
|
||||
video.uri to VideoTrimData(false, duration, 0, duration)
|
||||
} else {
|
||||
@@ -330,7 +332,7 @@ class MediaSelectionViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
store.update { it.copy(quality = sentMediaQuality, isPreUploadEnabled = false) }
|
||||
store.update { it.copy(quality = sentMediaQuality, isPreUploadEnabled = false, transcodingConfigs = TranscodingConfigProvider.getConfigsForMediaQuality(sentMediaQuality)) }
|
||||
repository.uploadRepository.cancelAllUploads()
|
||||
|
||||
store.state.selectedMedia.forEach { mediaItem ->
|
||||
@@ -360,7 +362,7 @@ class MediaSelectionViewModel(
|
||||
val durationEdited = clampedStartTime > 0 || endTimeUs < totalDurationUs
|
||||
val isEntireDuration = startTimeUs == 0L && endTimeUs == totalDurationUs
|
||||
val endMoved = !isEntireDuration && data.endTimeUs != endTimeUs
|
||||
val maxVideoDurationUs: Long = it.calculateMaxVideoDurationUs(getMediaConstraints().getEditorVideoMaxSize())
|
||||
val maxVideoDurationUs: Long = it.calculateMaxVideoDurationUs(getMediaConstraints().getEditorVideoMaxSize(), (endTimeUs - clampedStartTime).microseconds)
|
||||
val preserveStartTime = unedited || !endMoved
|
||||
val videoTrimData = VideoTrimData(durationEdited, totalDurationUs, clampedStartTime, endTimeUs)
|
||||
val updatedData = clampToMaxClipDuration(videoTrimData, maxVideoDurationUs, preserveStartTime)
|
||||
|
||||
+4
-2
@@ -69,11 +69,13 @@ import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
import org.thoughtcrime.securesms.util.fragments.requireListener
|
||||
import org.thoughtcrime.securesms.util.views.TouchInterceptingFrameLayout
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig
|
||||
import org.thoughtcrime.securesms.video.TranscodingQuality
|
||||
import java.io.IOException
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.time.Duration.Companion.microseconds
|
||||
import org.signal.core.ui.R as CoreUiR
|
||||
|
||||
/**
|
||||
@@ -584,7 +586,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||
val size: Long = tryGetUriSize(requireContext(), uri, Long.MAX_VALUE)
|
||||
val maxSend = sharedViewModel.getMediaConstraints().getEditorVideoMaxSize()
|
||||
if (size > maxSend) {
|
||||
videoTimeLine.setTimeLimit(state.transcodingPreset.calculateMaxVideoUploadDurationInSeconds(maxSend), TimeUnit.SECONDS)
|
||||
videoTimeLine.setTimeLimit(TranscodingConfig.calculateMaxVideoUploadDurationInSeconds(state.transcodingConfigs, state.getOrCreateVideoTrimData(uri).totalInputDurationUs.microseconds, maxSend), TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
if (state.isTouchEnabled) {
|
||||
@@ -602,7 +604,7 @@ class MediaReviewFragment : Fragment(R.layout.v2_media_review_fragment), Schedul
|
||||
|
||||
videoSizeHint.text = if (state.isVideoTrimmingVisible) {
|
||||
val seconds = trimData.getDuration().inWholeSeconds
|
||||
val bytes = TranscodingQuality.createFromPreset(state.transcodingPreset, trimData.getDuration().inWholeMilliseconds).byteCountEstimate
|
||||
val bytes = TranscodingQuality.createFromQualityTiers(state.transcodingConfigs, trimData.getDuration().inWholeMilliseconds).byteCountEstimate
|
||||
String.format(Locale.getDefault(), "%d:%02d • %s", seconds / 60, seconds % 60, bytes.bytes.toUnitString())
|
||||
} else {
|
||||
null
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.scribbles.ImageEditorFragment
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig
|
||||
import java.io.InputStream
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.resume
|
||||
@@ -129,9 +130,9 @@ object MediaSendV3Repository : MediaSendRepository {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMaxVideoDurationUs(quality: SentMediaQuality, maxFileSizeBytes: Long): Long {
|
||||
val preset = PushMediaConstraints(quality).videoTranscodingSettings
|
||||
return preset.calculateMaxVideoUploadDurationInSeconds(maxFileSizeBytes).seconds.inWholeMicroseconds
|
||||
override fun getMaxVideoDurationUs(quality: SentMediaQuality, maxFileSizeBytes: Long, duration: Duration): Long {
|
||||
val config = PushMediaConstraints(quality).videoTranscodingSettings
|
||||
return TranscodingConfig.calculateMaxVideoUploadDurationInSeconds(config, duration, maxFileSizeBytes).seconds.inWholeMicroseconds
|
||||
}
|
||||
|
||||
override fun getVideoMaxSizeBytes(): Long {
|
||||
|
||||
@@ -122,7 +122,7 @@ import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
object DataMessageProcessor {
|
||||
|
||||
private const val BODY_RANGE_PROCESSING_LIMIT = 250
|
||||
internal const val BODY_RANGE_PROCESSING_LIMIT = 250
|
||||
private const val POLL_QUESTION_CHARACTER_LIMIT = 200
|
||||
private const val POLL_CHARACTER_LIMIT = 100
|
||||
private const val POLL_OPTIONS_LIMIT = 10
|
||||
@@ -791,7 +791,8 @@ object DataMessageProcessor {
|
||||
return null
|
||||
}
|
||||
|
||||
val bodyRanges: BodyRangeList? = message.bodyRanges.filter { Util.allAreNull(it.mentionAci, it.mentionAciBinary) }.toList().toBodyRangeList()
|
||||
val cappedBodyRanges: List<BodyRange> = message.bodyRanges.take(BODY_RANGE_PROCESSING_LIMIT)
|
||||
val bodyRanges: BodyRangeList? = cappedBodyRanges.filter { Util.allAreNull(it.mentionAci, it.mentionAciBinary) }.toList().toBodyRangeList()
|
||||
|
||||
val mediaMessage = IncomingMessage(
|
||||
type = MessageType.NORMAL,
|
||||
@@ -805,7 +806,7 @@ object DataMessageProcessor {
|
||||
body = message.body,
|
||||
groupId = groupId,
|
||||
quote = quoteModel,
|
||||
mentions = getMentions(message.bodyRanges),
|
||||
mentions = getMentions(cappedBodyRanges),
|
||||
serverGuid = UuidUtil.getStringUUID(envelope.serverGuid, envelope.serverGuidBinary),
|
||||
messageRanges = bodyRanges
|
||||
)
|
||||
|
||||
@@ -124,7 +124,8 @@ object EditMessageProcessor {
|
||||
message: DataMessage,
|
||||
targetMessage: MmsMessageRecord
|
||||
): InsertResult? {
|
||||
val messageRanges: BodyRangeList? = message.bodyRanges.filter { Util.allAreNull(it.mentionAci, it.mentionAciBinary) }.toList().toBodyRangeList()
|
||||
val cappedBodyRanges = message.bodyRanges.take(DataMessageProcessor.BODY_RANGE_PROCESSING_LIMIT)
|
||||
val messageRanges: BodyRangeList? = cappedBodyRanges.filter { Util.allAreNull(it.mentionAci, it.mentionAciBinary) }.toList().toBodyRangeList()
|
||||
val targetQuote = targetMessage.quote
|
||||
val quote: QuoteModel? = if (targetQuote != null && (message.quote != null || (targetMessage.parentStoryId != null && message.storyContext != null))) {
|
||||
QuoteModel(
|
||||
@@ -159,7 +160,7 @@ object EditMessageProcessor {
|
||||
parentStoryId = targetMessage.parentStoryId,
|
||||
sharedContacts = emptyList(),
|
||||
linkPreviews = DataMessageProcessor.getLinkPreviews(message.preview, message.body ?: "", false),
|
||||
mentions = DataMessageProcessor.getMentions(message.bodyRanges),
|
||||
mentions = DataMessageProcessor.getMentions(cappedBodyRanges),
|
||||
serverGuid = UuidUtil.getStringUUID(envelope.serverGuid, envelope.serverGuidBinary),
|
||||
messageRanges = messageRanges
|
||||
)
|
||||
|
||||
@@ -159,6 +159,8 @@ object MessageDecryptor {
|
||||
SignalTrace.endSection()
|
||||
val endTimeNanos = System.nanoTime()
|
||||
|
||||
val hadSealedSenderSource = Util.allAreNull(envelope.sourceServiceId, envelope.sourceServiceIdBinary)
|
||||
|
||||
val envelope = if (cipherResult?.metadata?.sourceServiceId != null) {
|
||||
envelope.newBuilder()
|
||||
.sourceServiceIdBinary(cipherResult.metadata.sourceServiceId.toByteString())
|
||||
@@ -173,7 +175,7 @@ object MessageDecryptor {
|
||||
return Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations.toUnmodifiableList())
|
||||
}
|
||||
|
||||
if (cipherResult.metadata.sourceServiceId is PNI && (envelope.sourceServiceId == null && envelope.sourceServiceIdBinary == null)) {
|
||||
if (cipherResult.metadata.sourceServiceId is PNI && hadSealedSenderSource) {
|
||||
Log.w(TAG, "${logPrefix(envelope)} Invalid message! Sealed sender used for a PNI.")
|
||||
return Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations.toUnmodifiableList())
|
||||
}
|
||||
|
||||
+7
-4
@@ -1,19 +1,18 @@
|
||||
package org.thoughtcrime.securesms.messages.protocol
|
||||
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.libsignal.protocol.IdentityKey
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair
|
||||
import org.signal.libsignal.protocol.SignalProtocolAddress
|
||||
import org.signal.libsignal.protocol.state.IdentityKeyStore
|
||||
import org.signal.libsignal.protocol.state.IdentityKeyStore.IdentityChange
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.whispersystems.signalservice.api.SignalServiceAccountDataStore
|
||||
|
||||
/**
|
||||
* An in-memory identity key store that is intended to be used temporarily while decrypting messages.
|
||||
*/
|
||||
class BufferedIdentityKeyStore(
|
||||
private val selfServiceId: ServiceId,
|
||||
private val selfIdentityKeyPair: IdentityKeyPair,
|
||||
private val selfRegistrationId: Int
|
||||
) : IdentityKeyStore {
|
||||
@@ -45,8 +44,12 @@ class BufferedIdentityKeyStore(
|
||||
}
|
||||
|
||||
override fun isTrustedIdentity(address: SignalProtocolAddress, identityKey: IdentityKey, direction: IdentityKeyStore.Direction): Boolean {
|
||||
if (address.name == selfServiceId.toString()) {
|
||||
return identityKey == selfIdentityKeyPair.publicKey
|
||||
val isSelf = address.name == SignalStore.account.aci?.toString() ||
|
||||
address.name == SignalStore.account.pni?.toString() ||
|
||||
address.name == SignalStore.account.e164
|
||||
|
||||
if (isSelf) {
|
||||
return identityKey == SignalStore.account.aciIdentityKey.publicKey
|
||||
}
|
||||
|
||||
return when (direction) {
|
||||
|
||||
+2
-2
@@ -26,9 +26,9 @@ import java.util.UUID
|
||||
class BufferedSignalServiceAccountDataStore(selfServiceId: ServiceId) : SignalServiceAccountDataStore {
|
||||
|
||||
private val identityStore: BufferedIdentityKeyStore = if (selfServiceId == SignalStore.account.pni) {
|
||||
BufferedIdentityKeyStore(selfServiceId, SignalStore.account.pniIdentityKey, SignalStore.account.pniRegistrationId)
|
||||
BufferedIdentityKeyStore(SignalStore.account.pniIdentityKey, SignalStore.account.pniRegistrationId)
|
||||
} else {
|
||||
BufferedIdentityKeyStore(selfServiceId, SignalStore.account.aciIdentityKey, SignalStore.account.registrationId)
|
||||
BufferedIdentityKeyStore(SignalStore.account.aciIdentityKey, SignalStore.account.registrationId)
|
||||
}
|
||||
|
||||
private val oneTimePreKeyStore: BufferedOneTimePreKeyStore = BufferedOneTimePreKeyStore(selfServiceId)
|
||||
|
||||
@@ -11,24 +11,25 @@ import org.signal.mediasend.MediaConstraints;
|
||||
import org.signal.mediasend.SentMediaQuality;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.util.LocaleRemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.video.TranscodingPreset;
|
||||
import org.thoughtcrime.securesms.video.videoconverter.utils.DeviceCapabilities;
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class PushMediaConstraints extends MediaConstraints {
|
||||
|
||||
private static final int KB = 1024;
|
||||
private static final int MB = 1024 * KB;
|
||||
|
||||
private final MediaConfig currentConfig;
|
||||
private final MediaConfig currentConfig;
|
||||
private final SentMediaQuality sentMediaQuality;
|
||||
|
||||
public PushMediaConstraints(@Nullable SentMediaQuality sentMediaQuality) {
|
||||
currentConfig = getCurrentConfig(AppDependencies.getApplication(), sentMediaQuality);
|
||||
this.currentConfig = getCurrentConfig(AppDependencies.getApplication(), sentMediaQuality);
|
||||
this.sentMediaQuality = sentMediaQuality;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,8 +96,8 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranscodingPreset getVideoTranscodingSettings() {
|
||||
return currentConfig.videoPreset;
|
||||
public List<TranscodingConfig.QualityTier> getVideoTranscodingSettings() {
|
||||
return sentMediaQuality == SentMediaQuality.HIGH ? currentConfig.videoConfigs.getHigh() : currentConfig.videoConfigs.getStandard();
|
||||
}
|
||||
|
||||
private static @NonNull MediaConfig getCurrentConfig(@NonNull Context context, @Nullable SentMediaQuality sentMediaQuality) {
|
||||
@@ -105,44 +106,37 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
}
|
||||
|
||||
if (sentMediaQuality == SentMediaQuality.HIGH) {
|
||||
if (DeviceCapabilities.canEncodeHevc() && (RemoteConfig.useHevcEncoder() || SignalStore.internal().getHevcEncoding())) {
|
||||
return MediaConfig.LEVEL_3_H265;
|
||||
} else {
|
||||
return MediaConfig.LEVEL_3;
|
||||
}
|
||||
return MediaConfig.LEVEL_3;
|
||||
}
|
||||
return LocaleRemoteConfig.getMediaQualityLevel().orElse(MediaConfig.getDefault(context));
|
||||
}
|
||||
|
||||
public enum MediaConfig {
|
||||
LEVEL_1_LOW_MEMORY(true, 1, MB, new int[] { 768, 512 }, 70, TranscodingPreset.LEVEL_1),
|
||||
LEVEL_1_LOW_MEMORY(true, 1, MB, new int[] { 768, 512 }, 70),
|
||||
|
||||
LEVEL_1(false, 1, MB, new int[] { 1600, 1024, 768, 512 }, 70, TranscodingPreset.LEVEL_1),
|
||||
LEVEL_2(false, 2, (int) (1.5 * MB), new int[] { 2048, 1600, 1024, 768, 512 }, 75, TranscodingPreset.LEVEL_2),
|
||||
LEVEL_3(false, 3, (int) (3 * MB), new int[] { 4096, 3072, 2048, 1600, 1024, 768, 512 }, 75, TranscodingPreset.LEVEL_3),
|
||||
/** Experimental H265 level */
|
||||
LEVEL_3_H265(false, 4, 3 * MB, new int[] { 4096, 3072, 2048, 1600, 1024, 768, 512 }, 75, TranscodingPreset.LEVEL_3_H265);
|
||||
LEVEL_1(false, 1, MB, new int[] { 1600, 1024, 768, 512 }, 70),
|
||||
LEVEL_2(false, 2, (int) (1.5 * MB), new int[] { 2048, 1600, 1024, 768, 512 }, 75),
|
||||
LEVEL_3(false, 3, (int) (3 * MB), new int[] { 4096, 3072, 2048, 1600, 1024, 768, 512 }, 75);
|
||||
|
||||
private final boolean isLowMemory;
|
||||
private final int level;
|
||||
private final int maxImageFileSize;
|
||||
private final int[] imageSizeTargets;
|
||||
private final int qualitySetting;
|
||||
private final TranscodingPreset videoPreset;
|
||||
private final boolean isLowMemory;
|
||||
private final int level;
|
||||
private final int maxImageFileSize;
|
||||
private final int[] imageSizeTargets;
|
||||
private final int qualitySetting;
|
||||
private final TranscodingConfig.TranscodeConfig videoConfigs;
|
||||
|
||||
MediaConfig(boolean isLowMemory,
|
||||
int level,
|
||||
int maxImageFileSize,
|
||||
@NonNull int[] imageSizeTargets,
|
||||
@IntRange(from = 0, to = 100) int qualitySetting,
|
||||
TranscodingPreset videoPreset)
|
||||
@IntRange(from = 0, to = 100) int qualitySetting)
|
||||
{
|
||||
this.isLowMemory = isLowMemory;
|
||||
this.level = level;
|
||||
this.maxImageFileSize = maxImageFileSize;
|
||||
this.imageSizeTargets = imageSizeTargets;
|
||||
this.qualitySetting = qualitySetting;
|
||||
this.videoPreset = videoPreset;
|
||||
this.videoConfigs = TranscodingConfigProvider.getAllConfigs();
|
||||
}
|
||||
|
||||
public int getMaxImageFileSize() {
|
||||
@@ -157,10 +151,6 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
return qualitySetting;
|
||||
}
|
||||
|
||||
public TranscodingPreset getVideoPreset() {
|
||||
return videoPreset;
|
||||
}
|
||||
|
||||
public static @Nullable MediaConfig forLevel(int level) {
|
||||
boolean isLowMemory = Util.isLowMemory(AppDependencies.getApplication());
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.thoughtcrime.securesms.mms
|
||||
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import org.signal.mediasend.SentMediaQuality
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig
|
||||
|
||||
/**
|
||||
* Gets corresponding configs depending on locale and sent media quality
|
||||
*/
|
||||
object TranscodingConfigProvider {
|
||||
@JvmStatic
|
||||
fun getAllConfigs(): TranscodingConfig.TranscodeConfig {
|
||||
val countryCode = PhoneNumberUtil.getInstance().parse(SignalStore.account.e164, "").countryCode
|
||||
return TranscodingConfig.getTranscodeConfig(RemoteConfig.transcodeConfig, countryCode)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getConfigsForMediaQuality(quality: SentMediaQuality): List<TranscodingConfig.QualityTier> {
|
||||
val config = getAllConfigs()
|
||||
return when (quality) {
|
||||
SentMediaQuality.STANDARD -> config.standard
|
||||
SentMediaQuality.HIGH -> config.high
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,10 @@ package org.thoughtcrime.securesms.profiles;
|
||||
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentUploadJob;
|
||||
import org.signal.mediasend.MediaConstraints;
|
||||
import org.thoughtcrime.securesms.video.TranscodingConfig;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ProfileMediaConstraints extends MediaConstraints {
|
||||
@Override
|
||||
@@ -49,4 +53,9 @@ public class ProfileMediaConstraints extends MediaConstraints {
|
||||
public long getMaxAttachmentSize() {
|
||||
return AttachmentUploadJob.getMaxPlaintextSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TranscodingConfig.QualityTier> getVideoTranscodingSettings() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,7 +660,7 @@ class Recipient(
|
||||
}
|
||||
|
||||
private fun getUnknownDisplayName(context: Context): String {
|
||||
return if (registered == RegisteredState.NOT_REGISTERED) {
|
||||
return if (!isResolving && registered == RegisteredState.NOT_REGISTERED) {
|
||||
context.getString(R.string.Recipient_deleted_account)
|
||||
} else {
|
||||
context.getString(R.string.Recipient_unknown)
|
||||
|
||||
+3
-3
@@ -78,9 +78,9 @@ fun TransferAccountNavHost(
|
||||
entries = entries,
|
||||
onBack = { viewModel.goBack() },
|
||||
modifier = modifier,
|
||||
transitionSpec = TransitionSpecs.HorizontalSlide.transitionSpec,
|
||||
popTransitionSpec = TransitionSpecs.HorizontalSlide.popTransitionSpec,
|
||||
predictivePopTransitionSpec = TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec
|
||||
transitionSpec = { TransitionSpecs.HorizontalSlide.transitionSpec },
|
||||
popTransitionSpec = { TransitionSpecs.HorizontalSlide.popTransitionSpec },
|
||||
predictivePopTransitionSpec = { TransitionSpecs.HorizontalSlide.predictivePopTransitionSpec }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ fun RestoreLocalBackupNavDisplay(
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
NavDisplay(
|
||||
backStack = backstack,
|
||||
sceneStrategy = bottomSheetStrategy,
|
||||
sceneStrategies = listOf(bottomSheetStrategy),
|
||||
entryProvider = entryProvider {
|
||||
entry<RestoreLocalBackupNavKey.SelectLocalBackupTypeScreen> {
|
||||
SelectLocalBackupTypeScreen(
|
||||
|
||||
+4
-3
@@ -591,10 +591,11 @@ class AppRegistrationNetworkController(
|
||||
val aci = SignalStore.account.aci ?: return@withContext RequestResult.ApplicationError(IllegalStateException("ACI not available"))
|
||||
|
||||
val currentTime = System.currentTimeMillis()
|
||||
val messageBackupKey = aep.deriveMessageBackupKey()
|
||||
val messageCredential = SignalStore.backup.messageCredentials.byDay.getForCurrentTime(currentTime.milliseconds)
|
||||
|
||||
val access = if (messageCredential != null) {
|
||||
ArchiveServiceAccess(messageCredential, SignalStore.backup.messageBackupKey)
|
||||
ArchiveServiceAccess(messageCredential, messageBackupKey)
|
||||
} else {
|
||||
when (val credResult = SignalNetwork.archive.getServiceCredentials(currentTime)) {
|
||||
is NetworkResult.Success -> {
|
||||
@@ -602,7 +603,7 @@ class AppRegistrationNetworkController(
|
||||
SignalStore.backup.messageCredentials.clearOlderThan(currentTime)
|
||||
val credential = SignalStore.backup.messageCredentials.byDay.getForCurrentTime(currentTime.milliseconds)
|
||||
?: return@withContext RequestResult.ApplicationError(IllegalStateException("Failed to obtain backup credentials after fetch"))
|
||||
ArchiveServiceAccess(credential, SignalStore.backup.messageBackupKey)
|
||||
ArchiveServiceAccess(credential, messageBackupKey)
|
||||
}
|
||||
is NetworkResult.StatusCodeError -> return@withContext RequestResult.ApplicationError(IllegalStateException("Failed to fetch backup credentials: ${credResult.code}"))
|
||||
is NetworkResult.NetworkError -> return@withContext RequestResult.RetryableNetworkError(credResult.exception)
|
||||
@@ -729,7 +730,7 @@ class AppRegistrationNetworkController(
|
||||
val messageCredential = SignalStore.backup.messageCredentials.byDay.getForCurrentTime(currentTime.milliseconds)
|
||||
?: return@withContext RequestResult.ApplicationError(IllegalStateException("No message credential available"))
|
||||
|
||||
val access = ArchiveServiceAccess(messageCredential, SignalStore.backup.messageBackupKey)
|
||||
val access = ArchiveServiceAccess(messageCredential, aep.deriveMessageBackupKey())
|
||||
|
||||
val cdnCredentials = when (val cdnResult = SignalNetwork.archive.getCdnReadCredentials(cdn, aci, access)) {
|
||||
is NetworkResult.Success -> cdnResult.result.headers
|
||||
|
||||
+452
-157
@@ -6,75 +6,117 @@
|
||||
package org.thoughtcrime.securesms.registration.v2
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.google.common.io.CountingInputStream
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.signal.archive.LocalBackupRestoreProgress
|
||||
import org.signal.core.models.AccountEntropyPool
|
||||
import org.signal.core.models.MasterKey
|
||||
import org.signal.core.models.ServiceId
|
||||
import org.signal.core.models.ServiceId.ACI
|
||||
import org.signal.core.models.ServiceId.PNI
|
||||
import org.signal.core.models.backup.MediaRootBackupKey
|
||||
import org.signal.core.models.backup.MessageBackupKey
|
||||
import org.signal.core.util.AppUtil
|
||||
import org.signal.core.util.Result
|
||||
import org.signal.core.util.StreamUtil
|
||||
import org.signal.core.util.crypto.AttachmentSecretProvider
|
||||
import org.signal.core.util.getLength
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair
|
||||
import org.signal.libsignal.protocol.state.KyberPreKeyRecord
|
||||
import org.signal.libsignal.protocol.state.SignedPreKeyRecord
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
||||
import org.signal.registration.PreExistingRegistrationData
|
||||
import org.signal.registration.RestoreDecision
|
||||
import org.signal.registration.StorageController
|
||||
import org.signal.registration.StoredProfileData
|
||||
import org.signal.registration.proto.AccountData
|
||||
import org.signal.registration.proto.RegistrationData
|
||||
import org.signal.registration.screens.localbackuprestore.LocalBackupInfo
|
||||
import org.signal.registration.screens.messagesync.LinkAndSyncProgress
|
||||
import org.signal.registration.screens.remotebackuprestore.RemoteBackupRestoreProgress
|
||||
import org.thoughtcrime.securesms.backup.BackupEvent
|
||||
import org.thoughtcrime.securesms.backup.BackupPassphrase
|
||||
import org.thoughtcrime.securesms.backup.FullBackupImporter
|
||||
import org.thoughtcrime.securesms.backup.v2.BackupRepository
|
||||
import org.thoughtcrime.securesms.backup.v2.RemoteRestoreResult
|
||||
import org.thoughtcrime.securesms.backup.v2.RestoreV2Event
|
||||
import org.thoughtcrime.securesms.backup.v2.local.ArchiveFileSystem
|
||||
import org.thoughtcrime.securesms.backup.v2.local.LocalArchiver
|
||||
import org.thoughtcrime.securesms.backup.v2.local.SnapshotFileSystem
|
||||
import org.thoughtcrime.securesms.crypto.AppAttachmentSecretStore
|
||||
import org.thoughtcrime.securesms.crypto.PreKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.ProfileKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.SenderKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.storage.PreKeyMetadataStore
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalServiceAccountDataStoreImpl
|
||||
import org.thoughtcrime.securesms.database.IdentityTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.LinkedDeviceInfo
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.LocalRegistrationMetadata
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.RestoreDecisionState
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.runJobBlocking
|
||||
import org.thoughtcrime.securesms.jobs.CheckKeyTransparencyJob
|
||||
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob
|
||||
import org.thoughtcrime.securesms.jobs.LocalBackupRestoreMediaJob
|
||||
import org.thoughtcrime.securesms.jobs.PreKeysSyncJob
|
||||
import org.thoughtcrime.securesms.jobs.RefreshOwnProfileJob
|
||||
import org.thoughtcrime.securesms.jobs.RotateCertificateJob
|
||||
import org.thoughtcrime.securesms.keyvalue.Completed
|
||||
import org.thoughtcrime.securesms.keyvalue.NewAccount
|
||||
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.keyvalue.Skipped
|
||||
import org.thoughtcrime.securesms.keyvalue.isDecisionPending
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds
|
||||
import org.thoughtcrime.securesms.pin.SvrRepository
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.registration.data.RegistrationRepository
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.registration.util.RegistrationUtil
|
||||
import org.thoughtcrime.securesms.service.DirectoryRefreshListener
|
||||
import org.thoughtcrime.securesms.service.LocalBackupListener
|
||||
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener
|
||||
import org.thoughtcrime.securesms.util.BackupUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.link.TransferArchiveResponse
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.ZoneOffset
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
/**
|
||||
* Implementation of [StorageController] that bridges to the app's existing storage infrastructure.
|
||||
*/
|
||||
class AppRegistrationStorageController(private val context: Context) : StorageController {
|
||||
|
||||
/**
|
||||
* Restarts the process-wide network stack after account data is applied. Overridable only so tests can avoid
|
||||
* touching the real, suite-shared network module; production must never replace it.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal var restartNetwork: () -> Unit = {
|
||||
AppDependencies.resetNetwork()
|
||||
AppDependencies.startNetwork()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(AppRegistrationStorageController::class)
|
||||
private const val TEMP_PROTO_FILENAME = "registration-in-progress.proto"
|
||||
@@ -174,100 +216,44 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
|
||||
|
||||
override suspend fun commitRegistrationData() = withContext(Dispatchers.IO) {
|
||||
val data = readInProgressRegistrationData()
|
||||
val accountData = data.accountData
|
||||
|
||||
// The account's master key is always the one derived from the AEP, which we expect to have by the time we commit.
|
||||
// Restore it up-front so any master-key-derived state we touch below resolves against the correct value rather
|
||||
// than lazily generating a new AEP.
|
||||
val accountEntropyPool: AccountEntropyPool? = data.accountEntropyPool.takeIf { it.isNotEmpty() }?.let { AccountEntropyPool(it) }
|
||||
if (accountEntropyPool != null) {
|
||||
if (data.linkedDeviceData != null) {
|
||||
SignalStore.account.setAccountEntropyPoolFromPrimaryDevice(accountEntropyPool)
|
||||
} else {
|
||||
SignalStore.account.restoreAccountEntropyPool(accountEntropyPool)
|
||||
}
|
||||
}
|
||||
val masterKey: MasterKey? = applyAccountEntropyPool(data)
|
||||
|
||||
val masterKey: MasterKey? = accountEntropyPool?.deriveMasterKey()
|
||||
|
||||
// Build LocalRegistrationMetadata if we have enough data for account setup
|
||||
if (data.e164.isNotEmpty() && data.aci.isNotEmpty() && data.pni.isNotEmpty() && data.servicePassword.isNotEmpty()) {
|
||||
val profileKey = RegistrationRepository.getProfileKey(data.e164)
|
||||
|
||||
val metadata = LocalRegistrationMetadata.Builder().apply {
|
||||
if (data.aciIdentityKeyPair.size > 0) {
|
||||
aciIdentityKeyPair = data.aciIdentityKeyPair
|
||||
}
|
||||
if (data.pniIdentityKeyPair.size > 0) {
|
||||
pniIdentityKeyPair = data.pniIdentityKeyPair
|
||||
}
|
||||
if (data.aciSignedPreKey.size > 0) {
|
||||
aciSignedPreKey = data.aciSignedPreKey
|
||||
}
|
||||
if (data.pniSignedPreKey.size > 0) {
|
||||
pniSignedPreKey = data.pniSignedPreKey
|
||||
}
|
||||
if (data.aciLastResortKyberPreKey.size > 0) {
|
||||
aciLastRestoreKyberPreKey = data.aciLastResortKyberPreKey
|
||||
}
|
||||
if (data.pniLastResortKyberPreKey.size > 0) {
|
||||
pniLastRestoreKyberPreKey = data.pniLastResortKyberPreKey
|
||||
}
|
||||
|
||||
aci = data.aci
|
||||
pni = data.pni
|
||||
e164 = data.e164
|
||||
this.servicePassword = data.servicePassword
|
||||
this.profileKey = profileKey.serialize().toByteString()
|
||||
hasPin = data.pin.isNotEmpty()
|
||||
if (data.pin.isNotEmpty()) {
|
||||
pin = data.pin
|
||||
masterKey?.let { this.masterKey = it.serialize().toByteString() }
|
||||
}
|
||||
fcmEnabled = SignalStore.account.fcmEnabled
|
||||
fcmToken = SignalStore.account.fcmToken ?: ""
|
||||
reglockEnabled = data.registrationLockEnabled
|
||||
|
||||
data.linkedDeviceData?.let { linkData ->
|
||||
linkedDeviceInfo = LinkedDeviceInfo(
|
||||
deviceId = linkData.deviceId,
|
||||
deviceName = linkData.deviceName,
|
||||
ephemeralBackupKey = linkData.ephemeralBackupKey,
|
||||
accountEntropyPool = data.accountEntropyPool,
|
||||
mediaRootBackupKey = linkData.mediaRootBackupKey
|
||||
)
|
||||
}
|
||||
}.build()
|
||||
|
||||
SignalStore.account.registrationId = data.aciRegistrationId
|
||||
SignalStore.account.pniRegistrationId = data.pniRegistrationId
|
||||
|
||||
// TODO [greyson] Should probably move this stuff into this file as we get closer to being done
|
||||
RegistrationRepository.registerAccountLocally(context, metadata)
|
||||
SignalStore.registration.localRegistrationMetadata = metadata
|
||||
|
||||
data.linkedDeviceData?.readReceipts?.let { TextSecurePreferences.setReadReceiptsEnabled(context, it) }
|
||||
// We only want to apply account data a single time
|
||||
val svrStateUpdated = if (!data.accountDataCommitted && accountData != null && accountData.isComplete()) {
|
||||
applyAccountData(
|
||||
accountData = accountData,
|
||||
pin = data.pin,
|
||||
registrationLockEnabled = data.registrationLockEnabled,
|
||||
masterKey = masterKey
|
||||
)
|
||||
updateInProgressRegistrationData { accountDataCommitted = true }
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
// Handle PIN/master key
|
||||
if (data.pin.isNotEmpty() && masterKey != null && data.linkedDeviceData == null) {
|
||||
SvrRepository.onRegistrationComplete(
|
||||
masterKey,
|
||||
data.pin,
|
||||
true,
|
||||
data.registrationLockEnabled,
|
||||
data.accountEntropyPool.isNotEmpty()
|
||||
)
|
||||
} else if (data.pinOptedOut && data.linkedDeviceData == null) {
|
||||
if (data.pin.isNotEmpty() && masterKey != null && accountData?.linkedDeviceData == null) {
|
||||
// We call this same function in applyAccountData, so just avoiding double-calls
|
||||
if (!svrStateUpdated) {
|
||||
SvrRepository.onRegistrationComplete(
|
||||
masterKey = masterKey,
|
||||
userPin = data.pin,
|
||||
hasPinToRestore = true,
|
||||
setRegistrationLockEnabled = data.registrationLockEnabled,
|
||||
restoredAEP = data.accountEntropyPool.isNotEmpty()
|
||||
)
|
||||
}
|
||||
} else if (data.pinOptedOut && accountData?.linkedDeviceData == null) {
|
||||
Log.i(TAG, "[commitRegistrationData] User opted out of creating a PIN. Applying opt-out.")
|
||||
SvrRepository.optOutOfPin(rotateAep = false)
|
||||
}
|
||||
|
||||
// The temporaryMasterKey is the one-time key restored from SVR during re-registration. The account's own master key
|
||||
// is always the AEP-derived one above, so this is retained separately as the initial-restore key (used for the
|
||||
// first storage service sync + recovery password). It must be set last, as onRegistrationComplete will have cleared
|
||||
// the initial-restore key after recognizing the AEP-derived master key as our own.
|
||||
if (data.temporaryMasterKey.size > 0) {
|
||||
SignalStore.svr.masterKeyForInitialDataRestore = MasterKey(data.temporaryMasterKey.toByteArray())
|
||||
// This must be set last, as SvrRepository.onRegistrationComplete will have cleared the initial-restore key after recognizing the AEP-derived master key as our own.
|
||||
if (data.masterKeyForInitialDataRestore.size > 0) {
|
||||
SignalStore.svr.masterKeyForInitialDataRestore = MasterKey(data.masterKeyForInitialDataRestore.toByteArray())
|
||||
}
|
||||
|
||||
RegistrationUtil.maybeMarkRegistrationComplete()
|
||||
@@ -285,84 +271,195 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
|
||||
}
|
||||
}
|
||||
|
||||
override fun restoreLocalBackupV1(uri: Uri, passphrase: String): Flow<LocalBackupRestoreProgress> = flow {
|
||||
// TODO [greyson] better progress
|
||||
Log.d(TAG, "Starting V1 local backup restore from: $uri")
|
||||
override fun restoreLocalBackupV1(rootUri: Uri, backupUri: Uri, passphrase: String): Flow<LocalBackupRestoreProgress> = callbackFlow {
|
||||
Log.d(TAG, "Starting V1 local backup restore from: $backupUri")
|
||||
|
||||
emit(LocalBackupRestoreProgress.Preparing)
|
||||
trySend(LocalBackupRestoreProgress.Preparing)
|
||||
|
||||
try {
|
||||
if (!FullBackupImporter.validatePassphrase(context, uri, passphrase)) {
|
||||
emit(LocalBackupRestoreProgress.Error(IllegalArgumentException("Invalid passphrase")))
|
||||
return@flow
|
||||
// The importer only reports a running frame count with no total, so we track bytes read from the backup file against
|
||||
// its size to produce a real progress fraction, sampling the counting stream on each frame-progress event.
|
||||
val totalBytes = context.contentResolver.getLength(backupUri) ?: 0L
|
||||
var countingStream: CountingInputStream? = null
|
||||
|
||||
val subscriber = object {
|
||||
@Subscribe(threadMode = ThreadMode.POSTING)
|
||||
fun onBackupEvent(event: BackupEvent) {
|
||||
if (event.type == BackupEvent.Type.PROGRESS) {
|
||||
trySend(LocalBackupRestoreProgress.InProgress(bytesRead = countingStream?.count ?: 0L, totalBytes = totalBytes))
|
||||
}
|
||||
}
|
||||
|
||||
val database = SignalDatabase.backupDatabase
|
||||
FullBackupImporter.importFile(
|
||||
context,
|
||||
AttachmentSecretProvider.getInstance(context, AppAttachmentSecretStore).getOrCreateAttachmentSecret(),
|
||||
database,
|
||||
uri,
|
||||
passphrase,
|
||||
SignalStore.registration.localRegistrationMetadata != null
|
||||
)
|
||||
|
||||
SignalDatabase.runPostBackupRestoreTasks(database)
|
||||
|
||||
emit(LocalBackupRestoreProgress.Complete)
|
||||
Log.d(TAG, "V1 restore complete.")
|
||||
} catch (e: FullBackupImporter.DatabaseDowngradeException) {
|
||||
Log.w(TAG, "V1 restore failed: database downgrade", e)
|
||||
emit(LocalBackupRestoreProgress.Error(e))
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "V1 restore failed", e)
|
||||
emit(LocalBackupRestoreProgress.Error(e))
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
override fun restoreLocalBackupV2(rootUri: Uri, backupUri: Uri, aep: AccountEntropyPool): Flow<LocalBackupRestoreProgress> = flow {
|
||||
// TODO [greyson] better progress
|
||||
EventBus.getDefault().register(subscriber)
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
try {
|
||||
if (!FullBackupImporter.validatePassphrase(context, backupUri, passphrase)) {
|
||||
Log.w(TAG, "V1 restore failed: incorrect passphrase")
|
||||
trySend(LocalBackupRestoreProgress.IncorrectCredential)
|
||||
return@launch
|
||||
}
|
||||
|
||||
// If this flow has already committed an account locally, keep its fresh key material out of the restore.
|
||||
val inProgressData = readInProgressRegistrationData()
|
||||
val excludeKeyTables = inProgressData.accountDataCommitted
|
||||
|
||||
val database = SignalDatabase.backupDatabase
|
||||
val inputStream = context.contentResolver.openInputStream(backupUri) ?: throw IOException("Unable to open backup stream for $backupUri")
|
||||
CountingInputStream(inputStream).use { counting ->
|
||||
countingStream = counting
|
||||
FullBackupImporter.importFile(
|
||||
context,
|
||||
AttachmentSecretProvider.getInstance(context, AppAttachmentSecretStore).getOrCreateAttachmentSecret(),
|
||||
database,
|
||||
counting,
|
||||
passphrase,
|
||||
excludeKeyTables
|
||||
)
|
||||
}
|
||||
|
||||
SignalDatabase.runPostBackupRestoreTasks(database)
|
||||
|
||||
// The importer writes the restored key-value store straight to disk, bypassing the in-memory SignalStore cache.
|
||||
// Reset it so the state we read below reflects the restored values rather than stale pre-restore ones.
|
||||
SignalStore.onPostBackupRestore()
|
||||
|
||||
// A post-registration restore clobbers parts of SignalStore.account with the backup's values -- V1 backups
|
||||
// carry the identity keys and AEP. Re-apply the frozen account data to heal the committed registration.
|
||||
val committedAccountData = inProgressData.accountData
|
||||
if (inProgressData.accountDataCommitted && committedAccountData != null) {
|
||||
Log.i(TAG, "V1 restore ran after an account was committed. Re-applying committed account data.")
|
||||
val masterKey = applyAccountEntropyPool(inProgressData)
|
||||
applyAccountData(committedAccountData, pin = inProgressData.pin, registrationLockEnabled = inProgressData.registrationLockEnabled, masterKey = masterKey)
|
||||
}
|
||||
|
||||
reenableLegacyLocalBackups(rootUri, passphrase)
|
||||
|
||||
trySend(readRestoredLocalBackupState(includePreRegistrationKeys = true))
|
||||
Log.d(TAG, "V1 restore complete.")
|
||||
} catch (e: FullBackupImporter.DatabaseDowngradeException) {
|
||||
Log.w(TAG, "V1 restore failed: database downgrade", e)
|
||||
trySend(LocalBackupRestoreProgress.Error(e))
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "V1 restore failed", e)
|
||||
trySend(LocalBackupRestoreProgress.Error(e))
|
||||
} finally {
|
||||
channel.close()
|
||||
}
|
||||
}
|
||||
|
||||
awaitClose {
|
||||
EventBus.getDefault().unregister(subscriber)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun verifyLocalBackupKey(backupUri: Uri, aep: AccountEntropyPool): Boolean = withContext(Dispatchers.IO) {
|
||||
val backupDir = DocumentFile.fromTreeUri(context, backupUri)
|
||||
if (backupDir == null || !backupDir.canRead()) {
|
||||
Log.w(TAG, "[verifyLocalBackupKey] Could not open backup directory.")
|
||||
return@withContext false
|
||||
}
|
||||
|
||||
LocalArchiver.canDecryptMainArchive(SnapshotFileSystem(context, backupDir), aep.deriveMessageBackupKey())
|
||||
}
|
||||
|
||||
override fun restoreLocalBackupV2(rootUri: Uri, backupUri: Uri, aep: AccountEntropyPool): Flow<LocalBackupRestoreProgress> = callbackFlow {
|
||||
Log.d(TAG, "Starting V2 local backup restore from backup=$backupUri, root=$rootUri")
|
||||
|
||||
emit(LocalBackupRestoreProgress.Preparing)
|
||||
trySend(LocalBackupRestoreProgress.Preparing)
|
||||
|
||||
try {
|
||||
val backupDir = DocumentFile.fromTreeUri(context, backupUri)
|
||||
if (backupDir == null || !backupDir.canRead()) {
|
||||
emit(LocalBackupRestoreProgress.Error(IllegalStateException("Could not open backup directory")))
|
||||
return@flow
|
||||
}
|
||||
|
||||
val selfAci = SignalStore.account.aci
|
||||
val selfPni = SignalStore.account.pni
|
||||
val selfE164 = SignalStore.account.e164
|
||||
|
||||
if (selfAci == null || selfPni == null || selfE164 == null) {
|
||||
emit(LocalBackupRestoreProgress.Error(IllegalStateException("Account not registered, cannot restore V2 backup")))
|
||||
return@flow
|
||||
}
|
||||
|
||||
val selfData = BackupRepository.SelfData(selfAci, selfPni, selfE164, ProfileKeyUtil.getSelfProfileKey())
|
||||
val messageBackupKey = aep.deriveMessageBackupKey()
|
||||
val snapshotFileSystem = SnapshotFileSystem(context, backupDir)
|
||||
|
||||
when (val result = LocalArchiver.import(snapshotFileSystem, selfData, messageBackupKey)) {
|
||||
is Result.Success -> {
|
||||
emit(LocalBackupRestoreProgress.Complete)
|
||||
Log.d(TAG, "V2 restore complete.")
|
||||
}
|
||||
is Result.Failure -> {
|
||||
Log.w(TAG, "V2 restore failed: ${result.failure}")
|
||||
emit(LocalBackupRestoreProgress.Error(IOException("V2 restore failed: ${result.failure}")))
|
||||
// The import posts RestoreV2Event frame-progress events as it reads through the main archive stream, tracking bytes
|
||||
// read against the stream length. Bridge those into InProgress so the UI can show a real percentage.
|
||||
val subscriber = object {
|
||||
@Subscribe(threadMode = ThreadMode.POSTING)
|
||||
fun onRestoreEvent(event: RestoreV2Event) {
|
||||
if (event.type == RestoreV2Event.Type.PROGRESS_RESTORE) {
|
||||
trySend(LocalBackupRestoreProgress.InProgress(bytesRead = event.count.inWholeBytes, totalBytes = event.estimatedTotalCount.inWholeBytes))
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "V2 restore failed", e)
|
||||
emit(LocalBackupRestoreProgress.Error(e))
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
|
||||
EventBus.getDefault().register(subscriber)
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
try {
|
||||
val backupDir = DocumentFile.fromTreeUri(context, backupUri)
|
||||
if (backupDir == null || !backupDir.canRead()) {
|
||||
trySend(LocalBackupRestoreProgress.Error(IllegalStateException("Could not open backup directory")))
|
||||
return@launch
|
||||
}
|
||||
|
||||
val selfAci = SignalStore.account.aci
|
||||
val selfPni = SignalStore.account.pni
|
||||
val selfE164 = SignalStore.account.e164
|
||||
|
||||
if (selfAci == null || selfPni == null || selfE164 == null) {
|
||||
trySend(LocalBackupRestoreProgress.Error(IllegalStateException("Account not registered, cannot restore V2 backup")))
|
||||
return@launch
|
||||
}
|
||||
|
||||
val selfData = BackupRepository.SelfData(selfAci, selfPni, selfE164, ProfileKeyUtil.getSelfProfileKey())
|
||||
val messageBackupKey = aep.deriveMessageBackupKey()
|
||||
val snapshotFileSystem = SnapshotFileSystem(context, backupDir)
|
||||
|
||||
if (!LocalArchiver.canDecryptMainArchive(snapshotFileSystem, messageBackupKey)) {
|
||||
Log.w(TAG, "V2 restore failed: recovery key cannot decrypt backup")
|
||||
trySend(LocalBackupRestoreProgress.IncorrectCredential)
|
||||
return@launch
|
||||
}
|
||||
|
||||
when (val result = LocalArchiver.import(snapshotFileSystem, selfData, messageBackupKey)) {
|
||||
is Result.Success -> {
|
||||
AppDependencies.jobManager.add(LocalBackupRestoreMediaJob.create(rootUri))
|
||||
|
||||
// The entered recovery key decrypted the backup the user chose to restore, so it always becomes the
|
||||
// account's AEP -- even if the backup was made by a different account.
|
||||
SignalStore.account.restoreAccountEntropyPool(aep)
|
||||
updateInProgressRegistrationData { this.accountEntropyPool = aep.value }
|
||||
|
||||
// Re-enable new-style local backups pointing at the restored location, so the user keeps getting backups.
|
||||
// Skip it if the folder is the SignalBackups directory itself, since it can't be reused as a destination.
|
||||
val archiveFileSystem = ArchiveFileSystem.openForRestore(context, rootUri)
|
||||
if (archiveFileSystem != null && !archiveFileSystem.isRootedAtSignalBackups) {
|
||||
SignalStore.backup.newLocalBackupsDirectory = rootUri.toString()
|
||||
SignalStore.backup.newLocalBackupsEnabled = true
|
||||
LocalBackupListener.setNextBackupTimeToIntervalFromNow(context)
|
||||
LocalBackupListener.schedule(context)
|
||||
} else {
|
||||
Log.w(TAG, "V2 local backup directory can't be reused as a destination; not re-enabling local backups.")
|
||||
}
|
||||
|
||||
trySend(readRestoredLocalBackupState())
|
||||
Log.d(TAG, "V2 restore complete.")
|
||||
}
|
||||
is Result.Failure -> {
|
||||
Log.w(TAG, "V2 restore failed: ${result.failure}")
|
||||
trySend(LocalBackupRestoreProgress.Error(IOException("V2 restore failed: ${result.failure}")))
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "V2 restore failed", e)
|
||||
trySend(LocalBackupRestoreProgress.Error(e))
|
||||
} finally {
|
||||
channel.close()
|
||||
}
|
||||
}
|
||||
|
||||
awaitClose {
|
||||
EventBus.getDefault().unregister(subscriber)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun scanLocalBackupFolder(folderUri: Uri): List<LocalBackupInfo> = withContext(Dispatchers.IO) {
|
||||
// Persist access immediately, while the picker's transient grant is still alive. Restore jobs read from this
|
||||
// folder long after the registration activity (and its grant) are gone.
|
||||
try {
|
||||
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
context.contentResolver.takePersistableUriPermission(folderUri, takeFlags)
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Unable to take persistable permission for backup folder", e)
|
||||
}
|
||||
|
||||
val folder = DocumentFile.fromTreeUri(context, folderUri) ?: return@withContext emptyList()
|
||||
val children = folder.listFiles()
|
||||
|
||||
@@ -386,7 +483,11 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
|
||||
val match = MODERN_BACKUP_PATTERN.matchEntire(name) ?: continue
|
||||
val (year, month, day, hour, minute, second) = match.destructured
|
||||
try {
|
||||
// V2 snapshot folders are named in UTC (see ArchiveFileSystem.createSnapshot), so convert to the device zone for display.
|
||||
val date = LocalDateTime.of(year.toInt(), month.toInt(), day.toInt(), hour.toInt(), minute.toInt(), second.toInt())
|
||||
.atOffset(ZoneOffset.UTC)
|
||||
.atZoneSameInstant(ZoneId.systemDefault())
|
||||
.toLocalDateTime()
|
||||
backups.add(
|
||||
LocalBackupInfo(
|
||||
type = LocalBackupInfo.BackupType.V2,
|
||||
@@ -483,7 +584,7 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
|
||||
}
|
||||
|
||||
override fun restoreLinkAndSyncBackup(cdn: Int, key: String): Flow<LinkAndSyncProgress> = callbackFlow {
|
||||
val ephemeralBackupKeyBytes = SignalStore.registration.localRegistrationMetadata?.linkedDeviceInfo?.ephemeralBackupKey?.toByteArray()
|
||||
val ephemeralBackupKeyBytes = readInProgressRegistrationData().accountData?.linkedDeviceData?.ephemeralBackupKey?.toByteArray()
|
||||
|
||||
if (ephemeralBackupKeyBytes == null) {
|
||||
Log.i(TAG, "[restoreLinkAndSyncBackup] No ephemeral backup key present; nothing to restore.")
|
||||
@@ -544,4 +645,198 @@ class AppRegistrationStorageController(private val context: Context) : StorageCo
|
||||
previousUri?.let { AppDependencies.blobs.delete(context, it) }
|
||||
Unit
|
||||
}
|
||||
|
||||
/**
|
||||
* The account's master key is always the one derived from the AEP, which we expect to have by the time we commit.
|
||||
* Restore it up-front so any master-key-derived state we touch afterwards resolves against the correct value rather
|
||||
* than lazily generating a new AEP. Returns the AEP-derived master key, if an AEP is present.
|
||||
*/
|
||||
private fun applyAccountEntropyPool(data: RegistrationData): MasterKey? {
|
||||
val accountEntropyPool = data.accountEntropyPool.takeIf { it.isNotEmpty() }?.let { AccountEntropyPool(it) } ?: return null
|
||||
|
||||
if (data.accountData?.linkedDeviceData != null) {
|
||||
SignalStore.account.setAccountEntropyPoolFromPrimaryDevice(accountEntropyPool)
|
||||
} else {
|
||||
SignalStore.account.restoreAccountEntropyPool(accountEntropyPool)
|
||||
}
|
||||
|
||||
return accountEntropyPool.deriveMasterKey()
|
||||
}
|
||||
|
||||
private fun AccountData.isComplete(): Boolean {
|
||||
return e164.isNotEmpty() && aci.isNotEmpty() && pni.isNotEmpty() && servicePassword.isNotEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the one-time [AccountData] to permanent storage, registering the account locally. This runs once per
|
||||
* registration, guarded by [RegistrationData.accountDataCommitted] -- the only re-application is after a
|
||||
* post-registration V1 backup restore, which clobbers parts of [SignalStore.account] and re-applies this frozen
|
||||
* data to heal them.
|
||||
*/
|
||||
private suspend fun applyAccountData(accountData: AccountData, pin: String, registrationLockEnabled: Boolean, masterKey: MasterKey?) {
|
||||
Log.i(TAG, "[applyAccountData] Registering account locally.")
|
||||
|
||||
SignalStore.account.registrationId = accountData.aciRegistrationId
|
||||
SignalStore.account.pniRegistrationId = accountData.pniRegistrationId
|
||||
|
||||
accountData.linkedDeviceData?.let {
|
||||
SignalStore.account.deviceId = it.deviceId
|
||||
SignalStore.account.deviceName = it.deviceName
|
||||
}
|
||||
|
||||
val aciIdentityKeyPair = IdentityKeyPair(accountData.aciIdentityKeyPair.toByteArray())
|
||||
val pniIdentityKeyPair = IdentityKeyPair(accountData.pniIdentityKeyPair.toByteArray())
|
||||
SignalStore.account.restoreAciIdentityKeyFromBackup(aciIdentityKeyPair.publicKey.serialize(), aciIdentityKeyPair.privateKey.serialize())
|
||||
SignalStore.account.restorePniIdentityKeyFromBackup(pniIdentityKeyPair.publicKey.serialize(), pniIdentityKeyPair.privateKey.serialize())
|
||||
|
||||
val aci = ACI.parseOrThrow(accountData.aci)
|
||||
val pni = PNI.parseOrThrow(accountData.pni)
|
||||
val isAciChanged = SignalStore.account.aci != aci
|
||||
|
||||
SignalStore.account.setAci(aci)
|
||||
SignalStore.account.setPni(pni)
|
||||
|
||||
AppDependencies.resetProtocolStores()
|
||||
|
||||
AppDependencies.protocolStore.aci().sessions().archiveAllSessions()
|
||||
AppDependencies.protocolStore.pni().sessions().archiveAllSessions()
|
||||
SenderKeyUtil.clearAllState()
|
||||
|
||||
val aciProtocolStore = AppDependencies.protocolStore.aci()
|
||||
val pniProtocolStore = AppDependencies.protocolStore.pni()
|
||||
|
||||
storeSignedAndLastResortPreKeys(aciProtocolStore, SignalStore.account.aciPreKeys, SignedPreKeyRecord(accountData.aciSignedPreKey.toByteArray()), KyberPreKeyRecord(accountData.aciLastResortKyberPreKey.toByteArray()))
|
||||
storeSignedAndLastResortPreKeys(pniProtocolStore, SignalStore.account.pniPreKeys, SignedPreKeyRecord(accountData.pniSignedPreKey.toByteArray()), KyberPreKeyRecord(accountData.pniLastResortKyberPreKey.toByteArray()))
|
||||
|
||||
val profileKey = getOrCreateProfileKey(accountData.e164)
|
||||
val recipientTable = SignalDatabase.recipients
|
||||
val selfId = recipientTable.getAndPossiblyMergePnpVerified(aci, pni, accountData.e164)
|
||||
|
||||
recipientTable.setProfileSharing(selfId, true)
|
||||
recipientTable.markRegisteredOrThrow(selfId, aci)
|
||||
recipientTable.linkIdsForSelf(aci, pni, accountData.e164)
|
||||
recipientTable.setProfileKey(selfId, profileKey)
|
||||
|
||||
AppDependencies.recipientCache.clearSelf()
|
||||
|
||||
SignalStore.account.setE164(accountData.e164)
|
||||
|
||||
val now = System.currentTimeMillis()
|
||||
saveOwnIdentityKey(selfId, aci, aciProtocolStore, now)
|
||||
saveOwnIdentityKey(selfId, pni, pniProtocolStore, now)
|
||||
|
||||
accountData.linkedDeviceData?.mediaRootBackupKey?.let {
|
||||
SignalStore.backup.mediaRootBackupKey = MediaRootBackupKey(it.toByteArray())
|
||||
}
|
||||
|
||||
SignalStore.account.setServicePassword(accountData.servicePassword)
|
||||
SignalStore.account.setRegistered(registered = true, isAciChanged = isAciChanged)
|
||||
TextSecurePreferences.setPromptedPushRegistration(context, true)
|
||||
TextSecurePreferences.setUnauthorizedReceived(context, false)
|
||||
NotificationManagerCompat.from(context).cancel(NotificationIds.UNREGISTERED_NOTIFICATION_ID)
|
||||
|
||||
SvrRepository.onRegistrationComplete(
|
||||
masterKey = if (pin.isNotEmpty()) masterKey else null,
|
||||
userPin = pin.takeIf { it.isNotEmpty() },
|
||||
hasPinToRestore = pin.isNotEmpty(),
|
||||
setRegistrationLockEnabled = registrationLockEnabled,
|
||||
restoredAEP = SignalStore.account.restoredAccountEntropyPool
|
||||
)
|
||||
|
||||
restartNetwork()
|
||||
PreKeysSyncJob.enqueue()
|
||||
|
||||
recipientTable.clearSelfKeyTransparencyData()
|
||||
CheckKeyTransparencyJob.enqueueIfNecessary(addDelay = true)
|
||||
|
||||
val jobManager = AppDependencies.jobManager
|
||||
|
||||
if (accountData.linkedDeviceData == null) {
|
||||
jobManager.add(DirectoryRefreshJob(false))
|
||||
jobManager.add(RotateCertificateJob())
|
||||
|
||||
DirectoryRefreshListener.schedule(context)
|
||||
RotateSignedPreKeyListener.schedule(context)
|
||||
} else {
|
||||
SignalStore.account.isMultiDevice = true
|
||||
jobManager.runJobBlocking(RefreshOwnProfileJob(), 30.seconds)
|
||||
|
||||
jobManager.add(RotateCertificateJob())
|
||||
RotateSignedPreKeyListener.schedule(context)
|
||||
}
|
||||
|
||||
accountData.linkedDeviceData?.readReceipts?.let { TextSecurePreferences.setReadReceiptsEnabled(context, it) }
|
||||
}
|
||||
|
||||
private fun getOrCreateProfileKey(e164: String): ProfileKey {
|
||||
val existing = SignalDatabase.recipients.getByE164(e164).getOrNull()?.let { ProfileKeyUtil.profileKeyOrNull(SignalDatabase.recipients.getRecord(it).profileKey) }
|
||||
return existing ?: ProfileKeyUtil.createNew().also { Log.i(TAG, "[commitRegistrationData] No profile key found, created a new one") }
|
||||
}
|
||||
|
||||
private fun saveOwnIdentityKey(selfId: RecipientId, serviceId: ServiceId, protocolStore: SignalServiceAccountDataStoreImpl, now: Long) {
|
||||
protocolStore.identities().saveIdentityWithoutSideEffects(
|
||||
selfId,
|
||||
serviceId,
|
||||
protocolStore.identityKeyPair.publicKey,
|
||||
IdentityTable.VerifiedStatus.VERIFIED,
|
||||
true,
|
||||
now,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
private fun storeSignedAndLastResortPreKeys(protocolStore: SignalServiceAccountDataStoreImpl, metadataStore: PreKeyMetadataStore, signedPreKey: SignedPreKeyRecord, lastResortKyberPreKey: KyberPreKeyRecord) {
|
||||
PreKeyUtil.storeSignedPreKey(protocolStore, metadataStore, signedPreKey)
|
||||
metadataStore.isSignedPreKeyRegistered = true
|
||||
metadataStore.activeSignedPreKeyId = signedPreKey.id
|
||||
metadataStore.lastSignedPreKeyRotationTime = System.currentTimeMillis()
|
||||
|
||||
PreKeyUtil.storeLastResortKyberPreKey(protocolStore, metadataStore, lastResortKyberPreKey)
|
||||
metadataStore.lastResortKyberPreKeyId = lastResortKyberPreKey.id
|
||||
metadataStore.lastResortKyberPreKeyRotationTime = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists the restored backup folder as the backup directory and re-enables scheduled local backups, so the user
|
||||
* keeps getting backups after restoring. Best-effort: a failure here must not fail the restore itself.
|
||||
*/
|
||||
private fun reenableLegacyLocalBackups(rootUri: Uri, passphrase: String) {
|
||||
try {
|
||||
BackupPassphrase.set(context, passphrase)
|
||||
|
||||
val takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
context.contentResolver.takePersistableUriPermission(rootUri, takeFlags)
|
||||
SignalStore.settings.setSignalBackupDirectory(rootUri)
|
||||
|
||||
if (BackupUtil.canUserAccessBackupDirectory(context)) {
|
||||
LocalBackupListener.setNextBackupTimeToIntervalFromNow(context)
|
||||
SignalStore.settings.isBackupEnabled = true
|
||||
LocalBackupListener.schedule(context)
|
||||
} else {
|
||||
Log.w(TAG, "Can't access restored backup directory; not re-enabling local backups.")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Failed to re-enable local backups after V1 restore.", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun readRestoredLocalBackupState(includePreRegistrationKeys: Boolean = false): LocalBackupRestoreProgress.Complete {
|
||||
val restoredPin = SignalStore.svr.pin?.takeIf { it.isNotBlank() }
|
||||
val restoredProfileKey = SignalStore.account.aci
|
||||
?.let { SignalDatabase.recipients.getByAci(it).getOrNull() }
|
||||
?.let { SignalDatabase.recipients.getRecord(it).profileKey }
|
||||
?.let { ProfileKey(it) }
|
||||
|
||||
val restoredAccountEntropyPool = if (includePreRegistrationKeys) SignalStore.account.accountEntropyPoolOrNull else null
|
||||
val restoredAciIdentityKey = if (includePreRegistrationKeys && SignalStore.account.hasAciIdentityKey()) SignalStore.account.aciIdentityKey else null
|
||||
val restoredPniIdentityKey = if (includePreRegistrationKeys && SignalStore.account.hasPniIdentityKey()) SignalStore.account.pniIdentityKey else null
|
||||
|
||||
return LocalBackupRestoreProgress.Complete(
|
||||
restoredSvrPin = restoredPin,
|
||||
restoredProfileKey = restoredProfileKey,
|
||||
restoredAccountEntropyPool = restoredAccountEntropyPool,
|
||||
restoredAciIdentityKey = restoredAciIdentityKey,
|
||||
restoredPniIdentityKey = restoredPniIdentityKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,8 +183,8 @@ object StorageSyncHelper {
|
||||
|
||||
backupTier = when {
|
||||
SignalStore.account.isLinkedDevice -> null
|
||||
SignalStore.backup.areBackupsEnabled && SignalStore.backup.backupTier != null -> getBackupLevelValue(SignalStore.backup.backupTier!!)
|
||||
SignalStore.backup.backupTierInternalOverride != null -> getBackupLevelValue(SignalStore.backup.backupTierInternalOverride!!)
|
||||
SignalStore.backup.areBackupsEnabled && SignalStore.backup.backupTier != null -> SignalStore.backup.backupTier!!.toBackupLevel()
|
||||
SignalStore.backup.backupTierInternalOverride != null -> SignalStore.backup.backupTierInternalOverride!!.toBackupLevel()
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -213,14 +213,6 @@ object StorageSyncHelper {
|
||||
return accountRecord.toSignalAccountRecord(StorageId.forAccount(storageId)).toSignalStorageRecord()
|
||||
}
|
||||
|
||||
// TODO: Currently we don't have access to the private values of the BackupLevel. Update when it becomes available.
|
||||
private fun getBackupLevelValue(tier: MessageBackupTier): Long {
|
||||
return when (tier) {
|
||||
MessageBackupTier.FREE -> 200
|
||||
MessageBackupTier.PAID -> 201
|
||||
}
|
||||
}
|
||||
|
||||
private fun getNotificationProfileManualOverride(): AccountRecord.NotificationProfileManualOverride? {
|
||||
val profile = SignalDatabase.notificationProfiles.getProfile(SignalStore.notificationProfile.manuallyEnabledProfile)
|
||||
return if (profile != null && profile.deletedTimestampMs == 0L) {
|
||||
@@ -296,6 +288,13 @@ object StorageSyncHelper {
|
||||
setSubscriber(remoteBackupsSubscriber)
|
||||
}
|
||||
|
||||
if (SignalStore.account.isLinkedDevice) {
|
||||
val remoteBackupTier = MessageBackupTier.fromBackupLevel(update.new.proto.backupTier)
|
||||
if (remoteBackupTier != SignalStore.backup.backupTier) {
|
||||
SignalStore.backup.backupTier = remoteBackupTier
|
||||
}
|
||||
}
|
||||
|
||||
if (update.new.proto.subscriptionManuallyCancelled && !update.old.proto.subscriptionManuallyCancelled) {
|
||||
SignalStore.inAppPayments.updateLocalStateForManualCancellation(InAppPaymentSubscriberRecord.Type.DONATION)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ object Environment {
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val USE_NEW_REGISTRATION: Boolean = isInternal()
|
||||
val USE_NEW_REGISTRATION: Boolean = true
|
||||
|
||||
@JvmField
|
||||
val IS_LINK_AND_SYNC_AVAILABLE: Boolean = BuildConfig.DEBUG
|
||||
|
||||
@@ -1157,14 +1157,6 @@ object RemoteConfig {
|
||||
hotSwappable = true
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("useHevcEncoder")
|
||||
val useHevcEncoder: Boolean by remoteBoolean(
|
||||
key = "android.useHevcEncoder",
|
||||
defaultValue = false,
|
||||
hotSwappable = false
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@get:JvmName("useMessageSendRestFallback")
|
||||
val useMessageSendRestFallback: Boolean by remoteBoolean(
|
||||
@@ -1409,10 +1401,19 @@ object RemoteConfig {
|
||||
@JvmStatic
|
||||
@get:JvmName("disappearMore")
|
||||
val disappearMore: Boolean by remoteBoolean(
|
||||
key = "android.disappearMore",
|
||||
key = "android.disappearMore.2",
|
||||
defaultValue = false,
|
||||
hotSwappable = true
|
||||
)
|
||||
|
||||
/** A json string representing possible transcoding configurations for videos */
|
||||
@JvmStatic
|
||||
@get:JvmName("transcodeConfig")
|
||||
val transcodeConfig: String by remoteString(
|
||||
key = "client.attachments.videoTranscodingConfiguration",
|
||||
defaultValue = "",
|
||||
hotSwappable = true
|
||||
)
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
@@ -32,7 +32,10 @@ object UriUtil {
|
||||
}
|
||||
} else if (ContentResolver.SCHEME_CONTENT == uri.scheme) {
|
||||
val authority = uri.authority ?: return false
|
||||
return !authority.startsWith(context.packageName)
|
||||
|
||||
// Protect against URI's like "content://0@org.thoughtcrime.securesms.part/..."
|
||||
val normalizedAuthority = authority.substringAfterLast('@')
|
||||
return !normalizedAuthority.startsWith(context.packageName)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -43,6 +43,13 @@
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_appSettingsFragment_to_linkedDeviceAccountSettingsFragment"
|
||||
app:destination="@id/linkedDeviceAccountSettingsFragment"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
<action
|
||||
android:id="@+id/action_appSettingsFragment_to_remoteBackupsSettingsFragment"
|
||||
app:destination="@id/remoteBackupsSettingsFragment"
|
||||
@@ -211,6 +218,12 @@
|
||||
app:popExitAnim="@anim/fragment_close_exit" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/linkedDeviceAccountSettingsFragment"
|
||||
android:name="org.thoughtcrime.securesms.components.settings.app.account.LinkedDeviceAccountSettingsFragment"
|
||||
android:label="linked_device_account_settings_fragment"
|
||||
tools:layout="@layout/dsl_settings_fragment" />
|
||||
|
||||
<include app:graph="@navigation/app_settings_change_number" />
|
||||
|
||||
<fragment
|
||||
@@ -855,6 +868,16 @@
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
<action
|
||||
android:id="@+id/action_direct_to_linkedDeviceAccountSettingsFragment"
|
||||
app:destination="@id/linkedDeviceAccountSettingsFragment"
|
||||
app:enterAnim="@anim/fragment_open_enter"
|
||||
app:exitAnim="@anim/fragment_open_exit"
|
||||
app:popEnterAnim="@anim/fragment_close_enter"
|
||||
app:popExitAnim="@anim/fragment_close_exit"
|
||||
app:popUpTo="@id/app_settings"
|
||||
app:popUpToInclusive="true" />
|
||||
|
||||
<!-- endregion -->
|
||||
|
||||
<!-- Labs Settings -->
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Herregistreer Signal</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Herkoppel</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Navigeer terug.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -952,7 +952,7 @@
|
||||
<string name="BackupsPreferenceFragment__test_your_backup_passphrase">Toets jou wagwoordfrase en verifieer dat dit ooreenkom</string>
|
||||
<string name="BackupsPreferenceFragment__turn_on">Skakel rugsteun aan</string>
|
||||
<string name="BackupsPreferenceFragment__turn_off">Skakel af</string>
|
||||
<string name="BackupsPreferenceFragment__to_restore_a_backup">"Om 'n rugsteun te herwin, installeer 'n nuwe kopie van Signal. Maak die toepassing oop, tik op \"Herwin vanaf rugsteun\" en spoor dan 'n rugsteunlêer op. %1$s"</string>
|
||||
<string name="BackupsPreferenceFragment__to_restore_a_backup">"Om \'n rugsteun te herwin, installeer \'n nuwe kopie van Signal. Maak die toepassing oop, tik op \"Herwin vanaf rugsteun\" en spoor dan \'n rugsteunlêer op. %1$s"</string>
|
||||
<string name="BackupsPreferenceFragment__learn_more">Vind meer uit</string>
|
||||
<string name="BackupsPreferenceFragment__in_progress">Aan die gang…</string>
|
||||
<!-- Status text shown in backup preferences when verifying a backup -->
|
||||
@@ -2888,7 +2888,7 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">Geen resultate gevind vir \'%1$s\' nie</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">Geen resultate gevind nie</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
@@ -3492,9 +3492,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Herregistreer toestel</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Hierdie toestel is nie meer gekoppel nie. Herkoppel Signal aan jou foon om voort te gaan om boodskappe te stuur.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Herkoppel toestel</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">Jy is op hierdie toestel uit Signal uitgeteken.</string>
|
||||
@@ -3585,7 +3585,7 @@
|
||||
<string name="ContactSelectionListFragment_signal_requires_the_contacts_permission_in_order_to_display_your_contacts">Signal benodig Kontaktoestemming om jou kontakte te wys, maar dit is permanent geweier. Gaan asseblief na die toepassinginstelling-kieslys, kies \"Toestemmings\" en aktiveer \"Kontakte\".</string>
|
||||
<string name="ContactSelectionListFragment_error_retrieving_contacts_check_your_network_connection">Fout met herwinning van kontakte, gaan jou netwerkverbinding na</string>
|
||||
<string name="ContactSelectionListFragment_username_not_found">Gebruikersnaam nie gevind nie</string>
|
||||
<string name="ContactSelectionListFragment_s_is_not_a_signal_user">"\"%1$s\" is nie 'n Signal-gebruiker nie. Kontroleer asb. die gebruikersnaam en probeer weer."</string>
|
||||
<string name="ContactSelectionListFragment_s_is_not_a_signal_user">"\"%1$s\" is nie \'n Signal-gebruiker nie. Kontroleer asb. die gebruikersnaam en probeer weer."</string>
|
||||
<string name="ContactSelectionListFragment_you_do_not_need_to_add_yourself_to_the_group">Jy hoef nie jouself by die groep te voeg nie</string>
|
||||
<string name="ContactSelectionListFragment_maximum_group_size_reached">Maksimum groepgrootte bereik.</string>
|
||||
<string name="ContactSelectionListFragment_signal_groups_can_have_a_maximum_of_s_members">Signal-groepe kan \'n maksimum van %1$s lede hê.</string>
|
||||
@@ -5107,6 +5107,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">Kon nie data uitvee nie</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Dra rekening oor of herstel dit.</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">As jy voorheen \'n Signal-rekening geregistreer het, kan jy jou rekening en boodskappe oordra of herstel</string>
|
||||
@@ -8244,13 +8270,13 @@
|
||||
<string name="InactivePrimary__got_it">Ek verstaan</string>
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Om 'n rugsteun te herwin, installeer 'n nuwe kopie van Signal. Maak die toepassing oop, tik op \"Herwin rugsteun\" en vind dan die rugsteunlêer."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Om \'n rugsteun te herwin, installeer \'n nuwe kopie van Signal. Maak die toepassing oop, tik op \"Herwin rugsteun\" en vind dan die rugsteunlêer."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">Jou \"Optimaliseer Signal-stoorruimte\" is aangeskakel. As jy alle media in jou rugsteun op die toestel wil insluit, skakel hierdie instelling af.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Besigtig instellings</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Gaan voort sonder om af te skakel</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Verifieer jou herwinsleutel</string>
|
||||
@@ -8635,11 +8661,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">Stoorruimte-optimalisering kan slegs met die betaalde vlak van Signal se Veilige Rugsteun gebruik word. Jou rugsteun-intekening word nog verwerk en is nog nie aktief nie. Probeer asseblief later weer.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media sal van jou rugsteun op die toestel verwyder word</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">As jy \"Optimaliseer Signal-stoorruimte\" aanskakel, sal dit ou media van jou toestel aflaai. Jy kan dit enige tyd weer oplaai. Dit sal ook ou media uit jou rugsteun op die toestel verwyder.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Skakel aan</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -8722,6 +8748,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Intekening gekanselleer</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Outomatiese rugsteun met Signal se veilige end-tot-end-geënkripteerde stoorruimtediens.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"Intekening nie op hierdie toestel gevind nie."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -8825,6 +8853,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s om %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Nooit</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">Rugsteun nou</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9888,19 +9926,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Soek lede</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Soek deur kontakte</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Soek deur admins</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Filtreer volgens</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Alle lede</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Kontakte</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Nooi via groepskakel</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">Kan nie rugsteun herwin nie</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">أمواج</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">سيجنال يقوم بالتحديث…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">إنشاء مفتاح</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">مسافة للخلف</string>
|
||||
|
||||
@@ -464,7 +464,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">تجاوز حجم الملف المُرفَق الحد المسموح به لهذا الصنف من الرسائل.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">تعذَّر تسجيل الصوت!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">لا تستطيع إرسال الرسائل لهذه المجموعة لأنك لم تعد عضوًا فيها.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">لا يمكنك إرسال رسائل لأن المجموعة أُغلِقت.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">يمكن فقط لـ %1$s إرسال الرسائل.</string>
|
||||
<string name="ConversationActivity_admins">المُشرِفون</string>
|
||||
@@ -668,7 +668,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">إعادة تسجيل سيجنال</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">أعِد الربط</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">رجوع إلى الوراء.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1167,7 +1167,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">تتم مُزامنة رسائل سيجنال مع تطبيق سيجنال على هاتفك المحمول بعد ربطه. لن تظهر سجلات رسائلك السابقة.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">على الجهاز الذي ترغب بربطه، قُم بزيارة %1$s لتثبيت سيجنال</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">الأجهزة المُرتبِطة</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1208,7 +1208,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">إلغاء</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">فشل ربط ومزامنة البيانات على نظام أندرويد</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">فشلت مزامنة الرسالة</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1217,7 +1217,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">تمَّ ربط جهازك بنجاح، لكن تعذّر نقل رسائلك.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">اعرف المزيد</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">إعادة المُحاولة</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1366,7 +1366,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">جميع الأعضاء</string>
|
||||
<string name="GroupManagement_access_level_only_admins">للمُشرِفين فقط</string>
|
||||
<string name="GroupManagement_access_level_no_one">لا أحد</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1556,7 +1556,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">متابعة</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">لا، شكرًا</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">الطلبات والدعوات</string>
|
||||
@@ -1681,7 +1681,7 @@
|
||||
<!-- Progress dialog label when finishing a backup restore -->
|
||||
<string name="RemoteRestoreActivity__finishing_restore">جارٍ إنهاء العملية…</string>
|
||||
<!-- Progress dialog label while awaiting updates -->
|
||||
<string name="RemoteRestoreActivity__restoring">جارية الاستعادة...</string>
|
||||
<string name="RemoteRestoreActivity__restoring">جارية الاستعادة…</string>
|
||||
<!-- Progress readout for dialog while downloading or restoring a backup. First placeholder is the formatted size of the backup downloaded, the second is formatted total amount to go, and the last is a percentage. -->
|
||||
<string name="RemoteRestoreActivity__s_of_s_s">%1$s من %2$s (%3$s)</string>
|
||||
<!-- Feature list media label for paid tier -->
|
||||
@@ -2012,8 +2012,8 @@
|
||||
<string name="MediaOverviewActivity_audio">ملف صوتي</string>
|
||||
<string name="MediaOverviewActivity_video">مقطع فيديو</string>
|
||||
<string name="MediaOverviewActivity_image">صورة</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">مرسل من %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">مرسل منك</string>
|
||||
@@ -2047,13 +2047,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">بدء مكالمة سيجنال</string>
|
||||
@@ -2491,7 +2491,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">هل ترغبُ بالانضمام إلى هذه المجموعة؟ لن يعرفوا أنك قرأت رسائلهم حتى تقبل بذلك.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">هل ترغبُ بإزالة الحظر عن هذه المجموعة ومشاركة اسمك وصورتك مع أعضائها؟ لن تتلقَ أية رسائل حتى تُزيل الحظر عنها.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">عرض</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">عضو في %1$s</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">عضو في %1$s و%2$s</string>
|
||||
@@ -2656,7 +2656,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">إنشاء رقم الـ PIN</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">نفدَت تخميناتك لرقم التعريف الشخصي (PIN)، لكن مازال بإمكانك الوصول إلى حسابك على سيجنال من خلال إنشاء رقم تعريف شخصي (PIN) جديد. للحفاظ على خصوصيتك وأمن معلوماتك، سيتمُّ استرجاع حسابك لكن بدون أية معلومات أو إعدادات محفوظة عن الحساب.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">إنشاء رقم تعريف شخصي (PIN) جديد</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">أرسِل كود رسالة قصيرة</string>
|
||||
@@ -2742,7 +2742,7 @@
|
||||
<string name="WebRtcCallActivity__signal_s">سيجنال %1$s</string>
|
||||
<string name="WebRtcCallActivity__calling">جارٍ الاتصال…</string>
|
||||
<!-- Call status shown when an active call was disconnected (e.g., network hiccup) and is trying to reconnect -->
|
||||
<string name="WebRtcCallActivity__reconnecting">جارٍ إعادة الاتصال...</string>
|
||||
<string name="WebRtcCallActivity__reconnecting">جارٍ إعادة الاتصال…</string>
|
||||
<!-- Title for dialog warning about lacking bluetooth permissions during a call -->
|
||||
<string name="WebRtcCallActivity__bluetooth_permission_denied">تمَّ رفض إذن بلوتوث</string>
|
||||
<!-- Message for dialog warning about lacking bluetooth permissions during a call and references the permission needed by name -->
|
||||
@@ -2852,7 +2852,7 @@
|
||||
<string name="WebRtcCallView__call_is_full">المكالمة ممتلئة</string>
|
||||
<string name="WebRtcCallView__the_maximum_number_of_d_participants_has_been_Reached_for_this_call">وصلَ عدد المشاركين إلى %1$d مُشارِكًا، وهو الحد الأقصى في هذه المكالمة. حاوِل مرّة أخرى لاحقًا.</string>
|
||||
<string name="WebRtcCallView__your_video_is_off">توقَّف الفيديو لديك</string>
|
||||
<string name="WebRtcCallView__reconnecting">جارٍ إعادة الاتصال...</string>
|
||||
<string name="WebRtcCallView__reconnecting">جارٍ إعادة الاتصال…</string>
|
||||
<string name="WebRtcCallView__joining">يجري الانضمام…</string>
|
||||
<string name="WebRtcCallView__disconnected">توقَّف الاتصال</string>
|
||||
<!-- Utilized in the lobby before joining a call link -->
|
||||
@@ -3264,15 +3264,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">لم يتم العثور على أي نتيجة لـ \'%1$s\'</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">لم يتم العثور على أي نتائج.</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">إضافة إلى جهات الاتصال</string>
|
||||
@@ -3440,28 +3440,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">عند النقر على زر \"إرسال\"، سوف يُنشَر السجل على الإنترنت لمدة 30 يومًا في عنوان URL فريد غير منشور. يمكنك حفظه محليًا أولًا.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">الفلتر:</string>
|
||||
<string name="SupportEmailUtil_device_info">معلومات الجهاز:</string>
|
||||
<string name="SupportEmailUtil_android_version">إصدار اﻷندرويد:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">قفل التسجيل:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">تمَّ تحديث المجموعة</string>
|
||||
@@ -3625,10 +3625,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">حسنًا</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">تمَّ تشفير الرسالة لجلسة غير موجودة.</string>
|
||||
@@ -3916,9 +3916,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">أعِد تسجيل الجهاز</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">لم يعد هذا الجهاز مُرتبطًا. أعِد ربط سيجنال مع هاتفك لمواصلة المراسلة.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">أعِد ربط الجهاز</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">تمَّ تسجيل خروجك من تطبيق سيجنال على هذا الجهاز.</string>
|
||||
@@ -4397,7 +4397,7 @@
|
||||
<string name="EditProfileFragment__edit_group">تعديل المجموعة</string>
|
||||
<string name="EditProfileFragment__group_name">اسم المجموعة</string>
|
||||
<string name="EditProfileFragment__group_description">وصف المجموعة</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">تحديث سيجنال</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -4444,7 +4444,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">التحقُّق التلقائي غير متوفر</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">التحقُّق التلقائي غير متوفر لكل الدردشات.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">تمَّ التحقُّق من التشفير تلقائيًا لهذه الدردشة.</string>
|
||||
@@ -4478,7 +4478,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">تقديم</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">تعذَّر التحقُّق التلقائي من المفاتيح</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">اعرف المزيد</string>
|
||||
|
||||
@@ -4532,17 +4532,17 @@
|
||||
<string name="HelpFragment__whats_this">ما هذا؟</string>
|
||||
<string name="HelpFragment__how_do_you_feel">كيف تشعر؟ (اختياري)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">يُرجى إخبارنا عن سبب تواصلك معنا.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">معلومات الدعم</string>
|
||||
<string name="HelpFragment__signal_android_support_request">طلب الدعم من سيجنال أندرويد</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">لا يمكن تحميل السجلات</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">يُرجى تقديم شرح مُفصَّل قدر الإمكان لمساعدتنا على فهم المشكلة.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4766,7 +4766,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">إذا تمَّ إلغاء تفعيل مؤشِّرات الكتابة، فلن يمكنك رؤية المؤشر عند قيام الآخرين بالكتابة.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">الطلب من لوحة المفاتيح عدم تمكين التعلُّم المُخصَّص.</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">هذا الإعداد غير مضمون، وقد تتجاهله لوحة مفاتيحك.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">عند استخدام بيانات الجوّال</string>
|
||||
<string name="preferences_chats__when_using_wifi">عند استخدام الواي فاي</string>
|
||||
<string name="preferences_chats__when_roaming">عند استخدام التجوال</string>
|
||||
@@ -4887,9 +4887,9 @@
|
||||
<string name="configurable_single_select__customize_option">تخصيص الخيارات</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4933,14 +4933,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">عُطِّلَت المدفوعات</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">فشِلت عملية الدفع</string>
|
||||
<string name="PaymentsHomeFragment__details">التفاصيل</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">يُمكنك استخدام سيجنال لإرسال وتلقي عملة MobileCoin. تخضع كل عمليات الدفع لشروط استخدام MobileCoin ومحفظة MobileCoin. قد تواجه بعض المشاكل وقد لا يكون بالإمكان استعادة المدفوعات أو الأرصدة التي قد تخسرها. </string>
|
||||
<string name="PaymentsHomeFragment__activate">تفعيل</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">إظهار شروط التعامل بـ MobileCoin</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">لم تعد المدفوعات متاحة في سيجنال. يمكنك دومًا إرسال المبالغ إلى منصة للتداول، لكن لم يعد بإمكانك إرسال أو استلام المبالغ أو إضافة الأموال.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">هل تريد تفعيل قفل عملية الدفع للعمليات المُستقبلية؟</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4985,7 +4985,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">نسخ</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">تمَّ النسخ إلى الحافظة</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">لإضافة مبالغ، أرسِل عملات MobileCoin إلى عنوان محفظتك. ابدأ بالمعاملة انطلاقًا من حسابك في منصة تداول تدعم MobileCoin، بعدها امسح كود الـ QR أو انسخ عنوان محفظتك.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">التفاصيل</string>
|
||||
@@ -5006,8 +5006,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">رسوم تنظيف العملة</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">يتم فرض \"رسوم تنظيف العملة\" عندما يتعذَّر دمج العملات التي بحوزتك لإتمام معاملة. سيسمح لك التنظيف بمتابعة إرسال المدفوعات.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">لا تتوفَّر أي تفاصيل أخرى حول هذه المعاملة.</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">المبلغ المُرسَل</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">المبلغ المُستلَم</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">اكتملَت عملية الدفع %1$s</string>
|
||||
@@ -5052,7 +5052,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">مسافة للخلف</string>
|
||||
<string name="CreatePaymentFragment__add_note">إضافة ملاحظة</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">التحويلات هي تقديرات فقط، وقد لا تكون دقيقة.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">ملاحظة</string>
|
||||
@@ -5138,9 +5138,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">حذف</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">إعادة التوجيه</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -5209,7 +5209,7 @@
|
||||
<string name="conversation__menu_view_all_media">جميع الوسائط</string>
|
||||
<string name="conversation__menu_conversation_settings">إعدادات الدردشة</string>
|
||||
<string name="conversation__menu_add_shortcut">إضافة إلى الشاشة الرئيسية</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">إنشاء فقاعة</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">تنسيق النص</string>
|
||||
@@ -5220,11 +5220,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">إضافة إلى جهات الاتصال</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -5258,7 +5258,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">مجموعة جديدة</string>
|
||||
<string name="text_secure_normal__menu_settings">الإعدادات</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">قَفْل</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">اعتبار كل الرسائل مقروءة</string>
|
||||
<string name="text_secure_normal__invite_friends">اُدْعُ الأصدقاء</string>
|
||||
@@ -5304,7 +5304,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">إنشاء رقم تعريف شخصي (PIN) من أحرف وأرقام</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">إنشاء رقم تعريف شخصي (PIN) من أرقام</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -5346,7 +5346,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">نقدم لكم أرقام التعريف الشخصية (PINs)</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">الأرقام التعريفية الشخصية (PIN) تجعل المعلومات المحفوظة في سيجنال مُشفَّرة، ولا يمكن لأحد غيرك أن يصل إليها. سيتمُّ استرجاع حسابك الشخصي و إعداداتك وجهات اتصالك عندما يُعاد تثبيت سيجنال. لن تحتاج رقم التعريف الشخصي (PIN) لفتح التطبيق.</string>
|
||||
<string name="KbsSplashFragment__learn_more">اعرف المزيد</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">قفل التسجيل = رقم التعريف الشخصي (PIN)</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">قفل التسجيل يسمَّى الآن رقم التعريف الشخصي (PIN)، وهو مسؤول عن أشياء أخرى. حدِّثه الآن.</string>
|
||||
<string name="KbsSplashFragment__update_pin">تحديث رقم PIN</string>
|
||||
@@ -5367,7 +5367,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">تمَّ قفل حسابك لحماية خصوصيتك وأمانك. بعد %1$d يوم من خمول حسابك، سيكون بإمكانك إعادة التسجيل برقم هاتفك دون الحاجة إلى رقم التعريف الشخصي (PIN). سيتمُّ حذف جميع محتويات حسابك.</string>
|
||||
<string name="AccountLockedFragment__next">التالي</string>
|
||||
<string name="AccountLockedFragment__learn_more">اعرف المزيد</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">أدخِل رقم PIN</string>
|
||||
@@ -5639,6 +5639,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">فشلت عملية حذف البيانات</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">نقل أو استعادة الحساب</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">إذا سبق لك التسجيل بحساب سيجنال، يمكنك نقل أو استعادة حسابك وكذلك رسائلك.</string>
|
||||
@@ -5668,7 +5694,7 @@
|
||||
|
||||
<!-- NewDeviceTransferSetupFragment -->
|
||||
<string name="NewDeviceTransferSetup__preparing_to_connect_to_old_android_device">جارٍ إعداد الاتصال بجهاز أندرويد الجديد لديك…</string>
|
||||
<string name="NewDeviceTransferSetup__take_a_moment_should_be_ready_soon">يحتاج لبعض الوقت... سيصبح جاهزًا قريبًا.</string>
|
||||
<string name="NewDeviceTransferSetup__take_a_moment_should_be_ready_soon">يحتاج لبعض الوقت… سيصبح جاهزًا قريبًا.</string>
|
||||
<string name="NewDeviceTransferSetup__waiting_for_old_device_to_connect">بانتظار اتصال جهاز أندرويد القديم…</string>
|
||||
<string name="NewDeviceTransferSetup__signal_needs_the_location_permission_to_discover_and_connect_with_your_old_device">يحتاج سيجنال إلى إذن الوصول إلى الموقع لاكتشاف جهاز أندرويد القديم الخاص بك والاتصال به.</string>
|
||||
<string name="NewDeviceTransferSetup__signal_needs_location_services_enabled_to_discover_and_connect_with_your_old_device">يحتاج سيجنال إلى أن تكون خدمات الموقع مُفعَّلة لكي يكتشف جهاز أندرويد القديم الخاص بك ويتصل به.</string>
|
||||
@@ -5953,7 +5979,7 @@
|
||||
<!-- Title of progress dialog shown when a user deletes their account and the process is leaving all groups -->
|
||||
<string name="DeleteAccountFragment__leaving_groups">جارٍ مغادرة المجموعات…</string>
|
||||
<!-- Title of progress dialog shown when a user deletes their account and the process has left all groups -->
|
||||
<string name="DeleteAccountFragment__deleting_account">جارٍ حذف الحساب...</string>
|
||||
<string name="DeleteAccountFragment__deleting_account">جارٍ حذف الحساب…</string>
|
||||
<!-- Message of progress dialog shown when a user deletes their account and the process is canceling their subscription -->
|
||||
<string name="DeleteAccountFragment__canceling_your_subscription">جارٍ إلغاء اشتراكك…</string>
|
||||
<!-- Message of progress dialog shown when a user deletes their account and the process is leaving groups -->
|
||||
@@ -6057,9 +6083,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">عند توفُّر رصيد كبير لديك، قد تكون لديك الرغبة في زيادة حماية حسابك عبر تحديث رقم التعريف الشخصي (PIN) إلى أرقام وحروف.</string>
|
||||
<string name="payment_info_card_update_pin">تحديث رقم PIN</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">تعطيل المحفظة</string>
|
||||
@@ -6071,7 +6097,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">هل ترغب بالتعطيل بدون أي إرسال؟</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">سيبقى رصيدك في محفظتك المرتبطة بـسيجنال إذا اخترتَ إعادة تفعيل عمليات الدفع.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">حدث خطأ خلال تعطيل المحفظة.</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">عبارة الاستعادة</string>
|
||||
@@ -6111,8 +6137,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">عبارة الاستعادة غير صحيحة</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">تأكَّد من إدخالك الـ %1$d كلمات ثم حاوِل مرّة أخرى.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">التالي</string>
|
||||
@@ -6157,7 +6183,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">ليس لديك أي جهات اتصال ولا أي شخص سبق لك التواصل معه في هذه المجموعة. يُرجى مراجعة الطلبات بعناية قبل قبولها لتفادي أي رسائل غير مرغوب فيها.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">حول طلبات المراسلة</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">حسنًا</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">إليك معاينة للون الدردشة.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">اللون يظهر لك فقط.</string>
|
||||
|
||||
@@ -6527,7 +6553,7 @@
|
||||
<!-- NotificationsSettingsFragment -->
|
||||
<string name="NotificationsSettingsFragment__messages">الرسائل</string>
|
||||
<string name="NotificationsSettingsFragment__calls">المكالمات</string>
|
||||
<string name="NotificationsSettingsFragment__notify_when">أخبرني عند...</string>
|
||||
<string name="NotificationsSettingsFragment__notify_when">أخبرني عند…</string>
|
||||
<string name="NotificationsSettingsFragment__contact_joins_signal">انضمام جهة اتصال لسيجنال</string>
|
||||
<!-- Notification preference header -->
|
||||
<string name="NotificationsSettingsFragment__notification_profiles">ملفات الإشعارات</string>
|
||||
@@ -6573,7 +6599,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">إظهار أيقونة الحالة</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">عرض أيقونة في تفاصيل الرسالة للرسائل التي تمَّ إيصالها باستخدام المُرسِل المُشفَّر.</string>
|
||||
|
||||
@@ -6744,8 +6770,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">ميزة اختفاء الرسائل</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">الأصوات والإشعارات</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">معلومات عن جهة اتصال الهاتف</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">عرض رقم اﻷمان</string>
|
||||
<string name="ConversationSettingsFragment__block">حظر</string>
|
||||
@@ -7627,39 +7653,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="zero">هل ترغبُ بحذف %1$d قصة؟ لا يمكن التراجع عن هذا الإجراء.</item>
|
||||
@@ -8997,12 +9023,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"لاستعادة نسخة احتياطية، ثبِّت نسخة جديدة من سيجنال. افتح التطبيق وانقر على \"استعادة النسخة الاحتياطية\"، ثم حدِّد مكان ملف النسخة الاحتياطية."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">إعداد \"تحسين مساحة التخزين على سيجنال\" مُفعَّل. إذا كُنتَ ترغب في تضمين جميع ملفات الوسائط في النسخة الاحتياطية على الجهاز، يُرجى إيقاف تشغيل هذا الإعداد.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">إظهار الإعدادات</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">المواصلة دون إيقاف التشغيل</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">قُم بتأكيد مفتاح الاستعادة الخاص بك</string>
|
||||
@@ -9129,7 +9155,7 @@
|
||||
|
||||
<!-- BackupProgressService -->
|
||||
<!-- Notification title shown while backup restore job is running -->
|
||||
<string name="BackupProgressService_title">جارٍ استعادة النسخة الاحتياطية...</string>
|
||||
<string name="BackupProgressService_title">جارٍ استعادة النسخة الاحتياطية…</string>
|
||||
<!-- Notification title shown while downloading backup restore data -->
|
||||
<string name="BackupProgressService_title_downloading">جارٍ تنزيل البيانات الاحتياطية…</string>
|
||||
|
||||
@@ -9399,11 +9425,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">لا يمكن استخدام ميزة تحسين التخزين إلّا مع المُستوى المدفوع لنسخ سيجنال الاحتياطية. اشتراك النسخ الاحتياطية الخاص بك لا يزال قيد المعالجة ولم يتم تفعيله بعد. يُرجى المحاولة مرّة أخرى لاحقًا.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">سيتم حذف ملفات الوسائط من النسخة الاحتياطية على الجهاز لديك.</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">سيؤدي تفعيل \"تحسين مساحة التخزين على سيجنال\" إلى نقل الوسائط القديمة من جهازك. يمكنك تنزيلها من جديد في أي وقت. سيؤدي هذا أيضًا إلي حذف الوسائط القديمة من النسخة الاحتياطية على الجهاز.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">تشغيل</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -9498,6 +9524,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">تمَّ إلغاء الاشتراك</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">نسخ احتياطية تلقائية باستخدام خدمة تخزين مُشفَّرة من طرف لطرف على سيجنال.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"تعذَّر العثور على اشتراك في هذا الجهاز."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -9605,6 +9633,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s على %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">أبدًا</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">إنشاء نسخة احتياطية الآن</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -10136,10 +10174,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">خطأ في الشبكة عند استعادة النسخة الاحتياطية لسيجنال أندرويد</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">حدث فشل دائم في استعادة النسخة الاحتياطية لسيجنال أندرويد</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">أدخِل مفتاح الاستعادة الخاص بك.</string>
|
||||
@@ -10270,7 +10308,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">خطأ في الشبكة عند استعادة النسخة الاحتياطية لسيجنال أندرويد</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">هل ترغبُ بإرسال سجل الأخطاء؟</string>
|
||||
@@ -10373,26 +10411,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">البروكسي</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">التصفُّح نحو اﻷعلى</string>
|
||||
@@ -10704,19 +10742,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">البحث عن الأعضاء</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">البحث في جهات الاتصال</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">البحث في المُشرِفين</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">الفلترة بحسب</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">جميع الأعضاء</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">المُشرِفون</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">جهات الاتصال</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">الدعوة عبر رابط المجموعة</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">تعذَّرت استعادة النسخة الاحتياطية</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">Dalğalar</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">Signal yenilənir…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">Şifrə yarat</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Backspace</string>
|
||||
|
||||
@@ -448,7 +448,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Qoşma, göndərdiyiniz mesaj növü üçün həcm limitləri aşır.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">Səs yazıla bilmir!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">Üzv olmadığınız üçün bu qrupa mesaj göndərə bilməzsiniz.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">Qrup sonlandırıldığı üçün mesajlar göndərə bilmirsiniz.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">Yalnız %1$s mesaj göndərə bilər.</string>
|
||||
<string name="ConversationActivity_admins">adminlər</string>
|
||||
@@ -616,7 +616,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Signal-da təkrar qeydiyyatdan keçin</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Yenidən əlaqələndir</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Geri qayıt.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1038,7 +1038,7 @@
|
||||
<!-- Button in dialog asking user if they are sure they want to delete the selected scheduled message -->
|
||||
<string name="ScheduledMessagesBottomSheet_delete_dialog_message">Seçilmiş planlaşdırılan mesaj silinsin?</string>
|
||||
<!-- Progress message shown while deleting selected scheduled message -->
|
||||
<string name="ScheduledMessagesBottomSheet_deleting_progress_message">Planlaşdırılan mesaj silinir...</string>
|
||||
<string name="ScheduledMessagesBottomSheet_deleting_progress_message">Planlaşdırılan mesaj silinir…</string>
|
||||
|
||||
<!-- DecryptionFailedDialog -->
|
||||
<string name="DecryptionFailedDialog_chat_session_refreshed">Çat seansı təzələndi</string>
|
||||
@@ -1059,7 +1059,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">Signal mesajları əlaqələndirildikdən sonra mobil telefonunuzdakı Signal ilə sinxronlaşdırılır. Əvvəlki mesaj tarixçəniz görünməyəcək.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">Signal-ı quraşdırmaq üçün əlaqələndirmək istədiyiniz cihazdan %1$s vebsaytına daxil olun</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">Əlaqələndirilmiş cihazlarım</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1100,7 +1100,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">Ləğv et</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Android Link&Sync ixracı baş tutmadı</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">Mesaj sinxronlaşdırma baş tutmadı</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1109,7 +1109,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">Cihazınız uğurla əlaqələndirildi, lakin mesajlarınız ötürülmədi.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">Daha ətraflı</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">Yenidən sına</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1254,7 +1254,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">Bütün üzvlər</string>
|
||||
<string name="GroupManagement_access_level_only_admins">Yalnız adminlər</string>
|
||||
<string name="GroupManagement_access_level_no_one">Heç kim</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1392,7 +1392,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">Davam et</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">Xeyr, təşəkkürlər</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">Tələb və dəvətlər</string>
|
||||
@@ -1495,9 +1495,9 @@
|
||||
|
||||
<!-- RemoteRestoreActivity -->
|
||||
<!-- Progress dialog label when downloading a backup -->
|
||||
<string name="RemoteRestoreActivity__downloading_backup">Ehtiyat nüsxə endirilir...</string>
|
||||
<string name="RemoteRestoreActivity__downloading_backup">Ehtiyat nüsxə endirilir…</string>
|
||||
<!-- Progress dialog label when restoring a backup -->
|
||||
<string name="RemoteRestoreActivity__restoring_messages">Mesajlar bərpa olunur...</string>
|
||||
<string name="RemoteRestoreActivity__restoring_messages">Mesajlar bərpa olunur…</string>
|
||||
<!-- Progress dialog label when finishing a backup restore -->
|
||||
<string name="RemoteRestoreActivity__finishing_restore">Tamamlanır…</string>
|
||||
<!-- Progress dialog label while awaiting updates -->
|
||||
@@ -1792,8 +1792,8 @@
|
||||
<string name="MediaOverviewActivity_audio">Səs</string>
|
||||
<string name="MediaOverviewActivity_video">Video</string>
|
||||
<string name="MediaOverviewActivity_image">Təsvir</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">%1$s göndərdi</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Siz göndərdiniz</string>
|
||||
@@ -1827,13 +1827,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">Signal zəngi edilir</string>
|
||||
@@ -2231,7 +2231,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">Bu qrupa qoşulursunuz? Qəbul edənə qədər onların mesajlarını gördüyünüzü bilməyəcəklər.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">Bu qrupu blokdan çıxararaq adınızı və fotonuzu üzvlərlə paylaşırsınız? Blokdan çıxaranadək heç bir mesaj almayacaqsınız.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">Bax</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">%1$s qrupunun üzvü</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">%1$s və %2$s qruplarının üzvü</string>
|
||||
@@ -2368,7 +2368,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">PIN yaradın</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">PIN təxminləriniz bitdi, ancaq yenə də yeni bir PIN yaradaraq Signal hesabınıza müraciət edə bilərsiniz. Gizliliyiniz və güvənliyiniz üçün hesabınız, yadda saxlanılmış hər hansısa profil məlumatı və ya tənzimləmələri olmadan geri yüklənəcək.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">Yeni PIN yarat</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">SMS kodu göndər</string>
|
||||
@@ -2888,15 +2888,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">\'%1$s\' üçün heç nə tapılmadı</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">Heç nə tapılmadı</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">Əlaqələrə əlavə et</string>
|
||||
@@ -3048,28 +3048,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">\"Göndər\"ə kliklədiyinizdə, jurnalınızın unikal və dərc edilməmiş URL-də 30 gün ərzində onlayn paylaşılacaq. Əvvəlcə yerli yaddaşda saxlaya bilərsiniz.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">Filtr:</string>
|
||||
<string name="SupportEmailUtil_device_info">Cihaz məlumatı:</string>
|
||||
<string name="SupportEmailUtil_android_version">Android versiyası:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">Qeydiyyat kilidi:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">Qrup yeniləndi</string>
|
||||
@@ -3229,10 +3229,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">Oldu</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Mövcud olmayan seans üçün mesaj şifrələndi</string>
|
||||
@@ -3492,9 +3492,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Cihazı təkrar qeydiyyatdan keçirin</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Bu cihaz artıq qoşulu deyil. Mesajlaşmağa davam etmək üçün Signal-ı yenidən telefonunuzla əlaqələndirin.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Cihazı yenidən əlaqələndir</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">Bu cihazda Signal tətbiqindən çıxmısınız.</string>
|
||||
@@ -3917,7 +3917,7 @@
|
||||
<string name="EditProfileFragment__edit_group">Qrupa düzəliş et</string>
|
||||
<string name="EditProfileFragment__group_name">Qrup adı</string>
|
||||
<string name="EditProfileFragment__group_description">Qrup açıqlaması</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Signal-ı yenilə</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -3964,7 +3964,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">Avtomatik yoxlama aktiv deyil</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">Avtomatik yoxlama bütün çatlar üçün aktiv deyil.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">Bu çat üçün şifrələmə avtomatik olaraq yoxlanıldı</string>
|
||||
@@ -3998,7 +3998,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">Təqdim et</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">Avtomatik Şifrə Yoxlama Xətası</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">Daha ətraflı</string>
|
||||
|
||||
@@ -4052,17 +4052,17 @@
|
||||
<string name="HelpFragment__whats_this">Bu nədir?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">Özünüzü necə hiss edirsiniz?</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">Bizə niyə müraciət etdiyinizi deyin.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">Dəstək məlumatı</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Signal Android Dəstək Tələbi</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">Jurnal yüklənilə bilmədi</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">Zəhmət olmasa anlamağımıza kömək etmək üçün problemi daha aydın təsvir edin.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4278,7 +4278,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">\"Yazır\" statusu sıradan çıxarılsa, başqalarının \"yazır\" statusunu görə bilməyəcəksiniz.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">Klaviaturanın fərdiləşdirilmiş öyrənməni sıradan çıxartmasını tələb et.</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">Bu tənzimləməyə zəmanət verilmir və klaviaturanız buna əhəmiyyət verməyə bilər.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">Mobil verilənlər istifadə edərkən</string>
|
||||
<string name="preferences_chats__when_using_wifi">Wi-Fi istifadə edərkən</string>
|
||||
<string name="preferences_chats__when_roaming">Roaminqdə olarkən</string>
|
||||
@@ -4391,9 +4391,9 @@
|
||||
<string name="configurable_single_select__customize_option">Seçimi özəlləşdir</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4437,14 +4437,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">Ödənişlər deaktiv edildi.</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">Ödəniş edilmədi</string>
|
||||
<string name="PaymentsHomeFragment__details">Təfsilatlar</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">MobileCoin göndərmək və almaq üçün Signal-dan istifadə edə bilərsiniz. Bütün ödənişlər MobileCoins və MobileCoin Pulqabının İstifadə Şərtləri ilə tənzimlənir. Bəzi problemlərlə üzləşə bilərsiniz, yaxud da itirə biləcəyiniz ödəniş və balansları yenidən bərpa etməyiniz mümkün olmaya bilər. </string>
|
||||
<string name="PaymentsHomeFragment__activate">Aktivləşdir</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">MobileCoin şərtlərinə bax</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Ödənişlər, Signal-da artıq əlçatmazdır. Yenə də bir birjaya pul köçürə bilərsiniz, ancaq ödəniş göndərə və ala və ya pul əlavə edə bilməzsiniz.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">Gələcəkdəki göndərişlər üçün Ödəniş kilidi aktivləşdirilsin?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4489,7 +4489,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">Kopyala</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">Lövhəyə kopyalandı</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">Pul əlavə etmək üçün pulqabı ünvanınıza MobileCoin göndərin. MobileCoin dəstəkləyən bir birjada hesabınızdan bir əməliyyat başladın, daha sonra QR kodu skan edin və ya pulqabı ünvanınızı kopyalayın.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">Təfsilatlar</string>
|
||||
@@ -4510,8 +4510,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">Xırda pul təmizləmə haqqı</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">Sahib olduğunuz xırda pullar, bir əməliyyatı tamamlamaq üçün birləşdirilə bilməyəndə \"Xırda pul təmizləmə haqqı\" tutulur. Təmizləmə, ödəniş göndərməyə davam etməyinizi təmin edir.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">Bu əməliyyatla bağlı əlavə məlumat yoxdur</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">Ödəniş göndərildi</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">Ödəniş alındı</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">Ödəniş tamamlandı %1$s</string>
|
||||
@@ -4556,7 +4556,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">Backspace</string>
|
||||
<string name="CreatePaymentFragment__add_note">Qeyd əlavə et</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">Çevrilmə sadəcə təxminidir və dəqiq olmaya bilər.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">Qeyd</string>
|
||||
@@ -4604,7 +4604,7 @@
|
||||
|
||||
<!-- contact_selection_list -->
|
||||
<!-- Displayed in a row on the new call screen when searching by phone number. -->
|
||||
<string name="contact_selection_list__new_call">... yeni zəng</string>
|
||||
<string name="contact_selection_list__new_call">… yeni zəng</string>
|
||||
<string name="contact_selection_list__unknown_contact">Yeni mesaj</string>
|
||||
<string name="contact_selection_list__unknown_contact_block">İstifadəçini blokla</string>
|
||||
<string name="contact_selection_list__unknown_contact_add_to_group">Qrupa əlavə et</string>
|
||||
@@ -4638,9 +4638,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">Sil</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">Yönləndir</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4709,7 +4709,7 @@
|
||||
<string name="conversation__menu_view_all_media">Bütün media</string>
|
||||
<string name="conversation__menu_conversation_settings">Çat parametrləri</string>
|
||||
<string name="conversation__menu_add_shortcut">Əsas ekrana əlavə et</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">Şar yarat</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">Mətni formatla</string>
|
||||
@@ -4720,11 +4720,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">Əlaqələrə əlavə et</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -4754,7 +4754,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">Yeni qrup</string>
|
||||
<string name="text_secure_normal__menu_settings">Tənzimləmələr</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">Kilidlə</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">Hamısını oxundu olaraq işarələ</string>
|
||||
<string name="text_secure_normal__invite_friends">Dostları dəvət et</string>
|
||||
@@ -4800,7 +4800,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">Alfa nömrəli PIN yaradın</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">Nömrəli PIN yaradın</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -4834,7 +4834,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">Budur, PIN-lər</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">PIN-lər, Signal-da saxlanılan məlumatları şifrələnmiş olaraq tutur, beləcə yalnız siz müraciət edə bilərsiniz. Profiliniz, tənzimləmələriniz və əlaqələriniz, yenidən quraşdıranda geri yüklənəcək. Tətbiqi açmaq üçün PIN-inizə ehtiyac olmayacaq.</string>
|
||||
<string name="KbsSplashFragment__learn_more">Daha Ətraflı</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">Qeydiyyat Kilidi = PIN</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">Qeydiyyat Kilidiniz, indi PIN olaraq adlandırılır və daha çoxunu edir. İndi yeniləyin.</string>
|
||||
<string name="KbsSplashFragment__update_pin">PIN-i yenilə</string>
|
||||
@@ -4855,7 +4855,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">Hesabınız məxfilik və təhlükəsizliyinizi qorumaq üçün kilidləndi. Hesabınızda fəaliyyətsiz %1$d gündən sonra bu telefon nömrəsi ilə PIN-inizə ehtiyac olmadan yenidən qeydiyyatdan keçə biləcəksiniz. Bütün məzmunlar silinəcək.</string>
|
||||
<string name="AccountLockedFragment__next">Növbəti</string>
|
||||
<string name="AccountLockedFragment__learn_more">Daha Ətraflı</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">PIN-inizi daxil edin</string>
|
||||
@@ -5107,6 +5107,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">Verilənləri silmək mümkün olmadı</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Hesabınızı köçürün və ya geri yükləyin</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">Daha əvvəl bir Signal hesabını qeydiyyata almısınızsa, hesabınızı və mesajlarınızı köçürə və ya geri yükləyə bilərsiniz.</string>
|
||||
@@ -5497,9 +5523,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">Yüksək bir balans ilə, hesabınıza daha çox qoruma əlavə etmək üçün PIN-i alfanömrəli olaraq yeniləmək istəyə bilərsiniz.</string>
|
||||
<string name="payment_info_card_update_pin">PIN-i yenilə</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">Pulqabını deaktiv et</string>
|
||||
@@ -5511,7 +5537,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">Köçürmə olmadan deaktiv edilsin?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">Ödənişləri yenidən aktivləşdirməyi seçsəniz, balansınız Signal-a əlaqələndirilmiş pulqabınızda qalacaq.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">Pulqabını deaktiv edərkən xəta baş verdi.</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">Bərpa parolu</string>
|
||||
@@ -5547,8 +5573,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">Etibarsız bərpa parolu</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">%1$d sözü daxil etdiyinizə əmin olduqdan sonra yenidən sınayın.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">Növbəti</string>
|
||||
@@ -5593,7 +5619,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">Kontaktlarınızdan və ya söhbət etdiyiniz şəxslərdən heç biri bu qrupda yoxdur. Arzuolunmaz mesajlardan yayınmaq üçün qəbul etməzdən əvvəl tələbləri diqqətlə nəzərdən keçirin.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">Mesaj tələbləri haqqında</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">Oldu</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">Bu, çat ekranının rənginə bir önbaxışdır.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">Rəng, yalnız sizə görünür.</string>
|
||||
|
||||
@@ -5675,7 +5701,7 @@
|
||||
<string name="ExportAccountDataFragment__export_report_action">İxrac et</string>
|
||||
|
||||
<!-- Shown in a dialog with a spinner while the report is downloading -->
|
||||
<string name="ExportAccountDataFragment__download_progress">Hesabat yaradılır...</string>
|
||||
<string name="ExportAccountDataFragment__download_progress">Hesabat yaradılır…</string>
|
||||
<!-- Explanation that the report is only generated on export and is not saved on the device -->
|
||||
<string name="ExportAccountDataFragment__report_not_stored_disclaimer">Hesabatınız yalnız ixrac zamanı yaradılır və Signal tərəfindən cihazınızda saxlanmır.</string>
|
||||
|
||||
@@ -5973,7 +5999,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">Status nişanını göstər</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">Gizli göndərən istifadə edərək mesaj çatdırılanda təfsilatlarında bir nişan göstər.</string>
|
||||
|
||||
@@ -6136,8 +6162,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">Yox olan mesajlar</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">Səs və bildirişlər</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">Telefon kontaktı məlumatı</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">Güvənlik nömrəsinə bax</string>
|
||||
<string name="ConversationSettingsFragment__block">Blokla</string>
|
||||
@@ -6983,39 +7009,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">%1$d hekayə silinsin? Bu addım geri qaytarıla bilməz.</item>
|
||||
@@ -7334,7 +7360,7 @@
|
||||
<!-- Primary action for pending gift sheet to redeem badge later -->
|
||||
<string name="ViewReceivedGiftSheet__not_now">İndi yox</string>
|
||||
<!-- Dialog text while redeeming a gift -->
|
||||
<string name="ViewReceivedGiftSheet__redeeming_badge">Nişan alınır...</string>
|
||||
<string name="ViewReceivedGiftSheet__redeeming_badge">Nişan alınır…</string>
|
||||
<!-- Description text in gift thanks sheet -->
|
||||
<string name="GiftThanksSheet__youve_made_a_donation">Siz %1$s adından Signal-a ianə verdiniz. Ona öz dəstəyini profilində göstərmə imkanı veriləcək.</string>
|
||||
<!-- Expired gift sheet title -->
|
||||
@@ -7873,7 +7899,7 @@
|
||||
|
||||
<!-- Call Log Fragment -->
|
||||
<!-- Displayed when deleting call history items -->
|
||||
<string name="CallLogFragment__deleting">Silinir...</string>
|
||||
<string name="CallLogFragment__deleting">Silinir…</string>
|
||||
<!-- Displayed in a toast when a deletion fails for an unknown reason -->
|
||||
<string name="CallLogFragment__deletion_failed">Silinmədi.</string>
|
||||
<!-- Displayed as message in error dialog when can\'t delete links -->
|
||||
@@ -8245,12 +8271,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Ehtiyat nüsxəni bərpa etmək üçün Signal-ın yeni versiyasını quraşdırın. Tətbiqi açıb, \"Ehtiyat nüsxəni bərpa et\" seçiminə toxunun, sonra ehtiyat nüsxə faylını tapın."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">\"Signal yaddaşını optimallaşdır\" funksiyası açıqdır. Cihazdaxili ehtiyat nüsxədəki bütün media fayllarını əhatə etmək üçün parametrləri söndürün.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Parametrlərə bax</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Söndürmədən davam et</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Bərpa şifrənizi yoxlayın</string>
|
||||
@@ -8635,11 +8661,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">Yaddaş optimallaşdırması yalnız Signal-ın təhlükəsiz ehtiyat nüsxələrinin ödənişli səviyyəsi ilə istifadə oluna bilər. Ehtiyat nüsxə abunəliyiniz hələ də emal olunur və aktiv deyil. Daha sonra yenidən cəhd edin.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media faylı cihazdaxili ehtiyat nüsxədən silinəcək</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">\"Signal yaddaşını optimallaşdır\" funksiyasını açsanız, bu, cihazınızdan köhnə media faylların köçürülməsinə səbəb olacaq. Bunu istədiyiniz vaxt yenidən endirə bilərsiniz. Bu addım həmçinin cihazdaxili ehtiyat nüsxədən köhnə media faylını siləcək.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Aç</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -8722,6 +8748,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Abunəlik ləğv edildi</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Signal-ın təhlükəsiz tam şəkildə şifrələnmiş saxlama xidməti ilə avtomatik çıxarılan ehtiyat nüsxələr.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"Bu cihazda abunəlik tapılmadı."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -8825,6 +8853,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s, %2$s radəsində</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Heç vaxt</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">İndi Arxivləşdir</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9336,10 +9374,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Signal Android Ehtiyat Nüsxəsi bərpasında şəbəkə xətası</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Signal Android Ehtiyat nüsxəsinin bərpası ilə bağlı davam edən xəta</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">Bərpa şifrənizi daxil edin</string>
|
||||
@@ -9374,7 +9412,7 @@
|
||||
<!-- RestoreLocalBackupActivity: Screen subtitle explaining restore duration -->
|
||||
<string name="RestoreLocalBackupActivity__depending_on_the_size">Ehtiyat nüsxənin həcmindən asılı olaraq bu, bir neçə dəqiqə çəkə bilər.</string>
|
||||
<!-- RestoreLocalBackupActivity: Status text while restoring messages -->
|
||||
<string name="RestoreLocalBackupActivity__restoring_messages">Mesajlar bərpa olunur...</string>
|
||||
<string name="RestoreLocalBackupActivity__restoring_messages">Mesajlar bərpa olunur…</string>
|
||||
<!-- RestoreLocalBackupActivity: Status text while finalizing restore -->
|
||||
<string name="RestoreLocalBackupActivity__finalizing">Yekunlaşdırılır…</string>
|
||||
<!-- RestoreLocalBackupActivity: Status text when restore is complete -->
|
||||
@@ -9470,7 +9508,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Signal Android Ehtiyat nüsxəsi ixracında şəbəkə xətası</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">Sazlama jurnalı göndərilsin?</string>
|
||||
@@ -9573,26 +9611,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">Proksi</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">Yuxarı gedin</string>
|
||||
@@ -9888,19 +9926,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Üzvləri axtar</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Kontaktları axtar</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Adminləri axtar</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Buna görə filtrlə:</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Bütün üzvlər</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">Adminlər</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Əlaqələr</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Qrup keçidi vasitəsilə dəvət et</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">Ehtiyat nüsxəni bərpa etmək mümkün deyil</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">Хвалі</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">Ідзе абнаўленне Signal…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">Стварыць новы код</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Backspace</string>
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Далучэнне перавышае ліміт памеру для тыпу паведамлення, што вы адпраўляеце.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">Немагчыма запісаць аўдыё!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">Вы не можаце адпраўляць паведамленні ў гэтую групу, таму што вы больш не з\'яўляецеся яе ўдзельнікам.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">Вы не можаце адпраўляць паведамленні, таму што гэта група спынена.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">Толькі %1$s можа адпраўляць паведамленні.</string>
|
||||
<string name="ConversationActivity_admins">адміністратары</string>
|
||||
@@ -642,7 +642,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Зарэгістравацца паўторна ў Signal</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Звяжыце паўторна</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Перайсці назад.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1113,7 +1113,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">Паведамленні Signal будуць сінхранізаваны з Signal на вашым мабільным тэлефоне пасля таго, як ён будзе звязаны. Ваша папярэдняя гісторыя паведамленняў не будзе паказана.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">Калі вы жадаеце звязаць прыладу, наведайце на ёй %1$s, каб усталяваць Signal</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">Мае звязаныя прылады</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1154,7 +1154,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">Скасаваць</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Памылка экспарту Android (Link&Sync)</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">Сінхранізацыя паведамленняў не атрымалася</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1163,7 +1163,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">Ваша прылада была паспяхова звязана, але вашы паведамленні немагчыма перанесці.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">Даведацца больш</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">Паспрабаваць зноў</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1310,7 +1310,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">Усе ўдзельнікі</string>
|
||||
<string name="GroupManagement_access_level_only_admins">Толькі адміністратары</string>
|
||||
<string name="GroupManagement_access_level_no_one">Ніхто</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1474,7 +1474,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">Працягнуць</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">Не, дзякуй</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">Запыты і запрашэнні</string>
|
||||
@@ -1591,7 +1591,7 @@
|
||||
<!-- Progress dialog label when finishing a backup restore -->
|
||||
<string name="RemoteRestoreActivity__finishing_restore">Сканчаем…</string>
|
||||
<!-- Progress dialog label while awaiting updates -->
|
||||
<string name="RemoteRestoreActivity__restoring">Аднаўленне...</string>
|
||||
<string name="RemoteRestoreActivity__restoring">Аднаўленне…</string>
|
||||
<!-- Progress readout for dialog while downloading or restoring a backup. First placeholder is the formatted size of the backup downloaded, the second is formatted total amount to go, and the last is a percentage. -->
|
||||
<string name="RemoteRestoreActivity__s_of_s_s">%1$s з %2$s (%3$s)</string>
|
||||
<!-- Feature list media label for paid tier -->
|
||||
@@ -1902,8 +1902,8 @@
|
||||
<string name="MediaOverviewActivity_audio">Аўдыё</string>
|
||||
<string name="MediaOverviewActivity_video">Відэа</string>
|
||||
<string name="MediaOverviewActivity_image">Выява</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">Адпраўлена ад %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Адпраўлена вамі</string>
|
||||
@@ -1937,13 +1937,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">Пачынаецца званок праз Signal</string>
|
||||
@@ -2361,7 +2361,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">Далучыцца да гэтай групы? Яны не даведаюцца, што вы бачылі іх паведамленні, пакуль вы не прымеце запыт.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">Разблакаваць гэту групу і раскрыць свае імя і фота яе ўдзельнікам? Вы не атрымаеце паведамленняў, пакуль не разблакуеце гэту групу.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">Прагледзець</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">Удзельнік %1$s</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">Удзельнік %1$s і %2$s</string>
|
||||
@@ -2512,7 +2512,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">Стварыце свой PIN-код</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">У вас скончыліся спробы ўводу PIN-кода, але вы па-ранейшаму можаце атрымаць доступ да ўліковага запісу Signal, калі створыце новы PIN-код. Для канфідэнцыйнасці і бяспекі ваш уліковы запіс будзе адноўлены без захавання інфармацыі профілю або наладаў.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">Стварыць новы PIN-код</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">Адправіць SMS-код</string>
|
||||
@@ -3076,15 +3076,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">Няма вынікаў для «%1$s»</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">Вынікаў не знойдзена</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">Дадаць у кантакты</string>
|
||||
@@ -3244,28 +3244,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">Калі вы націснеце «Адправіць», ваш журнал будзе размешчаны ў інтэрнэце на працягу 30 дзён па ўнікальным неапублікаваным URL-адрасе. Вы можаце спачатку захаваць яго лакальна.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">Фільтр:</string>
|
||||
<string name="SupportEmailUtil_device_info">Інф. аб прыладзе:</string>
|
||||
<string name="SupportEmailUtil_android_version">Версія Android:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">Блакіроўка рэгістрацыі:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">Група абноўленая</string>
|
||||
@@ -3427,10 +3427,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">OK</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Паведамленне зашыфравана для неіснуючага сеансу</string>
|
||||
@@ -3704,9 +3704,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Зарэгістраваць паўторна прыладу</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Гэтая прылада больш не звязаная. Паўторна звязаць Signal да свайго тэлефона, каб працягнуць абмен паведамленнямі.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Звязаць прыладу нанова</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">Вы выйшлі з Signal на гэтай прыладзе.</string>
|
||||
@@ -4157,7 +4157,7 @@
|
||||
<string name="EditProfileFragment__edit_group">Рэдагаваць інф. аб групе</string>
|
||||
<string name="EditProfileFragment__group_name">Назва групы</string>
|
||||
<string name="EditProfileFragment__group_description">Апісанне групы</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Абнавіць Signal</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -4204,7 +4204,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">Аўтаматычная праверка недаступная</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">Аўтаматычная праверка недаступная для ўсіх чатаў.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">Шыфраванне для гэтага чата было праверана аўтаматычна</string>
|
||||
@@ -4238,7 +4238,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">Адправіць</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">Памылка падчас аўтаматычнай праверкі шыфравання ключоў</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">Даведацца больш</string>
|
||||
|
||||
@@ -4292,17 +4292,17 @@
|
||||
<string name="HelpFragment__whats_this">Што гэта?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">Як вы сябе адчуваеце? (неабавязкова)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">Апішыце вашу праблему.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">Інфармацыя аб падтрымцы</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Запыт падтрымкі Signal Android</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">Не атрымалася запампаваць журналы</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">Напішыце як мага больш падрабязна, каб нам было лягчэй зразумець праблему.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4522,7 +4522,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">Калі індыкатары набору тэксту адключаны, вы не зможаце бачыць індыкатары набору тэксту ад іншых людзей.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">Запытаць адключэнне персаналізаванага навучання клавіятуры.</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">Гэтая налада не з\'яўляецца гарантыяй, і ваша клавіятура можа яе ігнараваць.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">Праз мабільную сетку</string>
|
||||
<string name="preferences_chats__when_using_wifi">Праз Wi-Fi</string>
|
||||
<string name="preferences_chats__when_roaming">У роўмінгу</string>
|
||||
@@ -4639,9 +4639,9 @@
|
||||
<string name="configurable_single_select__customize_option">Наладзіць опцыю</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4685,14 +4685,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">«Плацяжы» дэактываваныя.</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">Плацеж не атрымаўся</string>
|
||||
<string name="PaymentsHomeFragment__details">Звесткі</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">Вы можаце выкарыстоўваць Signal, каб адпраўляць і атрымліваць MobileCoin. Усе плацяжы рэгламентаваны Умовамі выкарыстання MobileCoins і MobileCoin Wallet. Вы можаце сутыкнуцца з некаторымі праблемамі, і плацяжы або сродкі, якія вы можаце страціць, будзе немагчыма вярнуць. </string>
|
||||
<string name="PaymentsHomeFragment__activate">Актываваць</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">Прагледзець Умовы MobileCoin</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Опцыя «Плацяжы» ў Signal больш недаступная. Вы па-ранейшаму можаце пераводзіць сродкі для абмену, але больш не зможаце адпраўляць і атрымліваць плацяжы або дадаваць сродкі.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">Уключыць блакіроўку плацяжоў для будучых адпраўленняў?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4737,7 +4737,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">Капіраваць</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">Скапіравана ў буфер абмену</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">Адпраўце MobileCoin на адрас вашага кашалька, каб дадаць сродкі. Пачніце транзакцыю ў сваім уліковым запісе на біржы, якая падтрымлівае MobileCoin, потым праскануйце QR-код або скапіюйце адрас свайго кашалька.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">Звесткі</string>
|
||||
@@ -4758,8 +4758,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">Камісія за ачыстку манет</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">«Камісія за ачыстку манет» спаганяецца, калі манеты, якімі вы валодаеце, немагчыма аб\'яднаць, каб выканаць транзакцыю. Пасля ачысткі вы зможаце працягнуць адпраўляць плацяжы.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">Для гэтай транзакцыі няма больш падрабязнай інфармацыі</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">Адпраўлены плацеж</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">Атрыманы плацеж</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">Плацеж выкананы %1$s</string>
|
||||
@@ -4804,7 +4804,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">Backspace</string>
|
||||
<string name="CreatePaymentFragment__add_note">Дадаць нататку</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">Канверсіі з\'яўляюцца прыблізнымі і могуць быць недакладнымі.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">Нататка</string>
|
||||
@@ -4888,9 +4888,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">Выдаліць</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">Пераслаць</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4959,7 +4959,7 @@
|
||||
<string name="conversation__menu_view_all_media">Усе медыяфайлы</string>
|
||||
<string name="conversation__menu_conversation_settings">Налады чата</string>
|
||||
<string name="conversation__menu_add_shortcut">Дадаць на галоўны экран</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">Стварыць бурбалку</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">Фармаціраваць тэкст</string>
|
||||
@@ -4970,11 +4970,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">Дадаць у кантакты</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -5006,7 +5006,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">Новая група</string>
|
||||
<string name="text_secure_normal__menu_settings">Налады</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">Заблакаваць</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">Пазначыць усе як прачытаныя</string>
|
||||
<string name="text_secure_normal__invite_friends">Запрасіць сяброў</string>
|
||||
@@ -5052,7 +5052,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">Стварыць PIN-код з літараў і лічбаў</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">Стварыць лічбавы PIN-код</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -5090,7 +5090,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">Прадстаўляем PIN-коды</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">PIN-коды трымаюць інфармацыю, што захоўваецца ў Signal, зашыфраванай, таму толькі вы можаце атрымаць да яе доступ. Ваш профіль, налады і кантакты будуць адноўлены, калі вы зробіце паўторнае ўсталяванне. Вам не спатрэбіцца PIN-код, каб адкрыць праграму.</string>
|
||||
<string name="KbsSplashFragment__learn_more">Даведацца больш</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">Блакіроўка рэгістрацыі = PIN-код</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">«Блакіроўка рэгістрацыі» цяпер называецца «PIN-код», які ўмее значна больш. Абнавіце яго.</string>
|
||||
<string name="KbsSplashFragment__update_pin">Абнавіць PIN-код</string>
|
||||
@@ -5111,7 +5111,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">Ваш уліковы запіс быў заблакаваны, каб абараніць вашу канфідэнцыйнасць і бяспеку. Пасля %1$d дзён бяздзейнасці ў сваім уліковым запісе вы зможаце паўторна зарэгістраваць гэты нумар тэлефона без уводу PIN-кода. Увесь кантэнт будзе выдалены.</string>
|
||||
<string name="AccountLockedFragment__next">Далей</string>
|
||||
<string name="AccountLockedFragment__learn_more">Даведацца больш</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">Увядзіце свой PIN-код</string>
|
||||
@@ -5373,6 +5373,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">Не атрымалася выдаліць даныя</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Перанесці або аднавіць уліковы запіс</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">Калі вы раней ужо зарэгістравалі ўліковы запіс Signal, вы можаце перанесці або аднавіць як яго, так і свае паведамленні</string>
|
||||
@@ -5777,9 +5803,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">Калі вы маеце высокі баланс, можна абнавіць свой PIN-код на код з літараў і лічбаў, каб зрабіць ваш уліковы запіс яшчэ больш надзейным.</string>
|
||||
<string name="payment_info_card_update_pin">Абнавіць PIN-код</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">Дэактываваць кашалёк</string>
|
||||
@@ -5791,7 +5817,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">Дэактываваць без пераносу?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">Вашы сродкі застануцца ў вашым кашальку, што звязаны з Signal, і вы зможаце іх выкарыстоўваць, калі пазней зноў актывуеце плацяжы.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">Памылка падчас дэактывацыі кашалька.</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">Фраза для аднаўлення</string>
|
||||
@@ -5829,8 +5855,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">Несапраўдная фраза для аднаўлення</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">Праверце, што вы ўвялі %1$d слоў, і паўтарыце спробу.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">Далей</string>
|
||||
@@ -5875,7 +5901,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">Ні адзін з вашых кантактаў або людзей, з якімі вы размаўляеце ў чаце, не знаходзіцца ў гэтай групе. Перш чым прыняць запыт, уважліва праглядайце яго, каб пазбегнуць непажаданых паведамленняў.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">Аб запытах на перапіску</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">Добра</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">Гэта папярэдні прагляд колеру чата.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">Толькі вы можаце бачыць гэты колер.</string>
|
||||
|
||||
@@ -6273,7 +6299,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">Паказваць значок статусу</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">Паказваць значок у «Звесткі аб паведамленні», калі яны былі дастаўлены з дапамогай прыхаванага адпраўніка.</string>
|
||||
|
||||
@@ -6440,8 +6466,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">Знікаючыя паведамленні</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">Гукі & апавяшчэнні</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">Інфармацыя аб тэлефонным кантакце</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">Прагледзець код бяспекі</string>
|
||||
<string name="ConversationSettingsFragment__block">Заблакаваць</string>
|
||||
@@ -7305,39 +7331,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">Выдалiць %1$d гісторыю? Гэта нельга адмяніць.</item>
|
||||
@@ -8621,12 +8647,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Каб аднавіць рэзервовую копію, усталюйце новую копію Signal. Адкрыйце праграму і націсніце «Аднавіць рэзервовую копію», потым выберыце файл рэзервовай копіі."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">У вас уключана опцыя «Аптымізаваць сховішча Signal». Калі вы жадаеце ўключыць усе медыяфайлы ў рэзервовую копію на прыладзе, адключыце гэту опцыю.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Прагледзець налады</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Працягнуць, не выключаючы</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Праверце свой код для аднаўлення</string>
|
||||
@@ -9017,11 +9043,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">Аптымізацыю сховішча можна зрабіць толькі на платнай аснове бяспечнага рэзервовага капіравання Signal. Ваша падпіска на рэзервовае капіраванне яшчэ апрацоўваецца і пакуль не актыўная. Калі ласка, паўтарыце спробу пазней.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Медыяфайлы будуць выдалены з рэзервовай копіі на прыладзе</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Калі вы ўключыце опцыю «Аптымізаваць сховішча Signal», усе старыя медыяфайлы будуць выгружаны з прылады. Вы ў любы час можаце спампаваць іх нанова. Праз гэта таксама старыя медыяфайлы будуць выдалены з рэзервовай копіі на прыладзе.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Уключыць</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -9110,6 +9136,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Падпіска скасавана</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Аўтаматычнае рэзервовае капіраванне з дапамогай скразнога зашыфраванага сэрвісу захоўвання даных Signal.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"На гэтай прыладзе падпіска не знойдзена."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -9215,6 +9243,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s у %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Ніколі</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">Пачаць рэзервовае капіраванне</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9736,10 +9774,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Памылка сеткі падчас аднаўлення рэзервовай копіі Android Signal Android</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Пастаянны збой падчас аднаўлення рэзервовай копіі Signal Android</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">Увядзіце свой код для аднаўлення</string>
|
||||
@@ -9870,7 +9908,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Памылка сеткі падчас экспарту рэзервовай копіі Signal Android</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">Адправіць журнал адладкі?</string>
|
||||
@@ -9973,26 +10011,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">Проксі</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">Перайсці ўперад</string>
|
||||
@@ -10296,19 +10334,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Шукаць удзельнікаў</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Пошук кантактаў</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Пошук адміністратараў</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Адфільтраваць па</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Усе ўдзельнікі</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">Адміністратары</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Кантакты</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Запрасіць праз спасылку на групу</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">Не атрымалася аднавіць рэзервовую копію</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">Вълни</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">Signal се обновява…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">Създаване на нов ключ</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Назад</string>
|
||||
|
||||
@@ -448,7 +448,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Размерът на прикачения файл надминава допустимия лимит за типа съобщение, който изпращате.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">Не може да бъде записано аудио!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">Не може да изпращате съобщения на тази група, защото вече не сте неин член.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">Не можете да изпращате съобщения, защото групата е прекратена.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">Само %1$s могат да изпращат съобщения.</string>
|
||||
<string name="ConversationActivity_admins">администратори</string>
|
||||
@@ -616,7 +616,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Пререгистриране на Signal</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Свържете отново</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Връщане обратно.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1059,7 +1059,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">Съобщенията в Signal се синхронизират със Signal на мобилния ви телефон, след като бъде свързан. Предходната история на съобщенията ви няма да се появи.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">На устройството, което искате да свържете, посетете %1$s, за да инсталирате Signal</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">Моите свързани устройства</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1100,7 +1100,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">Отказ</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Неуспешно експортиране на Android (Link&Sync)</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">Неуспешно синхронизиране на съобщения</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1109,7 +1109,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">Устройството ви беше свързано успешно, но трансферът на съобщенията ви е неуспешен.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">Научете повече</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">Опитайте отново</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1254,7 +1254,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">Всеки член</string>
|
||||
<string name="GroupManagement_access_level_only_admins">Само администратори</string>
|
||||
<string name="GroupManagement_access_level_no_one">Никой</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1392,7 +1392,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">Продължете</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">Не, благодаря</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">Заявки и покани</string>
|
||||
@@ -1792,8 +1792,8 @@
|
||||
<string name="MediaOverviewActivity_audio">Аудио</string>
|
||||
<string name="MediaOverviewActivity_video">Видео</string>
|
||||
<string name="MediaOverviewActivity_image">Изображение</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">Изпратено от %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Изпратено от тебе</string>
|
||||
@@ -1827,13 +1827,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">Установяване на Signal разговор</string>
|
||||
@@ -2231,7 +2231,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">Присъединете се към тази група? Те няма да разберат, че сте виждали съобщенията им, докато не приемете.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">Отблокирайте тази група и споделете името и снимката си с членовете? Няма да получавате никакви съобщения, преди да ги отблокирате.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">Преглед</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">Член на %1$s</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">Член на %1$s и %2$s</string>
|
||||
@@ -2368,7 +2368,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">Създаване на ПИН</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">Изчерпали сте предположенията за ПИН, но все още можете да осъществите достъп до своя акаунт в Signal, като създадете нов ПИН. За вашата поверителност и сигурност акаунтът ви ще бъде възстановен без запазена информация за профила или настройки.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">Създайте нов ПИН</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">Изпращане на код чрез SMS</string>
|
||||
@@ -2888,15 +2888,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">Не са открити резултати за \'%1$s\'</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">Нищо не открихме</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">Добавяне към контакти</string>
|
||||
@@ -3048,28 +3048,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">Когато кликнете „Изпрати“, вашият регистър ще бъде качен онлайн за 30 дни на уникален, непубликуван URL адрес. Може преди това да го запазите локално.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">Филтър:</string>
|
||||
<string name="SupportEmailUtil_device_info">Информация за устройството:</string>
|
||||
<string name="SupportEmailUtil_android_version">Версия на Android:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">Регистрационно заключване:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">Групата е обновена</string>
|
||||
@@ -3229,10 +3229,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">ОК</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Съобщението е криптирано за несъществуаща сесия</string>
|
||||
@@ -3492,9 +3492,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Пререгистриране на устройство</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Това устройство вече не е свързано. Свържете Signal с телефона си отново, за да продължите да изпращате съобщения.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Повторно свързване на устройство</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">Вие сте излезли от Signal на това устройство.</string>
|
||||
@@ -3917,7 +3917,7 @@
|
||||
<string name="EditProfileFragment__edit_group">Промяна на групата</string>
|
||||
<string name="EditProfileFragment__group_name">Име на групата</string>
|
||||
<string name="EditProfileFragment__group_description">Описание на група</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Обновяване на Signal</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -3964,7 +3964,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">Автоматичната проверка не е достъпна</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">Автоматичната проверка не е достъпна за всички чатове.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">Криптирането беше автоматично проверено за този чат</string>
|
||||
@@ -3998,7 +3998,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">Изпращане</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">Неуспешна автоматична проверка на ключа</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">Научете повече</string>
|
||||
|
||||
@@ -4052,17 +4052,17 @@
|
||||
<string name="HelpFragment__whats_this">Какво е това?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">Как се чувствате? (По избор)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">Споделете защо се обръщате към нас.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">Информация за поддръжка</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Заявка за поддръжка на Signal за Android</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">Дневниците не можаха да се качат</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">Моля, бъдете възможно най-описателни, за да ни помогнете да разберем проблема.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4278,7 +4278,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">Ако индикаторите за писане са деактивирани, няма да можете да видите индикаторите на другите хора.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">Поискайте клавиатурата да деактивира персонализираното обучение.</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">Тази настройка не е гарантирана и клавиатурата ви може да я игнорира.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">Когато се използва мобилен интернет</string>
|
||||
<string name="preferences_chats__when_using_wifi">Когато се използва Wi-Fi</string>
|
||||
<string name="preferences_chats__when_roaming">Когато се използва роуминг</string>
|
||||
@@ -4391,9 +4391,9 @@
|
||||
<string name="configurable_single_select__customize_option">Опция за персонализиране</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4437,14 +4437,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">Плащанията бяха изключени.</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">Грешка при плащане</string>
|
||||
<string name="PaymentsHomeFragment__details">Подробности</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">Можете да използвате Signal за изпращане и получаване на MobileCoin. Всички плащания се ръководят от Условията за употреба на MobileCoins и Портфейла за MobileCoin. Може да срещнете проблеми и плащанията или балансите, които евентуално изгубите, няма да могат да бъдат възстановени. </string>
|
||||
<string name="PaymentsHomeFragment__activate">Включи</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">Вижте условията на MobileCoin</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Функцията за плащания в Signal вече не е налична. Пак можете да прехвърляте средства към борса, но вече не можете да изпращате и получавате плащания или да добавяте средства.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">Включете Заключване на плащанията за бъдещи изпращания?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4489,7 +4489,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">Копирай</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">Копирано</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">За да добавите средства, изпратете MobileCoin до адреса на своя портфейл. Започнете трансакция от акаунта си или от борса, която поддържа MobileCoin, след което сканирайте QR кода или копирайте адреса на портфейла си.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">Подробности</string>
|
||||
@@ -4510,8 +4510,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">Такса за почистване на монети</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">„Такса за почистване на монети“ се начислява, когато монетите във ваше притежание не могат да се комбинират за завършване на трансакция. Почистването ще ви позволи да продължите да изпращате плащания.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">Не са налични други данни за тази трансакция</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">Плащането беше изпратено</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">Плащането беше получено</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">Плащането е завършено %1$s</string>
|
||||
@@ -4556,7 +4556,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">Backspace</string>
|
||||
<string name="CreatePaymentFragment__add_note">Добавяне на бележка</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">Конверсиите са прогнозни и може да не са точни.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">Бележка</string>
|
||||
@@ -4638,9 +4638,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">Изтриване</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">Препращане</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4709,7 +4709,7 @@
|
||||
<string name="conversation__menu_view_all_media">Всички прикачените файлове</string>
|
||||
<string name="conversation__menu_conversation_settings">Настройки на чата</string>
|
||||
<string name="conversation__menu_add_shortcut">Добавяне на работния плот</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">Създаване на балон</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">Форматиране на текст</string>
|
||||
@@ -4720,11 +4720,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">Добавяне в контакти</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -4754,7 +4754,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">Нова група</string>
|
||||
<string name="text_secure_normal__menu_settings">Настройки</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">Заключи</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">Маркиране на всички като прочетени</string>
|
||||
<string name="text_secure_normal__invite_friends">Покани приятели</string>
|
||||
@@ -4800,7 +4800,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">Създайте буквено-цифров ПИН</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">Създайте цифров ПИН</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -4834,7 +4834,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">Представяме ПИН кодове</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">ПИН кодовете съхраняват информацията, съхранявана със Signal, криптирана, така че само вие да имате достъп до нея. Вашите профил, настройки и контакти ще се възстановят, когато преинсталирате. Няма да ви е необходим вашият ПИН, за да отворите приложението.</string>
|
||||
<string name="KbsSplashFragment__learn_more">Научи Още</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">Регистрационно заключване = ПИН</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">Вашето регистрационно заключване вече се нарича ПИН и върши повече неща. Актуализирайте го сега.</string>
|
||||
<string name="KbsSplashFragment__update_pin">Актуализирайте ПИН</string>
|
||||
@@ -4855,7 +4855,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">Вашият акаунт е заключен, за да защити вашата поверителност и сигурност. След %1$d дни на неактивност във вашия акаунт ще можете да пререгистрирате този телефонен номер, без да се нуждаете от своя ПИН. Цялото съдържание ще бъде изтрито.</string>
|
||||
<string name="AccountLockedFragment__next">Следващ</string>
|
||||
<string name="AccountLockedFragment__learn_more">Научи Още</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">Въведете своя ПИН</string>
|
||||
@@ -5107,6 +5107,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">Неуспешно изтриване на данни</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Прехвърли или възстанови акаунт</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">Ако преди сте регистрирали акаунт в Signal, можете да прехвърлите или възстановите акаунта си и съобщенията</string>
|
||||
@@ -5497,9 +5523,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">При висок баланс е препоръчително да въведете буквено-цифров PIN код, за да защитите акаунта си по-добре.</string>
|
||||
<string name="payment_info_card_update_pin">Актуализирайте ПИН</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">Деактивиране на портфейла</string>
|
||||
@@ -5511,7 +5537,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">Деактивиране без прехвърляне?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">Вашият баланс ще остане в портфейла ви, свързан със Signal, ако решите да активирате плащанията отново.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">Грешка при деактивирането на портфейла.</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">Фраза за възстановяване</string>
|
||||
@@ -5547,8 +5573,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">Невалидна фраза за възстановяване</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">Уверете се, че сте въвели %1$d думи, и опитайте отново.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">Напред</string>
|
||||
@@ -5593,7 +5619,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">Никой ваш контакт или лице, с което си пишете, не е в тази група. Прегледайте заявките внимателно, преди да приемете, за да избегнете нежелани съобщения.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">Относно заявки за съобщения</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">Добре</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">Ето преглед на цвета на чата.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">Цветът е видим само за вас.</string>
|
||||
|
||||
@@ -5973,7 +5999,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">Показване на икона за статуса</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">Показване на икона в подробностите за съобщенията, когато те са доставени със запечатан подател.</string>
|
||||
|
||||
@@ -6136,8 +6162,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">Изчезващи съобщения</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">Звуци и известия</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">Информация от контакта в телефона</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">Преглеждане на числото за сигурност</string>
|
||||
<string name="ConversationSettingsFragment__block">Блокиране</string>
|
||||
@@ -6983,39 +7009,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">Изтриване на %1$d история? Това не може да бъде отменено.</item>
|
||||
@@ -8245,12 +8271,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"За да възстановите резервно копие, инсталирайте ново копие на Signal. Отворете приложението и докоснете „Възстановяване на резервно копие“, след което открийте файла с резервното копие."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">„Оптимизация на хранилището на Signal“ е включено. Ако искате да включите всички мултимедийни файлове във вашето резервно копие на устройството, изключете настройката.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Преглед на настройката</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Продължаване без изключване</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Потвърдете своя ключ за възстановяване</string>
|
||||
@@ -8635,11 +8661,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">Оптимизацията на съхранението може да се използва само с платената версия на „Сигурни резервни копия на Signal“. Абонаментът ви за резервни копия все още се обработва и още не е активен. Моля, опитайте отново по-късно.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Мултимедийните файлове ще бъдат премахнати от вашето резервно копие на устройството</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Ако включите „Оптимизация на хранилището на Signal“, това ще разтовари старите мултимедийни файлове от вашето устройство. Можете да ги изтеглите отново по всяко време. Това също ще премахне старите мултимедийни файлове от вашето резервно копие на устройството.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Включване</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -8722,6 +8748,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Абонаментът е отменен</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Автоматични резервни копия, криптирани от край до край със защитената услуга за съхранение на Signal.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"Абонаментът не е открит на това устройство."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -8825,6 +8853,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s за %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Никога</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">Архивиране сега</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9336,10 +9374,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Мрежова грешка при възстановяване на резервно копие в Signal Android</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Перманентна грешка при възстановяване на резервно копие в Signal Android</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">Въведете своя ключ за възстановяване</string>
|
||||
@@ -9470,7 +9508,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Мрежова грешка при експортиране на резервно копие в Signal Android</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">Желаете ли да изпратите доклад за дебъг?</string>
|
||||
@@ -9573,26 +9611,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">Прокси</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">Навигиране нагоре</string>
|
||||
@@ -9888,19 +9926,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Търсене на членове</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Търсене на контакти</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Търсене на администратори</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Филтриране по</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Всички членове</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">Администратори</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Контакти</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Поканете чрез линк за групата</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">Неуспешно възстановяване на резервно копие</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">ঢেউ</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">সিগন্যাল আপডেট হচ্ছে…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">\'কি\' তৈরি করুন</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">ব্যাকস্পেস</string>
|
||||
|
||||
@@ -448,7 +448,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">আপনি যে বার্তা প্রেরণ করছেন সংযুক্তি তার আকারের সীমা অতিক্রম করেছে।</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">অডিও রেকর্ড করা যাচ্ছেনা!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">আপনি এই গ্রুপে বার্তা পাঠাতে পারবেন না কারন আপনি আর এই গ্রুপের সদস্য না</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">আপনি এই গ্রুপে মেসেজ পাঠাতে পারবেন না, কারণ এই গ্রুপটি বন্ধ হয়ে গিয়েছে।</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">কেবল %1$s বার্তা পাঠাতে পারবে।</string>
|
||||
<string name="ConversationActivity_admins">এডমিনগণ</string>
|
||||
@@ -616,7 +616,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">পুনরায় Signal-এ নিবন্ধন করুন</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">পুনরায় লিংক করুন</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">পিছনের দিকে নেভিগেট করুন।</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1059,7 +1059,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">এটি লিংক করার পর Signal মেসেজগুলো আপনার মোবাইল ফোনে Signal-এর সাথে সিঙ্ক করা হয়। আপনার পূর্ববর্তী মেসেজের ইতিহাস প্রদর্শিত হবে না।</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">আপনি যে ডিভাইসটি লিংক করতে চান তাতে Signal ইনস্টল করতে %1$s-এ যান</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">আমার লিংককৃত ডিভাইসসমূহ</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1100,7 +1100,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">বাতিল করুন</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Android Link&Sync এক্সপোর্ট ব্যর্থ হয়েছে</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">মেসেজ সিঙ্ক সফল হয়নি</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1109,7 +1109,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">আপনার ডিভাইস সফলভাবে লিঙ্ক করা হয়েছে, কিন্তু আপনার মেসেজ ট্রান্সফার করা যাচ্ছে না।</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">আরো জানুন</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">পুনরায় চেষ্টা করুন</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1254,7 +1254,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">সকল সদস্য</string>
|
||||
<string name="GroupManagement_access_level_only_admins">শুধু এডমিন</string>
|
||||
<string name="GroupManagement_access_level_no_one">কেউ না</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1392,7 +1392,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">চালিয়ে যান</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">না ধন্যবাদ</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">অনুরোধ & আমন্ত্রণ</string>
|
||||
@@ -1792,8 +1792,8 @@
|
||||
<string name="MediaOverviewActivity_audio">শব্দ</string>
|
||||
<string name="MediaOverviewActivity_video">ভিডিও</string>
|
||||
<string name="MediaOverviewActivity_image">ছবি</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">%1$s দ্বারা প্রেরিত</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">আপনার প্রেরিত</string>
|
||||
@@ -1827,13 +1827,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">Signal কল স্থাপন করা হচ্ছে</string>
|
||||
@@ -2231,7 +2231,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">এই গ্রুপে যোগ দেবেন? আপনি স্বীকার না করা পর্যন্ত তারা জানবেন না যে আপনি তাদের মেসেজ দেখেছেন।</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">এই গ্রুপটিকে আনব্লক করে এর সদস্যদের সাথে আপনার নাম ও ছবি শেয়ার করবেন? আপনি তাদের আনব্লক না করা পর্যন্ত কোন ম্যাসেজ পাবেন না।</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">দেখান</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">%1$sএর সদস্য</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">%1$s এবং %2$s এর সদস্য</string>
|
||||
@@ -2368,7 +2368,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">আপনার পিন তৈরি করুন</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">আপনার পিন অনুমান করার প্রচেষ্টার সংখ্যা শেষ হয়ে গেছে, কিন্তু আপনি একটি নতুন পিন তৈরি করে এখনও আপনার Signal অ্যাকাউন্টে প্রবেশ করতে পারবেন। আপনার অ্যাকাউন্টের গোপনীয়তা ও নিরাপত্তারর জন্য সেভ করে রাখা প্রোফাইলের তথ্য বা সেটিংস-এর তথ্য ছাড়াই আপনার অ্যাকাউন্টটি পুনর্বহাল করা হবে।</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">PIN তৈরি করুন</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">এসএমএস কোড পাঠান</string>
|
||||
@@ -2888,15 +2888,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">\'%1$s\' এর জন্য কোনও ফলাফল পাওয়া যায়নি</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">কোনও ফলাফল পাওয়া যায়নি</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">পরিচিতি যুক্ত করুন</string>
|
||||
@@ -3048,28 +3048,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">\'জমা দিন\' ক্লিক করলে, আপনার লগ অনলাইনে 30 দিনের জন্য একটি ইউনিক, অপ্রকাশিত ইউআরএল-এ পোস্ট করা হবে৷ আপনি প্রথমে স্থানীয়ভাবে এটি সেভ করতে পারেন।</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">ফিল্টার:</string>
|
||||
<string name="SupportEmailUtil_device_info">ডিভাইস-এর তথ্য:</string>
|
||||
<string name="SupportEmailUtil_android_version">অ্যান্ড্রয়েড সংস্করণ:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">রেজিস্ট্রেশন লক</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">গ্রুপ অাপডেট হয়েছে</string>
|
||||
@@ -3229,10 +3229,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">ঠিক আছে</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">অ-বিদ্যমান সেশনের জন্য বার্তা এনক্রিপ্ট করা হয়েছে</string>
|
||||
@@ -3492,9 +3492,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">ডিভাইসটি আবারো নিবন্ধন করুন</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">এই ডিভাইসটি আর সংযুক্ত নয়। ম্যাসেজ করা চালিয়ে যেতে আপনার ফোনের সাথে Signal আবারো সংযুক্ত করুন।</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">ডিভাইসটি আবারো সংযুক্ত করুন</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">আপনি এই ডিভাইসে Signal থেকে লগ আউট হয়ে গিয়েছেন।</string>
|
||||
@@ -3917,7 +3917,7 @@
|
||||
<string name="EditProfileFragment__edit_group">গ্রুপ সংশোধন করুন</string>
|
||||
<string name="EditProfileFragment__group_name">গ্রুপের নাম</string>
|
||||
<string name="EditProfileFragment__group_description">গ্রুপের বিবরণ</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Signal আপডেট করুন</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -3964,7 +3964,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">স্বয়ংক্রিয়-যাচাইকরণের সুবিধা নেই</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">সব চ্যাটের ক্ষেত্রে স্বয়ংক্রিয়-যাচাইকরণ সুবিধা নেই।</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">এই চ্যাটের ক্ষেত্রে এনক্রিপশন স্বয়ংক্রিয়ভাবে যাচাই করা হয়েছে</string>
|
||||
@@ -3998,7 +3998,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">সাবমিট</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">স্বয়ংক্রিয় \'কি\' যাচাইকরণ সফল হয়নি</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">আরো জানুন</string>
|
||||
|
||||
@@ -4052,17 +4052,17 @@
|
||||
<string name="HelpFragment__whats_this">এটা কী?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">আপনার অনুভূতি কী? (ঐচ্ছিক)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">কেন আপনি মেসেজ পাঠাচ্ছেন তা বলুন।</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">সহায়ক তথ্য</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Signal অ্যানড্রয়েড সহায়তা আবেদন</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">লগসমূহ আপলোড করা যায়নি</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">আমরা যাতে সমস্যাটি বুঝতে পারি সেজন্য যতটা সম্ভব বিস্তারিত বলুন।</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4278,7 +4278,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">যদি টাইপিং সূচকগুলি অক্ষম থাকে তবে আপনি অন্যের কাছ থেকে টাইপিং সূচকগুলি দেখতে সক্ষম হবেন না।</string>
|
||||
<string name="preferences__request_keyboard_to_disable">ঐকান্তিক শিক্ষাকে অক্ষম করতে কীবোর্ড কে অনুরোধ করুন।</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">এই সেটিংটি কোনও নিশ্চয়তা নয় এবং আপনার কীবোর্ড এটিকে এড়িয়ে যেতে পারে।</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">মোবাইল ডেটা ব্যবহার করার সময়</string>
|
||||
<string name="preferences_chats__when_using_wifi">ওয়াইফাই ব্যবহার করার সময়</string>
|
||||
<string name="preferences_chats__when_roaming">রোমিং করার সময়</string>
|
||||
@@ -4391,9 +4391,9 @@
|
||||
<string name="configurable_single_select__customize_option">বিকল্পগুলি কাস্টমাইজ করুন</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4437,14 +4437,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">পেমেন্ট বন্ধ করা হয়েছে।</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">পেমেন্ট ব্যর্থ হয়েছে</string>
|
||||
<string name="PaymentsHomeFragment__details">খুঁটিনাটি</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">আপনি MobileCoin পাঠাতে ও গ্রহণ করতে Signal ব্যবহার করতে পারেন। সকল পেমেন্ট MobileCoins ও MobileCoin ওয়ালেট ব্যবহারের শর্তাবলী মেনে সম্পাদিত হয়। আপনি কিছু কিছু সমস্যার সম্মুখীন হতে পারেন এবং আপনার হারানো পেমেন্ট বা ব্যালেন্স পুনরুদ্ধার করা যাবে না। </string>
|
||||
<string name="PaymentsHomeFragment__activate">সক্রিয় করুন</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">MobileCoin-এর শর্তাবলী দেখুন</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Signal-এ পেমেন্ট আর উপলভ্য নেই। আপনি এখনও কোনও এক্সচেঞ্জে আপনার ফান্ডগুলি ট্রান্সফার করতে পারেন তবে আপনি আর পেমেন্টগুলি প্রেরণ এবং গ্রহণ করতে বা ফান্ড যোগ করতে পারবেন না।</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">ভবিষ্যতে পাঠানোর জন্য পেমেন্ট লক চালু করবেন?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4489,7 +4489,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">অনুলিপি</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">ক্লিপবোর্ডে অনুলিপি করা হয়েছে</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">ফান্ড যোগ করতে আপনার ওয়ালেটের ঠিকানায় MobileCoin পাঠান। আপনার অ্যাকাউন্ট থেকে এমন কোনও লেনদেন শুরু করুন যা MobileCoin-কে সাপোর্ট করে, তারপরে QR কোডটি স্ক্যান করুন বা আপনার ওয়ালেটের ঠিকানাটি কপি করুন।</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">খুঁটিনাটি</string>
|
||||
@@ -4510,8 +4510,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">কয়েন ক্লিনআপ ফি</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">যখন আপনার দখলে থাকা কয়েন কোনও লেনদেন সম্পন্ন করার কাজে সংযুক্ত করা যাবে না, তখন “কয়েন ক্লিনআপ ফি” ধার্য করা হয়। ক্লিনআপের ফলে আপনি পেমেন্ট পাঠানো অব্যাহত রাখতে পারবেন।</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">এই লেনদেনের জন্য আর কোন বিস্তারিত বিবরণ নেই</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">পেমেন্ট পাঠানো হয়েছে</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">পেমেন্ট পেয়েছে</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">%1$s পেমেন্ট সম্পন্ন হয়েছে</string>
|
||||
@@ -4556,7 +4556,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">ব্যাকস্পেস</string>
|
||||
<string name="CreatePaymentFragment__add_note">নোট সংযুক্ত করুন</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">রূপান্তরগুলি অনুমান নির্ভর এবং সঠিক নাও হতে পারে।</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">নোট</string>
|
||||
@@ -4638,9 +4638,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">মুছে ফেলুন</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">ফরওয়ার্ড</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4709,7 +4709,7 @@
|
||||
<string name="conversation__menu_view_all_media">সমস্ত মিডিয়া</string>
|
||||
<string name="conversation__menu_conversation_settings">চ্যাট সেটিংস</string>
|
||||
<string name="conversation__menu_add_shortcut">হোম পর্দায় যোগ করুন</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">বাবল তৈরি করুন</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">টেক্সট ফরম্যাট করুন</string>
|
||||
@@ -4720,11 +4720,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">পরিচিতি তালিকায় যোগ করুন</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -4754,7 +4754,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">নতুন গ্রুপ</string>
|
||||
<string name="text_secure_normal__menu_settings">সেটিংস</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">লক্</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">সমস্ত পড়া হয়েছে চিহ্নিত করুন</string>
|
||||
<string name="text_secure_normal__invite_friends">বন্ধুদের আমন্ত্রণ</string>
|
||||
@@ -4800,7 +4800,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">বর্ণানুক্রমিক পিন তৈরি করুন</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">সংখ্যার পিন তৈরি করুন</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -4834,7 +4834,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">পিনের সাথে পরিচিত হন</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">পিনগুলি Signal -এ সঞ্চিত তথ্য এনক্রিপ্ট করে রাখে যাতে কেবল আপনি এটি অ্যাক্সেস করতে পারবেন। আপনি যখন পুনরায় ইনস্টল করবেন তখন আপনার প্রোফাইল, সেটিংস এবং পরিচিতিগুলি পুনরুদ্ধার করবে। অ্যাপটি খোলার জন্য আপনার পিনের দরকার হবে না।</string>
|
||||
<string name="KbsSplashFragment__learn_more">আরও জানুন</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">রেজিস্ট্রেশন লক = পিন</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">আপনার রেজিস্ট্রেশন লক এখন পিন নামে পরিচিত এবং এটি আরও অন্যান্য কাজ করে। এখনই এটি আপডেট করুন।</string>
|
||||
<string name="KbsSplashFragment__update_pin">পিন আপডেট করুন</string>
|
||||
@@ -4855,7 +4855,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">আপনার গোপনীয়তা এবং সুরক্ষা নিশ্চিত করতে আপনার অ্যাকাউন্টটি লক করা হয়েছে। আপনার অ্যাকাউন্টটি %1$d দিন নিষ্ক্রিয় থাকার পরে আপনি আপনার পিনের প্রয়োজন ছাড়াই এই ফোন নম্বরটি পুনরায় নিবন্ধন করতে সক্ষম হবেন। সকল বিষয়বস্তু মুছে ফেলা হবে।</string>
|
||||
<string name="AccountLockedFragment__next">পরবর্তী</string>
|
||||
<string name="AccountLockedFragment__learn_more">আরও জানুন</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">আপনার পিন প্রবেশ করান</string>
|
||||
@@ -5107,6 +5107,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">ডেটা মুছে ফেলা সফল হয়নি</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">অ্যাকাউন্ট ট্রান্সফার করুন বা পুনরুদ্ধার করুন</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">আপনি আগে একটি Signal অ্যাকাউন্টে রেজিস্টার করলে, আপনি আপনার অ্যাকাউন্ট বা মেসেজ ট্রান্সফার বা পুনরুদ্ধার করতে পারবেন</string>
|
||||
@@ -5497,9 +5523,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">বেশি ব্যালেন্সের ক্ষেত্রে আপনার অ্যাকাউন্টে অধিক সুরক্ষা যোগ করতে আপনি আলফানিউমেরি পিন-এ আপডেট করতে চাইতে পারেন।</string>
|
||||
<string name="payment_info_card_update_pin">পিন আপডেট করুন</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">ওয়ালেট বন্ধ করুন</string>
|
||||
@@ -5511,7 +5537,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">ট্রান্সফার না করেই বন্ধ করবেন?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">আপনি পেমেন্ট পুনরায় সক্রিয় করলে আপনার ব্যালান্স Signal-এর সাথে লিংককৃত ওয়ালেটে থাকবে।</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">ওয়ালেট বন্ধ করতে ত্রুটি।</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">রিকভার করার বাক্যাংশ</string>
|
||||
@@ -5547,8 +5573,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">রিকভারি ফ্রেজটি ভুল</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">আপনি যে %1$d শব্দটি লিখেছেন তা নিশ্চিত করে পুনরায় চেষ্টা করুন।</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">পরবর্তী</string>
|
||||
@@ -5593,7 +5619,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">আপনার কোনো কন্টাক্ট বা আপনি চ্যাট করেন এমন কেউ এই গ্রুপে নেই। অনাকাঙ্ক্ষিত ম্যাসেজ পাওয়া এড়াতে অনুরোধগুলো গ্রহণ করার আগে ভালোভাবে রিভিউ করুন।</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">মেসেজের অনুরোধ সম্পর্কে</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">ঠিক আছে</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">চ্যাটের রংয়ের একটি প্রিভিউ এখানে রয়েছে।</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">কেবলমাত্র আপনি রঙটি দেখতে পাবেন।</string>
|
||||
|
||||
@@ -5973,7 +5999,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">স্ট্যাটাস আইকন দেখান</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">সিল করা প্রেরকের মাধ্যমে কোন মেসেজ পাঠানো হলে মেসেজের বিস্তারিত বিবরণীতে একটি আইকন দেখান।</string>
|
||||
|
||||
@@ -6136,8 +6162,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">অদৃশ্য বার্তা</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">সাউন্ড & নোটিফিকেশন</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">ফোন কন্টাক্টের তথ্য</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">নিরাপত্তা নাম্বার দেখুন</string>
|
||||
<string name="ConversationSettingsFragment__block">ব্লক করুন</string>
|
||||
@@ -6983,39 +7009,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">%1$d-টি স্টোরি মুছে ফেলবেন? এটি পূর্বাবস্থায় ফেরানো যাবে না।</item>
|
||||
@@ -8245,12 +8271,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"ব্যাকআপ পুনর্বহাল করতে, Signal-এর একটি নতুন কপি ইনস্টল করুন। অ্যাপটি খুলুন ও ব্যাকআপ পুনর্বহাল করতে ট্যাপ করুন, তারপর ব্যাকআপ ফাইলটি শনাক্ত করুন।"</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">আপনার \"Signal স্টোরেজ অপ্টিমাইজ করুন\" চালু আছে। আপনি যদি আপনার ডিভাইসের ব্যাকআপে সব মিডিয়া অন্তর্ভুক্ত করতে চান, তাহলে সেটিংসটি বন্ধ করুন।</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">সেটিংস দেখুন</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">বন্ধ না করেই চালিয়ে যান</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">আপনার পুনরুদ্ধার \'কি\' যাচাই করুন</string>
|
||||
@@ -8635,11 +8661,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">স্টোরেজ অপ্টিমাইজেশন শুধুমাত্র Signal নিরাপদ ব্যাকআপের পেইড টিয়ারের ক্ষেত্রে ব্যবহার করা যেতে পারে। আপনার ব্যাকআপ সাবস্ক্রিপশন এখনো প্রক্রিয়া করা হচ্ছে এবং এখনো সক্রিয় নয়। অনুগ্রহ করে পরে আবার চেষ্টা করুন।</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">আপনার ডিভাইসের ব্যাকআপ থেকে মিডিয়া মুছে ফেলা হবে</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">\"Signal স্টোরেজ অপ্টিমাইজ করুন\" চালু করলে আপনার ডিভাইস থেকে পুরানো মিডিয়া অফলোড হয়ে যাবে। আপনি যেকোনো সময় এটি আবার ডাউনলোড করতে পারবেন। এটি আপনার ডিভাইসের ব্যাকআপ থেকে পুরোনো মিডিয়া ফাইলগুলোও মুছে ফেলবে।</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">চালু করুন</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -8722,6 +8748,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">সাবস্ক্রিপশন বাতিল করা হয়েছে</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Signal-এর সুরক্ষিত এন্ড-টু-এন্ড এনক্রিপ্ট করা স্টোরেজ পরিষেবা সহ স্বয়ংক্রিয় ব্যাকআপ।</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"এই ডিভাইসে সাবস্ক্রিপশন পাওয়া যায়নি।"</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -8825,6 +8853,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%2$s-তে %1$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">কখনোই না</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">এখনি ব্যাকআপ করুন</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9336,10 +9374,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Signal Android ব্যাকআপ পুনর্বহাল নেটওয়ার্কে ত্রুটি</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Signal Android ব্যাকআপ পুনর্বহালের স্থায়ী ব্যর্থতা</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">আপনার পুনরুদ্ধার \'কি\' লিখুন</string>
|
||||
@@ -9470,7 +9508,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Signal Android ব্যাকআপ এক্সপোর্টে নেটওয়ার্কে ত্রুটি দেখা দিয়েছে</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">ডিবাগ লগ জমা দেবেন?</string>
|
||||
@@ -9573,26 +9611,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">প্রক্সি</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">উপরে যাও</string>
|
||||
@@ -9888,19 +9926,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">সদস্য খুঁজুন</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">কন্টাক্ট খুঁজুন</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">অ্যাডমিনদের খুঁজুন</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">যার ভিত্তিতে ফিল্টার করবেন:</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">সকল সদস্য</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">অ্যাডমিন</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">পরিচিতিসমূহ</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">গ্রুপ লিংকের মাধ্যমে আমন্ত্রণ জানান</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">ব্যাকআপ পুনর্বহাল করা যায়নি</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">Valovi</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">Signal se ažurira …</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">Kreiraj ključ</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Backspace</string>
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">Veličina priloga veća je od dopuštene za vrstu poruke koju šaljete.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">Nije moguće snimiti zvuk!</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">Ne možete slati poruke ovoj grupi jer više niste njen član.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">Ne možete slati poruke jer je ova grupa okončana.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">Samo %1$s može slati poruke.</string>
|
||||
<string name="ConversationActivity_admins">administratori</string>
|
||||
@@ -642,7 +642,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Ponovo registrirajte Signal</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Ponovo poveži</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Navigiraj nazad.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -1113,7 +1113,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">Signal poruke se sinhronizuju sa Signalom na vašem mobilnom telefonu nakon što se poveže. Vaša prethodna historija poruka se neće pojaviti.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">Na uređaju koji želite povezati, posjetite %1$s da instalirate Signal</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">Moji povezani uređaji</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1154,7 +1154,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">Otkaži</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Android Link&Sync izvoz nije uspio</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">Sinhroniziranje poruka nije uspjelo</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1163,7 +1163,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">Vaš uređaj je uspješno povezan, ali vaše poruke se ne mogu prenijeti.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">Saznaj više</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">Pokušaj</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1310,7 +1310,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">Svi članovi</string>
|
||||
<string name="GroupManagement_access_level_only_admins">Samo administratori</string>
|
||||
<string name="GroupManagement_access_level_no_one">Niko</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1474,7 +1474,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">Nastavi</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">Ne, hvala</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">Zahtjevi i pozivnice</string>
|
||||
@@ -1902,8 +1902,8 @@
|
||||
<string name="MediaOverviewActivity_audio">Zvuk</string>
|
||||
<string name="MediaOverviewActivity_video">Video</string>
|
||||
<string name="MediaOverviewActivity_image">Slika</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">Poslao/la %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Vi ste poslali</string>
|
||||
@@ -1937,13 +1937,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">Uspostavljam Signal poziv</string>
|
||||
@@ -2361,7 +2361,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">Pristupiti ovoj grupi? Članovi neće znati da ste vidjeli njihove poruke dok ne prihvatite.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">Želite li odblokirati ovu grupu i dopustiti njenim članovima da vide vaše ime i sliku? Nećete primati poruke dok je ne odblokirate.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">Pregled</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">Član grupe %1$s</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">Član grupa %1$s i %2$s</string>
|
||||
@@ -2512,7 +2512,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">Kreirajte svoj PIN</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">Iskoristili ste sve pokušaje za unošenje PIN-a, ali i dalje možete pristupiti svom Signal računu kreiranjem novog PIN-a. Radi zaštite privatnosti i sigurnosti, Vaš će račun biti obnovljen, ali neće sadržavati stare informacije o profilu ili podešavanja.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">Kreiraj novi PIN</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">Pošaljite SMS kȏd</string>
|
||||
@@ -3076,15 +3076,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">Nema rezultata za \'%1$s\'</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">Nema rezultata</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">Dodaj među kontakte</string>
|
||||
@@ -3244,28 +3244,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">Kada kliknete Pošalji, vaš zapisnik će se objaviti online u trajanju od 30 dana na jedinstvenom, neobjavljenom URL-u. Možete ga najprije sačuvati lokalno.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">Filter:</string>
|
||||
<string name="SupportEmailUtil_device_info">Podaci o uređaju:</string>
|
||||
<string name="SupportEmailUtil_android_version">Verzija Androida:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">Zaključavanje registracije:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">Grupa ažurirana</string>
|
||||
@@ -3427,10 +3427,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">OK</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Poruka je šifrirana za nepostojeću sesiju</string>
|
||||
@@ -3704,9 +3704,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Ponovo registrirajte uređaj</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Ovaj uređaj više nije povezan. Ponovo povežite Signal s telefonom da nastavite slati poruke.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Ponovo poveži uređaj</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">Odjavljeni ste sa Signala na ovom uređaju.</string>
|
||||
@@ -4157,7 +4157,7 @@
|
||||
<string name="EditProfileFragment__edit_group">Uredi grupu</string>
|
||||
<string name="EditProfileFragment__group_name">Naziv grupe</string>
|
||||
<string name="EditProfileFragment__group_description">Opis grupe</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Ažurirajte Signal</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -4197,14 +4197,14 @@
|
||||
<!-- Button text to verify automatically -->
|
||||
<string name="verify_display_fragment__verify_automatic">Potvrdi automatski</string>
|
||||
<!-- Loading text when verifying -->
|
||||
<string name="verify_display_fragment__verifying">Potvrđivanje šifriranja...</string>
|
||||
<string name="verify_display_fragment__verifying">Potvrđivanje šifriranja…</string>
|
||||
<!-- Success text shown when encryption is verified -->
|
||||
<string name="verify_display_fragment__encryption_verified">Šifriranje je potvrđeno</string>
|
||||
<!-- Text shown when verification fails -->
|
||||
<string name="verify_display_fragment__encryption_unavailable">Automatska potvrda nije dostupna</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">Automatska potvrda nije dostupna za sve chatove.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">Šifriranje je automatski potvrđeno za ovaj chat</string>
|
||||
@@ -4238,7 +4238,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">Šalji</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">Automatska provjera ključa nije uspjela</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">Saznaj više</string>
|
||||
|
||||
@@ -4292,17 +4292,17 @@
|
||||
<string name="HelpFragment__whats_this">Šta je ovo?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">Kako se osjećate u vezi s ovim? (neobavezno)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">Kažite nam zašto tražite pomoć.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">Informacije o podršci</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Zahtjev za pomoć (Signal Android)</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">Neuspješan prenos zapisa</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">Molimo budite što detaljniji kako biste nam pomogli u razumijevanju problema.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4522,7 +4522,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">Ako je indikator kucanja isključen, nećete moći vidjeti indikator kucanja od drugih.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">Zahtijevaj od tastature da onemogući personalizovano učenje</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">Ovo podešavanje ipak nije garancija i tastatura ga može ignorisati.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">Prilikom korištenja mobilnog interneta</string>
|
||||
<string name="preferences_chats__when_using_wifi">Prilikom korištenja Wi-Fi konekcije</string>
|
||||
<string name="preferences_chats__when_roaming">Prilikom roaminga</string>
|
||||
@@ -4639,9 +4639,9 @@
|
||||
<string name="configurable_single_select__customize_option">Prilagodi</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4685,14 +4685,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">Plaćanja su deaktivirana.</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">Plaćanje nije uspjelo</string>
|
||||
<string name="PaymentsHomeFragment__details">Detalji</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">Signal možete koristiti za slanje i primanje MobileCoina. Sva plaćanja podliježu Uslovima korištenja za MobileCoins i MobileCoin Wallet. Možda ćete naići na neke probleme i uplate ili stanja koja možete izgubiti se ne mogu vratiti. </string>
|
||||
<string name="PaymentsHomeFragment__activate">Aktiviraj</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">Pregledaj uslove korištenja MobileCoina</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Plaćanja preko Signala više nisu dostupna. Još uvijek možete prenijeti sredstva na berzu, ali više ne možete vršiti isplate i uplate niti dodavati sredstva.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">Uključiti Osiguranje plaćanje za buduća slanja?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4737,7 +4737,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">Kopiraj</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">Kopirano u međuspremnik</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">Da dodate sredstva, pošaljite MobileCoin na adresu svoga novčanika. Započnite transakciju sa svoga računa na berzi koja podržava MobileCoin, potom skenirajte QR kōd ili kopirajte adresu svoga novčanika.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">Detalji</string>
|
||||
@@ -4758,8 +4758,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">Naknada za čišćenje novčića</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">“Naknada za čišćenje novčića” plaća se kad novčiće u Vašem vlasništvu nije moguće kombinovati da bi se izvršila transakcija. Čišćenje će Vam omogućiti da nastavite vršiti isplate.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">Nema dodatnih detalja o ovoj transakciji</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">Isplaćeno</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">Uplaćeno</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">Plaćanje izvršeno %1$s</string>
|
||||
@@ -4804,7 +4804,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">Backspace</string>
|
||||
<string name="CreatePaymentFragment__add_note">Dodaj napomenu</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">Konverzije su prikazane u približnim vrijednostima i ne moraju biti tačne.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">Napomena</string>
|
||||
@@ -4888,9 +4888,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">Izbriši</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">Proslijedi</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4959,7 +4959,7 @@
|
||||
<string name="conversation__menu_view_all_media">Svi prilozi</string>
|
||||
<string name="conversation__menu_conversation_settings">Postavke chata</string>
|
||||
<string name="conversation__menu_add_shortcut">Stavi na početni ekran</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">Kreiraj balončić</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">Formatiranje teksta</string>
|
||||
@@ -4970,11 +4970,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">Dodaj među kontakte</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -5006,7 +5006,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">Nova grupa</string>
|
||||
<string name="text_secure_normal__menu_settings">Podešavanja</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">Zaključaj</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">Sve označi kao pročitano</string>
|
||||
<string name="text_secure_normal__invite_friends">Pozovi prijatelje</string>
|
||||
@@ -5052,7 +5052,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">Kreiraj alfanumerički PIN</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">Kreiraj numerički PIN</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -5090,7 +5090,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">Novo: PIN-ovi</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">PIN služi za šifriranje informacija na Signalu tako da im samo Vi možete pristupiti. Vaš profil, podešavanja i kontakti bit će sačuvani i učitani kad ponovo instalirate Signal. PIN Vam neće trebati da otvorite aplikaciju.</string>
|
||||
<string name="KbsSplashFragment__learn_more">Saznaj više</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">Zaključavanje registracije = PIN</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">Vaš ključ za zaključavanje registracije sada se naziva PIN i on vrši dodatne funkcije. Izvršite nadogradnju odmah.</string>
|
||||
<string name="KbsSplashFragment__update_pin">Ažurirajte PIN</string>
|
||||
@@ -5111,7 +5111,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">Vaš je račun zaključan kako bi se zaštitila Vaša privatnost i sigurnost. Nakon %1$d dana neaktivnosti računa moći ćete se ponovo registrovati pomoću ovoga broja telefona a bez PIN-a. Sav raniji sadržaj računa bit će izbrisan.</string>
|
||||
<string name="AccountLockedFragment__next">Dalje</string>
|
||||
<string name="AccountLockedFragment__learn_more">Saznaj više</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">Unesite svoj PIN</string>
|
||||
@@ -5373,6 +5373,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">Brisanje podataka nije uspjelo</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Prenesi ili vrati račun</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">Ako imate odranije registrovan Signal račun, možete prenijeti ili vratiti svoj račun i poruke</string>
|
||||
@@ -5777,9 +5803,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">Sa visokim iznosom sredstava, možda ćete htjeti ažurirati PIN i koristiti alfanumeričke znakove kako biste povećali zaštitu svoga računa.</string>
|
||||
<string name="payment_info_card_update_pin">Ažurirajte PIN</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">Deaktivirajte novčanik</string>
|
||||
@@ -5791,7 +5817,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">Deaktivirati bez prenosa sredstava?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">Vaša će sredstva ostati u vašem novčaniku povezanom sa Signalom, ako odlučite ponovo aktivirati plaćanja.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">Greška prilikom deaktiviranja novčanika.</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">Fraza za obnavljanje</string>
|
||||
@@ -5829,8 +5855,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">Pogrešna fraza za obnavljanje</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">Potvrdite da ste unijeli %1$d riječi i pokušajte ponovo.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">Dalje</string>
|
||||
@@ -5875,7 +5901,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">Nijedan vaš kontakt niti osobe s kojima komunicirate nisu članovi ove grupe. Pažljivo pregledajte zahtjeve prije nego što ih prihvatite kako biste izbjegli neželjene poruke.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">O zahtjevima za komunikaciju</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">Uredu</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">Ovako izgleda boja poruke.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">Boja je prikazana samo za Vas.</string>
|
||||
|
||||
@@ -6273,7 +6299,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">Prikaži sličicu statusa</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">Prikaži sličicu u detaljima o poruci kad je poruka isporučena koristeći opciju zapečaćenog pošiljaoca</string>
|
||||
|
||||
@@ -6440,8 +6466,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">Nestajuće poruke</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">Zvuk i obavještenja</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">Kontakt podaci telefona</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">Vidi sigurnosni broj</string>
|
||||
<string name="ConversationSettingsFragment__block">Blokiraj</string>
|
||||
@@ -7305,39 +7331,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">Izbrisati %1$d priču? Ova radnja se ne može opozvati.</item>
|
||||
@@ -8621,12 +8647,12 @@
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Da biste vratili sigurnosnu kopiju, instalirajte novu kopiju Signala. Otvorite aplikaciju i dodirnite Vrati sigurnosnu kopiju, a zatim pronađite folder sigurnosne kopije."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">Uključena je opcija \"Optimiziraj pohranu Signala\". Ako želite uključiti sve medijske sadržaje u sigurnosnu kopiju na uređaju, isključite ovu postavku.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Prikaži postavku</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Nastavi bez isključivanja</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Potvrdite svoj ključ za oporavak</string>
|
||||
@@ -9017,11 +9043,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">Optimizacija pohrane može se koristiti samo s plaćenim nivoom usluge Signal Secure Backups. Vaša pretplata na sigurnosne kopije se još uvijek obrađuje i još nije aktivna. Pokušajte ponovo kasnije.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Medijski sadržaji će biti uklonjeni iz sigurnosne kopije na uređaju.</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Uključivanjem opcije \"Optimiziraj pohranu Signala\" stari medijski sadržaji bit će uklonjeni s uređaja. Možete ga ponovo preuzeti u bilo kojem trenutku. Time će se stari medijski sadržaji ukloniti i iz sigurnosne kopije na uređaju.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Uključi</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -9110,6 +9136,8 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Pretplata je otkazana</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Automatsko kreiranje rezervnih kopija sa Signalovim sigurnom sveobuhvatnom uslugom pohranjivanja.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"Pretplata nije pronađena na ovom uređaju."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
@@ -9215,6 +9243,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s u %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Nikad</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">Kreiraj kopiju sada</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -9736,10 +9774,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Greška mreže vraćanja sigurnosne kopije za Signal Android</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Trajna greška u vraćanju sigurnosne kopije za Signal Android</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">Unesite svoj ključ za oporavak</string>
|
||||
@@ -9870,7 +9908,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Greška mreže vraćanja sigurnosne kopije za Signal Android</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">Pošalji zapisnik o otklanjanju grešaka?</string>
|
||||
@@ -9973,26 +10011,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">Proxy</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">Prema gore</string>
|
||||
@@ -10296,19 +10334,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Pretraži članove</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Pretraži kontakte</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Pretraži administratore</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Filtriraj po</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Svi članovi</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">Administratori</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Kontakti</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Pozovi putem linka grupe</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">Nije moguće vratiti sigurnosnu kopiju</string>
|
||||
|
||||
@@ -5,25 +5,25 @@
|
||||
-->
|
||||
<!-- smartling.instruction_comments_enabled = on -->
|
||||
<resources>
|
||||
<string name="app_name" translatable="false">Signal</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="app_name" translatable="false">Signal</string> -->
|
||||
|
||||
<string name="install_url" translatable="false">https://signal.org/install</string>
|
||||
<string name="donate_url" translatable="false">https://signal.org/donate</string>
|
||||
<string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string>
|
||||
<string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string>
|
||||
<string name="support_center_url" translatable="false">https://support.signal.org/</string>
|
||||
<string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string>
|
||||
<string name="google_pay_url" translatable="false">https://pay.google.com</string>
|
||||
<string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string>
|
||||
<string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string>
|
||||
<string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string>
|
||||
<string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string>
|
||||
<string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string>
|
||||
<string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string>
|
||||
<string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string>
|
||||
<string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string>
|
||||
<string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="install_url" translatable="false">https://signal.org/install</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_url" translatable="false">https://signal.org/donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="backup_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="remote_backup_support_url" translatable="false">https://support.signal.org/hc/articles/9708267671322</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="transfer_support_url" translatable="false">https://support.signal.org/hc/articles/360007059752</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="support_center_url" translatable="false">https://support.signal.org/</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="terms_and_privacy_policy_url" translatable="false">https://signal.org/legal</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="google_pay_url" translatable="false">https://pay.google.com</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donation_decline_code_error_url" translatable="false">https://support.signal.org/hc/articles/4408365318426#errors</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="sms_export_url" translatable="false">https://support.signal.org/hc/articles/360007321171</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="signal_me_username_url" translatable="false">https://signal.me/#u/%1$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="username_support_url" translatable="false">https://support.signal.org/hc/articles/5389476324250</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="export_account_data_url" translatable="false">https://support.signal.org/hc/articles/5538911756954</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="pending_transfer_url" translatable="false">https://support.signal.org/hc/articles/360031949872#pending</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="donate_faq_url" translatable="false">https://support.signal.org/hc/articles/360031949872#donate</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="inactive_primary_support" translatable="false">https://support.signal.org/hc/articles/9021007554074</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="recovery_key_phishing_support_url" translatable="false">https://support.signal.org/hc/articles/9932566320410</string> -->
|
||||
|
||||
<!-- First placeholder is productId, second placeholder is app package -->
|
||||
<string name="backup_subscription_management_url">https://play.google.com/store/account/subscriptions?sku=%1$s&package=%2$s</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<string name="app_icon_label_waves">Ones</string>
|
||||
|
||||
<!-- AlbumThumbnailView -->
|
||||
<string name="AlbumThumbnailView_plus" translatable="false">\+%d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AlbumThumbnailView_plus" translatable="false">\+%d</string> -->
|
||||
|
||||
<!-- ApplicationMigrationActivity -->
|
||||
<string name="ApplicationMigrationActivity__signal_is_updating">El Signal s\'actualitza…</string>
|
||||
@@ -70,16 +70,16 @@
|
||||
<string name="AdvancedPinSettingsFragment_rotate_aep_dialog_positive_button">Crea una clau</string>
|
||||
|
||||
<!-- NumericKeyboardView -->
|
||||
<string name="NumericKeyboardView__1" translatable="false">1</string>
|
||||
<string name="NumericKeyboardView__2" translatable="false">2</string>
|
||||
<string name="NumericKeyboardView__3" translatable="false">3</string>
|
||||
<string name="NumericKeyboardView__4" translatable="false">4</string>
|
||||
<string name="NumericKeyboardView__5" translatable="false">5</string>
|
||||
<string name="NumericKeyboardView__6" translatable="false">6</string>
|
||||
<string name="NumericKeyboardView__7" translatable="false">7</string>
|
||||
<string name="NumericKeyboardView__8" translatable="false">8</string>
|
||||
<string name="NumericKeyboardView__9" translatable="false">9</string>
|
||||
<string name="NumericKeyboardView__0" translatable="false">0</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__1" translatable="false">1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__2" translatable="false">2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__3" translatable="false">3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__4" translatable="false">4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__5" translatable="false">5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__6" translatable="false">6</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__7" translatable="false">7</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__8" translatable="false">8</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__9" translatable="false">9</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="NumericKeyboardView__0" translatable="false">0</string> -->
|
||||
<!-- Back button on numeric keyboard -->
|
||||
<string name="NumericKeyboardView__backspace">Retrocés</string>
|
||||
|
||||
@@ -448,7 +448,7 @@
|
||||
<string name="ConversationActivity_attachment_exceeds_size_limits">El fitxer adjunt excedeix la mida màxima per a aquest tipus de missatges.</string>
|
||||
<string name="ConversationActivity_unable_to_record_audio">No s\'ha pogut enregistrar l\'àudio.</string>
|
||||
<string name="ConversationActivity_you_cant_send_messages_to_this_group">No podeu enviar missatges a aquest grup perquè ja no en sou membre.</string>
|
||||
<string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DisabledInputView__incognito_mode" translatable="false">Incognito mode (Labs)</string> -->
|
||||
<string name="ConversationActivity_you_cant_send_messages_because_group_ended">No pots enviar missatges perquè aquest grup s\'ha tancat.</string>
|
||||
<string name="ConversationActivity_only_s_can_send_messages">Només els %1$s poden enviar missatges.</string>
|
||||
<string name="ConversationActivity_admins">administradors</string>
|
||||
@@ -616,7 +616,7 @@
|
||||
<!-- Action shown to allow a user to re-register as they are no longer registered -->
|
||||
<string name="ConversationFragment__reregister_signal">Torna a registrar Signal</string>
|
||||
<!-- Action shown in the conversation input area to allow a user to re-link this device as it is no longer linked -->
|
||||
<string name="ConversationFragment__relink_signal">Re-link</string>
|
||||
<string name="ConversationFragment__relink_signal">Torna a enllaçar</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to return to the previous screen. -->
|
||||
<string name="ConversationFragment__content_description_back_button">Tornar enrere.</string>
|
||||
<!-- Label for a button displayed in the conversation toolbar to open the main screen of the app. -->
|
||||
@@ -930,9 +930,9 @@
|
||||
<!-- Remote media restoration paused status title. -->
|
||||
<string name="RestoreMediaReminder__Restoring_media_paused">La restauració dels arxius s s\'ha interromput</string>
|
||||
<!-- Remote media restoration paused status description for when the restore is paused because unmetered connectivity, such as WiFi, is unavailable. -->
|
||||
<string name="RestoreMediaReminder__Waiting_for_Wifi">Esperant el WiFi...</string>
|
||||
<string name="RestoreMediaReminder__Waiting_for_Wifi">Esperant el WiFi…</string>
|
||||
<!-- Remote media restoration paused status description for when the restore is paused because internet is unavailable. -->
|
||||
<string name="RestoreMediaReminder__Waiting_for_internet_connection">Esperant la connexió a Internet...</string>
|
||||
<string name="RestoreMediaReminder__Waiting_for_internet_connection">Esperant la connexió a Internet…</string>
|
||||
<!-- Remote media restoration paused status description for when the device\'s battery is low -->
|
||||
<string name="RestoreMediaReminder__low_battery">Bateria baixa. Carrega el teu dispositiu.</string>
|
||||
<!-- Remote media restoration call to action when the device is out of space. The placeholder string is a file size, such as "1.23 GB". -->
|
||||
@@ -952,7 +952,7 @@
|
||||
<string name="BackupsPreferenceFragment__test_your_backup_passphrase">Proveu la contrasenya de còpia de seguretat i verifiqueu que coincideix.</string>
|
||||
<string name="BackupsPreferenceFragment__turn_on">Activar les còpies de seguretat</string>
|
||||
<string name="BackupsPreferenceFragment__turn_off">Desactiva</string>
|
||||
<string name="BackupsPreferenceFragment__to_restore_a_backup">"Per restaurar una còpia de seguretat, instal·leu una còpia del Signal. Obriu l'aplicació i toqueu Restaura la còpia de seguretat. Indiqueu el fitxer de còpia de seguretat. %1$s"</string>
|
||||
<string name="BackupsPreferenceFragment__to_restore_a_backup">"Per restaurar una còpia de seguretat, instal·leu una còpia del Signal. Obriu l\'aplicació i toqueu Restaura la còpia de seguretat. Indiqueu el fitxer de còpia de seguretat. %1$s"</string>
|
||||
<string name="BackupsPreferenceFragment__learn_more">Més informació</string>
|
||||
<string name="BackupsPreferenceFragment__in_progress">En curs…</string>
|
||||
<!-- Status text shown in backup preferences when verifying a backup -->
|
||||
@@ -1059,7 +1059,7 @@
|
||||
<string name="LinkDeviceFragment__signal_messages_are_synchronized">Els missatges de Signal se sincronitzaran amb l\'app al teu telèfon un cop l\'hagis vinculat. L\'historial de missatges anteriors no apareixerà.</string>
|
||||
<!-- Bottom sheet description explaining that for non-desktop/iPad devices, they should go to %s to download Signal where %s is Signal\'s website -->
|
||||
<string name="LinkDeviceFragment__on_other_device_visit_signal">En l\'altre dispositiu que vols vincular, ves a %1$s per instal·lar Signal</string>
|
||||
<string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__signal_download_url" translatable="false">signal.org/download</string> -->
|
||||
<!-- Header title listing out current linked devices -->
|
||||
<string name="LinkDeviceFragment__my_linked_devices">Els meus dispositius connectats</string>
|
||||
<!-- Dialog confirmation to unlink a device -->
|
||||
@@ -1073,7 +1073,7 @@
|
||||
<!-- Toast message shown after a device has been linked -->
|
||||
<string name="LinkDeviceFragment__device_approved">Dispositiu aprovat</string>
|
||||
<!-- Progress dialog message indicating that the list of linked devices is currently loading -->
|
||||
<string name="LinkDeviceFragment__loading">Carregant...</string>
|
||||
<string name="LinkDeviceFragment__loading">Carregant…</string>
|
||||
<!-- Progress dialog message indicating that you are syncing messages to your linked device -->
|
||||
<string name="LinkDeviceFragment__syncing_messages">Sincronitzant missatges…</string>
|
||||
<!-- Text message shown when the user has no linked devices -->
|
||||
@@ -1100,7 +1100,7 @@
|
||||
<string name="LinkDeviceFragment__cancel">Cancel·lar</string>
|
||||
<!-- Email subject when contacting support on a linked device syncing issue -->
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email">Error en l\'exportació d\'Android Link&Sync</string>
|
||||
<string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__link_sync_failure_support_email_filter" translatable="false">Android Link&Sync Export Failed</string> -->
|
||||
<!-- Title of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
<string name="LinkDeviceFragment__sync_failure_title">La sincronització de missatges ha fallat</string>
|
||||
<!-- Body of a dialog letting the user know that syncing messages to their linked device failed -->
|
||||
@@ -1109,7 +1109,7 @@
|
||||
<string name="LinkDeviceFragment__sync_failure_body_unretryable">El dispositiu s\'ha enllaçat amb èxit, però els teus missatges no s\'han pogut transferir.</string>
|
||||
<!-- Text button in a dialog that, when pressed, will redirect to the Signal support page -->
|
||||
<string name="LinkDeviceFragment__learn_more">Més informació</string>
|
||||
<string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="LinkDeviceFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007320551</string> -->
|
||||
<!-- Text button of a button in a dialog that, when pressed, will restart the process of linking a device -->
|
||||
<string name="LinkDeviceFragment__sync_failure_retry_button">Torna a provar-ho</string>
|
||||
<!-- Text button of a button in a dialog that, when pressed, will ignore syncing errors and link a new device without syncing message content -->
|
||||
@@ -1254,7 +1254,7 @@
|
||||
<string name="GroupManagement_access_level_all_members">Tots els membres</string>
|
||||
<string name="GroupManagement_access_level_only_admins">Només els administradors</string>
|
||||
<string name="GroupManagement_access_level_no_one">Cap</string>
|
||||
<string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupManagement_access_level_unknown" translatable="false">Unknown</string> -->
|
||||
<array name="GroupManagement_edit_group_membership_choices">
|
||||
<item>@string/GroupManagement_access_level_all_members</item>
|
||||
<item>@string/GroupManagement_access_level_only_admins</item>
|
||||
@@ -1392,7 +1392,7 @@
|
||||
<string name="PromptBatterySaverBottomSheet__continue">Continuar</string>
|
||||
<!-- Button to dismiss battery saver dialog prompt-->
|
||||
<string name="PromptBatterySaverBottomSheet__no_thanks">No, gràcies.</string>
|
||||
<string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PromptBatterySaverBottomSheet__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007318711#android_notifications_troubleshooting</string> -->
|
||||
|
||||
<!-- PendingMembersActivity -->
|
||||
<string name="PendingMembersActivity_pending_group_invites">Sol·licituds i invitacions</string>
|
||||
@@ -1419,8 +1419,8 @@
|
||||
<string name="RequestingMembersFragment_pending_member_requests">Sol·licituds d\'adhesió pendents</string>
|
||||
<string name="RequestingMembersFragment_no_member_requests_to_show">No hi ha cap sol·licitud d\'adhesió per mostrar.</string>
|
||||
<string name="RequestingMembersFragment_explanation">La gent d\'aquesta llista intenta afegir-se a aquest grup per l\'enllaç del grup.</string>
|
||||
<string name="RequestingMembersFragment_added_s">"S'hi ha afegit %1$s"</string>
|
||||
<string name="RequestingMembersFragment_denied_s">"S'ha rebutjat %1$s"</string>
|
||||
<string name="RequestingMembersFragment_added_s">"S\'hi ha afegit %1$s"</string>
|
||||
<string name="RequestingMembersFragment_denied_s">"S\'ha rebutjat %1$s"</string>
|
||||
|
||||
<!-- AddMembersActivity -->
|
||||
<string name="AddMembersActivity__done">Fet</string>
|
||||
@@ -1792,8 +1792,8 @@
|
||||
<string name="MediaOverviewActivity_audio">Àudio</string>
|
||||
<string name="MediaOverviewActivity_video">Vídeo</string>
|
||||
<string name="MediaOverviewActivity_image">Imatge</string>
|
||||
<string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string>
|
||||
<string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_2_part" translatable="false">%1$s · %2$s</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="MediaOverviewActivity_detail_line_3_part" translatable="false">%1$s · %2$s · %3$s</string> -->
|
||||
|
||||
<string name="MediaOverviewActivity_sent_by_s">Enviat per %1$s</string>
|
||||
<string name="MediaOverviewActivity_sent_by_you">Ho heu enviat</string>
|
||||
@@ -1827,13 +1827,13 @@
|
||||
|
||||
<!-- StarredMessagesFragment -->
|
||||
<!-- Title for the starred messages screen -->
|
||||
<string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesActivity__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Empty state text when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__no_starred_messages" translatable="false">No starred messages</string> -->
|
||||
<!-- Empty state description when there are no starred messages -->
|
||||
<string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessagesFragment__tap_and_hold_on_a_message_to_star_it" translatable="false">Tap and hold on a message to star it.</string> -->
|
||||
<!-- Format for starred message source label, e.g. "Alice › Book Club" -->
|
||||
<string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StarredMessages__s_chevron_s" translatable="false">%1$s \u203A %2$s</string> -->
|
||||
|
||||
<!-- NotificationBarManager -->
|
||||
<string name="NotificationBarManager__establishing_signal_call">S\'estableix la trucada del Signal</string>
|
||||
@@ -2231,7 +2231,7 @@
|
||||
<!-- Shown when you are invited to a group and explains that until you accept the invitation to the group, members will not know that you have seen their messages. -->
|
||||
<string name="MessageRequestBottomView_join_this_group_they_wont_know_youve_seen_their_messages_until_you_accept">Voleu afegir-vos a aquest grup? No sabran que n\'heu vist els missatges fins que no ho accepteu.</string>
|
||||
<string name="MessageRequestBottomView_unblock_this_group_and_share_your_name_and_photo_with_its_members">Vols desbloquejar aquest grup i compartir el nom i la fotografia amb els seus membres? No rebràs cap missatge fins que no el desbloquegis.</string>
|
||||
<string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MessageRequestBottomView_legacy_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="MessageRequestProfileView_view">Mostra</string>
|
||||
<string name="MessageRequestProfileView_member_of_one_group">Membre de %1$s</string>
|
||||
<string name="MessageRequestProfileView_member_of_two_groups">Membre de %1$s i %2$s</string>
|
||||
@@ -2368,7 +2368,7 @@
|
||||
<string name="PinRestoreLockedFragment_create_your_pin">Creeu el PIN</string>
|
||||
<string name="PinRestoreLockedFragment_youve_run_out_of_pin_guesses">Se us han acabat els intents del PIN, però encara podeu accedir al compte del Signal creant un PIN nou. Per a la vostra privadesa i seguretat, el compte es restaurarà sense cap tipus d\'informació ni configuració de perfil.</string>
|
||||
<string name="PinRestoreLockedFragment_create_new_pin">Crea un PIN nou</string>
|
||||
<string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PinRestoreLockedFragment_learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- Dialog button text indicating user wishes to send an sms code isntead of skipping it -->
|
||||
<string name="ReRegisterWithPinFragment_send_sms_code">Enviar codi per SMS</string>
|
||||
@@ -2888,15 +2888,15 @@
|
||||
<!-- Search -->
|
||||
<string name="SearchFragment_no_results">No s\'ha trobat cap resultat per a «%1$s»</string>
|
||||
<!-- Text shown when no search results are found. -->
|
||||
<string name="SearchFragment_no_results_empty">No results found</string>
|
||||
<string name="SearchFragment_no_results_empty">No s\'ha trobat cap resultat.</string>
|
||||
|
||||
<!-- ShakeToReport -->
|
||||
<string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string>
|
||||
<string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string>
|
||||
<string name="ShakeToReport_submit" translatable="false">Submit</string>
|
||||
<string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string>
|
||||
<string name="ShakeToReport_success" translatable="false">Success!</string>
|
||||
<string name="ShakeToReport_share" translatable="false">Share</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_shake_detected" translatable="false">Shake detected</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit_debug_log" translatable="false">Submit debug log?</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_submit" translatable="false">Submit</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_failed_to_submit" translatable="false">Failed to submit :(</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_success" translatable="false">Success!</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ShakeToReport_share" translatable="false">Share</string> -->
|
||||
|
||||
<!-- SharedContactDetailsActivity -->
|
||||
<string name="SharedContactDetailsActivity_add_to_contacts">Afegeix als contactes</string>
|
||||
@@ -3048,28 +3048,28 @@
|
||||
<!-- Banner message shown while submitting debug log -->
|
||||
<string name="SubmitDebugLogActivity_your_log_will_be_posted_online">Quan cliqueu a Envia, el registre es penjarà en línia durant 30 dies en un URL únic i no publicat. Primer podeu desar-lo localment.</string>
|
||||
<!-- Debug log level names to filter by levels. -->
|
||||
<string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string>
|
||||
<string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string>
|
||||
<string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string>
|
||||
<string name="SubmitDebugLogActivity_info" translatable="false">Info</string>
|
||||
<string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string>
|
||||
<string name="SubmitDebugLogActivity_error" translatable="false">Error</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_signal_uncaught_exception" translatable="false">Uncaught</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_verbose" translatable="false">Verbose</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_debug" translatable="false">Debug</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_info" translatable="false">Info</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_warning" translatable="false">Warn</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_error" translatable="false">Error</string> -->
|
||||
<!-- Title of dialog shown when debug log prefix generation is unusually slow -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_title" translatable="false">Slow log generation</string> -->
|
||||
<!-- Body of dialog shown when debug log prefix generation is unusually slow. %1$d is duration in seconds. -->
|
||||
<string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SubmitDebugLogActivity_slow_log_message" translatable="false">Generating the debug log header took %1$d seconds. We should figure out what\'s slowing things down.</string> -->
|
||||
|
||||
<!-- SupportEmailUtil -->
|
||||
<string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_support_email" translatable="false">support@signal.org</string> -->
|
||||
<string name="SupportEmailUtil_filter">Filtre:</string>
|
||||
<string name="SupportEmailUtil_device_info">Informació del dispositiu:</string>
|
||||
<string name="SupportEmailUtil_android_version">Versió d\'Android:</string>
|
||||
<string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string>
|
||||
<string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_version" translatable="false">Signal version:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_signal_package" translatable="false">Signal package:</string> -->
|
||||
<string name="SupportEmailUtil_registration_lock">Bloqueig de registre:</string>
|
||||
<string name="SupportEmailUtil_locale" translatable="false">Locale:</string>
|
||||
<string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string>
|
||||
<string name="SupportEmailUtil_registered" translatable="false">Registered:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_locale" translatable="false">Locale:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_challenge_received" translatable="false">Challenge Received:</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="SupportEmailUtil_registered" translatable="false">Registered:</string> -->
|
||||
|
||||
<!-- ThreadRecord -->
|
||||
<string name="ThreadRecord_group_updated">S\'ha actualitzat el grup</string>
|
||||
@@ -3229,10 +3229,10 @@
|
||||
<string name="VerifyDisplayFragment__scan_result_dialog_ok">D\'acord</string>
|
||||
|
||||
<!-- ViewOnceMessageActivity -->
|
||||
<string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ViewOnceMessageActivity_video_duration" translatable="false">%1$02d:%2$02d</string> -->
|
||||
|
||||
<!-- AudioView -->
|
||||
<string name="AudioView_duration" translatable="false">%1$d:%2$02d</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AudioView_duration" translatable="false">%1$d:%2$02d</string> -->
|
||||
|
||||
<!-- MessageDisplayHelper -->
|
||||
<string name="MessageDisplayHelper_message_encrypted_for_non_existing_session">Missatge encriptat per a una sessió que no existeix</string>
|
||||
@@ -3492,9 +3492,9 @@
|
||||
<!-- Action in reminder banner that will take user to re-register -->
|
||||
<string name="UnauthorizedReminder_reregister_action">Tornar a registrar dispositiu</string>
|
||||
<!-- Message shown in a reminder banner when this linked device is no longer linked to a primary device -->
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">This device is no longer linked. Re-link Signal with your phone to continue messaging.</string>
|
||||
<string name="UnauthorizedReminder_this_device_is_no_longer_linked_relink_to_continue_messaging">Aquest dispositiu ja no està enllaçat. Torna a enllaçar Signal amb el teu telèfon per continuar enviant missatges.</string>
|
||||
<!-- Action in reminder banner that will take the user to re-link this device -->
|
||||
<string name="UnauthorizedReminder_relink_action">Re-link device</string>
|
||||
<string name="UnauthorizedReminder_relink_action">Tornar a enllaçar dispositiu</string>
|
||||
|
||||
<!-- Push notification when the app is forcibly logged out by the server. -->
|
||||
<string name="LoggedOutNotification_you_have_been_logged_out">S\'ha tancat la teva sessió de Signal en aquest dispositiu.</string>
|
||||
@@ -3585,7 +3585,7 @@
|
||||
<string name="ContactSelectionListFragment_signal_requires_the_contacts_permission_in_order_to_display_your_contacts">El Signal necessita el permís de l\'aplicació dels contactes per tal de mostrar-ne els vostres, però s\'ha denegat permanentment. Si us plau, continueu cap al menú de configuració de l\'aplicació, seleccioneu Permisos i activeu-hi els contactes.</string>
|
||||
<string name="ContactSelectionListFragment_error_retrieving_contacts_check_your_network_connection">Error en recuperar els contactes. Comproveu la connexió de xarxa.</string>
|
||||
<string name="ContactSelectionListFragment_username_not_found">No s\'ha trobat l\'àlies.</string>
|
||||
<string name="ContactSelectionListFragment_s_is_not_a_signal_user">"%1$s no és un usuari del Signal. Si us plau, comproveu-ne l'àlies i torneu-ho a provar."</string>
|
||||
<string name="ContactSelectionListFragment_s_is_not_a_signal_user">"%1$s no és un usuari del Signal. Si us plau, comproveu-ne l\'àlies i torneu-ho a provar."</string>
|
||||
<string name="ContactSelectionListFragment_you_do_not_need_to_add_yourself_to_the_group">No cal que us afegiu al grup.</string>
|
||||
<string name="ContactSelectionListFragment_maximum_group_size_reached">S\'ha assolit la mida màxima del grup.</string>
|
||||
<string name="ContactSelectionListFragment_signal_groups_can_have_a_maximum_of_s_members">Els grups del Signal poden tenir un màxim de %1$s membres.</string>
|
||||
@@ -3917,7 +3917,7 @@
|
||||
<string name="EditProfileFragment__edit_group">Edita el grup</string>
|
||||
<string name="EditProfileFragment__group_name">Nom del grup</string>
|
||||
<string name="EditProfileFragment__group_description">Descripció del grup</string>
|
||||
<string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EditProfileFragment__support_link" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<!-- The title of a dialog prompting user to update to the latest version of Signal. -->
|
||||
<string name="EditProfileFragment_deprecated_dialog_title">Actualitza el Signal</string>
|
||||
<!-- The body of a dialog prompting user to update to the latest version of Signal. -->
|
||||
@@ -3964,7 +3964,7 @@
|
||||
<string name="verify_display_fragment__encryption_unavailable">La verificació automàtica no està disponible</string>
|
||||
<!-- Caption text explaining more about automatic verification -->
|
||||
<string name="verify_display_fragment__auto_verify_not_available">La verificació automàtica no està disponible per a tots els xats.</string>
|
||||
<string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="verify_display_fragment__link" translatable="false">https://support.signal.org/hc/articles/10223569377562</string> -->
|
||||
|
||||
<!-- Bottom sheet title when encryption is auto-verified -->
|
||||
<string name="EncryptionVerifiedSheet__title_success">La codificació d\'aquest xat s\'ha verificat automàticament</string>
|
||||
@@ -3998,7 +3998,7 @@
|
||||
<string name="SelfVerificationFailureSheet__submit">Envia</string>
|
||||
<!-- Email subject line when submitting logs following a verification failure -->
|
||||
<string name="SelfVerificationFailureSheet__email_subject">Error de verificació automàtica de claus</string>
|
||||
<string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SelfVerificationFailureSheet__email_filter" translatable="false">AutomaticKeyVerificationFailure</string> -->
|
||||
<!-- Link to learn more about debug logs -->
|
||||
<string name="SelfVerificationFailureSheet__learn_more">Més informació</string>
|
||||
|
||||
@@ -4052,17 +4052,17 @@
|
||||
<string name="HelpFragment__whats_this">Què és això?</string>
|
||||
<string name="HelpFragment__how_do_you_feel">Com us sentiu? (opcional)</string>
|
||||
<string name="HelpFragment__tell_us_why_youre_reaching_out">Expliqueu-nos per què us poseu en contacte.</string>
|
||||
<string name="HelpFragment__emoji_5" translatable="false">emoji_5</string>
|
||||
<string name="HelpFragment__emoji_4" translatable="false">emoji_4</string>
|
||||
<string name="HelpFragment__emoji_3" translatable="false">emoji_3</string>
|
||||
<string name="HelpFragment__emoji_2" translatable="false">emoji_2</string>
|
||||
<string name="HelpFragment__emoji_1" translatable="false">emoji_1</string>
|
||||
<string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string>
|
||||
<string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_5" translatable="false">emoji_5</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_4" translatable="false">emoji_4</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_3" translatable="false">emoji_3</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_2" translatable="false">emoji_2</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__emoji_1" translatable="false">emoji_1</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__debug_info" translatable="false">https://support.signal.org/hc/articles/360007318591</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__link__faq" translatable="false">https://support.signal.org</string> -->
|
||||
<!-- Heading used within support email that lists additional information to help with debugging -->
|
||||
<string name="HelpFragment__support_info">Informació de suport</string>
|
||||
<string name="HelpFragment__signal_android_support_request">Petició de suport de Signal d\'Android</string>
|
||||
<string name="HelpFragment__debug_log" translatable="false">Debug Log:</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="HelpFragment__debug_log" translatable="false">Debug Log:</string> -->
|
||||
<string name="HelpFragment__could_not_upload_logs">No s\'han pogut carregar els registres.</string>
|
||||
<string name="HelpFragment__please_be_as_descriptive_as_possible">Si us plau, expliqueu-ho de la manera més descriptiva possible per ajudar-nos a entendre el problema.</string>
|
||||
<!-- Error shown under the "tell us what\'s going on" field when the entered description is shorter than the required minimum length. The placeholder is the minimum number of characters. -->
|
||||
@@ -4278,7 +4278,7 @@
|
||||
<string name="preferences__if_typing_indicators_are_disabled_you_wont_be_able_to_see_typing_indicators">Si els indicadors de tecleig estan desactivats, no podreu veure els indicadors de tecleig dels altres.</string>
|
||||
<string name="preferences__request_keyboard_to_disable">Sol·licita un teclat per desactivar l\'aprenentatge personalitzat.</string>
|
||||
<string name="preferences__this_setting_is_not_a_guarantee">Aquesta opció de configuració no és una garantia i és possible que el teclat l’ignori.</string>
|
||||
<string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__incognito_keyboard_learn_more" translatable="false">https://support.signal.org/hc/articles/360055276112</string> -->
|
||||
<string name="preferences_chats__when_using_mobile_data">En usar dades mòbils</string>
|
||||
<string name="preferences_chats__when_using_wifi">En usar Wi-Fi</string>
|
||||
<string name="preferences_chats__when_roaming">En itinerància</string>
|
||||
@@ -4391,9 +4391,9 @@
|
||||
<string name="configurable_single_select__customize_option">Opció de personalització</string>
|
||||
|
||||
<!-- Internal only preferences -->
|
||||
<string name="preferences__internal_preferences" translatable="false">Internal Preferences</string>
|
||||
<string name="preferences__internal_details" translatable="false">Internal Details</string>
|
||||
<string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_preferences" translatable="false">Internal Preferences</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_details" translatable="false">Internal Details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="preferences__internal_stories_dialog_launcher" translatable="false">Stories dialog launcher</string> -->
|
||||
|
||||
|
||||
<!-- Payments -->
|
||||
@@ -4437,14 +4437,14 @@
|
||||
<string name="PaymentsHomeFragment__payments_deactivated">Pagaments desactivats</string>
|
||||
<string name="PaymentsHomeFragment__payment_failed">Ha fallat el pagament.</string>
|
||||
<string name="PaymentsHomeFragment__details">Detalls</string>
|
||||
<string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__learn_more__activate_payments" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_activate</string> -->
|
||||
<!-- Displayed as a description in a dialog when the user tries to activate payments -->
|
||||
<string name="PaymentsHomeFragment__you_can_use_signal_to_send_and">Pots fer servir Signal per enviar i rebre MobileCoin. Tots els pagaments estan subjectes a les Condicions d\'ús de MobileCoins i MobileCoin Wallet. És possible que tinguis algun problema, i els pagaments o fons que perdis no podran ser recuperats. </string>
|
||||
<string name="PaymentsHomeFragment__activate">Activa\'ls</string>
|
||||
<string name="PaymentsHomeFragment__view_mobile_coin_terms">Vegeu els termes de MobileCoin</string>
|
||||
<string name="PaymentsHomeFragment__payments_not_available">Els pagaments al Signal ja no estan disponibles. Encara podeu transferir fons a un intercanvi, però ja no podeu enviar ni rebre pagaments ni afegir-hi fons.</string>
|
||||
|
||||
<string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsHomeFragment__mobile_coin_terms_url" translatable="false">https://www.mobilecoin.com/terms-of-use.html</string> -->
|
||||
<!-- Alert dialog title which shows up after a payment to turn on payment lock -->
|
||||
<string name="PaymentsHomeFragment__turn_on">Vols activar el bloqueig de pagament per a futurs enviaments?</string>
|
||||
<!-- Alert dialog description for why payment lock should be enabled before sending payments -->
|
||||
@@ -4489,7 +4489,7 @@
|
||||
<string name="PaymentsAddMoneyFragment__copy">Copia</string>
|
||||
<string name="PaymentsAddMoneyFragment__copied_to_clipboard">Copiat al porta-retalls</string>
|
||||
<string name="PaymentsAddMoneyFragment__to_add_funds">Per afegir-hi fons, envieu MobileCoin a la vostra adreça de cartera. Inicieu una transacció des del compte amb un intercanvi que admeti MobileCoin i, a continuació, escaneu el codi QR o copieu la vostra adreça de cartera.</string>
|
||||
<string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsAddMoneyFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
|
||||
<!-- PaymentsDetailsFragment -->
|
||||
<string name="PaymentsDetailsFragment__details">Detalls</string>
|
||||
@@ -4510,8 +4510,8 @@
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_fee">Comissió de neteja de monedes</string>
|
||||
<string name="PaymentsDetailsFragment__coin_cleanup_information">Es cobra una comissió de neteja de monedes quan les monedes que teniu no es poden combinar per completar una transacció. La neteja us permetrà continuar enviant pagaments.</string>
|
||||
<string name="PaymentsDetailsFragment__no_details_available">No hi ha més detalls disponibles per a aquesta transacció.</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string>
|
||||
<string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__information" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsDetailsFragment__learn_more__cleanup_fee" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_details_fees</string> -->
|
||||
<string name="PaymentsDetailsFragment__sent_payment">Pagament enviat</string>
|
||||
<string name="PaymentsDetailsFragment__received_payment">Pagament rebut</string>
|
||||
<string name="PaymentsDeatilsFragment__payment_completed_s">Pagament fet: %1$s</string>
|
||||
@@ -4556,7 +4556,7 @@
|
||||
<string name="CreatePaymentFragment__backspace">Retrocés</string>
|
||||
<string name="CreatePaymentFragment__add_note">Afegeix-hi una nota</string>
|
||||
<string name="CreatePaymentFragment__conversions_are_just_estimates">Les conversions són només estimacions i és possible que no siguin exactes.</string>
|
||||
<string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="CreatePaymentFragment__learn_more__conversions" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_currency_conversion</string> -->
|
||||
|
||||
<!-- EditNoteFragment -->
|
||||
<string name="EditNoteFragment_note">Nota</string>
|
||||
@@ -4638,9 +4638,9 @@
|
||||
<!-- Button to delete a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_delete">Esborrar</string>
|
||||
<!-- Button to star a message to save it for later; Action item -->
|
||||
<string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_star" translatable="false">Star (Labs)</string> -->
|
||||
<!-- Button to remove the star from a message; Action item -->
|
||||
<string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_selection__menu_unstar" translatable="false">Unstar (Labs)</string> -->
|
||||
<!-- Button to forward a message to another person or group chat; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
<string name="conversation_selection__menu_forward">Reenvia</string>
|
||||
<!-- Button to reply to a message; Action item with hyphenation. Translation can use soft hyphen - Unicode U+00AD -->
|
||||
@@ -4709,7 +4709,7 @@
|
||||
<string name="conversation__menu_view_all_media">Tot el contingut</string>
|
||||
<string name="conversation__menu_conversation_settings">Ajustos del xat</string>
|
||||
<string name="conversation__menu_add_shortcut">Afegeix a la pantalla d\'inici</string>
|
||||
<string name="conversation__menu_export" translatable="false">Export (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation__menu_export" translatable="false">Export (Labs)</string> -->
|
||||
<string name="conversation__menu_create_bubble">Crea una bombolla</string>
|
||||
<!-- Overflow menu option that allows formatting of text -->
|
||||
<string name="conversation__menu_format_text">Format del text</string>
|
||||
@@ -4720,11 +4720,11 @@
|
||||
<string name="conversation_add_to_contacts__menu_add_to_contacts">Afegeix als contactes</string>
|
||||
|
||||
<!-- conversation export -->
|
||||
<string name="conversation_export__exporting" translatable="false">Exporting chat…</string>
|
||||
<string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string>
|
||||
<string name="conversation_export__export_failed" translatable="false">Export failed</string>
|
||||
<string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string>
|
||||
<string name="conversation_export__preparing" translatable="false">Preparing export…</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__exporting" translatable="false">Exporting chat…</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_complete" translatable="false">Chat exported successfully</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_failed" translatable="false">Export failed</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__export_cancelled" translatable="false">Export cancelled</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="conversation_export__preparing" translatable="false">Preparing export…</string> -->
|
||||
|
||||
<!-- conversation scheduled messages bar -->
|
||||
|
||||
@@ -4754,7 +4754,7 @@
|
||||
<string name="text_secure_normal__menu_new_group">Grup nou</string>
|
||||
<string name="text_secure_normal__menu_settings">Configuració</string>
|
||||
<!-- Menu item in the main conversation list to view all starred messages -->
|
||||
<string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="text_secure_normal__starred_messages" translatable="false">Starred messages (Labs)</string> -->
|
||||
<string name="text_secure_normal__menu_clear_passphrase">Bloca</string>
|
||||
<string name="text_secure_normal__mark_all_as_read">Marca-ho tot com a llegit</string>
|
||||
<string name="text_secure_normal__invite_friends">Convideu-hi amistats</string>
|
||||
@@ -4800,7 +4800,7 @@
|
||||
<string name="BaseKbsPinFragment__create_alphanumeric_pin">Creeu un PIN alfanumèric</string>
|
||||
<!-- Button label to prompt them to return to creating a numbers-only password ("PIN") -->
|
||||
<string name="BaseKbsPinFragment__create_numeric_pin">Creeu un PIN numèric</string>
|
||||
<string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BaseKbsPinFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- CreateKbsPinFragment -->
|
||||
<plurals name="CreateKbsPinFragment__pin_must_be_at_least_characters">
|
||||
@@ -4834,7 +4834,7 @@
|
||||
<string name="KbsSplashFragment__introducing_pins">S\'introdueixen els PIN</string>
|
||||
<string name="KbsSplashFragment__pins_keep_information_stored_with_signal_encrypted">Els PIN mantenen encriptada la informació desada amb el Signal de manera que no hi pugui accedir ningú més. El perfil, la configuració i els contactes es restauraran quan el reinstal·leu. No necessitareu el PIN per obrir l\'aplicació.</string>
|
||||
<string name="KbsSplashFragment__learn_more">Més informació</string>
|
||||
<string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="KbsSplashFragment__learn_more_link" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
<string name="KbsSplashFragment__registration_lock_equals_pin">Bloqueig de registre = PIN</string>
|
||||
<string name="KbsSplashFragment__your_registration_lock_is_now_called_a_pin">El bloqueig de registre ara s\'anomena PIN i serveix per a molt més. Actualitzeu-lo ara.</string>
|
||||
<string name="KbsSplashFragment__update_pin">Actualitza el PIN</string>
|
||||
@@ -4855,7 +4855,7 @@
|
||||
<string name="AccountLockedFragment__your_account_has_been_locked_to_protect_your_privacy">Hem blocat el compte per protegir la vostra privadesa i seguretat. Al cap de %1$d dies d’inactivitat, podreu tornar a registrar aquest número de telèfon sense necessitar el PIN. Se n\'esborrarà tot el contingut.</string>
|
||||
<string name="AccountLockedFragment__next">Següent</string>
|
||||
<string name="AccountLockedFragment__learn_more">Més informació</string>
|
||||
<string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AccountLockedFragment__learn_more_url" translatable="false">https://support.signal.org/hc/articles/360007059792</string> -->
|
||||
|
||||
<!-- KbsLockFragment -->
|
||||
<string name="RegistrationLockFragment__enter_your_pin">Marqueu el PIN</string>
|
||||
@@ -5107,6 +5107,32 @@
|
||||
<!-- Error message shown when we fail to delete the data for some unknown reason -->
|
||||
<string name="preferences_account_delete_all_data_failed">No s\'han pogut eliminar les dades</string>
|
||||
|
||||
<!-- LinkedDeviceAccountSettingsFragment -->
|
||||
<!-- Title of an informational card shown on the account settings screen of a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_is_a_linked_device">This is a linked device</string>
|
||||
<!-- Body of an informational card explaining that account settings must be managed from the primary device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__to_manage_your_account_settings">To manage your account settings, open Signal on your primary device.</string>
|
||||
<!-- Title of a settings row that deletes all Signal data from this linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data">Delete app data</string>
|
||||
<!-- Subtitle of the delete app data row explaining what it does -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_remove_all_data">This will remove all data from the Signal app on this device.</string>
|
||||
<!-- Title of the confirmation dialog shown when deleting app data from a linked device -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__delete_app_data_question">Delete app data?</string>
|
||||
<!-- Message of the confirmation dialog explaining that only this device\'s data is deleted, not the account -->
|
||||
<string name="LinkedDeviceAccountSettingsFragment__this_will_delete_all_data_and_messages">This will delete all data and messages from the Signal app on this device. Your Signal account and data on your primary device or other linked devices will not be deleted. The app will close after this process is complete.</string>
|
||||
|
||||
<!-- LinkedDeviceAccountLearnMoreBottomSheet -->
|
||||
<!-- Emphasized lead-in phrase shown in bold at the start of the learn more sheet body. Must appear verbatim within LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices">Linked Devices</string>
|
||||
<!-- Body text of the linked devices learn more sheet. The leading \"Linked Devices\" is shown in bold. -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__linked_devices_let_you_access">Linked Devices let you access your Signal account and messages securely on any of your additional devices.</string>
|
||||
<!-- Bullet point describing what devices can be linked -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__you_can_link_a_desktop">You can link a desktop, tablet or additional phone</string>
|
||||
<!-- Bullet point describing that the primary device manages linked devices -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__your_primary_device_manages">Your primary device manages what\'s linked, you can link up to 5 devices.</string>
|
||||
<!-- Bullet point describing that some settings are only available on the primary device -->
|
||||
<string name="LinkedDeviceAccountLearnMoreBottomSheet__some_account_settings">Some account settings are managed on your primary device only, including account settings and backups.</string>
|
||||
|
||||
<!-- TransferOrRestoreFragment -->
|
||||
<string name="TransferOrRestoreFragment__transfer_or_restore_account">Transfereix o restaura el compte</string>
|
||||
<string name="TransferOrRestoreFragment__if_you_have_previously_registered_a_signal_account">Si prèviament heu registrat un compte del Signal, podeu transferir o restaurar el compte i els missatges.</string>
|
||||
@@ -5497,9 +5523,9 @@
|
||||
<string name="payment_info_card_with_a_high_balance">Amb un saldo elevat, és possible que vulgueu passar a un PIN alfanumèric per afegir més protecció al compte.</string>
|
||||
<string name="payment_info_card_update_pin">Actualitza el PIN</string>
|
||||
|
||||
<string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string>
|
||||
<string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string>
|
||||
<string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__about_mobilecoin" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_which_ones</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__adding_to_your_wallet" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_from_exchange</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="payment_info_card__learn_more__cashing_out" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_transfer_to_exchange</string> -->
|
||||
|
||||
<!-- DeactivateWalletFragment -->
|
||||
<string name="DeactivateWalletFragment__deactivate_wallet">Desactiva la cartera</string>
|
||||
@@ -5511,7 +5537,7 @@
|
||||
<string name="DeactivateWalletFragment__deactivate_without_transferring_question">Voleu desactivar els fons sense transferir-los?</string>
|
||||
<string name="DeactivateWalletFragment__your_balance_will_remain">El saldo es mantindrà a la cartera enllaçada amb Signal si decideixes reactivar els pagaments.</string>
|
||||
<string name="DeactivateWalletFragment__error_deactivating_wallet">Error en desactivar la cartera</string>
|
||||
<string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="DeactivateWalletFragment__learn_more__we_recommend_transferring_your_funds" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_deactivate</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryStartFragment -->
|
||||
<string name="PaymentsRecoveryStartFragment__recovery_phrase">Frase de recuperació</string>
|
||||
@@ -5547,8 +5573,8 @@
|
||||
<string name="PaymentsRecoveryPasteFragment__invalid_recovery_phrase">Frase de recuperació no vàlida</string>
|
||||
<string name="PaymentsRecoveryPasteFragment__make_sure">Assegureu-vos que heu introduït %1$d paraules i torneu-ho a provar.</string>
|
||||
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string>
|
||||
<string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__view" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_view_passphrase</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="PaymentsRecoveryStartFragment__learn_more__restore" translatable="false">https://support.signal.org/hc/articles/360057625692#payments_wallet_restore_passphrase</string> -->
|
||||
|
||||
<!-- PaymentsRecoveryPhraseFragment -->
|
||||
<string name="PaymentsRecoveryPhraseFragment__next">Següent</string>
|
||||
@@ -5593,7 +5619,7 @@
|
||||
<string name="GroupsInCommonMessageRequest__none_of_your_contacts_or_people_you_chat_with_are_in_this_group">Cap dels teus contactes o persones amb qui xateges forma part d\'aquest grup. Revisa les sol·licituds amb atenció abans d’acceptar-les per evitar missatges no desitjats.</string>
|
||||
<string name="GroupsInCommonMessageRequest__about_message_requests">Quant a les sol·licituds de missatges</string>
|
||||
<string name="GroupsInCommonMessageRequest__okay">D\'acord</string>
|
||||
<string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="GroupsInCommonMessageRequest__support_article" translatable="false">https://support.signal.org/hc/articles/360007459591</string> -->
|
||||
<string name="ChatColorSelectionFragment__heres_a_preview_of_the_chat_color">Aquí tens una previsualització del color del xat.</string>
|
||||
<string name="ChatColorSelectionFragment__the_color_is_visible_to_only_you">El color només el veieu vós.</string>
|
||||
|
||||
@@ -5973,7 +5999,7 @@
|
||||
<!-- Alert dialog button to cancel the dialog -->
|
||||
|
||||
<!-- AdvancedPrivacySettingsFragment -->
|
||||
<string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="AdvancedPrivacySettingsFragment__sealed_sender_link" translatable="false">https://signal.org/blog/sealed-sender</string> -->
|
||||
<string name="AdvancedPrivacySettingsFragment__show_status_icon">Mostra la icona d\'estat</string>
|
||||
<string name="AdvancedPrivacySettingsFragment__show_an_icon">Mostra una icona als detalls del missatge quan es lliuri mitjançant un remitent segellat.</string>
|
||||
|
||||
@@ -6136,8 +6162,8 @@
|
||||
<string name="ConversationSettingsFragment__disappearing_messages">Missatges efímers</string>
|
||||
<string name="ConversationSettingsFragment__sounds_and_notifications">Sons i notificacions</string>
|
||||
<!-- Label for the starred messages option in conversation settings -->
|
||||
<string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string>
|
||||
<string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__starred_messages" translatable="false">Starred messages</string> -->
|
||||
<!-- Removed by excludeNonTranslatables <string name="ConversationSettingsFragment__internal_details" translatable="false">Internal details</string> -->
|
||||
<string name="ConversationSettingsFragment__contact_details">Informació de contacte del telèfon</string>
|
||||
<string name="ConversationSettingsFragment__view_safety_number">Mostra el número de seguretat</string>
|
||||
<string name="ConversationSettingsFragment__block">Bloquejar</string>
|
||||
@@ -6193,7 +6219,7 @@
|
||||
<!-- Warning title shown before restricting member labels to admins only. -->
|
||||
<string name="PermissionsSettingsFragment__member_labels_will_be_cleared_title">S\'eliminaran les categories de membres</string>
|
||||
<!-- Warning body shown before restricting member labels to admins only. -->
|
||||
<string name="PermissionsSettingsFragment__member_labels_will_be_cleared_body">"Si canvies aquest permís a Només admins, s'eliminaran les categories de membres establertes pels no administradors d'aquest grup."</string>
|
||||
<string name="PermissionsSettingsFragment__member_labels_will_be_cleared_body">"Si canvies aquest permís a Només admins, s\'eliminaran les categories de membres establertes pels no administradors d\'aquest grup."</string>
|
||||
<!-- Confirm button for changing member label permission after warning. -->
|
||||
<string name="PermissionsSettingsFragment__change_permission">Canviar permís</string>
|
||||
|
||||
@@ -6983,39 +7009,39 @@
|
||||
|
||||
<!-- StoryArchive -->
|
||||
<!-- Title for the story archive screen -->
|
||||
<string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__story_archive" translatable="false">Story archive (Labs)</string> -->
|
||||
<!-- Section header in story settings -->
|
||||
<string name="StoryArchive__archive" translatable="false">Archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__archive" translatable="false">Archive</string> -->
|
||||
<!-- Label for switch to enable story archiving -->
|
||||
<string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_in_archive" translatable="false">Keep stories in archive</string> -->
|
||||
<!-- Description for the archive toggle -->
|
||||
<string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__save_stories_after_they_expire" translatable="false">Save your sent stories after they leave the active feed.</string> -->
|
||||
<!-- Label for archive duration preference -->
|
||||
<string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__keep_stories_for" translatable="false">Keep stories for</string> -->
|
||||
<!-- Archive duration option: forever -->
|
||||
<string name="StoryArchive__forever" translatable="false">Forever</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__forever" translatable="false">Forever</string> -->
|
||||
<!-- Archive duration option: 1 year -->
|
||||
<string name="StoryArchive__1_year" translatable="false">1 year</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__1_year" translatable="false">1 year</string> -->
|
||||
<!-- Archive duration option: 6 months -->
|
||||
<string name="StoryArchive__6_months" translatable="false">6 months</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__6_months" translatable="false">6 months</string> -->
|
||||
<!-- Archive duration option: 30 days -->
|
||||
<string name="StoryArchive__30_days" translatable="false">30 days</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__30_days" translatable="false">30 days</string> -->
|
||||
<!-- Empty state title when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories" translatable="false">No archived stories</string> -->
|
||||
<!-- Empty state message when no archived stories exist -->
|
||||
<string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__no_archived_stories_message" translatable="false">Turn on \"Save Stories to Archive\" in story settings to auto-archive your stories.</string> -->
|
||||
<!-- Empty state button to navigate to story settings -->
|
||||
<string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__go_to_settings" translatable="false">Go to settings</string> -->
|
||||
<!-- Label for sort order menu -->
|
||||
<string name="StoryArchive__sort_by" translatable="false">Sort by</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__sort_by" translatable="false">Sort by</string> -->
|
||||
<!-- Sort order option: newest first -->
|
||||
<string name="StoryArchive__newest" translatable="false">Newest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__newest" translatable="false">Newest</string> -->
|
||||
<!-- Sort order option: oldest first -->
|
||||
<string name="StoryArchive__oldest" translatable="false">Oldest</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__oldest" translatable="false">Oldest</string> -->
|
||||
<!-- Delete action in story archive multi-select bottom bar -->
|
||||
<string name="StoryArchive__delete" translatable="false">Delete</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__delete" translatable="false">Delete</string> -->
|
||||
<!-- Content description for selecting a story in multi-select mode -->
|
||||
<string name="StoryArchive__select_story" translatable="false">Select story</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="StoryArchive__select_story" translatable="false">Select story</string> -->
|
||||
<!-- Confirmation dialog body when deleting stories from archive -->
|
||||
<plurals name="StoryArchive__delete_n_stories">
|
||||
<item quantity="one">Eliminar la història de %1$d? Aquesta acció no es pot desfer.</item>
|
||||
@@ -7521,7 +7547,7 @@
|
||||
<!-- Section header for who can view a group story -->
|
||||
<string name="GroupStorySettingsFragment__who_can_view_this_story">Qui pot veure aquesta història</string>
|
||||
<!-- Explanation of who can view a group story -->
|
||||
<string name="GroupStorySettingsFragment__members_of_the_group_s">"Els membres del grup \"%1$s\" poden veure i respondre a aquesta història. Pots actualitzar l'afiliació a aquest xat a través del grup."</string>
|
||||
<string name="GroupStorySettingsFragment__members_of_the_group_s">"Els membres del grup \"%1$s\" poden veure i respondre a aquesta història. Pots actualitzar l\'afiliació a aquest xat a través del grup."</string>
|
||||
<!-- Preference label for removing this group story -->
|
||||
<string name="GroupStorySettingsFragment__remove_group_story">Suprimir història de grup</string>
|
||||
|
||||
@@ -8244,13 +8270,13 @@
|
||||
<string name="InactivePrimary__got_it">Entesos</string>
|
||||
|
||||
<!-- Text describing how to restore a backup displayed on the on-device backups screen -->
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Per restaurar una còpia de seguretat, instal·la una nova còpia de Signal. Obre l'app i toca Restaura la còpia de seguretat, i selecciona el fitxer de còpia de seguretat."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won't be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">You have \"Optimize Signal storage\" on. If you want to include all media in your on-device backup, turn the setting off.</string>
|
||||
<string name="OnDeviceBackupsScreen__to_restore_a_backup">"Per restaurar una còpia de seguretat, instal·la una nova còpia de Signal. Obre l\'app i toca Restaura la còpia de seguretat, i selecciona el fitxer de còpia de seguretat."</string>
|
||||
<!-- Body of a dialog shown when turning on on-device backups while "Optimize Signal storage" is enabled, warning that optimized media won\'t be included -->
|
||||
<string name="OnDeviceBackupsScreen__you_have_optimize_signal_storage_on">Tens l\'opció \"Optimitzar l\'emmagatzematge de Signal\" activada. Desactiva-la si vols incloure tots els teus arxius multimèdia a la teva còpia de seguretat local.</string>
|
||||
<!-- Dialog action that takes the user to the "Optimize Signal storage" setting -->
|
||||
<string name="OnDeviceBackupsScreen__view_setting">View setting</string>
|
||||
<string name="OnDeviceBackupsScreen__view_setting">Veure configuració</string>
|
||||
<!-- Dialog action to proceed with turning on on-device backups without turning off "Optimize Signal storage" -->
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continue without turning off</string>
|
||||
<string name="OnDeviceBackupsScreen__continue_without_turning_off">Continuar sense desactivar</string>
|
||||
|
||||
<!-- Title of a megaphone shown to prompt the user to verify their recovery key -->
|
||||
<string name="VerifyBackupKey__title">Verifica la teva clau de recuperació</string>
|
||||
@@ -8635,11 +8661,11 @@
|
||||
<!-- Dialog message for paid tier pending dialog -->
|
||||
<string name="ManageStorageSettingsFragment__storage_optimization_can_only_be_used">L\'optimització d\'emmagatzematge només es pot utilitzar amb el nivell de subscripció de pagament de Còpies de seguretat segures de Signal. La teva subscripció a còpies de seguretat s\'està processant i encara no està activa. Torna-ho a provar més tard.</string>
|
||||
<!-- Title of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">Media will be removed from your on-device backup</string>
|
||||
<string name="ManageStorageSettingsFragment__media_will_be_removed_from_your_on_device_backup">S\'eliminaran els arxius multimèdia de la teva còpia de seguretat local</string>
|
||||
<!-- Body of a dialog shown when turning on "Optimize Signal storage" while on-device backups are enabled -->
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Turning on \"Optimize Signal storage\" will offload old media from your device. You can download it again any time. It will also remove old media from your on-device backup.</string>
|
||||
<string name="ManageStorageSettingsFragment__turning_on_optimize_signal_storage_will_offload">Si actives l\'opció \"Optimitzar l\'emmagatzematge de Signal\", s\'eliminaran els arxius multimèdia antics del teu dispositiu. Podràs tornar-los a descarregar quan vulguis. També s\'eliminaran els arxius multimèdia antics de la teva còpia de seguretat local.</string>
|
||||
<!-- Dialog action to confirm turning on "Optimize Signal storage" -->
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Turn on</string>
|
||||
<string name="ManageStorageSettingsFragment__turn_on">Activar</string>
|
||||
|
||||
<!-- UpgradeToEnableOptimizedStorageSheet -->
|
||||
<!-- Title on a bottom sheet, detailing that the user must upgrade to enable storage optimization -->
|
||||
@@ -8722,8 +8748,10 @@
|
||||
<string name="BackupsSettingsFragment__subscription_canceled">Subscripció cancel·lada</string>
|
||||
<!-- Subtitle for row for no backup ever created -->
|
||||
<string name="BackupsSettingsFragment_automatic_backups_with_signals">Còpies de seguretat automàtiques amb el servei d\'emmagatzematge xifrat segur d\'extrem a extrem de Signal.</string>
|
||||
<!-- Subtitle shown on a linked device when backups are off, directing the user to set them up on their phone -->
|
||||
<string name="BackupsSettingsFragment__automatic_backups_get_started_on_your_phone">Automatic backups with Signal\'s secure end-to-end encrypted storage service. Get started on your phone.</string>
|
||||
<!-- Subtitle for row for backups that are active but subscription not found -->
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"No s'ha trobat una subscripció en aquest dispositiu."</string>
|
||||
<string name="BackupsSettingsFragment_subscription_not_found_on_this_device">"No s\'ha trobat una subscripció en aquest dispositiu."</string>
|
||||
<!-- Action button label to set up backups -->
|
||||
<string name="BackupsSettingsFragment_set_up">Configurar</string>
|
||||
<!-- Action button label to open remote backup settings -->
|
||||
@@ -8825,6 +8853,16 @@
|
||||
<string name="RemoteBackupsSettingsFragment__s_at_s">%1$s a %2$s</string>
|
||||
<!-- Subtext describing when a backup has never taken place. -->
|
||||
<string name="RemoteBackupsSettingsFragment__never">Mai</string>
|
||||
<!-- Subtext on a linked device describing when the primary device last backed up. Placeholder is the formatted date and time. -->
|
||||
<string name="RemoteBackupsSettingsFragment__your_phone_s">Your phone · %1$s</string>
|
||||
<!-- Message shown on a linked device with a free backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_your_subscription_on_your_primary_device">You can manage or upgrade your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a paid backup plan explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_cancel_your_subscription_on_your_primary_device">You can manage or cancel your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device with a canceled backup subscription explaining that the subscription is managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_renew_your_subscription_on_your_primary_device">You can manage or renew your Signal Secure Backups subscription on your primary device.</string>
|
||||
<!-- Message shown on a linked device when backups are off or the subscription was not found, explaining that backups are managed on the primary device -->
|
||||
<string name="RemoteBackupsSettingsFragment__you_can_manage_or_upgrade_backups_on_your_primary_device">You can manage or upgrade Signal Secure Backups on your primary device.</string>
|
||||
<!-- Button label to perform a backup immediately -->
|
||||
<string name="RemoteBackupsSettingsFragment__back_up_now">Fes-ne una còpia de seguretat ara</string>
|
||||
<!-- Dialog title when confirming whether to turn off and deleting backups -->
|
||||
@@ -8877,9 +8915,9 @@
|
||||
<!-- Linear progress dialog text shown when preparing a backup -->
|
||||
<string name="RemoteBackupsSettingsFragment__preparing_backup">Preparant la còpia de seguretat…</string>
|
||||
<!-- Linear progress dialog text shown when backup is paused because unmetered connectivity, such as WiFi, is unavailable. -->
|
||||
<string name="RemoteBackupsSettingsFragment__Waiting_for_Wifi">Esperant el WiFi...</string>
|
||||
<string name="RemoteBackupsSettingsFragment__Waiting_for_Wifi">Esperant el WiFi…</string>
|
||||
<!-- Linear progress dialog text shown when backup is paused because internet is unavailable. -->
|
||||
<string name="RemoteBackupsSettingsFragment__Waiting_for_internet_connection">Esperant la connexió a Internet...</string>
|
||||
<string name="RemoteBackupsSettingsFragment__Waiting_for_internet_connection">Esperant la connexió a Internet…</string>
|
||||
<!-- Linear progress dialog text shown when processing messages for backup. First placeholder is completed count, second is approximate total count, third is percent completed. -->
|
||||
<plurals name="RemoteBackupsSettingsFragment__processing_messages_progress_text">
|
||||
<item quantity="one">Processant %1$s de %2$s missatges (%3$d %%)</item>
|
||||
@@ -9336,10 +9374,10 @@
|
||||
|
||||
<!-- Email subject when contacting support on a restore backup network issue -->
|
||||
<string name="EnterBackupKey_network_failure_support_email">Error de xarxa de restauració de la còpia de seguretat de Signal Android</string>
|
||||
<string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_network_failure_support_email_filter" translatable="false">Android SignalBackups Import Failed</string> -->
|
||||
<!-- Email subject when contacting support on a permanent backup import failure -->
|
||||
<string name="EnterBackupKey_permanent_failure_support_email">Error permanent en restaurar la còpia de seguretat de Signal Android</string>
|
||||
<string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="EnterBackupKey_permanent_failure_support_email_filter" translatable="false">Android SignalBackups Import Permanent Failure</string> -->
|
||||
|
||||
<!-- EnterLocalBackupKeyScreen: Screen title for entering recovery key for local backup restore -->
|
||||
<string name="EnterLocalBackupKeyScreen__enter_your_recovery_key">Introdueix la teva clau de recuperació</string>
|
||||
@@ -9470,7 +9508,7 @@
|
||||
<!-- Email subject when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_network_failure_support_email">Error de xarxa d\'exportació de la còpia de seguretat de Signal Android</string>
|
||||
<!-- Email filter when contacting support on a create backup failure -->
|
||||
<string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="BackupAlertBottomSheet_export_failure_filter" translatable="false">Android SignalBackups Export Failed</string> -->
|
||||
|
||||
<!-- Title of dialog asking to submit debuglogs -->
|
||||
<string name="ContactSupportDialog_submit_debug_log">Vols enviar un registre de depuració?</string>
|
||||
@@ -9573,26 +9611,26 @@
|
||||
<!-- Accessibility label for more options button in MainToolbar -->
|
||||
<string name="MainToolbar__proxy_content_description">Servidor intermediari</string>
|
||||
<!-- Accessibility label for search filter button in MainToolbar -->
|
||||
<string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="MainToolbar__search_filter_content_description" translatable="false">Search filter</string> -->
|
||||
|
||||
<!-- SearchFilterBottomSheet: Title -->
|
||||
<string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__filter_search" translatable="false">Filter search</string> -->
|
||||
<!-- SearchFilterBottomSheet: Start date label -->
|
||||
<string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__start_date" translatable="false">Start date</string> -->
|
||||
<!-- SearchFilterBottomSheet: End date label -->
|
||||
<string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__end_date" translatable="false">End date</string> -->
|
||||
<!-- SearchFilterBottomSheet: Author label -->
|
||||
<string name="SearchFilterBottomSheet__author" translatable="false">Author</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__author" translatable="false">Author</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset date -->
|
||||
<string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__not_set" translatable="false">Not set</string> -->
|
||||
<!-- SearchFilterBottomSheet: Placeholder for unset author -->
|
||||
<string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__anyone" translatable="false">Anyone</string> -->
|
||||
<!-- SearchFilterBottomSheet: Apply button -->
|
||||
<string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__apply" translatable="false">Apply</string> -->
|
||||
<!-- SearchFilterBottomSheet: Clear button -->
|
||||
<string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__clear" translatable="false">Clear</string> -->
|
||||
<!-- SearchFilterBottomSheet: Select date dialog title -->
|
||||
<string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string>
|
||||
<!-- Removed by excludeNonTranslatables <string name="SearchFilterBottomSheet__select_date" translatable="false">Select date</string> -->
|
||||
|
||||
<!-- Accessibility label for a button displayed in the toolbar to return to the previous screen. -->
|
||||
<string name="DefaultTopAppBar__navigate_up_content_description">Amunt</string>
|
||||
@@ -9888,19 +9926,19 @@
|
||||
<!-- Header for a section showing all group member -->
|
||||
<string name="MemberSearchFragment__search_members">Buscar membres</string>
|
||||
<!-- Header for a section showing all group members who are contacts -->
|
||||
<string name="MemberSearchFragment__search_contacts">Search contacts</string>
|
||||
<string name="MemberSearchFragment__search_contacts">Buscar contactes</string>
|
||||
<!-- Header for a section showing all group member who are admins -->
|
||||
<string name="MemberSearchFragment__search_admins">Search admins</string>
|
||||
<string name="MemberSearchFragment__search_admins">Buscar admins</string>
|
||||
<!-- Dialog title to filter search by -->
|
||||
<string name="MemberSearchFragment__filter">Filter by</string>
|
||||
<string name="MemberSearchFragment__filter">Filtrar per</string>
|
||||
<!-- Dialog option for all group members -->
|
||||
<string name="MemberSearchFragment__filter_all_members">All members</string>
|
||||
<string name="MemberSearchFragment__filter_all_members">Tots els membres</string>
|
||||
<!-- Dialog option for group admins -->
|
||||
<string name="MemberSearchFragment__filter_admins">Admins</string>
|
||||
<string name="MemberSearchFragment__filter_admins">Administradors</string>
|
||||
<!-- Dialog option for your contacts -->
|
||||
<string name="MemberSearchFragment__filter_contacts">Contacts</string>
|
||||
<string name="MemberSearchFragment__filter_contacts">Contactes</string>
|
||||
<!-- Button to invite members via a group link -->
|
||||
<string name="MemberSearchFragment__invite_via">Invite via group link</string>
|
||||
<string name="MemberSearchFragment__invite_via">Convidar mitjançant enllaç de grup</string>
|
||||
|
||||
<!-- Title of the sheet shown when a local backup restore could not be completed -->
|
||||
<string name="CouldNotCompleteBackupRestoreSheet__title">No es pot restaurar la còpia de seguretat</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user