diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index 13dca3db33d0f66c8b8af3bd6b1eb06db666aa83..8cbe448f6ffb21cd44d01a5f534581dff4675ce2 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -3,10 +3,10 @@ name: "Validate Gradle Wrapper" on: push: branches: - - master + - main pull_request: branches: - - master + - main jobs: validation: diff --git a/Corona-Warn-App/build.gradle b/Corona-Warn-App/build.gradle index 83f49f75d73e527a3c7e21e3fb8fa5694c66c4da..255c61a8b5e1c2bfb4ad40b161fb60b148ff5e3b 100644 --- a/Corona-Warn-App/build.gradle +++ b/Corona-Warn-App/build.gradle @@ -163,11 +163,12 @@ android { } println("deviceForTesters adjusted versionName: $adjustedVersionName") } - - variant.outputs.each { output -> - def apkName = "Corona-Warn-App-${output.versionNameOverride}-${flavor.name}-${variant.buildType.name}.apk" - println("APK Name: $apkName") - output.outputFileName = apkName + if (flavor.name != "device") { + variant.outputs.each { output -> + def apkName = "Corona-Warn-App-${output.versionNameOverride}-${flavor.name}-${variant.buildType.name}.apk" + println("Override APK Name: $apkName") + output.outputFileName = apkName + } } } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt index 234022907e2c603253e6ac70c8abffa1dd72143d..44d3e0cd08a2688511a8c20589bfe3b428659d36 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/crash.ui/SettingsCrashReportViewModel.kt @@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.asLiveData import androidx.lifecycle.map -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.bugreporting.event.BugEvent import de.rki.coronawarnapp.bugreporting.reportProblem @@ -12,9 +11,7 @@ import de.rki.coronawarnapp.bugreporting.storage.repository.BugRepository import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import timber.log.Timber -import java.lang.Exception class SettingsCrashReportViewModel @AssistedInject constructor( private val crashReportRepository: BugRepository @@ -28,7 +25,7 @@ class SettingsCrashReportViewModel @AssistedInject constructor( createBugEventFormattedText(it) } - fun deleteAllCrashReports() = viewModelScope.launch(Dispatchers.IO) { + fun deleteAllCrashReports() = launch(Dispatchers.IO) { crashReportRepository.clear() } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt index e2d85089b1776f300d7c77c79be4a8b0d9a1fc6a..e976d87f84dc5205795dd6f1fcde9786c7d67a80 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/debugoptions/ui/DebugOptionsFragmentViewModel.kt @@ -1,7 +1,6 @@ package de.rki.coronawarnapp.test.debugoptions.ui import android.content.Context -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.environment.EnvironmentSetup import de.rki.coronawarnapp.environment.EnvironmentSetup.Type.Companion.toEnvironmentType @@ -15,8 +14,6 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.ui.smartLiveData import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import java.io.File class DebugOptionsFragmentViewModel @AssistedInject constructor( @@ -69,7 +66,7 @@ class DebugOptionsFragmentViewModel @AssistedInject constructor( fun shareLogFile() { CWADebug.fileLogger?.let { - viewModelScope.launch(context = Dispatchers.Default) { + launch { if (!it.logFile.exists()) return@launch val externalPath = File( diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/menu/ui/TestMenuFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/menu/ui/TestMenuFragmentViewModel.kt index 36d71e9cb89f0fde006cbb5c9f2df53e228d6c33..ef3eff6e88c7362e04b9766d57312bedf0c536ae 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/menu/ui/TestMenuFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/menu/ui/TestMenuFragmentViewModel.kt @@ -8,6 +8,7 @@ import de.rki.coronawarnapp.test.crash.ui.SettingsCrashReportFragment import de.rki.coronawarnapp.test.debugoptions.ui.DebugOptionsFragment import de.rki.coronawarnapp.test.keydownload.ui.KeyDownloadTestFragment import de.rki.coronawarnapp.test.risklevel.ui.TestRiskLevelCalculationFragment +import de.rki.coronawarnapp.test.submission.ui.SubmissionTestFragment import de.rki.coronawarnapp.test.tasks.ui.TestTaskControllerFragment import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -23,6 +24,7 @@ class TestMenuFragmentViewModel @AssistedInject constructor() : CWAViewModel() { TestRiskLevelCalculationFragment.MENU_ITEM, KeyDownloadTestFragment.MENU_ITEM, TestTaskControllerFragment.MENU_ITEM, + SubmissionTestFragment.MENU_ITEM, SettingsCrashReportFragment.MENU_ITEM ).let { MutableLiveData(it) } } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt index 0867b6e6bfcbce4261cde511273134389288fe83..f9834cdc79257082699d1f3606c70d72d74252d4 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragment.kt @@ -15,7 +15,6 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.sharing.ExposureSharingService import de.rki.coronawarnapp.test.menu.ui.TestMenuItem import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel -import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -39,7 +38,6 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le ) private val settingsViewModel: SettingsViewModel by activityViewModels() - private val submissionViewModel: SubmissionViewModel by activityViewModels() private val binding: FragmentTestRiskLevelCalculationBinding by viewBindingLazy() @@ -51,7 +49,10 @@ class TestRiskLevelCalculationFragment : Fragment(R.layout.fragment_test_risk_le } binding.settingsViewModel = settingsViewModel - binding.submissionViewModel = submissionViewModel + + vm.showRiskStatusCard.observe2(this) { + binding.showRiskStatusCard = it + } binding.buttonRetrieveDiagnosisKeys.setOnClickListener { vm.retrieveDiagnosisKeys() } binding.buttonProvideKeyViaQr.setOnClickListener { vm.scanLocalQRCodeAndProvide() } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index e052aec80178e2c79482eb549d2e8623fd7db0eb..3e0afe10007afd1115b73f493acb55448d8356a2 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -4,7 +4,6 @@ import android.content.Context import androidx.lifecycle.MutableLiveData import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.asLiveData -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.appconfig.AppConfigProvider @@ -21,11 +20,13 @@ import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange import de.rki.coronawarnapp.storage.AppDatabase import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.RiskLevelRepository +import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.common.DefaultTaskRequest import de.rki.coronawarnapp.task.submitBlocking import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.util.KeyFileHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.security.SecurityHelper @@ -33,8 +34,8 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.sample -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber import java.io.File @@ -60,6 +61,9 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( val riskLevelResetEvent = SingleLiveEvent<Unit>() val apiKeysProvidedEvent = SingleLiveEvent<DiagnosisKeyProvidedEvent>() val riskScoreState = MutableLiveData<RiskScoreState>(RiskScoreState()) + val showRiskStatusCard = SubmissionRepository.deviceUIStateFlow.map { + it.withSuccess(false) { true } + }.asLiveData(dispatcherProvider.Default) val tracingCardState = tracingCardStateProvider.state .sample(150L) @@ -85,7 +89,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( } fun resetRiskLevel() { - viewModelScope.launch { + launch { withContext(Dispatchers.IO) { try { // Preference reset @@ -117,7 +121,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( ) fun startENFObserver() { - viewModelScope.launch { + launch { try { var workState = riskScoreState.value!! @@ -200,7 +204,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( dir.mkdirs() var googleFileList: List<File> - viewModelScope.launch { + launch { googleFileList = KeyFileHelper.asyncCreateExportFiles(appleFiles, dir) Timber.i("Provide ${googleFileList.count()} files with ${appleKeyList.size} keys with token $token") @@ -226,7 +230,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor( } fun clearKeyCache() { - viewModelScope.launch { keyCacheRepository.clear() } + launch { keyCacheRepository.clear() } } @AssistedInject.Factory diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..e758be589d545f339e9700bdabdea8d6934a3749 --- /dev/null +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragment.kt @@ -0,0 +1,45 @@ +package de.rki.coronawarnapp.test.submission.ui + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.databinding.FragmentTestSubmissionBinding +import de.rki.coronawarnapp.test.menu.ui.TestMenuItem +import de.rki.coronawarnapp.util.di.AutoInject +import de.rki.coronawarnapp.util.ui.observe2 +import de.rki.coronawarnapp.util.ui.viewBindingLazy +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider +import de.rki.coronawarnapp.util.viewmodel.cwaViewModels +import javax.inject.Inject + +@SuppressLint("SetTextI18n") +class SubmissionTestFragment : Fragment(R.layout.fragment_test_submission), AutoInject { + @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory + private val vm: SubmissionTestFragmentViewModel by cwaViewModels { viewModelFactory } + + private val binding: FragmentTestSubmissionBinding by viewBindingLazy() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + vm.currentTestId.observe2(this) { + binding.registrationTokenCurrent.text = "Current: '$it'" + } + + binding.apply { + deleteTokenAction.setOnClickListener { vm.deleteRegistrationToken() } + scrambleTokenAction.setOnClickListener { vm.scrambleRegistrationToken() } + } + } + + companion object { + val TAG: String = SubmissionTestFragment::class.simpleName!! + val MENU_ITEM = TestMenuItem( + title = "Submission Test Options", + description = "Submission related test options..", + targetId = R.id.test_submission_fragment + ) + } +} diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentModule.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..f123767b6fb40c678849cb0723ff722422cb95bb --- /dev/null +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentModule.kt @@ -0,0 +1,18 @@ +package de.rki.coronawarnapp.test.submission.ui + +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey + +@Module +abstract class SubmissionTestFragmentModule { + @Binds + @IntoMap + @CWAViewModelKey(SubmissionTestFragmentViewModel::class) + abstract fun testKeyDownloadFragment( + factory: SubmissionTestFragmentViewModel.Factory + ): CWAViewModelFactory<out CWAViewModel> +} diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..c5d678dedff0cc54c1c97663f696f15303b27288 --- /dev/null +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt @@ -0,0 +1,31 @@ +package de.rki.coronawarnapp.test.submission.ui + +import androidx.lifecycle.asLiveData +import com.squareup.inject.assisted.AssistedInject +import de.rki.coronawarnapp.storage.LocalData +import de.rki.coronawarnapp.util.coroutine.DispatcherProvider +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory +import kotlinx.coroutines.flow.MutableStateFlow +import java.util.UUID + +class SubmissionTestFragmentViewModel @AssistedInject constructor( + dispatcherProvider: DispatcherProvider +) : CWAViewModel(dispatcherProvider = dispatcherProvider) { + + private val internalToken = MutableStateFlow(LocalData.registrationToken()) + val currentTestId = internalToken.asLiveData() + + fun scrambleRegistrationToken() { + LocalData.registrationToken(UUID.randomUUID().toString()) + internalToken.value = LocalData.registrationToken() + } + + fun deleteRegistrationToken() { + LocalData.registrationToken(null) + internalToken.value = LocalData.registrationToken() + } + + @AssistedInject.Factory + interface Factory : SimpleCWAViewModelFactory<SubmissionTestFragmentViewModel> +} diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/ui/main/MainActivityTestModule.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/ui/main/MainActivityTestModule.kt index 41cca0d6071aab1aca83653e9283893028312c39..e406155bac41e9b12c5287b985790baad7617a8f 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/ui/main/MainActivityTestModule.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/ui/main/MainActivityTestModule.kt @@ -14,6 +14,8 @@ import de.rki.coronawarnapp.test.menu.ui.TestMenuFragment import de.rki.coronawarnapp.test.menu.ui.TestMenuFragmentModule import de.rki.coronawarnapp.test.risklevel.ui.TestRiskLevelCalculationFragment import de.rki.coronawarnapp.test.risklevel.ui.TestRiskLevelCalculationFragmentModule +import de.rki.coronawarnapp.test.submission.ui.SubmissionTestFragment +import de.rki.coronawarnapp.test.submission.ui.SubmissionTestFragmentModule import de.rki.coronawarnapp.test.tasks.ui.TestTaskControllerFragment import de.rki.coronawarnapp.test.tasks.ui.TestTaskControllerFragmentModule @@ -40,4 +42,7 @@ abstract class MainActivityTestModule { @ContributesAndroidInjector(modules = [KeyDownloadTestFragmentModule::class]) abstract fun keyDownload(): KeyDownloadTestFragment + + @ContributesAndroidInjector(modules = [SubmissionTestFragmentModule::class]) + abstract fun submissionTest(): SubmissionTestFragment } diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml index 9e29d88d479a233ef358cbe19976dfd67bd4798f..a58a1ff4308801da783ab9a23022f15b82fd008a 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_risk_level_calculation.xml @@ -11,8 +11,8 @@ <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" /> <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> + name="showRiskStatusCard" + type="Boolean" /> <variable name="settingsViewModel" @@ -48,7 +48,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_normal" - android:visibility="@{FormatterSubmissionHelper.formatShowRiskStatusCard(submissionViewModel.deviceUiState)}" + gone="@{showRiskStatusCard == null || !showRiskStatusCard}" android:focusable="true" android:backgroundTint="@{tracingCard.getRiskInfoContainerBackgroundTint(context)}" android:backgroundTintMode="src_over"> diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_submission.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_submission.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac69680e903cf5df93ecff2f503a2a65dcee8fe5 --- /dev/null +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_submission.xml @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="utf-8"?> + +<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:ignore="HardcodedText"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="8dp" + android:orientation="vertical" + android:paddingBottom="32dp"> + + <androidx.constraintlayout.widget.ConstraintLayout + style="@style/card" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="@dimen/spacing_tiny" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:orientation="vertical"> + <TextView + android:id="@+id/registration_token_title" + style="@style/body1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Submission registration token " + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + <TextView + android:id="@+id/registration_token_current" + style="@style/body2" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_tiny" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/registration_token_title" + tools:text="Current test ID: 1234567890" /> + <Button + android:id="@+id/delete_token_action" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_tiny" + android:layout_weight="1" + android:text="Delete token" + app:layout_constraintEnd_toStartOf="@+id/scramble_token_action" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/registration_token_current" /> + <Button + android:id="@+id/scramble_token_action" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_tiny" + android:layout_weight="1" + android:text="Random token" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/delete_token_action" + app:layout_constraintTop_toBottomOf="@+id/registration_token_current" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + + </LinearLayout> +</androidx.core.widget.NestedScrollView> \ No newline at end of file diff --git a/Corona-Warn-App/src/deviceForTesters/res/navigation/test_nav_graph.xml b/Corona-Warn-App/src/deviceForTesters/res/navigation/test_nav_graph.xml index 226a618a77e11982b3a1ead5d9fbf879429c7188..14d89e5a3de75e9d667feafc4a67a991d2e0759d 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/navigation/test_nav_graph.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/navigation/test_nav_graph.xml @@ -31,6 +31,9 @@ <action android:id="@+id/action_test_menu_fragment_to_keyDownloadTestFragment" app:destination="@id/test_keydownload_fragment" /> + <action + android:id="@+id/action_test_menu_fragment_to_submissionTestFragment" + app:destination="@id/test_submission_fragment" /> </fragment> <fragment @@ -86,5 +89,10 @@ android:name="de.rki.coronawarnapp.test.keydownload.ui.KeyDownloadTestFragment" android:label="KeyDownloadTestFragment" tools:layout="@layout/fragment_test_keydownload" /> + <fragment + android:id="@+id/test_submission_fragment" + android:name="de.rki.coronawarnapp.test.submission.ui.SubmissionTestFragment" + android:label="SubmissionTestFragment" + tools:layout="@layout/fragment_test_submission" /> </navigation> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt index ebe7c473fc3d6037becb4bcab9981d8fe5fccf6f..4f6ca66e84a6002ed43c19c30350c392a816ff63 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt @@ -11,6 +11,7 @@ import androidx.work.WorkManager import dagger.android.AndroidInjector import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector +import de.rki.coronawarnapp.appconfig.ConfigChangeDetector import de.rki.coronawarnapp.bugreporting.loghistory.LogHistoryTree import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler import de.rki.coronawarnapp.exception.reporting.ErrorReportReceiver @@ -44,6 +45,7 @@ class CoronaWarnApplication : Application(), HasAndroidInjector { @Inject lateinit var taskController: TaskController @Inject lateinit var foregroundState: ForegroundState @Inject lateinit var workManager: WorkManager + @Inject lateinit var configChangeDetector: ConfigChangeDetector @Inject lateinit var deadmanNotificationScheduler: DeadmanNotificationScheduler @LogHistoryTree @Inject lateinit var rollingLogHistory: Timber.Tree @@ -79,6 +81,8 @@ class CoronaWarnApplication : Application(), HasAndroidInjector { if (LocalData.onboardingCompletedTimestamp() != null) { deadmanNotificationScheduler.schedulePeriodic() } + + configChangeDetector.launch() } private val activityLifecycleCallback = object : ActivityLifecycleCallbacks { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigProvider.kt index 71906e83169d8e0ef4a68e34aa1208ec958defc5..7e17e84061ba36ea8f851ebd7afb0a407d0a2758 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/AppConfigProvider.kt @@ -22,7 +22,7 @@ class AppConfigProvider @Inject constructor( loggingTag = "AppConfigProvider", scope = scope, coroutineContext = dispatcherProvider.IO, - sharingBehavior = SharingStarted.WhileSubscribed(replayExpirationMillis = 0) + sharingBehavior = SharingStarted.Lazily ) { source.retrieveConfig() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetector.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetector.kt new file mode 100644 index 0000000000000000000000000000000000000000..cf17b9f3e954cf2840ff98d16bb2bf45c21bc943 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetector.kt @@ -0,0 +1,63 @@ +package de.rki.coronawarnapp.appconfig + +import androidx.annotation.VisibleForTesting +import de.rki.coronawarnapp.risk.RiskLevel +import de.rki.coronawarnapp.risk.RiskLevelData +import de.rki.coronawarnapp.risk.RiskLevelTask +import de.rki.coronawarnapp.storage.RiskLevelRepository +import de.rki.coronawarnapp.task.TaskController +import de.rki.coronawarnapp.task.common.DefaultTaskRequest +import de.rki.coronawarnapp.util.coroutine.AppScope +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import timber.log.Timber +import javax.inject.Inject + +class ConfigChangeDetector @Inject constructor( + private val appConfigProvider: AppConfigProvider, + private val taskController: TaskController, + @AppScope private val appScope: CoroutineScope, + private val riskLevelData: RiskLevelData +) { + + fun launch() { + Timber.v("Monitoring config changes.") + appConfigProvider.currentConfig + .distinctUntilChangedBy { it.identifier } + .onEach { + Timber.v("Running app config change checks.") + check(it.identifier) + } + .catch { Timber.e(it, "App config change checks failed.") } + .launchIn(appScope) + } + + @VisibleForTesting + internal fun check(newIdentifier: String) { + if (riskLevelData.lastUsedConfigIdentifier == null) { + // No need to reset anything if we didn't calculate a risklevel yet. + Timber.d("Config changed, but no previous identifier is available.") + return + } + + val oldConfigId = riskLevelData.lastUsedConfigIdentifier + if (newIdentifier != oldConfigId) { + Timber.i("New config id ($newIdentifier) differs from last one ($oldConfigId), resetting.") + RiskLevelRepositoryDeferrer.resetRiskLevel() + taskController.submit(DefaultTaskRequest(RiskLevelTask::class)) + } else { + Timber.v("Config identifier ($oldConfigId) didn't change, NOOP.") + } + } + + @VisibleForTesting + internal object RiskLevelRepositoryDeferrer { + + fun resetRiskLevel() { + RiskLevelRepository.setRiskLevelScore(RiskLevel.UNDETERMINED) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt index 4fa8b6effbc3f77ca7a780ac791cd07eb93f8ffc..fc89eff4627de3bd0fb3069f8937876563fb0341 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/http/CwaWebException.kt @@ -27,7 +27,6 @@ open class CwaSuccessResponseWithCodeMismatchNotSupportedError(statusCode: Int) open class CwaInformationalNotSupportedError(statusCode: Int) : CwaWebException(statusCode) open class CwaRedirectNotSupportedError(statusCode: Int) : CwaWebException(statusCode) -class CwaUnknownHostException : CwaWebException(901) class BadRequestException : CwaClientError(400) class UnauthorizedException : CwaClientError(401) class ForbiddenException : CwaClientError(403) @@ -44,5 +43,6 @@ class ServiceUnavailableException : CwaServerError(503) class GatewayTimeoutException : CwaServerError(504) class HTTPVersionNotSupported : CwaServerError(505) class NetworkAuthenticationRequiredException : CwaServerError(511) +class CwaUnknownHostException : CwaServerError(597) class NetworkReadTimeoutException : CwaServerError(598) class NetworkConnectTimeoutException : CwaServerError(599) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt index bc347abb919fbbeff9ada2c2d768b3ef679334ff..1061abc7e164af4ff5ac41ec2e63776004ebcce3 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/HttpErrorParser.kt @@ -26,6 +26,7 @@ import de.rki.coronawarnapp.exception.http.UnauthorizedException import de.rki.coronawarnapp.exception.http.UnsupportedMediaTypeException import okhttp3.Interceptor import okhttp3.Response +import java.net.SocketTimeoutException import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection @@ -66,6 +67,8 @@ class HttpErrorParser : Interceptor { throw CwaWebException(code) } } + } catch (err: SocketTimeoutException) { + throw NetworkConnectTimeoutException() } catch (err: UnknownHostException) { throw CwaUnknownHostException() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorage.kt index 01e93c4b9ab724a44dc953b0466c2b6a7b366c31..c4299cafe56f85562c86d276a10d910bb5e39287 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorage.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorage.kt @@ -2,6 +2,8 @@ package de.rki.coronawarnapp.nearby.modules.detectiontracker import android.content.Context import com.google.gson.Gson +import de.rki.coronawarnapp.exception.ExceptionCategory +import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.serialization.BaseGson import de.rki.coronawarnapp.util.serialization.fromJson @@ -44,11 +46,13 @@ class ExposureDetectionTrackerStorage @Inject constructor( if (!storageFile.exists()) return@withLock emptyMap() gson.fromJson<Map<String, TrackedExposureDetection>>(storageFile).also { + require(it.size >= 0) Timber.v("Loaded detection data: %s", it) lastCalcuationData = it } } catch (e: Exception) { Timber.e(e, "Failed to load tracked detections.") + if (storageFile.delete()) Timber.w("Storage file was deleted.") emptyMap() } } @@ -63,6 +67,7 @@ class ExposureDetectionTrackerStorage @Inject constructor( gson.toJson(data, storageFile) } catch (e: Exception) { Timber.e(e, "Failed to save tracked detections.") + e.report(ExceptionCategory.INTERNAL) } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt index 5ea6e2adf596a9cb6b68002a93c6855ebfd28c93..4dfcc3bec4bca9d23aac720a173792d91220752c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/DefaultRiskLevels.kt @@ -33,7 +33,6 @@ import javax.inject.Singleton class DefaultRiskLevels @Inject constructor( private val appConfigProvider: AppConfigProvider ) : RiskLevels { - private var appConfig: ConfigData init { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelData.kt new file mode 100644 index 0000000000000000000000000000000000000000..83372c3f5d5d671f21c29ceb1c478e23df6fed79 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelData.kt @@ -0,0 +1,31 @@ +package de.rki.coronawarnapp.risk + +import android.content.Context +import androidx.core.content.edit +import de.rki.coronawarnapp.util.di.AppContext +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class RiskLevelData @Inject constructor( + @AppContext private val context: Context +) { + + private val prefs by lazy { + context.getSharedPreferences(NAME_SHARED_PREFS, Context.MODE_PRIVATE) + } + + /** + * The identifier of the config used during the last risklevel calculation + */ + var lastUsedConfigIdentifier: String? + get() = prefs.getString(PKEY_RISKLEVEL_CALC_LAST_CONFIG_ID, null) + set(value) = prefs.edit(true) { + putString(PKEY_RISKLEVEL_CALC_LAST_CONFIG_ID, value) + } + + companion object { + private const val NAME_SHARED_PREFS = "risklevel_localdata" + private const val PKEY_RISKLEVEL_CALC_LAST_CONFIG_ID = "risklevel.config.identifier.last" + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt index fd1c6d91c03a3e62b5dcbcb5f464947048d70151..960d30f494cacabfbb57b7528eef12a7ac406f17 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt @@ -2,6 +2,8 @@ package de.rki.coronawarnapp.risk import android.content.Context import com.google.android.gms.nearby.exposurenotification.ExposureWindow +import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.appconfig.ConfigData import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.nearby.ENFClient @@ -35,7 +37,9 @@ class RiskLevelTask @Inject constructor( @AppContext private val context: Context, private val enfClient: ENFClient, private val timeStamper: TimeStamper, - private val backgroundModeStatus: BackgroundModeStatus + private val backgroundModeStatus: BackgroundModeStatus, + private val riskLevelData: RiskLevelData, + private val appConfigProvider: AppConfigProvider ) : Task<DefaultProgress, RiskLevelTask.Result> { private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>() @@ -57,6 +61,8 @@ class RiskLevelTask @Inject constructor( return Result(NO_CALCULATION_POSSIBLE_TRACING_OFF) } + val configData: ConfigData = appConfigProvider.getAppConfig() + with(riskLevels) { return Result( when { @@ -84,6 +90,7 @@ class RiskLevelTask @Inject constructor( }.also { checkCancel() updateRepository(it, timeStamper.nowUTC.millis) + riskLevelData.lastUsedConfigIdentifier = configData.identifier } ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt index 6661469b1b925ccd87655eb7e65b2fc449d64e01..7b5b247029fadd06588505ffa98bc25c5976998c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/RiskLevelRepository.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow object RiskLevelRepository { - private val internalRisklevelScore = MutableStateFlow(RiskLevelConstants.UNKNOWN_RISK_INITIAL) + private val internalRisklevelScore = MutableStateFlow(getLastSuccessfullyCalculatedScore().raw) val riskLevelScore: Flow<Int> = internalRisklevelScore private val internalRiskLevelScoreLastSuccessfulCalculated = diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt index b601e6d77475a9a9a2e1bd665c0f5ba50d8d58ff..62ae3efc8d07896be527db56dad3dab1b75e4275 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt @@ -1,16 +1,13 @@ package de.rki.coronawarnapp.storage -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.asLiveData import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.service.submission.SubmissionService -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.formatter.TestResult import de.rki.coronawarnapp.worker.BackgroundWorkScheduler @@ -26,15 +23,12 @@ object SubmissionRepository { AppInjector.component.appScope } - val uiStateStateFlowInternal = MutableStateFlow(ApiRequestState.IDLE) - val uiStateStateFlow: Flow<ApiRequestState> = uiStateStateFlowInternal - val uiStateState: LiveData<ApiRequestState> = uiStateStateFlow.asLiveData() - private val testResultReceivedDateFlowInternal = MutableStateFlow(Date()) val testResultReceivedDateFlow: Flow<Date> = testResultReceivedDateFlowInternal - private val deviceUIStateFlowInternal = MutableStateFlow(DeviceUIState.UNPAIRED) - val deviceUIStateFlow: Flow<DeviceUIState> = deviceUIStateFlowInternal + private val deviceUIStateFlowInternal = + MutableStateFlow<NetworkRequestWrapper<DeviceUIState, Throwable>>(NetworkRequestWrapper.RequestIdle) + val deviceUIStateFlow: Flow<NetworkRequestWrapper<DeviceUIState, Throwable>> = deviceUIStateFlowInternal private val testResultFlow = MutableStateFlow<TestResult?>(null) @@ -80,37 +74,33 @@ object SubmissionRepository { LocalData.teletan(teletan) } - private val uiStateErrorInternal = MutableLiveData<Event<CwaWebException>>(null) - val uiStateError: LiveData<Event<CwaWebException>> = uiStateErrorInternal - // TODO this should be more UI agnostic fun refreshDeviceUIState(refreshTestResult: Boolean = true) { var refresh = refreshTestResult - deviceUIStateFlowInternal.value.let { + deviceUIStateFlowInternal.value.withSuccess { if (it != DeviceUIState.PAIRED_NO_RESULT && it != DeviceUIState.UNPAIRED) { refresh = false Timber.d("refreshDeviceUIState: Change refresh, state ${it.name} doesn't require refresh") } } - uiStateStateFlowInternal.value = ApiRequestState.STARTED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestStarted + appScope.launch { try { refreshUIState(refresh) - uiStateStateFlowInternal.value = ApiRequestState.SUCCESS } catch (err: CwaWebException) { - uiStateErrorInternal.postValue(Event(err)) - uiStateStateFlowInternal.value = ApiRequestState.FAILED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) } catch (err: Exception) { + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestFailed(err) err.report(ExceptionCategory.INTERNAL) } } } fun reset() { - uiStateStateFlowInternal.value = ApiRequestState.IDLE - deviceUIStateFlowInternal.value = DeviceUIState.UNPAIRED + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestIdle } // TODO this should be more UI agnostic @@ -132,6 +122,6 @@ object SubmissionRepository { } } } - deviceUIStateFlowInternal.value = uiState + deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(uiState) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt index 6592ad0bae0059a1eb86540ff09d9f3f94515d2a..517a077b37f4a65a2c9b01b65737da156353a039 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardState.kt @@ -3,7 +3,7 @@ package de.rki.coronawarnapp.ui.main.home import android.content.Context import android.graphics.drawable.Drawable import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState +import de.rki.coronawarnapp.exception.http.CwaServerError import de.rki.coronawarnapp.util.DeviceUIState import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_ERROR import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_NEGATIVE @@ -12,72 +12,113 @@ import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_REDEEMED import de.rki.coronawarnapp.util.DeviceUIState.SUBMITTED_FINAL +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess data class SubmissionCardState( - val deviceUiState: DeviceUIState, - val isDeviceRegistered: Boolean, - val uiStateState: ApiRequestState + val deviceUiState: NetworkRequestWrapper<DeviceUIState, Throwable>, + val isDeviceRegistered: Boolean ) { - fun isRiskCardVisible(): Boolean = deviceUiState != PAIRED_POSITIVE && - deviceUiState != PAIRED_POSITIVE_TELETAN && - deviceUiState != SUBMITTED_FINAL + fun isRiskCardVisible(): Boolean = + deviceUiState.withSuccess(true) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN, SUBMITTED_FINAL -> false + else -> true + } + } fun isUnregisteredCardVisible(): Boolean = !isDeviceRegistered fun isFetchingCardVisible(): Boolean = - isDeviceRegistered && (uiStateState == ApiRequestState.STARTED || uiStateState == ApiRequestState.FAILED) + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error is CwaServerError + is NetworkRequestWrapper.RequestStarted -> true + else -> false + } fun isFailedCardVisible(): Boolean = - isDeviceRegistered && uiStateState == ApiRequestState.SUCCESS && deviceUiState == PAIRED_REDEEMED + isDeviceRegistered && when (deviceUiState) { + is NetworkRequestWrapper.RequestFailed -> deviceUiState.error !is CwaServerError + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == PAIRED_REDEEMED + else -> false + } - fun isPositiveSubmissionCardVisible(): Boolean = uiStateState == ApiRequestState.SUCCESS && - (deviceUiState == PAIRED_POSITIVE || - deviceUiState == PAIRED_POSITIVE_TELETAN) + fun isPositiveSubmissionCardVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> true + else -> false + } + } fun isSubmissionDoneCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && deviceUiState == SUBMITTED_FINAL + when (deviceUiState) { + is NetworkRequestWrapper.RequestSuccessful -> deviceUiState.data == SUBMITTED_FINAL + else -> false + } fun isContentCardVisible(): Boolean = - uiStateState == ApiRequestState.SUCCESS && (deviceUiState == PAIRED_ERROR || - deviceUiState == PAIRED_NEGATIVE || - deviceUiState == PAIRED_NO_RESULT) + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_ERROR, PAIRED_NEGATIVE, PAIRED_NO_RESULT -> true + else -> false + } + } - fun getContentCardTitleText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available - PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending - else -> R.string.submission_status_card_title_pending - }.let { c.getString(it) } + fun getContentCardTitleText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_title_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED, PAIRED_NEGATIVE -> R.string.submission_status_card_title_available + PAIRED_NO_RESULT -> R.string.submission_status_card_title_pending + else -> R.string.submission_status_card_title_pending + } + }.let { c.getString(it) } - fun getContentCardSubTitleText(c: Context): String = when (deviceUiState) { - PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid - else -> null - }?.let { c.getString(it) } ?: "" + fun getContentCardSubTitleText(c: Context): String = + deviceUiState.withSuccess(null) { + when (it) { + PAIRED_NEGATIVE -> R.string.submission_status_card_subtitle_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_subtitle_invalid + else -> null + } + }?.let { c.getString(it) } ?: "" - fun getContentCardSubTitleTextColor(c: Context): Int = when (deviceUiState) { - PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen - PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral - else -> R.color.colorTextPrimary1 - }.let { c.getColor(it) } + fun getContentCardSubTitleTextColor(c: Context): Int = + deviceUiState.withSuccess(R.color.colorTextPrimary1) { + when (it) { + PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + PAIRED_ERROR, PAIRED_REDEEMED -> R.color.colorTextSemanticNeutral + else -> R.color.colorTextPrimary1 + } + }.let { c.getColor(it) } - fun isContentCardStatusTextVisible(): Boolean = when (deviceUiState) { - PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true - else -> false - } + fun isContentCardStatusTextVisible(): Boolean = + deviceUiState.withSuccess(false) { + when (it) { + PAIRED_NEGATIVE, PAIRED_REDEEMED, PAIRED_ERROR -> true + else -> false + } + } - fun getContentCardBodyText(c: Context): String = when (deviceUiState) { - PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid - PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative - PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending - else -> R.string.submission_status_card_body_pending - }.let { c.getString(it) } + fun getContentCardBodyText(c: Context): String = + deviceUiState.withSuccess(R.string.submission_status_card_body_pending) { + when (it) { + PAIRED_ERROR, PAIRED_REDEEMED -> R.string.submission_status_card_body_invalid + PAIRED_NEGATIVE -> R.string.submission_status_card_body_negative + PAIRED_NO_RESULT -> R.string.submission_status_card_body_pending + else -> R.string.submission_status_card_body_pending + } + }.let { c.getString(it) } - fun getContentCardIcon(c: Context): Drawable? = when (deviceUiState) { - PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending - PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending - PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative - PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid - else -> R.drawable.ic_main_illustration_invalid - }.let { c.getDrawable(it) } + fun getContentCardIcon(c: Context): Drawable? = + deviceUiState.withSuccess(R.drawable.ic_main_illustration_invalid) { + when (it) { + PAIRED_NO_RESULT -> R.drawable.ic_main_illustration_pending + PAIRED_POSITIVE, PAIRED_POSITIVE_TELETAN -> R.drawable.ic_main_illustration_pending + PAIRED_NEGATIVE -> R.drawable.ic_main_illustration_negative + PAIRED_ERROR, PAIRED_REDEEMED -> R.drawable.ic_main_illustration_invalid + else -> R.drawable.ic_main_illustration_invalid + } + }.let { c.getDrawable(it) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt index 087c1e1f72a0036b0f460a6c4a5423a2cd8c33b7..9fc9fa97657ced734ffb64974820b824ba64ebc6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/SubmissionCardsStateProvider.kt @@ -3,8 +3,6 @@ package de.rki.coronawarnapp.ui.main.home import dagger.Reusable import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.ui.submission.ApiRequestState -import de.rki.coronawarnapp.util.DeviceUIState import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.onCompletion @@ -17,12 +15,10 @@ import javax.inject.Inject class SubmissionCardsStateProvider @Inject constructor() { val state: Flow<SubmissionCardState> = combine( - SubmissionRepository.deviceUIStateFlow, - SubmissionRepository.uiStateStateFlow + SubmissionRepository.deviceUIStateFlow ) { args -> SubmissionCardState( - deviceUiState = args[0] as DeviceUIState, - uiStateState = args[1] as ApiRequestState, + deviceUiState = args[0], isDeviceRegistered = LocalData.registrationToken() != null ) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt index 9d996c01ebf7532defd6ebd9235a603fa05040d7..a710675c0b0b106baf0222a0ccc1355063e5c3ec 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt @@ -1,6 +1,5 @@ package de.rki.coronawarnapp.ui.onboarding -import androidx.lifecycle.viewModelScope import com.squareup.inject.assisted.AssistedInject import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report @@ -10,7 +9,6 @@ import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository import de.rki.coronawarnapp.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory -import kotlinx.coroutines.launch class OnboardingTracingFragmentViewModel @AssistedInject constructor( private val interoperabilityRepository: InteroperabilityRepository @@ -25,7 +23,7 @@ class OnboardingTracingFragmentViewModel @AssistedInject constructor( // Reset tracing state in onboarding fun resetTracing() { - viewModelScope.launch { + launch { try { if (InternalExposureNotificationClient.asyncIsEnabled()) { InternalExposureNotificationClient.asyncStop() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt index a1d42d3961c96b916e3498af53c1e9347c231ca8..0de5f0efad201d2a0f065cd443291523ca65275c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultFragment.kt @@ -15,8 +15,8 @@ import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DialogHelper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withFailure import de.rki.coronawarnapp.util.di.AutoInject -import de.rki.coronawarnapp.util.observeEvent import de.rki.coronawarnapp.util.ui.doNavigate import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy @@ -79,6 +79,11 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ viewModel.uiState.observe2(this) { binding.uiState = it + it.deviceUiState.withFailure { + if (it is CwaWebException) { + DialogHelper.showDialog(buildErrorDialog(it)) + } + } } // registers callback when the os level back is pressed @@ -99,10 +104,6 @@ class SubmissionTestResultFragment : Fragment(R.layout.fragment_submission_test_ DialogHelper.showDialog(tracingRequiredDialog) } - viewModel.uiStateError.observeEvent(viewLifecycleOwner) { - DialogHelper.showDialog(buildErrorDialog(it)) - } - viewModel.showRedeemedTokenWarning.observe2(this) { val dialog = DialogHelper.DialogInstance( requireActivity(), diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt index 97586ba507f291498d92a0145b88e1eacedd4e76..370ecbf292818116417636008439820aeb2a02e7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultViewModel.kt @@ -3,7 +3,6 @@ package de.rki.coronawarnapp.ui.submission.testresult import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import com.squareup.inject.assisted.AssistedInject -import de.rki.coronawarnapp.exception.http.CwaWebException import de.rki.coronawarnapp.nearby.ENFClient import de.rki.coronawarnapp.notification.TestResultNotificationService import de.rki.coronawarnapp.service.submission.SubmissionService @@ -12,7 +11,7 @@ import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.submission.Symptoms import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionNavigationEvents import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.Event +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -37,20 +36,22 @@ class SubmissionTestResultViewModel @AssistedInject constructor( private val tokenErrorMutex = Mutex() val uiState: LiveData<TestResultUIState> = combineTransform( - SubmissionRepository.uiStateStateFlow, SubmissionRepository.deviceUIStateFlow, SubmissionRepository.testResultReceivedDateFlow - ) { apiRequestState, deviceUiState, resultDate -> + ) { deviceUiState, resultDate -> tokenErrorMutex.withLock { - if (!wasRedeemedTokenErrorShown && deviceUiState == DeviceUIState.PAIRED_REDEEMED) { - wasRedeemedTokenErrorShown = true - showRedeemedTokenWarning.postValue(Unit) + if (!wasRedeemedTokenErrorShown) { + deviceUiState.withSuccess { + if (it == DeviceUIState.PAIRED_REDEEMED) { + wasRedeemedTokenErrorShown = true + showRedeemedTokenWarning.postValue(Unit) + } + } } } TestResultUIState( - apiRequestState = apiRequestState, deviceUiState = deviceUiState, testResultReceivedDate = resultDate ).let { emit(it) } @@ -58,11 +59,13 @@ class SubmissionTestResultViewModel @AssistedInject constructor( suspend fun observeTestResultToSchedulePositiveTestResultReminder() = SubmissionRepository.deviceUIStateFlow - .first { it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN } + .first { request -> + request.withSuccess(false) { + it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN + } + } .also { testResultNotificationService.schedulePositiveTestResultReminder() } - val uiStateError: LiveData<Event<CwaWebException>> = SubmissionRepository.uiStateError - fun onBackPressed() { routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt index b1909eb805d6cbaa923b41336f14d60cb30aa45b..a34a02cad13d8a16e1c550ef47aa4c2ce27dfd2d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/TestResultUIState.kt @@ -1,11 +1,10 @@ package de.rki.coronawarnapp.ui.submission.testresult -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import java.util.Date data class TestResultUIState( - val apiRequestState: ApiRequestState, - val deviceUiState: DeviceUIState, + val deviceUiState: NetworkRequestWrapper<DeviceUIState, Throwable>, val testResultReceivedDate: Date? ) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt deleted file mode 100644 index 6b668e6c420a52ee06796f5a4365794fd96452b6..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.ui.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.asLiveData -import de.rki.coronawarnapp.storage.SubmissionRepository -import de.rki.coronawarnapp.util.DeviceUIState -import de.rki.coronawarnapp.util.viewmodel.CWAViewModel - -class SubmissionViewModel : CWAViewModel() { - - val deviceUiState: LiveData<DeviceUIState> = SubmissionRepository.deviceUIStateFlow.asLiveData() -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt new file mode 100644 index 0000000000000000000000000000000000000000..47d1c57e48abe6bf8d816ad9305c0d9366ea74ee --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/NetworkRequestWrapper.kt @@ -0,0 +1,30 @@ +package de.rki.coronawarnapp.util + +sealed class NetworkRequestWrapper<out T, out U> { + object RequestIdle : NetworkRequestWrapper<Nothing, Nothing>() + object RequestStarted : NetworkRequestWrapper<Nothing, Nothing>() + data class RequestSuccessful<T, U>(val data: T) : NetworkRequestWrapper<T, U>() + data class RequestFailed<T, U>(val error: U) : NetworkRequestWrapper<T, U>() + + companion object { + fun <T, U, W> NetworkRequestWrapper<T, U>?.withSuccess(without: W, block: (data: T) -> W): W { + return if (this is RequestSuccessful) { + block(this.data) + } else { + without + } + } + + fun <T, U> NetworkRequestWrapper<T, U>?.withSuccess(block: (data: T) -> Unit) { + if (this is RequestSuccessful) { + block(this.data) + } + } + + fun <T, U> NetworkRequestWrapper<T, U>?.withFailure(block: (error: U) -> Unit) { + if (this is RequestFailed) { + block(this.error) + } + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/flow/HotDataFlow.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/flow/HotDataFlow.kt index 91086980e2bd33336558e889a15272962e37bd83..1fe9db2d964a52c0bc216428d4a5e6fe1ec415c4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/flow/HotDataFlow.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/flow/HotDataFlow.kt @@ -15,6 +15,8 @@ import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.plus +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import timber.log.Timber import kotlin.coroutines.CoroutineContext @@ -37,20 +39,32 @@ class HotDataFlow<T : Any>( extraBufferCapacity = Int.MAX_VALUE, onBufferOverflow = BufferOverflow.SUSPEND ) + private val valueGuard = Mutex() private val internalProducer: Flow<Holder<T>> = channelFlow { - var currentValue = startValueProvider().also { - Timber.tag(tag).v("startValue=%s", it) - val updatedBy: suspend T.() -> T = { it } - send(Holder.Data(value = it, updatedBy = updatedBy)) + var currentValue = valueGuard.withLock { + startValueProvider().also { + Timber.tag(tag).v("startValue=%s", it) + val updatedBy: suspend T.() -> T = { it } + send(Holder.Data(value = it, updatedBy = updatedBy)) + } } + Timber.tag(tag).v("startValue=%s", currentValue) - updateActions.collect { updateAction -> - currentValue = updateAction(currentValue).also { - currentValue = it - send(Holder.Data(value = it, updatedBy = updateAction)) + updateActions + .onCompletion { + Timber.tag(tag).v("updateActions onCompletion -> resetReplayCache()") + updateActions.resetReplayCache() } - } + .collect { updateAction -> + currentValue = valueGuard.withLock { + updateAction(currentValue).also { + send(Holder.Data(value = it, updatedBy = updateAction)) + } + } + } + + Timber.tag(tag).v("internal channelFlow finished.") } private val internalFlow = internalProducer @@ -65,7 +79,10 @@ class HotDataFlow<T : Any>( throw it } } - .onCompletion { Timber.tag(tag).v("Internal onCompletion") } + .onCompletion { err -> + if (err != null) Timber.tag(tag).w(err, "internal onCompletion due to error") + else Timber.tag(tag).v("internal onCompletion") + } .shareIn( scope = scope + coroutineContext, replay = 1, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt index 156f8efee0289c727be6c85d0aa6e4a96b116674..e573e202356a4b6faef650422585624285eb8c6d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt @@ -8,11 +8,13 @@ import android.text.Spannable import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan +import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R import de.rki.coronawarnapp.submission.Symptoms -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper +import de.rki.coronawarnapp.util.NetworkRequestWrapper.Companion.withSuccess import de.rki.coronawarnapp.util.TimeAndDateExtensions.toUIFormat import java.util.Date import java.util.Locale @@ -49,33 +51,37 @@ fun isEnableSymptomCalendarButtonByState(currentState: Symptoms.StartOf?): Boole return currentState != null } -fun formatTestResultSpinnerVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState != ApiRequestState.SUCCESS) - -fun formatTestResultVisible(uiStateState: ApiRequestState?): Int = - formatVisibility(uiStateState == ApiRequestState.SUCCESS) - -fun formatTestResultStatusText(uiState: DeviceUIState?): String { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.test_result_card_status_negative) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getString(R.string.test_result_card_status_positive) - else -> appContext.getString(R.string.test_result_card_status_invalid) +fun formatTestResultSpinnerVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.VISIBLE) { + View.GONE } -} -fun formatTestResultStatusColor(uiState: DeviceUIState?): Int { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NEGATIVE -> appContext.getColor(R.color.colorTextSemanticGreen) - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getColor(R.color.colorTextSemanticRed) - else -> appContext.getColor(R.color.colorTextSemanticRed) +fun formatTestResultVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + View.VISIBLE } -} -fun formatTestResult(uiState: DeviceUIState?): Spannable { +fun formatTestResultStatusText(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): String = + uiState.withSuccess(R.string.test_result_card_status_invalid) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.string.test_result_card_status_negative + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.string.test_result_card_status_positive + else -> R.string.test_result_card_status_invalid + } + }.let { CoronaWarnApplication.getAppContext().getString(it) } + +fun formatTestResultStatusColor(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(R.color.colorTextSemanticRed) { + when (it) { + DeviceUIState.PAIRED_NEGATIVE -> R.color.colorTextSemanticGreen + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN -> R.color.colorTextSemanticRed + else -> R.color.colorTextSemanticRed + } + }.let { CoronaWarnApplication.getAppContext().getColor(it) } + +fun formatTestResult(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Spannable { val appContext = CoronaWarnApplication.getAppContext() return SpannableStringBuilder() .append(appContext.getString(R.string.test_result_card_virus_name_text)) @@ -87,33 +93,36 @@ fun formatTestResult(uiState: DeviceUIState?): Spannable { ) } -fun formatTestResultCardContent(uiState: DeviceUIState?): Spannable { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> - SpannableString(appContext.getString(R.string.test_result_card_status_pending)) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> - SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) - - DeviceUIState.PAIRED_POSITIVE, - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) - else -> SpannableString("") +fun formatTestResultCardContent(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Spannable { + return uiState.withSuccess(SpannableString("")) { + val appContext = CoronaWarnApplication.getAppContext() + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> + SpannableString(appContext.getString(R.string.test_result_card_status_pending)) + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> + SpannableString(appContext.getString(R.string.test_result_card_status_invalid)) + + DeviceUIState.PAIRED_POSITIVE, + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_NEGATIVE -> formatTestResult(uiState) + else -> SpannableString("") + } } } -fun formatTestStatusIcon(uiState: DeviceUIState?): Drawable? { - val appContext = CoronaWarnApplication.getAppContext() - return when (uiState) { - DeviceUIState.PAIRED_NO_RESULT -> appContext.getDrawable(R.drawable.ic_test_result_illustration_pending) - DeviceUIState.PAIRED_POSITIVE_TELETAN, - DeviceUIState.PAIRED_POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive) - DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_negative) - DeviceUIState.PAIRED_ERROR, - DeviceUIState.PAIRED_REDEEMED -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - else -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid) - } +fun formatTestStatusIcon(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Drawable? { + return uiState.withSuccess(R.drawable.ic_test_result_illustration_invalid) { + when (it) { + DeviceUIState.PAIRED_NO_RESULT -> R.drawable.ic_test_result_illustration_pending + DeviceUIState.PAIRED_POSITIVE_TELETAN, + DeviceUIState.PAIRED_POSITIVE -> R.drawable.ic_test_result_illustration_positive + DeviceUIState.PAIRED_NEGATIVE -> R.drawable.ic_test_result_illustration_negative + DeviceUIState.PAIRED_ERROR, + DeviceUIState.PAIRED_REDEEMED -> R.drawable.ic_test_result_illustration_invalid + else -> R.drawable.ic_test_result_illustration_invalid + } + }.let { CoronaWarnApplication.getAppContext().getDrawable(it) } } fun formatTestResultRegisteredAtText(registeredAt: Date?): String { @@ -122,24 +131,30 @@ fun formatTestResultRegisteredAtText(registeredAt: Date?): String { .format(registeredAt?.toUIFormat(appContext)) } -fun formatTestResultPendingStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NO_RESULT) +fun formatTestResultPendingStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NO_RESULT) } -fun formatTestResultNegativeStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_NEGATIVE) +fun formatTestResultNegativeStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { formatVisibility(it == DeviceUIState.PAIRED_NEGATIVE) } -fun formatTestResultPositiveStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_POSITIVE || uiState == DeviceUIState.PAIRED_POSITIVE_TELETAN) +fun formatTestResultPositiveStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_POSITIVE || it == DeviceUIState.PAIRED_POSITIVE_TELETAN) + } -fun formatTestResultInvalidStepsVisible(uiState: DeviceUIState?): Int = - formatVisibility(uiState == DeviceUIState.PAIRED_ERROR || uiState == DeviceUIState.PAIRED_REDEEMED) +fun formatTestResultInvalidStepsVisible(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility(it == DeviceUIState.PAIRED_ERROR || it == DeviceUIState.PAIRED_REDEEMED) + } -fun formatShowRiskStatusCard(deviceUiState: DeviceUIState?): Int = - formatVisibility( - deviceUiState != DeviceUIState.PAIRED_POSITIVE && - deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN && - deviceUiState != DeviceUIState.SUBMITTED_FINAL - ) +fun formatShowRiskStatusCard(uiState: NetworkRequestWrapper<DeviceUIState, Throwable>?): Int = + uiState.withSuccess(View.GONE) { + formatVisibility( + it != DeviceUIState.PAIRED_POSITIVE && + it != DeviceUIState.PAIRED_POSITIVE_TELETAN && + it != DeviceUIState.SUBMITTED_FINAL + ) + } fun formatCountryIsoTagToLocalizedName(isoTag: String?): String { val country = if (isoTag != null) Locale("", isoTag).displayCountry else "" diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/serialization/GsonExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/serialization/GsonExtensions.kt index 601f833c3ded2777122e62d6814e07edff3380a3..f014dc54c28ca112b2a49db88917add6c83fedca 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/serialization/GsonExtensions.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/serialization/GsonExtensions.kt @@ -11,12 +11,13 @@ inline fun <reified T> Gson.fromJson(json: String): T = fromJson( object : TypeToken<T>() {}.type ) -inline fun <reified T> Gson.fromJson(file: File): T = file.reader().use { +inline fun <reified T> Gson.fromJson(file: File): T = file.bufferedReader().use { fromJson(it, object : TypeToken<T>() {}.type) } -inline fun <reified T> Gson.toJson(data: T, file: File) = file.writer().use { writer -> +inline fun <reified T> Gson.toJson(data: T, file: File) = file.bufferedWriter().use { writer -> toJson(data, writer) + writer.flush() } fun <T : Any> KClass<T>.getDefaultGsonTypeAdapter(): TypeAdapter<T> = Gson().getAdapter(this.java) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt index 9f3eddff208662fb70a1996c9756b4fcec245f27..40cd6f7685f0ef272a58f763ef318c676be1d5c2 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/viewmodel/CWAViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import de.rki.coronawarnapp.util.coroutine.DefaultDispatcherProvider import de.rki.coronawarnapp.util.coroutine.DispatcherProvider +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job import kotlinx.coroutines.launch import timber.log.Timber import kotlin.coroutines.CoroutineContext @@ -29,7 +29,13 @@ abstract class CWAViewModel constructor( fun launch( context: CoroutineContext = dispatcherProvider.Default, block: suspend CoroutineScope.() -> Unit - ): Job = viewModelScope.launch(context = context, block = block) + ) { + try { + viewModelScope.launch(context = context, block = block) + } catch (e: CancellationException) { + Timber.w(e, "launch()ed coroutine was canceled.") + } + } @CallSuper override fun onCleared() { diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml index a34166dd59df62849ed4df4572518c4ef5ea3e24..ecf73ebc437f034b2ec90d622215160aba1e9a20 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_calendar.xml @@ -9,10 +9,6 @@ <import type="de.rki.coronawarnapp.submission.Symptoms.StartOf" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <ScrollView diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml index 0fb5a5e024a58ccb1cb3699b28add5c405dee041..e577341719fc20305e51f0ef2b7ea5eaeb8d37e2 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_symptom_intro.xml @@ -7,10 +7,6 @@ <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <ScrollView diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml index 3521faa0f64126875ffb9317c6782159fa998fff..9b40a94aa99fca525d7cf72b5313f2b2e1f8cef3 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml @@ -34,7 +34,7 @@ style="?android:attr/progressBarStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(uiState.apiRequestState)}" + android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(uiState.deviceUiState)}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -48,7 +48,7 @@ android:layout_width="@dimen/match_constraint" android:layout_height="@dimen/match_constraint" android:layout_marginBottom="@dimen/button_padding_top_bottom" - android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(uiState.apiRequestState)}" + android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(uiState.deviceUiState)}" app:layout_constraintBottom_toTopOf="@+id/include_submission_test_result_buttons" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml b/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml index d95f4ed9f6f4201980e57caa01ec1e06c2d1ff6e..6cbbd318066a22c37059ae2209bd487f7851b341 100644 --- a/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml +++ b/Corona-Warn-App/src/main/res/layout/include_submission_symptom_length_selection.xml @@ -8,10 +8,6 @@ <import type="de.rki.coronawarnapp.submission.Symptoms.StartOf" /> - <variable - name="submissionViewModel" - type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" /> - </data> <androidx.constraintlayout.widget.ConstraintLayout diff --git a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml index dcdcdea37b799ecb255d0e23b0b3d68d0499f0ad..01364c7898c6942746da48f840b496513e186caf 100644 --- a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml +++ b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml @@ -13,7 +13,7 @@ <variable name="deviceUIState" - type="de.rki.coronawarnapp.util.DeviceUIState" /> + type="de.rki.coronawarnapp.util.NetworkRequestWrapper<de.rki.coronawarnapp.util.DeviceUIState,java.lang.Throwable>" /> </data> <androidx.constraintlayout.widget.ConstraintLayout diff --git a/Corona-Warn-App/src/main/res/values-bg/strings.xml b/Corona-Warn-App/src/main/res/values-bg/strings.xml index 7b20d46a9c3aa5b49191a72f9d811bc7c7f13a15..7190043852699ba78b8454cb60ccc1dadfe9f525 100644 --- a/Corona-Warn-App/src/main/res/values-bg/strings.xml +++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml @@ -109,6 +109,10 @@ <string name="notification_headline">"Corona-Warn-App"</string> <!-- XTXT: Notification body --> <string name="notification_body">"Имате нови ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ приложението Corona-Warn-App."</string> + <!-- XHED: Notification title - Reminder to share a positive test result--> + <string name="notification_headline_share_positive_result">"Можете да помогнете!"</string> + <!-- XTXT: Notification body - Reminder to share a positive test result--> + <string name="notification_body_share_positive_result">"МолÑ, Ñподелете резултата от теÑта Ñи и предупредете оÑтаналите потребители."</string> <!-- #################################### App Auto Update @@ -146,15 +150,13 @@ <item quantity="many">"%1$s Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</item> </plurals> <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк е било активно през %1$s от изминалите 14 дни."</string> + <string name="risk_card_body_saved_days">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк беше активно през %1$s от изминалите 14 дни."</string> <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"ÐÑма прекъÑване на региÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Ð’Ñе още не е извършвана проверка на излаганиÑта на риÑк."</string> + <string name="risk_card_body_not_yet_fetched">"Ð’Ñе още не е извършвана проверка на контактите."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Ðктуализирано: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Ежедневно актуализиране"</string> <!-- XTXT: risk card - hint to open the app daily --> <string name="risk_card_body_open_daily">"Бележка: МолÑ, отварÑйте приложението вÑеки ден, за да актуализирате ÑÐ²Ð¾Ñ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк."</string> <!-- XBUT: risk card - update risk --> @@ -185,13 +187,19 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"Ð’ момента не Ñе извършва региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"ПоÑледно региÑтриране на излагане на риÑк:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"ПоÑледна проверка за излагане на риÑк:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"Ðевъзможно региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> <string name="risk_card_outdated_risk_body">"РегиÑтърът на излаганиÑта на риÑк не е обновÑван повече от 24 чаÑа."</string> <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"ВашиÑÑ‚ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк не е обновÑван от повече от 48 чаÑа. МолÑ, актуализирайте го."</string> + <!-- XHED: risk card - risk check failed headline, no internet connection --> + <string name="risk_card_check_failed_no_internet_headline">"Проверката за излагане на риÑк е неуÑпешна"</string> + <!-- XTXT: risk card - risk check failed, please check your internet connection --> + <string name="risk_card_check_failed_no_internet_body">"СинхронизациÑта на Ñлучайни ИД ÑÑŠÑ Ñървъра е неуÑпешна. Можете да Ñ Ñ€ÐµÑтартирате ръчно."</string> + <!-- XTXT: risk card - risk check failed, restart button --> + <string name="risk_card_check_failed_no_internet_restart_button">"РеÑтартиране"</string> <!-- #################################### Risk Card - Progress @@ -245,9 +253,9 @@ <!-- XACT: main overview page title --> <string name="main_overview_accessibility_title">"Общ преглед"</string> <!-- XHED: App overview subtitle for tracing explanation--> - <string name="main_overview_subtitle_tracing">"РегиÑтриране на излаганиÑта на риÑк"</string> + <string name="main_overview_subtitle_tracing">"РегиÑÑ‚ÑŠÑ€ на риÑковете"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк е една от трите оÑновни функции на приложението. Когато е активирана, вÑички оÑъщеÑтвени контакти между уÑтройÑтва Ñе запиÑват, без да е необходимо да правите друго."</string> + <string name="main_overview_body_tracing">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк е една от трите оÑновни функции на приложението. Когато е активирана, вÑички оÑъщеÑтвени контакти между Ñмартфоните Ñе запиÑват, без да е необходимо да правите друго."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"РиÑк от заразÑване"</string> <!-- YTXT: App overview body text about risk levels --> @@ -357,7 +365,7 @@ <item quantity="many">"Изложени Ñте на повишен риÑк от заразÑване, защото преди %1$s дни Ñте имали продължителен и близък контакт Ñ Ð¿Ð¾Ð½Ðµ едно лице, диагноÑтицирано Ñ COVID-19."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"РиÑкът от заразÑване Ñе изчиÑлÑва въз оÑнова на данните за излагане (продължителноÑÑ‚ и близоÑÑ‚ на контакта), региÑтрирани на вашето локално уÑтройÑтво. Ðикой оÑвен Ð’Ð°Ñ Ð½Ðµ може да види или да получи данни за Вашето ниво на риÑк."</string> + <string name="risk_details_information_body_notice">"РиÑкът от заразÑване Ñе изчиÑлÑва въз оÑнова на данните за излагане (продължителноÑÑ‚ и близоÑÑ‚ на контакта), региÑтрирани във Ð²Ð°ÑˆÐ¸Ñ Ñмартфон. Ðикой оÑвен Ð’Ð°Ñ Ð½Ðµ може да види или да получи данни за Вашето ниво на риÑк."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> <string name="risk_details_information_body_notice_increased">"Това е причината да определим Ð’Ð°ÑˆÐ¸Ñ Ñ€Ð¸Ñк от заразÑване като повишен. РиÑкът от заразÑване Ñе изчиÑлÑва въз оÑнова на данните за излагане (продължителноÑÑ‚ и близоÑÑ‚ на контакта), региÑтрирани на вашето локално уÑтройÑтво. Ðикой оÑвен Ð’Ð°Ñ Ð½Ðµ може да види или да получи данни за Вашето ниво на риÑк. Когато Ñе приберете у дома, избÑгвайте близките контакти Ñ Ñ‡Ð»ÐµÐ½Ð¾Ð²ÐµÑ‚Ðµ на домакинÑтвото Ñи."</string> <!-- NOTR --> @@ -415,7 +423,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"Повече защита за Ð’Ð°Ñ Ð¸ за вÑички наÑ. С помощта на приложението Corona-Warn-App можем да прекъÑнем веригите на заразÑване много по-бързо."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"Превърнете уÑтройÑтвото Ñи в предупредителна ÑиÑтема за коронавируÑ. Прегледайте ÑÐ²Ð¾Ñ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк и разберете дали през поÑледните 14 дни Ñте имали близък контакт Ñ Ð»Ð¸Ñ†Ðµ, диагноÑтицирано Ñ COVID-19."</string> + <string name="onboarding_body">"Превърнете Ñмартфона Ñи в предупредителна ÑиÑтема за коронавируÑ. Прегледайте ÑÐ²Ð¾Ñ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк и разберете дали през поÑледните 14 дни Ñте имали близък контакт Ñ Ð»Ð¸Ñ†Ðµ, диагноÑтицирано Ñ COVID-19."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"Приложението региÑтрира контакти на лица поÑредÑтвом обмÑна на криптирани Ñлучайни ИД кодове между уÑтройÑтвата им, без да оÑъщеÑтвÑва доÑтъп до каквито и да било лични данни."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -432,13 +440,13 @@ <!-- XHED: onboarding(tracing) - how to enable tracing --> <string name="onboarding_tracing_headline">"Как да активирате региÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XHED: onboarding(tracing) - two/three line headline under an illustration --> - <string name="onboarding_tracing_subtitle">"За да уÑтановите дали за Ð’Ð°Ñ ÑъщеÑтвува риÑк от заразÑване, Ñ‚Ñ€Ñбва да активирате функциÑта за региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк."</string> + <string name="onboarding_tracing_subtitle">"За да уÑтановите дали Ñте заÑтрашени от заразÑване, Ñ‚Ñ€Ñбва да активирате функциÑта за региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк."</string> <!-- YTXT: onboarding(tracing) - explain tracing --> <string name="onboarding_tracing_body">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк Ñе извършва Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰Ñ‚Ð° на Bluetooth връзка, при коÑто ВашиÑÑ‚ Ñмартфон получава криптираните Ñлучайни идентификационни кодове на други потребители и изпраща до техните уÑтройÑтва Вашите Ñлучайни ИД. ФункциÑта може да бъде дезактивирана по вÑÑко време. "</string> <!-- YTXT: onboarding(tracing) - explain tracing --> <string name="onboarding_tracing_body_emphasized">"Криптираните Ñлучайни идентификатори предават Ñамо Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° дата, продължителноÑÑ‚ и близоÑÑ‚ на контакта (изчиÑлена от Ñилата на Ñигнала). СамоличноÑтта Ви не може да бъде уÑтановена по Ñлучайните ИД."</string> <!-- YTXT: onboarding(tracing) - easy language explain tracing link--> - <string name="onboarding_tracing_easy_language_explanation"><a href="https://www.bundesregierung.de/breg-de/themen/corona-warn-app/corona-warn-app-leichte-sprache-gebaerdensprache">"Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° приложението на опроÑтен и жеÑтомимичен език."</a></string> + <string name="onboarding_tracing_easy_language_explanation"><a href="https://www.bundesregierung.de/breg-de/themen/corona-warn-app/corona-warn-app-leichte-sprache-gebaerdensprache">"Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° приложението на опроÑтен и жеÑтомимичен език"</a></string> <!-- NOTR: onboarding(tracing) - easy language explain tracing link URL--> <string name="onboarding_tracing_easy_language_explanation_url">"https://www.bundesregierung.de/breg-de/themen/corona-warn-app/corona-warn-app-leichte-sprache-gebaerdensprache"</string> <!-- XBUT: onboarding(tracing) - button enable tracing --> @@ -452,7 +460,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"Ðазад"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Фоновите актуализации Ñа дезактивирани"</string> + <string name="onboarding_background_fetch_dialog_headline">"Фоновото опреÑнÑване за приложението е дезактивирано"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"Дезактивирали Ñте фоновите актуализации за приложението Corona-Warn-App. МолÑ, активирайте ги, за да използвате автоматичното региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк. Ðко не го направите, региÑтрирането на излаганиÑта може да бъде Ñтартирано Ñамо ръчно от приложението. Може да активирате фоновите актуализации за приложението от наÑтройките на Вашето уÑтройÑтво."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -494,7 +502,7 @@ <!-- XACT: Onboarding (datashare) page title --> <string name="onboarding_notifications_accessibility_title">"Въведение - Ñтраница 6 от 6: Получаване на Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ идентифициране на риÑкове"</string> <!-- XHED: onboarding(datashare) - about positive tests --> - <string name="onboarding_notifications_headline">"Получаване на Ð¿Ñ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ идентифициране на риÑкове"</string> + <string name="onboarding_notifications_headline">"ÐŸÑ€ÐµÐ´ÑƒÐ¿Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ риÑкове"</string> <!-- XHED: onboarding(datashare) - two/three line headline under an illustration --> <string name="onboarding_notifications_subtitle">"Приложението може да Ви уведомÑва автоматично за Ð’Ð°ÑˆÐ¸Ñ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк от заразÑване и да Ви предупреждава за нови заразÑÐ²Ð°Ð½Ð¸Ñ Ð½Ð° хора, Ñ ÐºÐ¾Ð¸Ñ‚Ð¾ Ñте били в контакт. Позволете на приложението да Ви изпраща извеÑтиÑ."</string> <!-- YTXT: onboarding(datashare) - explain test --> @@ -524,7 +532,7 @@ <!-- XTXT: settings - off, like a label next to a setting --> <string name="settings_off">"Изключено"</string> <!-- XHED: settings(tracing) - page title --> - <string name="settings_tracing_title">"РегиÑтриране на излаганиÑта на риÑк"</string> + <string name="settings_tracing_title">"РегиÑÑ‚ÑŠÑ€ на риÑковете"</string> <!-- XHED: settings(tracing) - headline bellow illustration --> <string name="settings_tracing_headline">"Как работи региÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XTXT: settings(tracing) - explain text in settings overview under headline --> @@ -606,7 +614,7 @@ <!-- XTXT: settings(notification) - next to a switch --> <string name="settings_notifications_subtitle_update_risk">"ПромÑна на Ð’Ð°ÑˆÐ¸Ñ Ñ€Ð¸Ñк от заразÑване"</string> <!-- XTXT: settings(notification) - next to a switch --> - <string name="settings_notifications_subtitle_update_test">"Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð½Ð° Ð’Ð°ÑˆÐ¸Ñ Ñ‚ÐµÑÑ‚ за COVID-19"</string> + <string name="settings_notifications_subtitle_update_test">"Ðаличие на резултат от Ваш теÑÑ‚ за COVID-19"</string> <!-- XBUT: settings(notification) - go to operating settings --> <string name="settings_notifications_button_open_settings">"Към наÑтройките за уÑтройÑтвото"</string> <!-- XACT: main (overview) - illustraction description, explanation image, displays notificatin status, active --> @@ -652,7 +660,7 @@ <!-- XTXT: settings(background priority) - explains user what to do on card if background priority is enabled --> <string name="settings_background_priority_card_body">"Можете да активирате и дезактивирате приоритетната работа във фонов режим от наÑтройките на уÑтройÑтвото."</string> <!-- XBUT: settings(background priority) - go to operating system settings button on card --> - <string name="settings_background_priority_card_button">"Към наÑтройките за уÑтройÑтвото"</string> + <string name="settings_background_priority_card_button">"Към наÑтройките на уÑтройÑтвото"</string> <!-- XHED : settings(background priority) - headline on card about the current status and what to do --> <string name="settings_background_priority_card_headline">"ПромÑна на приоритетната работа във фонов режим"</string> @@ -671,7 +679,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"ИнÑтитутът „Роберт Кох“ (RKI) е федералната Ñлужба за общеÑтвено здравеопазване в ГерманиÑ. Той е издател на приложението Corona-Warn-App по поръчка на федералното правителÑтво. Приложението е предназначено да бъде дигитално допълнение на вече въведените мерки за опазване на общеÑтвеното здраве: Ñоциално диÑтанциране, поддържане на виÑока хигиена и ноÑене на маÑки."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"Хората, които използват приложението, помагат за проÑледÑване и прекъÑване на веригите на заразÑване. Приложението запазва във Вашето уÑтройÑтво данните за контактите Ви Ñ Ð´Ñ€ÑƒÐ³Ð¸ хора. Получавате извеÑтие, ако Ñте били в контакт Ñ Ð»Ð¸Ñ†Ð°, които впоÑледÑтвие Ñа били диагноÑтицирани Ñ COVID-19. Вашата ÑамоличноÑÑ‚ и неприкоÑновеноÑтта на данните Ви Ñа защитени по вÑÑко време."</string> + <string name="information_about_body">"Ð’Ñеки, който използва приложението, помага за проÑледÑване и прекъÑване на веригите на заразÑване. Приложението запазва във Ð’Ð°ÑˆÐ¸Ñ Ñмартфон данните за контактите Ви Ñ Ð´Ñ€ÑƒÐ³Ð¸ хора. Получавате извеÑтие, ако Ñте били в контакт Ñ Ð»Ð¸Ñ†Ð°, които впоÑледÑтвие Ñа били диагноÑтицирани Ñ COVID-19. Вашата ÑамоличноÑÑ‚ и неприкоÑновеноÑтта на данните Ви Ñа защитени по вÑÑко време."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"Група лица използват Ñмартфоните Ñи, придвижвайки Ñе из града."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -689,13 +697,13 @@ <!-- XTXT: Path to the full blown terms html, to translate it exchange "_de" to "_en" and provide the corresponding html file --> <string name="information_terms_html_path">"terms_en.html"</string> <!-- XHED: Page title for technical contact and hotline information page, also menu item / button text --> - <string name="information_contact_title">"Гореща Ð»Ð¸Ð½Ð¸Ñ Ð·Ð° техничеÑки въпроÑи"</string> + <string name="information_contact_title">"ТехничеÑки въпроÑи"</string> <!-- XHED: Subtitle for technical contact and hotline information page --> <string name="information_contact_headline">"Как можем да Ви помогнем?"</string> <!-- YTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body">"За техничеÑки въпроÑи отноÑно Corona-Warn-App Ñе обадете на горещата линиÑ.\n\nЛицата ÑÑŠÑ Ñлухови Ð·Ð°Ñ‚Ñ€ÑƒÐ´Ð½ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³Ð°Ñ‚ да използват релейните уÑлуги Tess (за превод между пиÑмен немÑки и жеÑтомимичен език), за да Ñе обаждат на горещата телефонна линиÑ. Може да изтеглите приложението от Google Play."</string> <!-- XHED: Subtitle for technical contact and hotline information page --> - <string name="information_contact_subtitle_phone">"Гореща Ð»Ð¸Ð½Ð¸Ñ Ð·Ð° техничеÑки въпроÑи:"</string> + <string name="information_contact_subtitle_phone">"ТехничеÑки въпроÑи:"</string> <!-- XLNK: Button / hyperlink to phone call for technical contact and hotline information page --> <string name="information_contact_button_phone">"+49 800 7540001"</string> <!-- XBUT: CAUTION - ONLY UPDATE THE NUMBER IF NEEDED, ONLY NUMBERS AND NO SPECIAL CHARACTERS EXCEPT "+" and "space" ALLOWED IN THIS FIELD; --> @@ -703,9 +711,9 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"ÐашиÑÑ‚ екип за обÑлужване на клиенти е готов да Ви помогне."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"Езици: немÑки, английÑки, турÑки\nРаботно време:"<xliff:g id="line_break">"\n"</xliff:g>"понеделник до неделÑ: 7:00 - 22:00"<xliff:g id="line_break">"\n(Ñ Ð¸Ð·ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ на национални празници)"</xliff:g><xliff:g id="line_break">"\nОбаждането е безплатно."</xliff:g></string> + <string name="information_contact_body_open">"Езици: английÑки, немÑки, турÑки\nРаботно време:"<xliff:g id="line_break">"\n"</xliff:g>"понеделник до неделÑ: 7:00 - 22:00"<xliff:g id="line_break">"\n(Ñ Ð¸Ð·ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ на национални празници)"</xliff:g><xliff:g id="line_break">"\nОбаждането е безплатно."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_other">"Ðко имате въпроÑи, Ñвързани ÑÑŠÑ Ð·Ð´Ñ€Ð°Ð²ÐµÑ‚Ð¾, Ñе обадете на Ð»Ð¸Ñ‡Ð½Ð¸Ñ Ñи лекар или на горещата Ð»Ð¸Ð½Ð¸Ñ Ð½Ð° Ñлужбата за медицинÑка помощ на телефон 116 117"</string> + <string name="information_contact_body_other">"Ðко имате въпроÑи, Ñвързани ÑÑŠÑ Ð·Ð´Ñ€Ð°Ð²ÐµÑ‚Ð¾, Ñе обадете на Ð»Ð¸Ñ‡Ð½Ð¸Ñ Ñи лекар или на горещата Ð»Ð¸Ð½Ð¸Ñ Ð½Ð° Ñлужбата за медицинÑка помощ на телефон 116 117."</string> <!-- XACT: describes illustration --> <string name="information_contact_illustration_description">"Мъж ÑÑŠÑ Ñлушалки провежда телефонен разговор."</string> <!-- XLNK: Menu item / hyper link / button text for navigation to FAQ website --> @@ -788,9 +796,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"Ðазад"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Грешки в теÑта"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"QR кодът вече не е валиден"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"Възникнаха грешки при проверката на Ð’Ð°ÑˆÐ¸Ñ Ñ‚ÐµÑÑ‚. Този QR код вече е изтекъл."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"ВашиÑÑ‚ теÑÑ‚ е направен преди повече от 21 дни и вече не може да бъде региÑтриран в приложението. Ðко в бъдеще Ñи правите нов теÑÑ‚, Ð¼Ð¾Ð»Ñ Ñканирайте QR кода в момента, в който го получите."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string> @@ -851,7 +859,7 @@ <!-- Submission Test Result --> <!-- XHED: Page headline for test result --> - <string name="submission_test_result_headline">"Резултат от теÑта"</string> + <string name="submission_test_result_headline">"Резултат от теÑÑ‚"</string> <!-- XHED: Page subheadline for test result --> <string name="submission_test_result_subtitle">"Как работи:"</string> <!-- XHED: Page headline for results next steps --> @@ -865,15 +873,15 @@ <!-- XBUT: test result pending : refresh button --> <string name="submission_test_result_pending_refresh_button">"Ðктуализиране"</string> <!-- XBUT: test result pending : remove the test button --> - <string name="submission_test_result_pending_remove_test_button">"Изтриване на теÑÑ‚"</string> + <string name="submission_test_result_pending_remove_test_button">"Изтриване на теÑта"</string> <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Резултатът от Ð’Ð°ÑˆÐ¸Ñ Ñ‚ÐµÑÑ‚"</string> <!-- YTXT: Body text for next steps section of test negative result --> <string name="submission_test_result_negative_steps_negative_body">"ВашиÑÑ‚ лабораторен резултат не потвърждава заразÑване Ñ ÐºÐ¾Ñ€Ð¾Ð½Ð°Ð²Ð¸Ñ€ÑƒÑ SARS-CoV-2.\n\nМолÑ, изтрийте теÑта от приложението Corona-Warn-App, за да можете да запазите нов код на теÑÑ‚, ако е необходимо."</string> <!-- XBUT: negative test result : remove the test button --> - <string name="submission_test_result_negative_remove_test_button">"Изтриване на теÑÑ‚"</string> + <string name="submission_test_result_negative_remove_test_button">"Изтриване на теÑта"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"Предупреждаване на оÑтаналите потребители"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"Предупредете другите"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"Споделете Ñвоите Ñлучайни идентификатори и предупредете околните.\nПомогнете ни да определÑме риÑка от заразÑване за Ñ‚ÑÑ… по-точно, като Ñподелите и кога за пръв път Ñте забелÑзали Ñимптомите на коронавируÑната инфекциÑ."</string> <!-- XBUT: positive test result : continue button --> @@ -952,13 +960,13 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"РегиÑтрирайте теÑта Ñи, като Ñканирате QR кода на документа."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"СъглаÑие"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"ПоверителноÑÑ‚"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"By tapping “Acceptâ€, you consent to the App querying the status of your coronavirus test and displaying it in the App. This feature is available to you if you have received a QR code and have consented to your test result being transmitted to the App’s server system. As soon as the testing lab has stored your test result on the server, you will be able to see the result in the App. If you have enabled notifications, you will also receive a notification outside the App telling you that your test result has been received. However, for privacy reasons, the test result itself will only be displayed in the App. You can withdraw this consent at any time by deleting your test registration in the App. Withdrawing your consent will not affect the lawfulness of processing before its withdrawal. Further information can be found in the menu under “Data Privacyâ€."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Приемам"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Разрешавам"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Ðе приемам"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Ðе разрешавам"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"ТÐРкод"</string> <!-- YTXT: Body text for TAN code dispatcher option --> @@ -972,7 +980,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"Предупреждаване на оÑтаналите потребители"</string> + <string name="submission_positive_other_warning_title">"Предупредете другите"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"МолÑ, помогнете на вÑички наÑ!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -980,7 +988,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Приемам"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"УÑтройÑтво предава на ÑиÑтемата Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° положителен резултат от теÑÑ‚."</string> + <string name="submission_positive_other_illustration_description">"Смартфонът предава на ÑиÑтемата Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° положителен резултат от теÑÑ‚."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"Ð’ момента в международното региÑтриране на излаганиÑта учаÑтват Ñледните държави:"</string> @@ -1071,9 +1079,9 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"РегиÑтрирайте теÑта, като въведете ТÐРкода в приложението."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Езици: \nнемÑки, английÑки, турÑки\n\nРаботно време:\nот понеделник до неделÑ: 24 чаÑа\n\nОбажданиÑта Ñа безплатни."</string> + <string name="submission_contact_operating_hours_body">"Езици: \nанглийÑки, немÑки, турÑки\n\nРаботно време:\nот понеделник до неделÑ: 24 чаÑа\n\nОбажданиÑта Ñа безплатни."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="submission_contact_body_other">"Ðко имате въпроÑи, Ñвързани ÑÑŠÑ Ð·Ð´Ñ€Ð°Ð²ÐµÑ‚Ð¾, Ñе обадете на Ð»Ð¸Ñ‡Ð½Ð¸Ñ Ñи лекар или на горещата Ð»Ð¸Ð½Ð¸Ñ Ð½Ð° Ñлужбата за медицинÑка помощ на телефон 116 117"</string> + <string name="submission_contact_body_other">"Ðко имате въпроÑи, Ñвързани ÑÑŠÑ Ð·Ð´Ñ€Ð°Ð²ÐµÑ‚Ð¾, Ñе обадете на Ð»Ð¸Ñ‡Ð½Ð¸Ñ Ñи лекар или на горещата Ð»Ð¸Ð½Ð¸Ñ Ð½Ð° Ñлужбата за медицинÑка помощ на телефон 116 117."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"Обадете Ñе на горещата Ð»Ð¸Ð½Ð¸Ñ Ð¸ поиÑкайте ТÐРкод"</string> @@ -1100,7 +1108,7 @@ <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> - <string name="submission_status_card_title_fetching">"Извършва Ñе извличане на данни"</string> + <string name="submission_status_card_title_fetching">"Извършва Ñе извличане на данни..."</string> <!-- XHED: Page title for the various submission status: unregistered --> <string name="submission_status_card_title_unregistered">"Правили ли Ñте Ñи теÑÑ‚?"</string> <!-- XHED: Page title for the various submission status: pending --> @@ -1201,7 +1209,10 @@ <string name="errors_google_update_needed">"Вашето приложение Corona-Warn-App е инÑталирано правилно, но „СиÑтемата за извеÑÑ‚Ñване при Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк от заразÑване Ñ COVID-19†не Ñе предлага за операционната ÑиÑтема на Ð’Ð°ÑˆÐ¸Ñ Ñмартфон. Това означава, че не можете да използвате приложението Corona-Warn-App. Повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да намерите в Ñтраницата „ЧЗВ“ на адреÑ: https://www.coronawarn.app/en/faq/"</string> <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"Приложението Corona-Warn-App работи правилно, но не можем да актуализираме Ð’Ð°ÑˆÐ¸Ñ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк. РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк вÑе още е активно и функционира правилно. За повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¿Ð¾Ñетете Ñтраницата „ЧЗВ“ на адреÑ: https://www.coronawarn.app/en/faq/"</string> - + <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_title">"Лимитът вече е доÑтигнат"</string> + <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_description">"Ðе може да правите повече проверки за излагане на риÑк до ÐºÑ€Ð°Ñ Ð½Ð° денÑ, тъй като Ñте доÑтигнали макÑÐ¸Ð¼Ð°Ð»Ð½Ð¸Ñ Ð±Ñ€Ð¾Ð¹ проверки, определен от вашата операционна ÑиÑтема. МолÑ, проверете ÑтатуÑа Ñи на риÑк утре."</string> <!-- #################################### Generic Error Messages ###################################### --> @@ -1359,7 +1370,7 @@ <!-- YMSG: Onboarding tracing step third section in interoperability after the title. --> <string name="interoperability_onboarding_randomid_download_free">"Ежедневното изтеглÑне на ÑпиÑъка ÑÑŠÑ Ñлучайни идентификатори обикновено е безплатно за ВаÑ. Това означава, че мобилните оператори не такÑуват използваните от приложението данни и не начиÑлÑват за Ñ‚ÑÑ… такÑи за роуминг в други държави от ЕС. За повече подробноÑти Ñе обърнете към ÑÐ²Ð¾Ñ Ð¼Ð¾Ð±Ð¸Ð»ÐµÐ½ оператор."</string> <!-- XTXT: Small header above the country list in the onboarding screen for interoperability. --> - <string name="interoperability_onboarding_list_title">"Ð’ момента в обмена учаÑтват Ñредните държави:"</string> + <string name="interoperability_onboarding_list_title">"Ð’ момента в обмена учаÑтват Ñледните държави:"</string> <!-- XTXT: Description of the expanded terms in delta interopoerability screen part 1 --> <string name="interoperability_onboarding_delta_expanded_terms_text_part_1">"УÑловиÑта за ползване Ñъщо бÑха актуализирани, за да отразÑÑ‚ разширената функционалноÑÑ‚ на приложението."</string> @@ -1389,6 +1400,6 @@ <!-- YMSW: Subtitle for the interoperability onboarding if country download fails --> <string name="interoperability_onboarding_list_subtitle_failrequest_no_network">"Възможно е да нÑмате доÑтъп до интернет. МолÑ, проверете дали имате връзка."</string> <!-- XBUT: Title for the interoperability onboarding Settings-Button if no network is available --> - <string name="interoperability_onboarding_list_button_title_no_network">"Към наÑтройките за уÑтройÑтвото"</string> + <string name="interoperability_onboarding_list_button_title_no_network">"Към наÑтройките на уÑтройÑтвото"</string> </resources> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values-de/legal_strings.xml b/Corona-Warn-App/src/main/res/values-de/legal_strings.xml index e2eb4cebe4ba6da24b7ef14d76ae4b65e4e2bb22..7f0c34277b2fa2ab614afd2ce7c969b6a6cf1225 100644 --- a/Corona-Warn-App/src/main/res/values-de/legal_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/legal_strings.xml @@ -11,5 +11,5 @@ <!-- XHED: onboarding(tracing) - headline for consent information --> <string name="onboarding_tracing_headline_consent">"Einwilligungserklärung"</string> <!-- YTXT: onboarding(tracing) - body for consent information --> - <string name="onboarding_tracing_body_consent">"Um zu erfahren, ob Sie Risiko-Begegnungen mit App-Nutzern der teilnehmenden Länder hatten und für Sie ein Infektionsrisiko besteht, müssen Sie die Risiko-Ermittlung aktivieren. Der Aktivierung der Risiko-Ermittlung und der damit im Zusammenhang stehenden Datenverarbeitung durch die App stimmen Sie mit Antippen des Buttons „Risiko-Ermittlung aktivieren“ zu.\n\nUm die Risiko-Ermittlung nutzen zu können müssen Sie zudem auf Ihrem Android-Smartphone die von Google bereitgestellte Funktion „COVID-19-Benachrichtigungen“ aktivieren und für die Corona-Warn-App freigeben.\n\nBei aktiviertem COVID-19-Benachrichtigungssystem erzeugt Ihr Android-Smartphone kontinuierlich Zufalls-IDs und versendet diese per Bluetooth, damit diese von Smartphones in Ihrer Umgebung empfangen werden können. Umgekehrt empfängt Ihr Android-Smartphone die Zufalls-IDs von anderen Smartphones. Die eigenen und die von anderen Smartphones empfangenen Zufalls-IDs werden von Ihrem Android-Smartphone aufgezeichnet und dort für 14 Tage gespeichert.\n\nFür die Risiko-Ermittlung lädt die App täglich eine aktuelle Liste mit den Zufalls-IDs aller Nutzer herunter, die diese über ihre offizielle Corona-App geteilt haben. Diese Liste wird dann mit den von Ihrem Smartphone aufgezeichneten Zufalls-IDs anderer Nutzer verglichen.\n\nWenn dabei eine Risiko-Begegnung festgestellt wird, werden Sie von der App informiert. In diesem Fall erhält die App Zugriff auf die von Ihrem Smartphone zu der Risiko-Begegnung aufgezeichneten Daten (Datum, Dauer und Bluetooth-Signalstärke des Kontakts). Aus der Bluetooth-Signalstärke wird der räumliche Abstand zu dem anderen Nutzer abgeleitet (je stärker das Signal, desto geringer der Abstand). Diese Angaben werden von der App ausgewertet, um Ihr Infektionsrisiko zu berechnen und Ihnen Verhaltensempfehlungen zu geben. Diese Auswertung wird ausschließlich lokal auf Ihrem Smartphone durchgeführt.\n\nAußer Ihnen erfährt niemand (auch nicht das RKI oder die Gesundheitsbehörden teilnehmender Länder), ob Sie eine Risiko-Begegnung hatten und welches Infektionsrisiko für Sie ermittelt wird.\n\nZum Widerruf Ihrer Einwilligung in die Risiko-Ermittlung können Sie die Funktion über den Schieberegler innerhalb der App deaktivieren oder die App löschen. Wenn Sie die Risiko-Ermittlung wieder nutzen möchten, können Sie den Schieberegler erneut aktivieren oder die App erneut installieren. Wenn Sie die Risiko-Ermittlung deaktivieren, prüft die App nicht mehr, ob Sie Risiko-Begegnungen hatten. Um auch das Aussenden und den Empfang der Zufalls-IDs anzuhalten, müssen Sie das COVID-19-Benachrichtigungssystem in den Einstellungen Ihres Android-Smartphones deaktivieren. Bitte beachten Sie, dass die vom COVID-19-Benachrichtigungssystem Ihres Android-Smartphones aufgezeichneten fremden und eigenen Zufalls-IDs nicht von der App gelöscht werden. Diese können Sie nur in den Einstellungen Ihres Android-Smartphones dauerhaft löschen.\n\nDie Datenschutzerklärung der App (einschließlich Informationen zur Datenverarbeitung für die länderübergreifende Risiko-Ermittlung) finden Sie unter dem Menüpunkt „App-Informationen“ > „Datenschutz“."</string> + <string name="onboarding_tracing_body_consent">"Um zu erfahren, ob Sie Risiko-Begegnungen mit App-Nutzern der teilnehmenden Länder hatten und für Sie ein Infektionsrisiko besteht, müssen Sie die Risiko-Ermittlung aktivieren. Der Aktivierung der Risiko-Ermittlung und der damit im Zusammenhang stehenden Datenverarbeitung durch die App stimmen Sie mit Antippen des Buttons „Risiko-Ermittlung aktivieren“ zu.\n\nUm die Risiko-Ermittlung nutzen zu können, müssen Sie zudem auf Ihrem Android-Smartphone die von Google bereitgestellte Funktion „COVID-19-Benachrichtigungen“ aktivieren und für die Corona-Warn-App freigeben.\n\nBei aktiviertem COVID-19-Benachrichtigungssystem erzeugt Ihr Android-Smartphone kontinuierlich Zufalls-IDs und versendet diese per Bluetooth, damit diese von Smartphones in Ihrer Umgebung empfangen werden können. Umgekehrt empfängt Ihr Android-Smartphone die Zufalls-IDs von anderen Smartphones. Die eigenen und die von anderen Smartphones empfangenen Zufalls-IDs werden von Ihrem Android-Smartphone aufgezeichnet und dort für 14 Tage gespeichert.\n\nFür die Risiko-Ermittlung lädt die App täglich eine aktuelle Liste mit den Zufalls-IDs aller Nutzer herunter, die diese über ihre offizielle Corona-App geteilt haben. Diese Liste wird dann mit den von Ihrem Smartphone aufgezeichneten Zufalls-IDs anderer Nutzer verglichen.\n\nWenn dabei eine Risiko-Begegnung festgestellt wird, werden Sie von der App informiert. In diesem Fall erhält die App Zugriff auf die von Ihrem Smartphone zu der Risiko-Begegnung aufgezeichneten Daten (Datum, Dauer und Bluetooth-Signalstärke des Kontakts). Aus der Bluetooth-Signalstärke wird der räumliche Abstand zu dem anderen Nutzer abgeleitet (je stärker das Signal, desto geringer der Abstand). Diese Angaben werden von der App ausgewertet, um Ihr Infektionsrisiko zu berechnen und Ihnen Verhaltensempfehlungen zu geben. Diese Auswertung wird ausschließlich lokal auf Ihrem Smartphone durchgeführt.\n\nAußer Ihnen erfährt niemand (auch nicht das RKI oder die Gesundheitsbehörden teilnehmender Länder), ob Sie eine Risiko-Begegnung hatten und welches Infektionsrisiko für Sie ermittelt wird.\n\nZum Widerruf Ihrer Einwilligung in die Risiko-Ermittlung können Sie die Funktion über den Schieberegler innerhalb der App deaktivieren oder die App löschen. Wenn Sie die Risiko-Ermittlung wieder nutzen möchten, können Sie den Schieberegler erneut aktivieren oder die App erneut installieren. Wenn Sie die Risiko-Ermittlung deaktivieren, prüft die App nicht mehr, ob Sie Risiko-Begegnungen hatten. Um auch das Aussenden und den Empfang der Zufalls-IDs anzuhalten, müssen Sie das COVID-19-Benachrichtigungssystem in den Einstellungen Ihres Android-Smartphones deaktivieren. Bitte beachten Sie, dass die vom COVID-19-Benachrichtigungssystem Ihres Android-Smartphones aufgezeichneten fremden und eigenen Zufalls-IDs nicht von der App gelöscht werden. Diese können Sie nur in den Einstellungen Ihres Android-Smartphones dauerhaft löschen.\n\nDie Datenschutzerklärung der App (einschließlich Informationen zur Datenverarbeitung für die länderübergreifende Risiko-Ermittlung) finden Sie unter dem Menüpunkt „App-Informationen“ > „Datenschutz“."</string> </resources> diff --git a/Corona-Warn-App/src/main/res/values-en/strings.xml b/Corona-Warn-App/src/main/res/values-en/strings.xml index 568659f0360416649e4005c198a66d174be6ff68..9d8ce585c349ee851eb51c61acf866140fad5166 100644 --- a/Corona-Warn-App/src/main/res/values-en/strings.xml +++ b/Corona-Warn-App/src/main/res/values-en/strings.xml @@ -109,6 +109,10 @@ <string name="notification_headline">"Corona-Warn-App"</string> <!-- XTXT: Notification body --> <string name="notification_body">"You have new messages from your Corona-Warn-App."</string> + <!-- XHED: Notification title - Reminder to share a positive test result--> + <string name="notification_headline_share_positive_result">"You can help!"</string> + <!-- XTXT: Notification body - Reminder to share a positive test result--> + <string name="notification_body_share_positive_result">"Please share your test result and warn others."</string> <!-- #################################### App Auto Update @@ -150,11 +154,9 @@ <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"Exposure logging permanently active"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Exposures have not yet been checked."</string> + <string name="risk_card_body_not_yet_fetched">"Encounters have not yet been checked."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Updated: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Updated daily"</string> <!-- XTXT: risk card - hint to open the app daily --> <string name="risk_card_body_open_daily">"Note: Please open the app daily to update your risk status."</string> <!-- XBUT: risk card - update risk --> @@ -185,13 +187,19 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"Exposure logging stopped"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"Last exposure logging:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"Last exposure check:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"Exposure logging is not possible"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> <string name="risk_card_outdated_risk_body">"Your exposure logging could not be updated for more than 24 hours."</string> <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"Your risk status has not been updated for more than 48 hours. Please update your risk status."</string> + <!-- XHED: risk card - risk check failed headline, no internet connection --> + <string name="risk_card_check_failed_no_internet_headline">"Exposure check failed"</string> + <!-- XTXT: risk card - risk check failed, please check your internet connection --> + <string name="risk_card_check_failed_no_internet_body">"The synchronization of random IDs with the server failed. You can restart the synchronization manually."</string> + <!-- XTXT: risk card - risk check failed, restart button --> + <string name="risk_card_check_failed_no_internet_restart_button">"Restart"</string> <!-- #################################### Risk Card - Progress @@ -247,7 +255,7 @@ <!-- XHED: App overview subtitle for tracing explanation--> <string name="main_overview_subtitle_tracing">"Exposure Logging"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"Exposure logging is one of the three central features of the app. When you activate it, encounters with people\'s devices are logged. You don\'t have to do anything else."</string> + <string name="main_overview_body_tracing">"Exposure logging is one of three central features of the app. Once you activate it, encounters with people\'s smartphones are logged. You don\'t have to do anything else."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"Risk of Infection"</string> <!-- YTXT: App overview body text about risk levels --> @@ -357,9 +365,9 @@ <item quantity="many">"You have an increased risk of infection because you were last exposed %1$s days ago over a longer period of time and at close proximity to at least one person diagnosed with COVID-19."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your device. Your risk of infection cannot be seen by, or passed on to, anyone else."</string> + <string name="risk_details_information_body_notice">"Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your smartphone. Your risk of infection cannot be seen by, or passed on to, anyone else."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> - <string name="risk_details_information_body_notice_increased">"Therefore, your risk of infection has been ranked as increased. Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your device. Your risk of infection cannot be seen by, or passed on to, anyone else. When you get home, please also avoid close contact with members of your family or household."</string> + <string name="risk_details_information_body_notice_increased">"Therefore, your risk of infection has been ranked as increased. Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your smartphone. Your risk of infection cannot be seen by, or passed on to, anyone else. When you get home, please also avoid close contact with members of your family or household."</string> <!-- NOTR --> <string name="risk_details_button_update">@string/risk_card_button_update</string> <!-- NOTR --> @@ -415,7 +423,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"More protection for you and for us all. By using the Corona-Warn-App we can break infection chains much quicker."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"Turn your device into a coronavirus warning system. Get an overview of your risk status and find out whether you\'ve had close contact with anyone diagnosed with COVID-19 in the last 14 days."</string> + <string name="onboarding_body">"Turn your smartphone into a coronavirus warning system. Get an overview of your risk status and find out whether you\'ve had close contact with anyone diagnosed with COVID-19 in the last 14 days."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"The app logs encounters between individuals by exchanging encrypted, random IDs between their devices, whereby no personal data whatsoever is accessed."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -452,7 +460,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"Back"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Background updates deactivated"</string> + <string name="onboarding_background_fetch_dialog_headline">"Background app refresh deactivated"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"You have deactivated background updates for the Corona-Warn-App. Please activate background updates to use automatic exposure logging. If you do not activate background updates, you can only start exposure logging manually in the app. You can activate background updates for the app in your device settings."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -474,7 +482,7 @@ <!-- XBUT: onboarding(tracing) - dialog about manual checking button --> <string name="onboarding_manual_required_dialog_button">"OK"</string> <!-- XACT: onboarding(tracing) - illustraction description, header image --> - <string name="onboarding_tracing_illustration_description">"Three people have activated exposure logging on their devices, which will log their encounters with each other."</string> + <string name="onboarding_tracing_illustration_description">"Three persons have activated exposure logging on their smartphones, which will log their encounters with each other."</string> <!-- XHED: onboarding(tracing) - location explanation for bluetooth headline --> <string name="onboarding_tracing_location_headline">"Allow location access"</string> <!-- XTXT: onboarding(tracing) - location explanation for bluetooth body text --> @@ -671,7 +679,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"Robert Koch Institute (RKI) is Germany’s federal public health body. The RKI publishes the Corona-Warn-App on behalf of the Federal Government. The app is intended as a digital complement to public health measures already introduced: social distancing, hygiene, and face masks."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"People who use the app help to trace and break chains of infection. The app saves encounters with other people locally on your device. You are notified if you have encountered people who were later diagnosed with COVID-19. Your identity and privacy are always protected."</string> + <string name="information_about_body">"Whoever uses the app helps to trace and break chains of infection. The app saves encounters with other persons locally on your smartphone. You are notified if you have encountered persons who were later diagnosed with COVID-19. Your identity and privacy are always protected."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"A group of persons use their smartphones around town."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -703,9 +711,9 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"Our customer service is here to help."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"Languages: German, English, Turkish\nBusiness hours:"<xliff:g id="line_break">"\n"</xliff:g>"Monday to Saturday: 7am - 10pm"<xliff:g id="line_break">"\n(except national holidays)"</xliff:g><xliff:g id="line_break">"\nThe call is free of charge."</xliff:g></string> + <string name="information_contact_body_open">"Languages: English, German, Turkish\nBusiness hours:"<xliff:g id="line_break">"\n"</xliff:g>"Monday to Saturday: 7am - 10pm"<xliff:g id="line_break">"\n(except national holidays)"</xliff:g><xliff:g id="line_break">"\nThe call is free of charge."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the hotline for the medical emergency service, telephone: 116 117."</string> + <string name="information_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the medical emergency service hotline, telephone: 116 117."</string> <!-- XACT: describes illustration --> <string name="information_contact_illustration_description">"A man wears a headset while making a phone call."</string> <!-- XLNK: Menu item / hyper link / button text for navigation to FAQ website --> @@ -788,9 +796,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"Back"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Test has errors"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"QR code no longer valid"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"There was a problem evaluating your test. Your QR code has already expired."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"Your test is more than 21 days old and can no longer be registered in the app. If you are tested again in future, please make sure to scan the QR code as soon as you get it."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string> @@ -865,15 +873,15 @@ <!-- XBUT: test result pending : refresh button --> <string name="submission_test_result_pending_refresh_button">"Update"</string> <!-- XBUT: test result pending : remove the test button --> - <string name="submission_test_result_pending_remove_test_button">"Delete Test"</string> + <string name="submission_test_result_pending_remove_test_button">"Remove test"</string> <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Your Test Result"</string> <!-- YTXT: Body text for next steps section of test negative result --> <string name="submission_test_result_negative_steps_negative_body">"The laboratory result indicates no verification that you have coronavirus SARS-CoV-2.\n\nPlease delete the test from the Corona-Warn-App, so that you can save a new test code here if necessary."</string> <!-- XBUT: negative test result : remove the test button --> - <string name="submission_test_result_negative_remove_test_button">"Delete Test"</string> + <string name="submission_test_result_negative_remove_test_button">"Remove test"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"Warning Others"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"Warn Others"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"Share your random IDs and warn others.\nHelp determine the risk of infection for others more accurately by also indicating when you first noticed any coronavirus symptoms."</string> <!-- XBUT: positive test result : continue button --> @@ -952,13 +960,13 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"Register your test by scanning the QR code of your test document."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"Consent"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"Declaration of Consent"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"By tapping “Acceptâ€, you consent to the App querying the status of your coronavirus test and displaying it in the App. This feature is available to you if you have received a QR code and have consented to your test result being transmitted to the App’s server system. As soon as the testing lab has stored your test result on the server, you will be able to see the result in the App. If you have enabled notifications, you will also receive a notification outside the App telling you that your test result has been received. However, for privacy reasons, the test result itself will only be displayed in the App. You can withdraw this consent at any time by deleting your test registration in the App. Withdrawing your consent will not affect the lawfulness of processing before its withdrawal. Further information can be found in the menu under “Data Privacyâ€."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Allow"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Do Not Accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Do Not Allow"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"TAN"</string> <!-- YTXT: Body text for TAN code dispatcher option --> @@ -972,7 +980,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"Warning Others"</string> + <string name="submission_positive_other_warning_title">"Warn Others"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"Please help all of us!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -980,7 +988,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Accept"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"A device transmits an encrypted positive test diagnosis to the system."</string> + <string name="submission_positive_other_illustration_description">"A smartphone transmits an encrypted positive test diagnosis to the system."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"The following countries currently participate in transnational exposure logging:"</string> @@ -1046,7 +1054,7 @@ <!-- XBUT: symptom initial screen no button --> <string name="submission_symptom_negative_button">"No"</string> <!-- XBUT: symptom initial screen no information button --> - <string name="submission_symptom_no_information_button">"No answer"</string> + <string name="submission_symptom_no_information_button">"No statement"</string> <!-- XBUT: symptom initial screen continue button --> <string name="submission_symptom_further_button">"Next"</string> @@ -1071,9 +1079,9 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Register the test by entering the TAN in the app."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> + <string name="submission_contact_operating_hours_body">"Languages: \nEnglish, German, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="submission_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the hotline for the medical emergency service, telephone: 116 117."</string> + <string name="submission_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the medical emergency service hotline, telephone: 116 117."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"Call the hotline and request a TAN"</string> @@ -1096,7 +1104,7 @@ <!-- XBUT: symptom calendar screen more than 2 weeks button --> <string name="submission_symptom_more_two_weeks">"More than 2 weeks ago"</string> <!-- XBUT: symptom calendar screen verify button --> - <string name="submission_symptom_verify">"No answer"</string> + <string name="submission_symptom_verify">"No statement"</string> <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> @@ -1157,7 +1165,7 @@ <!-- YTXT: invalid status text --> <string name="test_result_card_status_invalid">"Evaluation is not possible"</string> <!-- YTXT: pending status text --> - <string name="test_result_card_status_pending">"Your result is not available yet"</string> + <string name="test_result_card_status_pending">"Your result is not yet available"</string> <!-- XHED: Title for further info of test result negative --> <string name="test_result_card_negative_further_info_title">"Other information:"</string> <!-- YTXT: Content for further info of test result negative --> @@ -1201,7 +1209,10 @@ <string name="errors_google_update_needed">"Your Corona-Warn-App is correctly installed, but the \"COVID-19 Exposure Notifications System\" is not available on your smartphone\'s operating system. This means that you cannot use the Corona-Warn-App. For further information, please see our FAQ page: https://www.coronawarn.app/en/faq/"</string> <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"The Corona-Warn-App is running correctly, but we cannot update your current risk status. Exposure logging remains active and is working correctly. For further information, please see our FAQ page: https://www.coronawarn.app/en/faq/"</string> - + <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_title">"Limit already reached"</string> + <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_description">"No more exposure checks possible today, as you have reached the maximum number of checks per day defined by your operating system. Please check your risik status again tomorrow."</string> <!-- #################################### Generic Error Messages ###################################### --> @@ -1357,7 +1368,7 @@ <!-- YMSG: Onboarding tracing step second section in interoperability after the title --> <string name="interoperability_onboarding_second_section">"When a user submits their random IDs to the exchange server jointly operated by the participating countries, users of the official corona apps in all these countries can be warned of potential exposure."</string> <!-- YMSG: Onboarding tracing step third section in interoperability after the title. --> - <string name="interoperability_onboarding_randomid_download_free">"The daily download of the list with the random IDs is usually free of charge for you. Specifically, this means that mobile network operators do not charge you for the data used by the app in this context, and nor do they apply roaming charges for this in other EU countries. Please contact your mobile network operator for more information."</string> + <string name="interoperability_onboarding_randomid_download_free">"The daily download of the list with the random IDs is usually free of charge for you. Specifically, this means that mobile network operators do not charge you for the data used by the app in this context, nor do they apply roaming charges for this in other EU countries. Please contact your mobile network operator for more information."</string> <!-- XTXT: Small header above the country list in the onboarding screen for interoperability. --> <string name="interoperability_onboarding_list_title">"The following countries currently participate:"</string> diff --git a/Corona-Warn-App/src/main/res/values-pl/strings.xml b/Corona-Warn-App/src/main/res/values-pl/strings.xml index 0f8a8191a508dc0d04aa93af8d0c2aca7ebc8576..7a02cc77e432e7b759abccf6b70709355bc9e5bb 100644 --- a/Corona-Warn-App/src/main/res/values-pl/strings.xml +++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml @@ -109,6 +109,10 @@ <string name="notification_headline">"Corona-Warn-App"</string> <!-- XTXT: Notification body --> <string name="notification_body">"Masz nowe wiadomoÅ›ci od Corona-Warn-App."</string> + <!-- XHED: Notification title - Reminder to share a positive test result--> + <string name="notification_headline_share_positive_result">"Możesz pomóc!"</string> + <!-- XTXT: Notification body - Reminder to share a positive test result--> + <string name="notification_body_share_positive_result">"UdostÄ™pnij swój wynik testu i ostrzeż innych."</string> <!-- #################################### App Auto Update @@ -132,7 +136,7 @@ <item quantity="one">"%1$s narażenie z niskim ryzykiem"</item> <item quantity="other">"%1$s narażenia z niskim ryzykiem"</item> <item quantity="zero">"Brak narażenia z niskim ryzykiem do tej pory"</item> - <item quantity="two">"%1$s narażenia z niskim ryzykiem"</item> + <item quantity="two">"%1$s narażeÅ„ z niskim ryzykiem"</item> <item quantity="few">"%1$s narażenia z niskim ryzykiem"</item> <item quantity="many">"%1$s narażeÅ„ z niskim ryzykiem"</item> </plurals> @@ -150,13 +154,11 @@ <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"Rejestrowanie narażenia stale aktywne"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Narażenia nie zostaÅ‚y jeszcze sprawdzone."</string> + <string name="risk_card_body_not_yet_fetched">"Kontakty nie zostaÅ‚y jeszcze sprawdzone."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Zaktualizowano: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Aktualizowane codziennie"</string> <!-- XTXT: risk card - hint to open the app daily --> - <string name="risk_card_body_open_daily">"Uwaga: ProszÄ™ codziennie otwierać aplikacjÄ™, aby zaktualizować swój status ryzyka."</string> + <string name="risk_card_body_open_daily">"Uwaga: Otwieraj codziennie aplikacjÄ™, aby aktualizować swój status ryzyka."</string> <!-- XBUT: risk card - update risk --> <string name="risk_card_button_update">"Aktualizuj"</string> <!-- XBUT: risk card - update risk with time display --> @@ -185,13 +187,19 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"Rejestrowanie narażenia zatrzymane"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"Ostatnie rejestrowanie narażenia:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"Ostatnie sprawdzenie narażenia:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"Rejestrowanie narażenia jest niemożliwe"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> <string name="risk_card_outdated_risk_body">"Rejestrowanie narażenia nie mogÅ‚o zostać zaktualizowane przez okres dÅ‚uższy niż 24 godziny."</string> <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"Twój status ryzyka nie byÅ‚ aktualizowany od ponad 48 godzin. Zaktualizuj swój status ryzyka."</string> + <!-- XHED: risk card - risk check failed headline, no internet connection --> + <string name="risk_card_check_failed_no_internet_headline">"Sprawdzanie narażeÅ„ nie powiodÅ‚o siÄ™"</string> + <!-- XTXT: risk card - risk check failed, please check your internet connection --> + <string name="risk_card_check_failed_no_internet_body">"Synchronizacja losowych identyfikatorów z serwerem nie powiodÅ‚a siÄ™. Możesz ponownie uruchomić synchronizacjÄ™ rÄ™cznie."</string> + <!-- XTXT: risk card - risk check failed, restart button --> + <string name="risk_card_check_failed_no_internet_restart_button">"Uruchom ponownie"</string> <!-- #################################### Risk Card - Progress @@ -247,7 +255,7 @@ <!-- XHED: App overview subtitle for tracing explanation--> <string name="main_overview_subtitle_tracing">"Rejestrowanie narażenia"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"Rejestrowanie narażenia jest jednÄ… z trzech głównych funkcji aplikacji. Po jej aktywacji rejestrowane sÄ… kontakty z urzÄ…dzeniami innych osób. Nie musisz robić nic wiÄ™cej."</string> + <string name="main_overview_body_tracing">"Rejestrowanie narażenia jest jednÄ… z trzech głównych funkcji aplikacji. Po jej aktywacji rejestrowane sÄ… kontakty ze smartfonami innych osób. Nie musisz robić nic wiÄ™cej."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"Ryzyko zakażenia"</string> <!-- YTXT: App overview body text about risk levels --> @@ -357,9 +365,9 @@ <item quantity="many">"Masz podwyższone ryzyko zakażenia, ponieważ %1$s dni temu byÅ‚eÅ›(-aÅ›) narażony(-a) na dÅ‚uższy, bliski kontakt z co najmniej jednÄ… osobÄ…, u której zdiagnozowano COVID-19."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"Ryzyko zakażenia jest obliczane na podstawie danych rejestrowania narażenia (czas trwania i bliskość kontaktu) lokalnie w urzÄ…dzeniu. Twoje ryzyko zakażenia nie jest widoczne dla nikogo ani nikomu przekazywane."</string> + <string name="risk_details_information_body_notice">"Ryzyko zakażenia jest obliczane na podstawie danych rejestrowania narażenia (czas trwania i bliskość kontaktu) lokalnie w smartfonie. Twoje ryzyko zakażenia nie jest widoczne dla nikogo ani nikomu przekazywane."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> - <string name="risk_details_information_body_notice_increased">"Dlatego Twoje ryzyko zakażenia zostaÅ‚o ocenione jako podwyższone. Ryzyko zakażenia jest obliczane na podstawie danych rejestrowania narażenia (czas trwania i bliskość kontaktu) lokalnie w urzÄ…dzeniu. Twoje ryzyko zakażenia nie jest widoczne dla nikogo ani nikomu przekazywane. Po powrocie do domu unikaj również bliskiego kontaktu z czÅ‚onkami rodziny lub gospodarstwa domowego."</string> + <string name="risk_details_information_body_notice_increased">"Dlatego Twoje ryzyko zakażenia zostaÅ‚o ocenione jako podwyższone. Ryzyko zakażenia jest obliczane na podstawie danych rejestrowania narażenia (czas trwania i bliskość kontaktu) lokalnie na smartfonie. Twoje ryzyko zakażenia nie jest widoczne dla nikogo ani nikomu przekazywane. Po powrocie do domu unikaj również bliskiego kontaktu z czÅ‚onkami rodziny lub gospodarstwa domowego."</string> <!-- NOTR --> <string name="risk_details_button_update">@string/risk_card_button_update</string> <!-- NOTR --> @@ -415,7 +423,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"WiÄ™ksza ochrona dla Ciebie i dla nas wszystkich. KorzystajÄ…c z aplikacji Corona-Warn-App, możemy znacznie szybciej przerwać Å‚aÅ„cuchy zakażeÅ„."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"ZmieÅ„ swoje urzÄ…dzenie w system ostrzegania przed koronawirusem. Zapoznaj siÄ™ ze swoim statusem ryzyka i dowiedz siÄ™, czy miaÅ‚eÅ›(-aÅ›) bliski kontakt z osobÄ…, u której w ciÄ…gu ostatnich 14 dni zdiagnozowano COVID-19."</string> + <string name="onboarding_body">"ZmieÅ„ swój smartfon w system ostrzegania przed koronawirusem. Zapoznaj siÄ™ ze swoim statusem ryzyka i dowiedz siÄ™, czy miaÅ‚eÅ›(-aÅ›) bliski kontakt z osobÄ…, u której w ciÄ…gu ostatnich 14 dni zdiagnozowano COVID-19."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"Aplikacja rejestruje kontakty miÄ™dzy osobami poprzez wymianÄ™ zaszyfrowanych, losowych identyfikatorów miÄ™dzy ich urzÄ…dzeniami bez uzyskiwania dostÄ™pu do danych osobowych."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -452,7 +460,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"Wstecz"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Aktualizacje w tle dezaktywowane"</string> + <string name="onboarding_background_fetch_dialog_headline">"OdÅ›wieżanie aplikacji w tle dezaktywowane"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"DezaktywowaÅ‚eÅ›(-aÅ›) aktualizacje w tle dla aplikacji Corona-Warn-App. Aktywuj aktualizacje w tle, aby korzystać z automatycznego rejestrowania narażenia. JeÅ›li nie aktywujesz aktualizacji w tle, możliwe bÄ™dzie tylko rÄ™czne uruchomienie rejestrowania narażenia w aplikacji. Możesz aktywować aktualizacje w tle dla aplikacji w ustawieniach swojego urzÄ…dzenia."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -474,7 +482,7 @@ <!-- XBUT: onboarding(tracing) - dialog about manual checking button --> <string name="onboarding_manual_required_dialog_button">"OK"</string> <!-- XACT: onboarding(tracing) - illustraction description, header image --> - <string name="onboarding_tracing_illustration_description">"Trzy osoby aktywowaÅ‚y rejestrowanie narażenia na swoich urzÄ…dzeniach, które bÄ™dÄ… rejestrować ich wzajemne kontakty."</string> + <string name="onboarding_tracing_illustration_description">"Trzy osoby aktywowaÅ‚y rejestrowanie narażenia na swoich smartfonach, które bÄ™dÄ… rejestrować ich wzajemne kontakty."</string> <!-- XHED: onboarding(tracing) - location explanation for bluetooth headline --> <string name="onboarding_tracing_location_headline">"Zezwól na dostÄ™p do lokalizacji"</string> <!-- XTXT: onboarding(tracing) - location explanation for bluetooth body text --> @@ -536,7 +544,7 @@ <!-- XTXT: settings(tracing) - shows status under header in home, inactive location --> <string name="settings_tracing_body_inactive_location">"UsÅ‚ugi lokalizacji dezaktywowane"</string> <!-- YTXT: settings(tracing) - explains tracings --> - <string name="settings_tracing_body_text">"Musisz wÅ‚Ä…czyć funkcjÄ™ rejestrowania narażenia, aby aplikacja mogÅ‚a ustalić, czy dotyczy CiÄ™ ryzyko zakażenia po kontakcie z zainfekowanym użytkownikiem aplikacji. Funkcja rejestrowania narażenia dziaÅ‚a we wszystkich uczestniczÄ…cych krajach, co oznacza, że potencjalne narażenie użytkowników jest wykrywane również przez inne oficjalne aplikacje koronawirusowe.\n\nDziaÅ‚anie funkcji rejestrowania narażenia polega na odbieraniu przez Twój smartfon za pomocÄ… Bluetooth zaszyfrowanych, losowych identyfikatorów innych użytkowników i przekazywaniu Twoich wÅ‚asnych, losowych identyfikatorów do ich urzÄ…dzeÅ„. Codziennie aplikacja pobiera listÄ™ losowych identyfikatorów – wraz z wszelkimi opcjonalnie podawanymi informacjami o wystÄ…pieniu objawów – wszystkich użytkowników, którzy mieli pozytywny wynik testu na wirusa i dobrowolnie udostÄ™pnili tÄ™ informacjÄ™ poprzez aplikacjÄ™. Lista jest nastÄ™pnie porównywana z losowymi identyfikatorami innych użytkowników, które zarejestrowaÅ‚ Twój smartfon, w celu obliczenia prawdopodobieÅ„stwa Twojego zakażenia i ostrzeżenia CiÄ™ w razie potrzeby. FunkcjÄ™ tÄ™ można wyÅ‚Ä…czyć w dowolnym momencie..\n\nAplikacja nigdy nie gromadzi danych osobowych takich jak imiÄ™ i nazwisko, adres czy lokalizacja. Takie informacje nie sÄ… też przekazywane innym użytkownikom. Nie jest możliwe wykorzystanie losowych identyfikatorów w celu ustalenia tożsamoÅ›ci poszczególnych osób."</string> + <string name="settings_tracing_body_text">"Musisz wÅ‚Ä…czyć funkcjÄ™ rejestrowania narażenia, aby aplikacja mogÅ‚a ustalić, czy dotyczy CiÄ™ ryzyko zakażenia po kontakcie z zainfekowanym użytkownikiem aplikacji. Funkcja rejestrowania narażenia dziaÅ‚a w skali miÄ™dzynarodowej, co oznacza, że potencjalne narażenie użytkowników jest wykrywane również przez inne oficjalne aplikacje koronawirusowe.\n\nDziaÅ‚anie funkcji rejestrowania narażenia polega na odbieraniu przez Twój smartfon za pomocÄ… Bluetooth zaszyfrowanych, losowych identyfikatorów innych użytkowników i przekazywaniu Twoich wÅ‚asnych, losowych identyfikatorów do ich smartfonów. Codziennie aplikacja pobiera listÄ™ losowych identyfikatorów – wraz z wszelkimi opcjonalnie podawanymi informacjami o wystÄ…pieniu objawów – wszystkich użytkowników, którzy mieli pozytywny wynik testu na koronawirusa i dobrowolnie udostÄ™pnili tÄ™ informacjÄ™ poprzez aplikacjÄ™. Lista jest nastÄ™pnie porównywana z losowymi identyfikatorami innych użytkowników, które zarejestrowaÅ‚ Twój smartfon, w celu obliczenia prawdopodobieÅ„stwa Twojego zakażenia i ostrzeżenia CiÄ™ w razie potrzeby. FunkcjÄ™ tÄ™ można wyÅ‚Ä…czyć w dowolnym momencie.\n\nAplikacja nigdy nie gromadzi danych osobowych, takich jak imiÄ™ i nazwisko, adres czy lokalizacja. Takie informacje nie sÄ… też przekazywane innym użytkownikom. Nie jest możliwe wykorzystanie losowych identyfikatorów w celu ustalenia tożsamoÅ›ci poszczególnych osób."</string> <!-- XTXT: settings(tracing) - status next to switch under title --> <string name="settings_tracing_status_active">"Aktywne"</string> <!-- XTXT: settings(tracing) - status next to switch under title --> @@ -570,7 +578,7 @@ <!-- XTXT: settings(tracing) - explains the circle progress indicator to the right with the current value --> <plurals name="settings_tracing_status_body_active"> <item quantity="one">"Rejestrowanie narażenia jest aktywne od jednego dnia.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> - <item quantity="other">"Rejestrowanie narażenia jest aktywne od %1$s dni.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> + <item quantity="other">"Rejestrowanie narażenia jest aktywne od %1$s dnia.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> <item quantity="zero">"Rejestrowanie narażenia jest aktywne od %1$s dni.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> <item quantity="two">"Rejestrowanie narażenia jest aktywne od %1$s dni.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> <item quantity="few">"Rejestrowanie narażenia jest aktywne od %1$s dni.\nSprawdzanie narażeÅ„ jest wiarygodne tylko wtedy, gdy rejestrowanie narażenia jest aktywowane na staÅ‚e."</item> @@ -671,7 +679,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"Instytut Roberta Kocha (RKI) to niemiecka federalna instytucja zdrowia publicznego. RKI publikuje aplikacjÄ™ Corona-Warn-App w imieniu rzÄ…du federalnego. Aplikacja ta sÅ‚uży jako cyfrowe uzupeÅ‚nienie już wprowadzonych Å›rodków ochrony zdrowia publicznego, takich jak zachowanie dystansu spoÅ‚ecznego, dbanie o higienÄ™ oraz noszenie maseczek."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"Osoby korzystajÄ…ce z aplikacji pomagajÄ… w Å›ledzeniu i przerwaniu Å‚aÅ„cuchów zakażeÅ„. Aplikacja zapisuje kontakty z innymi osobami lokalnie na Twoim urzÄ…dzeniu. Otrzymasz powiadomienie, jeÅ›li okaże siÄ™, że u osób, z którymi miaÅ‚eÅ›(-aÅ›) kontakt, zdiagnozowano później COVID-19. Twoja tożsamość i prywatność sÄ… zawsze chronione."</string> + <string name="information_about_body">"Wszystkie osoby korzystajÄ…ce z aplikacji pomagajÄ… w Å›ledzeniu i przerwaniu Å‚aÅ„cuchów zakażeÅ„. Aplikacja zapisuje kontakty z innymi osobami lokalnie na Twoim smartfonie. Otrzymasz powiadomienie, jeÅ›li okaże siÄ™, że u osób, z którymi miaÅ‚eÅ›(-aÅ›) kontakt, zdiagnozowano później COVID-19. Twoja tożsamość i prywatność sÄ… zawsze chronione."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"Grupa osób korzysta ze smartfonów na mieÅ›cie."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -703,7 +711,7 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"Nasz zespół obsÅ‚ugi klienta jest gotowy do pomocy."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"JÄ™zyki: niemiecki, angielski, turecki\nGodziny pracy:"<xliff:g id="line_break">"\n"</xliff:g>"od poniedziaÅ‚ku do soboty: 7:00 - 22:00"<xliff:g id="line_break">"\n(za wyjÄ…tkiem Å›wiÄ…t paÅ„stwowych)"</xliff:g><xliff:g id="line_break">"\nPoÅ‚Ä…czenie jest bezpÅ‚atne."</xliff:g></string> + <string name="information_contact_body_open">"JÄ™zyki: angielski, niemiecki, turecki\nGodziny pracy:"<xliff:g id="line_break">"\n"</xliff:g>"od poniedziaÅ‚ku do soboty: 7:00 - 22:00"<xliff:g id="line_break">"\n(za wyjÄ…tkiem Å›wiÄ…t paÅ„stwowych)"</xliff:g><xliff:g id="line_break">"\nPoÅ‚Ä…czenie jest bezpÅ‚atne."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_other">"W razie jakichkolwiek pytaÅ„ zwiÄ…zanych ze zdrowiem skontaktuj siÄ™ z lekarzem rodzinnym lub lekarzem dyżurnym pod numerem: 116 117."</string> <!-- XACT: describes illustration --> @@ -788,9 +796,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"Wstecz"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Test zawiera bÅ‚Ä™dy"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"Kod QR straciÅ‚ ważność"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"Podczas ustalania wyniku testu pojawiÅ‚ siÄ™ bÅ‚Ä…d. Twój kod QR wygasÅ‚."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"Twój test ma wiÄ™cej niż 21 dni i nie można go już zarejestrować w aplikacji. JeÅ›li w przyszÅ‚oÅ›ci bÄ™dziesz ponownie poddawać siÄ™ testowi, zeskanuj kod QR, gdy tylko go otrzymasz."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string> @@ -869,11 +877,11 @@ <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Twój wynik testu"</string> <!-- YTXT: Body text for next steps section of test negative result --> - <string name="submission_test_result_negative_steps_negative_body">"Wynik laboratoryjny nie potwierdza zakażenia wirusem SARS-CoV-2.\n\nUsuÅ„ test z aplikacji Corona-Warn-App, aby w razie potrzeby móc zapisać w niej kod nowego testu."</string> + <string name="submission_test_result_negative_steps_negative_body">"Wynik laboratoryjny nie potwierdza zakażenia koronawirusem SARS-CoV-2.\n\nUsuÅ„ test z aplikacji Corona-Warn-App, aby w razie potrzeby móc zapisać w niej kod nowego testu."</string> <!-- XBUT: negative test result : remove the test button --> <string name="submission_test_result_negative_remove_test_button">"UsuÅ„ test"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"Ostrzeganie innych"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"Ostrzegaj innych"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"UdostÄ™pnij swoje losowe identyfikatory, aby ostrzegać innych.\nPomóż innym dokÅ‚adniej ocenić ryzyko zakażenia, wysyÅ‚ajÄ…c informacjÄ™, gdy dostrzeżesz u siebie objawy koronawirusa."</string> <!-- XBUT: positive test result : continue button --> @@ -952,13 +960,13 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"Zarejestruj test poprzez zeskanowanie kodu QR dokumentu testu."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"Zgoda"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"OÅ›wiadczenia o wyrażeniu zgody"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"By tapping “Acceptâ€, you consent to the App querying the status of your coronavirus test and displaying it in the App. This feature is available to you if you have received a QR code and have consented to your test result being transmitted to the App’s server system. As soon as the testing lab has stored your test result on the server, you will be able to see the result in the App. If you have enabled notifications, you will also receive a notification outside the App telling you that your test result has been received. However, for privacy reasons, the test result itself will only be displayed in the App. You can withdraw this consent at any time by deleting your test registration in the App. Withdrawing your consent will not affect the lawfulness of processing before its withdrawal. Further information can be found in the menu under “Data Privacyâ€."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Akceptuj"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Zezwól"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Nie akceptuj"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Nie zezwalaj"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"TAN"</string> <!-- YTXT: Body text for TAN code dispatcher option --> @@ -972,7 +980,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"Ostrzeganie innych"</string> + <string name="submission_positive_other_warning_title">"Ostrzegaj innych"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"Pomóż nam wszystkim!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -980,7 +988,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Akceptuj"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"UrzÄ…dzenie przesyÅ‚a zaszyfrowanÄ… diagnozÄ™ zakażenia do systemu."</string> + <string name="submission_positive_other_illustration_description">"Zaszyfrowana diagnoza zakażenia jest przesyÅ‚ana do systemu."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"NastÄ™pujÄ…ce kraje uczestniczÄ… obecnie w miÄ™dzynarodowym rejestrowaniu narażenia:"</string> @@ -1046,7 +1054,7 @@ <!-- XBUT: symptom initial screen no button --> <string name="submission_symptom_negative_button">"Nie"</string> <!-- XBUT: symptom initial screen no information button --> - <string name="submission_symptom_no_information_button">"Brak odpowiedzi"</string> + <string name="submission_symptom_no_information_button">"Bez komentarza"</string> <!-- XBUT: symptom initial screen continue button --> <string name="submission_symptom_further_button">"Dalej"</string> @@ -1071,7 +1079,7 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Zarejestruj test poprzez wpisanie numeru TAN w aplikacji."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"JÄ™zyki: \nniemiecki, angielski, turecki\n\nGodziny pracy:\nod poniedziaÅ‚ku do niedzieli: 24 godziny na dobÄ™\n\nPoÅ‚Ä…czenie jest bezpÅ‚atne."</string> + <string name="submission_contact_operating_hours_body">"JÄ™zyki: \nangielski, niemiecki, turecki\n\nGodziny pracy:\nod poniedziaÅ‚ku do niedzieli: caÅ‚odobowo\n\nPoÅ‚Ä…czenie jest bezpÅ‚atne."</string> <!-- YTXT: Body text for technical contact and hotline information page --> <string name="submission_contact_body_other">"W razie jakichkolwiek pytaÅ„ zwiÄ…zanych ze zdrowiem skontaktuj siÄ™ z lekarzem rodzinnym lub lekarzem dyżurnym pod numerem: 116 117."</string> @@ -1086,7 +1094,7 @@ <!-- XHED: Page title for calendar page in submission symptom flow --> <string name="submission_symptom_calendar_title">"PoczÄ…tek wystÄ…pienia objawów"</string> <!-- XHED: Page headline for calendar page in symptom submission flow --> - <string name="submission_symptom_calendar_headline">"Kiedy zaczÄ…Å‚eÅ›(-ęłaÅ›) odczuwać te objawy? "</string> + <string name="submission_symptom_calendar_headline">"Kiedy zaczÄ…Å‚eÅ›(-Å‚aÅ›) odczuwać te objawy? "</string> <!-- YTXT: Body text for calendar page in symptom submission flow--> <string name="submission_symptom_calendar_body">"Wybierz dokÅ‚adnÄ… datÄ™ w kalendarzu lub, jeÅ›li nie pamiÄ™tasz dokÅ‚adnej daty, wybierz jednÄ… z innych opcji."</string> <!-- XBUT: symptom calendar screen less than 7 days button --> @@ -1096,7 +1104,7 @@ <!-- XBUT: symptom calendar screen more than 2 weeks button --> <string name="submission_symptom_more_two_weeks">"Ponad 2 tygodnie temu"</string> <!-- XBUT: symptom calendar screen verify button --> - <string name="submission_symptom_verify">"Brak odpowiedzi"</string> + <string name="submission_symptom_verify">"Bez komentarza"</string> <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> @@ -1157,7 +1165,7 @@ <!-- YTXT: invalid status text --> <string name="test_result_card_status_invalid">"Ustalenie wyniku jest niemożliwe"</string> <!-- YTXT: pending status text --> - <string name="test_result_card_status_pending">"Wynik Twojego testu nie jest jeszcze dostÄ™pny"</string> + <string name="test_result_card_status_pending">"Twój wynik testu nie jest jeszcze dostÄ™pny"</string> <!-- XHED: Title for further info of test result negative --> <string name="test_result_card_negative_further_info_title">"Inne informacje:"</string> <!-- YTXT: Content for further info of test result negative --> @@ -1201,7 +1209,10 @@ <string name="errors_google_update_needed">"Twoja aplikacja Corona-Warn-App jest poprawnie zainstalowana, ale system „Powiadomienia o narażeniu na COVID-19†nie jest dostÄ™pny w systemie operacyjnym Twojego smartfona. Oznacza to, że nie możesz korzystać z aplikacji Corona-Warn-App. WiÄ™cej informacji znajduje siÄ™ na naszej stronie „CzÄ™sto zadawane pytaniaâ€: https://www.coronawarn.app/en/faq/."</string> <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"Aplikacja Corona-Warn-App dziaÅ‚a prawidÅ‚owo, ale nie możemy zaktualizować Twojego aktualnego statusu ryzyka. Rejestrowanie narażenia pozostaje aktywne i dziaÅ‚a prawidÅ‚owo. WiÄ™cej informacji można znaleźć na naszej stronie „CzÄ™sto zadawane pytaniaâ€: https://www.coronawarn.app/en/faq/"</string> - + <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_title">"Limit zostaÅ‚ już osiÄ…gniÄ™ty"</string> + <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_description">"Sprawdzanie narażeÅ„ nie jest już dzisiaj możliwe, ponieważ osiÄ…gniÄ™to maksymalnÄ… liczbÄ™ takich kontroli na dzieÅ„ okreÅ›lonÄ… przez system operacyjny. Sprawdź ponownie swój status ryzyka jutro."</string> <!-- #################################### Generic Error Messages ###################################### --> @@ -1342,7 +1353,7 @@ <!-- XHED: Header of interoperability information/configuration view --> <string name="interoperability_configuration_title">"Rejestrowanie narażenia\nw różnych krajach"</string> <!-- XTXT: First section after the header of the interoperability information/configuration view --> - <string name="interoperability_configuration_first_section">"Wiele krajów współpracuje ze sobÄ… w celu aktywacji transgranicznych alertów wysyÅ‚anych poprzez wspólny serwer wymiany danych. Na przykÅ‚ad podczas rejestrowania narażenia można uwzglÄ™dnić również kontakty z użytkownikami oficjalnych aplikacji koronawirusowych z innych uczestniczÄ…cych krajów."</string> + <string name="interoperability_configuration_first_section">"Wiele krajów współpracuje ze sobÄ… w celu aktywacji transgranicznych alertów wysyÅ‚anych poprzez wspólny serwer wymiany danych. Na przykÅ‚ad przy rejestrowaniu narażenia można wziąć pod uwagÄ™ również kontakty z użytkownikami oficjalnych aplikacji koronawirusowych z innych uczestniczÄ…cych krajów."</string> <!-- XTXT: Second section after the header of the interoperability information/configuration view --> <string name="interoperability_configuration_second_section">"W tym celu aplikacja pobiera listÄ™, która jest aktualizowana codziennie, z losowymi identyfikatorami wszystkich użytkowników, którzy udostÄ™pnili swoje losowe identyfikatory poprzez wÅ‚asnÄ… aplikacjÄ™. Lista jest nastÄ™pnie porównywana z losowymi identyfikatorami zarejestrowanymi przez Twój smartfon. Codzienne pobieranie listy z losowymi identyfikatorami jest z reguÅ‚y bezpÅ‚atne – za dane używane przez aplikacjÄ™ w tym kontekÅ›cie nie bÄ™dÄ… pobierane opÅ‚aty roamingowe w innych krajach UE."</string> <!-- XHED: Header right above the country list in the interoperability information/configuration view --> @@ -1357,7 +1368,7 @@ <!-- YMSG: Onboarding tracing step second section in interoperability after the title --> <string name="interoperability_onboarding_second_section">"Gdy użytkownik przeÅ›le swój losowy identyfikator do serwera wymiany danych obsÅ‚ugiwanego wspólnie przez kraje uczestniczÄ…ce, o potencjalnym narażeniu mogÄ… zostać ostrzeżeni użytkownicy oficjalnych aplikacji koronawirusowych we wszystkich tych krajach."</string> <!-- YMSG: Onboarding tracing step third section in interoperability after the title. --> - <string name="interoperability_onboarding_randomid_download_free">"Codzienne pobieranie listy z losowymi identyfikatorami jest z reguÅ‚y bezpÅ‚atne. Oznacza to, że operatorzy sieci mobilnych nie bÄ™dÄ… pobierać opÅ‚at za transmisjÄ™ danych używanych przez aplikacjÄ™ w tym kontekÅ›cie ani też nie bÄ™dÄ… naliczane opÅ‚aty roamingowe w innych krajach UE. Aby uzyskać wiÄ™cej informacji, skontaktuj siÄ™ ze swoim operatorem sieci mobilnej."</string> + <string name="interoperability_onboarding_randomid_download_free">"Codzienne pobieranie listy z losowymi identyfikatorami jest z reguÅ‚y bezpÅ‚atne. Oznacza to, że operatorzy sieci mobilnych nie bÄ™dÄ… pobierać opÅ‚at za transmisjÄ™ danych używanych przez aplikacjÄ™ w tym kontekÅ›cie ani też nie bÄ™dÄ… naliczane opÅ‚aty roamingowe z tego tytuÅ‚u w innych krajach UE. Aby uzyskać wiÄ™cej informacji, skontaktuj siÄ™ ze swoim operatorem sieci mobilnej."</string> <!-- XTXT: Small header above the country list in the onboarding screen for interoperability. --> <string name="interoperability_onboarding_list_title">"Obecnie uczestniczÄ… nastÄ™pujÄ…ce kraje:"</string> @@ -1377,7 +1388,7 @@ <string name="interoperability_onboarding_delta_free_download">"Codzienne pobieranie listy z losowymi identyfikatorami jest z reguÅ‚y bezpÅ‚atne. Oznacza to, że operatorzy sieci mobilnych nie bÄ™dÄ… pobierać opÅ‚at za transmisjÄ™ danych używanych przez aplikacjÄ™ w tym kontekÅ›cie ani też nie bÄ™dÄ… naliczane opÅ‚aty roamingowe z tego tytuÅ‚u w innych krajach UE. Aby uzyskać wiÄ™cej informacji, skontaktuj siÄ™ ze swoim operatorem sieci mobilnej."</string> <!-- XACT: interoperability (eu) - illustraction description, explanation image --> - <string name="interoperability_eu_illustration_description">"RÄ™ka trzyma smartfon. W tle przedstawiona jest Europa i flaga europejska."</string> + <string name="interoperability_eu_illustration_description">"RÄ™ka trzyma smartfon. Europa i flaga europejska sÄ… przedstawione w tle."</string> <!-- XTXT: Title for the interoperability onboarding if country download fails --> <string name="interoperability_onboarding_list_title_failrequest">"Kraje uczestniczÄ…ce"</string> diff --git a/Corona-Warn-App/src/main/res/values-ro/strings.xml b/Corona-Warn-App/src/main/res/values-ro/strings.xml index 6c78674ea18deac47d80a941d4aefde469f79695..450e1d43d8ed8d36d654740c95fa828f1fa4ce01 100644 --- a/Corona-Warn-App/src/main/res/values-ro/strings.xml +++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml @@ -109,6 +109,10 @@ <string name="notification_headline">"Corona-Warn-App"</string> <!-- XTXT: Notification body --> <string name="notification_body">"AveÈ›i mesaje noi de la aplicaÈ›ia Corona-Warn."</string> + <!-- XHED: Notification title - Reminder to share a positive test result--> + <string name="notification_headline_share_positive_result">"PuteÈ›i fi de ajutor!"</string> + <!-- XTXT: Notification body - Reminder to share a positive test result--> + <string name="notification_body_share_positive_result">"Vă rugăm să partajaÈ›i rezultatul testului dvs. pentru a-i avertiza pe ceilalÈ›i."</string> <!-- #################################### App Auto Update @@ -150,11 +154,9 @@ <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"ÃŽnregistrarea în jurnal a expunerilor este permanent activă"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Expunerile nu au fost încă verificate."</string> + <string name="risk_card_body_not_yet_fetched">"ÃŽntâlnirile nu au fost încă verificate."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Actualizată: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Actualizată zilnic"</string> <!-- XTXT: risk card - hint to open the app daily --> <string name="risk_card_body_open_daily">"ReÈ›ineÈ›i: DeschideÈ›i aplicaÈ›ia zilnic pentru a actualiza starea riscului dvs."</string> <!-- XBUT: risk card - update risk --> @@ -185,13 +187,19 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"ÃŽnregistrarea în jurnal a expunerilor a fost oprită"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"Ultima înregistrare în jurnal a expunerilor:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"Ultima verificare a expunerilor:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"ÃŽnregistrarea în jurnal a expunerilor nu este posibilă"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> <string name="risk_card_outdated_risk_body">"ÃŽnregistrarea în jurnal a expunerilor dvs. nu a putut fi actualizată timp de peste 24 de ore."</string> <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"Starea riscului dvs. nu a fost actualizată timp de peste 48 de ore. Vă rugăm să activaÈ›i starea riscului dvs."</string> + <!-- XHED: risk card - risk check failed headline, no internet connection --> + <string name="risk_card_check_failed_no_internet_headline">"Verificarea expunerii a eÈ™uat"</string> + <!-- XTXT: risk card - risk check failed, please check your internet connection --> + <string name="risk_card_check_failed_no_internet_body">"Sincronizarea ID-urilor aleatorii cu serverul a eÈ™uat. PuteÈ›i relansa manual sincronizarea."</string> + <!-- XTXT: risk card - risk check failed, restart button --> + <string name="risk_card_check_failed_no_internet_restart_button">"Relansare"</string> <!-- #################################### Risk Card - Progress @@ -247,7 +255,7 @@ <!-- XHED: App overview subtitle for tracing explanation--> <string name="main_overview_subtitle_tracing">"ÃŽnregistrarea în jurnal a expunerilor"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"ÃŽnregistrarea în jurnal a expunerilor este una dintre cele trei caracteristici centrale ale aplicaÈ›iei. Când o activaÈ›i, sunt înregistrate întâlnirile cu dispozitivele altor persoane. Nu trebuie să faceÈ›i nimic altceva."</string> + <string name="main_overview_body_tracing">"ÃŽnregistrarea în jurnal a expunerilor este una dintre cele trei caracteristici centrale ale aplicaÈ›iei. Când o activaÈ›i, sunt înregistrate întâlnirile cu smartphone-urile altor persoane. Nu trebuie să faceÈ›i nimic altceva."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"Risc de infectare"</string> <!-- YTXT: App overview body text about risk levels --> @@ -285,7 +293,7 @@ <!-- XHED: App overview subtitle for glossary keys --> <string name="main_overview_subtitle_glossary_keys">"ID aleatoriu"</string> <!-- YTXT: App overview body for glossary keys --> - <string name="main_overview_body_glossary_keys">"ID-urile aleatorii sunt combinaÈ›ii de cifre È™i litere generate aleatoriu. Acestea sunt schimbate între dispozitivele aflate în proximitate strânsă. ID-urile aleatorii nu pot fi asociate cu o persoană anume È™i sunt È™terse automat după 14 zile. Persoanele diagnosticate cu COVID-19 pot opta să trimită ID-urile aleatorii din ultimele 14 zile altor utilizatori ai aplicaÈ›iei."</string> + <string name="main_overview_body_glossary_keys">"ID-urile aleatorii sunt combinaÈ›ii de cifre È™i litere generate aleatoriu. Acestea sunt schimbate între dispozitivele aflate în proximitate strânsă. ID-urile aleatorii nu pot fi asociate cu o persoană anume È™i sunt È™terse automat după 14 zile. Persoanele diagnosticate cu COVID-19 pot opta să trimită ID-urile aleatorii din ultimele 14 zile È™i altor utilizatori ai aplicaÈ›iei."</string> <!-- XACT: main (overview) - illustraction description, explanation image --> <string name="main_overview_illustration_description">"Un smartphone afiÈ™ează conÈ›inut variat, numerotat de la 1 la 3."</string> <!-- XACT: App main page title --> @@ -344,7 +352,7 @@ <!-- XMSG: risk details - risk calculation wasn't possible for 24h, below behaviors --> <string name="risk_details_information_body_outdated_risk">"ÃŽnregistrarea în jurnal a expunerilor dvs. nu a putut fi actualizată timp de peste 24 de ore."</string> <!-- YTXT: risk details - low risk explanation text --> - <string name="risk_details_information_body_low_risk">"AveÈ›i un risc redus de infectare deoarece nu a fost înregistrată nicio expunere la persoane diagnosticate ulterior cu COVID-19 sau întâlnirile au fost limitate la o perioadă scurtă È™i la o distanță mai mare."</string> + <string name="risk_details_information_body_low_risk">"AveÈ›i un risc redus de infectare deoarece nu a fost înregistrată nicio expunere la persoane diagnosticate ulterior cu COVID-19 sau întâlnirile dvs. au fost limitate la o perioadă scurtă È™i la o distanță mai mare."</string> <!-- YTXT: risk details - low risk explanation text with encounter with low risk --> <string name="risk_details_information_body_low_risk_with_encounter">"Riscul de infectare este calculat local pe smartphone-ul dvs., utilizând datele de înregistrare în jurnal a expunerilor. Calculul poate È›ine cont È™i de distanÈ›a È™i durata expunerii la persoane diagnosticate cu COVID-19, precum È™i de potenÈ›iala contagiozitate a acestora. Riscul dvs. de infectare nu poate fi observat sau transmis mai departe niciunei alte persoane."</string> <!-- YTXT: risk details - increased risk explanation text with variable for day(s) since last contact --> @@ -357,9 +365,9 @@ <item quantity="many">"AveÈ›i un risc crescut de infectare deoarece aÈ›i fost expus ultima dată acum %1$s zile pe o perioadă mai lungă de timp È™i în strânsă proximitate cu cel puÈ›in o persoană diagnosticată cu COVID-19."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"Riscul dvs. de infectare este calculat pe baza datelor de înregistrare în jurnal a expunerilor (durata È™i proximitatea) la nivel local pe dispozitivul dvs. Riscul dvs. de infectare nu poate fi văzut de o altă persoană sau transmis unei alte persoane."</string> + <string name="risk_details_information_body_notice">"Riscul dvs. de infectare este calculat pe baza datelor de înregistrare în jurnal a expunerilor (durata È™i proximitatea) la nivel local pe smartphone-ul dvs. Riscul dvs. de infectare nu poate fi văzut de o altă persoană sau transmis unei alte persoane."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> - <string name="risk_details_information_body_notice_increased">"Prin urmare, riscul dvs. de infectare a fost clasificat ca fiind crescut. Riscul dvs. de infectare este calculat pe baza datelor de înregistrare în jurnal a expunerilor (durata È™i proximitatea) la nivel local pe dispozitivul dvs. Riscul dvs. de infectare nu poate fi văzut de o altă persoană sau transmis unei alte persoane. Când ajungeÈ›i acasă, evitaÈ›i contactul strâns cu membrii familiei sau cu cei din gospodăria dvs."</string> + <string name="risk_details_information_body_notice_increased">"Prin urmare, riscul dvs. de infectare a fost clasificat ca fiind crescut. Riscul dvs. de infectare este calculat pe baza datelor de înregistrare în jurnal a expunerilor (durata È™i proximitatea) la nivel local pe smartphone-ul dvs. Riscul dvs. de infectare nu poate fi văzut de o altă persoană sau transmis unei alte persoane. Când ajungeÈ›i acasă, evitaÈ›i contactul strâns cu membrii familiei sau cu cei din gospodăria dvs."</string> <!-- NOTR --> <string name="risk_details_button_update">@string/risk_card_button_update</string> <!-- NOTR --> @@ -415,7 +423,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"Mai multă protecÈ›ie pentru dvs. È™i pentru noi toÈ›i. Utilizând Corona-Warn-App putem întrerupe mai uÈ™or lanÈ›ul de infectare."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"TransformaÈ›i-vă dispozitivul într-un sistem de avertizare împotriva coronavirusului. ObÈ›ineÈ›i un sumar al stării de risc È™i aflaÈ›i dacă aÈ›i intrat în contact strâns cu persoane diagnosticate cu COVID-19 în ultimele 14 zile."</string> + <string name="onboarding_body">"TransformaÈ›i-vă smartphone-ul într-un sistem de avertizare împotriva coronavirusului. ObÈ›ineÈ›i un sumar al stării de risc È™i aflaÈ›i dacă aÈ›i intrat în contact strâns cu persoane diagnosticate cu COVID-19 în ultimele 14 zile."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"AplicaÈ›ia înregistrează în jurnal întâlnirile dintre persoane prin dispozitivele acestora, care schimbă ID-uri aleatorii criptate, fără a accesa niciun fel de date personale."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -452,7 +460,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"ÃŽnapoi"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Actualizări în fundal dezactivate"</string> + <string name="onboarding_background_fetch_dialog_headline">"ÃŽmprospătarea aplicaÈ›iei în fundal dezactivată"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"AÈ›i dezactivat actualizările în fundal pentru aplicaÈ›ia Corona-Warn. ActivaÈ›i actualizările în fundal pentru a utiliza înregistrarea automată în jurnal a expunerilor. Dacă nu activaÈ›i actualizările în fundal, puteÈ›i porni doar manual din aplicaÈ›ie înregistrarea în jurnal a expunerilor. PuteÈ›i activa actualizările în fundal pentru aplicaÈ›ie din setările dispozitivului dvs."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -474,7 +482,7 @@ <!-- XBUT: onboarding(tracing) - dialog about manual checking button --> <string name="onboarding_manual_required_dialog_button">"OK"</string> <!-- XACT: onboarding(tracing) - illustraction description, header image --> - <string name="onboarding_tracing_illustration_description">"Trei persoane È™i-au activat pe dispozitiv înregistrarea în jurnal a expunerilor, ceea ce va duce la înregistrarea întâlnirilor lor."</string> + <string name="onboarding_tracing_illustration_description">"Trei persoane È™i-au activat pe smartphone înregistrarea în jurnal a expunerilor, ceea ce va duce la înregistrarea întâlnirilor lor."</string> <!-- XHED: onboarding(tracing) - location explanation for bluetooth headline --> <string name="onboarding_tracing_location_headline">"PermiteÈ›i accesul la locaÈ›ie"</string> <!-- XTXT: onboarding(tracing) - location explanation for bluetooth body text --> @@ -671,7 +679,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"Robert Koch Institute (RKI) este un organism federal de sănătate publică din Germania. RKI a publicat aplicaÈ›ia Corona-Warn în numele Guvernului Federal. AplicaÈ›ia are drept scop să completeze sub formă digitală măsurile de sănătate publică deja introduse: distanÈ›area socială, igiena È™i purtarea măștii."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"Persoanele care utilizează aplicaÈ›ia ajută la urmărirea È™i întreruperea lanÈ›urilor de infectare. AplicaÈ›ia salvează local, pe dispozitivul dvs., întâlnirile cu alte persoane. SunteÈ›i notificat dacă aÈ›i întâlnit persoane care au fost diagnosticate ulterior cu COVID-19. Identitatea È™i confidenÈ›ialitatea dvs. sunt protejate întotdeauna."</string> + <string name="information_about_body">"Persoanele care utilizează aplicaÈ›ia ajută la urmărirea È™i întreruperea lanÈ›urilor de infectare. AplicaÈ›ia salvează local, pe smartphone-ul dvs., întâlnirile cu alte persoane. SunteÈ›i notificat dacă aÈ›i întâlnit persoane care au fost diagnosticate ulterior cu COVID-19. Identitatea È™i confidenÈ›ialitatea dvs. sunt protejate întotdeauna."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"Un grup de persoane își utilizează smartphone-urile prin oraÈ™."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -703,9 +711,9 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"Serviciul clienÈ›i vă stă la dispoziÈ›ie."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"Limbi: germană, engleză, turcă\nProgram de lucru:"<xliff:g id="line_break">"\n"</xliff:g>"luni - sâmbătă: 07:00 - 22:00"<xliff:g id="line_break">"\n(exceptând sărbătorile legale)"</xliff:g><xliff:g id="line_break">"\nApelul este gratuit."</xliff:g></string> + <string name="information_contact_body_open">"Limbi: engleză, germană, turcă\nProgram de lucru:"<xliff:g id="line_break">"\n"</xliff:g>"luni - sâmbătă: 07:00 - 22:00"<xliff:g id="line_break">"\n(exceptând sărbătorile legale)"</xliff:g><xliff:g id="line_break">"\nApelul este gratuit."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_other">"Dacă aveÈ›i întrebări legate de starea de sănătate, vă rugăm să contactaÈ›i medicul de familie sau hotline-ul pentru servicii medicale de urgență, la numărul de telefon: 112."</string> + <string name="information_contact_body_other">"Dacă aveÈ›i întrebări legate de starea de sănătate, vă rugăm să contactaÈ›i medicul de familie sau hotline-ul pentru servicii medicale de urgență, la numărul de telefon: 116 117 (Germania) sau 112 (România)."</string> <!-- XACT: describes illustration --> <string name="information_contact_illustration_description">"Un bărbat poartă căști în timpul unei convorbiri telefonice."</string> <!-- XLNK: Menu item / hyper link / button text for navigation to FAQ website --> @@ -788,9 +796,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"ÃŽnapoi"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Testul are erori"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"Codul QR nu mai este valabil"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"A apărut o problemă la evaluarea testului dvs. Codul dvs. QR a expirat deja."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"Testul dvs. are o vechime de peste 21 de zile È™i nu mai poate fi înregistrat în aplicaÈ›ie. Dacă sunteÈ›i testat din nou în viitor, nu uitaÈ›i să scanaÈ›i codul QR imediat ce îl primiÈ›i."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string> @@ -865,15 +873,15 @@ <!-- XBUT: test result pending : refresh button --> <string name="submission_test_result_pending_refresh_button">"Actualizare"</string> <!-- XBUT: test result pending : remove the test button --> - <string name="submission_test_result_pending_remove_test_button">"Ștergere test"</string> + <string name="submission_test_result_pending_remove_test_button">"Eliminare test"</string> <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Rezultatul testului dvs."</string> <!-- YTXT: Body text for next steps section of test negative result --> <string name="submission_test_result_negative_steps_negative_body">"Rezultatul de laborator nu indică o confirmare a infecÈ›iei cu coronavirusul SARS-CoV-2.\n\nȘtergeÈ›i testul din Corona-Warn-App pentru a salva un nou cod de test aici dacă este necesar."</string> <!-- XBUT: negative test result : remove the test button --> - <string name="submission_test_result_negative_remove_test_button">"Ștergere test"</string> + <string name="submission_test_result_negative_remove_test_button">"Eliminare test"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"Avertizarea altora"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"AvertizaÈ›i-i pe ceilalÈ›i"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"PartajaÈ›i ID-urile dvs. aleatorii È™i avertizaÈ›i-i pe ceilalÈ›i.\nAjutaÈ›i la stabilirea riscului de infectare pentru ceilalÈ›i cu mai multă acurateÈ›e, indicând momentul în care aÈ›i observat prima dată simptomele de coronavirus."</string> <!-- XBUT: positive test result : continue button --> @@ -952,13 +960,13 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"ÃŽnregistraÈ›i-vă testul scanând codul QR al documentului de testare."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"Consimțământ"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"DeclaraÈ›ie de consimțământ"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"By tapping “Acceptâ€, you consent to the App querying the status of your coronavirus test and displaying it in the App. This feature is available to you if you have received a QR code and have consented to your test result being transmitted to the App’s server system. As soon as the testing lab has stored your test result on the server, you will be able to see the result in the App. If you have enabled notifications, you will also receive a notification outside the App telling you that your test result has been received. However, for privacy reasons, the test result itself will only be displayed in the App. You can withdraw this consent at any time by deleting your test registration in the App. Withdrawing your consent will not affect the lawfulness of processing before its withdrawal. Further information can be found in the menu under “Data Privacyâ€."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"PermiteÈ›i"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Nu accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Nu permiteÈ›i"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"TAN"</string> <!-- YTXT: Body text for TAN code dispatcher option --> @@ -972,7 +980,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"Avertizarea altor persoane"</string> + <string name="submission_positive_other_warning_title">"AvertizaÈ›i-i pe ceilalÈ›i"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"Să ne ajutăm împreună!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -980,7 +988,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Accept"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"Un dispozitiv transmite un diagnostic de test pozitiv criptat către sistem."</string> + <string name="submission_positive_other_illustration_description">"Un smartphone transmite un diagnostic de test pozitiv criptat către sistem."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"Următoarele țări participă în prezent la înregistrarea în jurnal a expunerilor la nivel transnaÈ›ional:"</string> @@ -1046,7 +1054,7 @@ <!-- XBUT: symptom initial screen no button --> <string name="submission_symptom_negative_button">"Nu"</string> <!-- XBUT: symptom initial screen no information button --> - <string name="submission_symptom_no_information_button">"Nu răspund"</string> + <string name="submission_symptom_no_information_button">"Nu comentez"</string> <!-- XBUT: symptom initial screen continue button --> <string name="submission_symptom_further_button">"ÃŽnainte"</string> @@ -1071,9 +1079,9 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"ÃŽnregistraÈ›i testul introducând codul TAN în aplicaÈ›ie."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Limbi: \ngermană, engleză, turcă\n\nProgram de lucru:\nluni - duminică: non-stop\n\nApelul este gratuit."</string> + <string name="submission_contact_operating_hours_body">"Limbi: \nengleză, germană, turcă\n\nProgram de lucru:\nluni - duminică: non-stop\n\nApelul este gratuit."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="submission_contact_body_other">"Dacă aveÈ›i întrebări legate de starea de sănătate, vă rugăm să contactaÈ›i medicul de familie sau hotline-ul pentru servicii medicale de urgență, la numărul de telefon: 112."</string> + <string name="submission_contact_body_other">"Dacă aveÈ›i întrebări legate de starea de sănătate, vă rugăm să contactaÈ›i medicul de familie sau hotline-ul pentru servicii medicale de urgență, la numărul de telefon: 116 117 (Germania) sau 112 (România)."</string> <!-- XACT: Submission contact page title --> <string name="submission_contact_accessibility_title">"SunaÈ›i la hotline È™i solicitaÈ›i un TAN"</string> @@ -1096,7 +1104,7 @@ <!-- XBUT: symptom calendar screen more than 2 weeks button --> <string name="submission_symptom_more_two_weeks">"Cu peste 2 săptămâni în urmă"</string> <!-- XBUT: symptom calendar screen verify button --> - <string name="submission_symptom_verify">"Nu răspund"</string> + <string name="submission_symptom_verify">"Nu comentez"</string> <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> @@ -1201,7 +1209,10 @@ <string name="errors_google_update_needed">"AplicaÈ›ia dvs. Corona-Warn este instalată corect, dar serviciul „Notificări privind expunerea la COVID-19†nu este disponibil în sistemul de operare al smartphone-ului dvs. Aceasta înseamnă că nu puteÈ›i utiliza aplicaÈ›ia Corona-Warn. Pentru mai multe informaÈ›ii, consultaÈ›i pagina noastră de întrebări frecvente: https://www.coronawarn.app/en/faq/"</string> <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"AplicaÈ›ia Corona-Warn funcÈ›ionează corect, dar nu putem actualiza starea curentă a riscului dvs. ÃŽnregistrarea în jurnal a expunerilor rămâne activă È™i funcÈ›ionează corect. Pentru mai multe informaÈ›ii, consultaÈ›i pagina noastră de întrebări frecvente: https://www.coronawarn.app/en/faq/"</string> - + <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_title">"Limita a fost deja atinsă"</string> + <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_description">"Astăzi nu mai este posibilă verificarea expunerii, deoarece aÈ›i atins numărul maxim de verificări pe zi definit de sistemul dvs. de operare. VerificaÈ›i din nou mâine starea riscului dvs."</string> <!-- #################################### Generic Error Messages ###################################### --> @@ -1357,7 +1368,7 @@ <!-- YMSG: Onboarding tracing step second section in interoperability after the title --> <string name="interoperability_onboarding_second_section">"Când un utilizator transmite ID-urile sale aleatorii la serverul de schimb operat în comun de țările participante, utilizatorii aplicaÈ›iilor oficiale anticoronavirus din toate aceste țări pot fi avertizaÈ›i de posibila expunere."</string> <!-- YMSG: Onboarding tracing step third section in interoperability after the title. --> - <string name="interoperability_onboarding_randomid_download_free">"Descărcarea zilnică a listei cu ID-urilor aleatorii este, de obicei, gratuită pentru dvs. ÃŽn mod specific, aceasta înseamnă că operatorii de reÈ›ele mobile nu percep costuri pentru datele utilizate de aplicaÈ›ie în acest context È™i nu aplică niciun fel de costuri de roaming pentru această opÈ›iune în alte țări UE. ContactaÈ›i operatorul reÈ›elei mobile pentru mai multe informaÈ›ii."</string> + <string name="interoperability_onboarding_randomid_download_free">"Descărcarea zilnică a listei cu ID-uri aleatorii este, de obicei, gratuită pentru dvs. ÃŽn mod specific, aceasta înseamnă că operatorii de reÈ›ele mobile nu percep costuri pentru datele utilizate de aplicaÈ›ie în acest context È™i nu aplică niciun fel de costuri de roaming pentru această opÈ›iune în alte țări UE. ContactaÈ›i operatorul reÈ›elei mobile pentru mai multe informaÈ›ii."</string> <!-- XTXT: Small header above the country list in the onboarding screen for interoperability. --> <string name="interoperability_onboarding_list_title">"ÃŽn prezent participă următoarele țări:"</string> diff --git a/Corona-Warn-App/src/main/res/values-tr/strings.xml b/Corona-Warn-App/src/main/res/values-tr/strings.xml index 02255db8b322545744f9c3fa76f6a5958bb01296..6cfc04d3387a2264a34c84c8fcfa388f74338253 100644 --- a/Corona-Warn-App/src/main/res/values-tr/strings.xml +++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml @@ -109,6 +109,10 @@ <string name="notification_headline">"Corona-Warn-App"</string> <!-- XTXT: Notification body --> <string name="notification_body">"Corona-Warn-App uygulamasından yeni mesajlarınız var."</string> + <!-- XHED: Notification title - Reminder to share a positive test result--> + <string name="notification_headline_share_positive_result">"Yardımcı olabilirsiniz!"</string> + <!-- XTXT: Notification body - Reminder to share a positive test result--> + <string name="notification_body_share_positive_result">"Lütfen test sonucunuzu paylaşın ve diÄŸer kullanıcıları uyarın."</string> <!-- #################################### App Auto Update @@ -150,11 +154,9 @@ <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"Maruz kalma günlüğü sürekli etkin"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Maruz kalmalar henüz kontrol edilmedi."</string> + <string name="risk_card_body_not_yet_fetched">"KarşılaÅŸmalar henüz kontrol edilmedi."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Güncelleme: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Günlük olarak güncellenir"</string> <!-- XTXT: risk card - hint to open the app daily --> <string name="risk_card_body_open_daily">"Not: Risk durumunuzu güncellemek için lütfen uygulamayı her gün açın."</string> <!-- XBUT: risk card - update risk --> @@ -185,13 +187,19 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"Maruz kalma günlüğü durduruldu"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"Son maruz kalma günlüğü:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"Son maruz kalma kontrolü:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"Maruz kalma günlüğü oluÅŸturulamıyor"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> <string name="risk_card_outdated_risk_body">"Maruz kalma günlüğünüz 24 saatten uzun süre için güncellenemedi."</string> <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"Risk durumunuz 48 saatten uzun süredir güncellenmedi. Lütfen risk durumunuzu güncelleyin."</string> + <!-- XHED: risk card - risk check failed headline, no internet connection --> + <string name="risk_card_check_failed_no_internet_headline">"Maruz kalma kontrolü baÅŸarısız oldu"</string> + <!-- XTXT: risk card - risk check failed, please check your internet connection --> + <string name="risk_card_check_failed_no_internet_body">"Rastgele kimliklerin sunucu ile senkronizasyonu baÅŸarısız oldu. Senkronizasyonu manüel olarak baÅŸlatabilirsiniz."</string> + <!-- XTXT: risk card - risk check failed, restart button --> + <string name="risk_card_check_failed_no_internet_restart_button">"Yeniden baÅŸlat"</string> <!-- #################################### Risk Card - Progress @@ -247,7 +255,7 @@ <!-- XHED: App overview subtitle for tracing explanation--> <string name="main_overview_subtitle_tracing">"Maruz Kalma Günlüğü"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"Maruz kalma günlüğü, uygulamanın üç temel özelliÄŸinden biridir. Bu özelliÄŸi etkinleÅŸtirdiÄŸinizde, diÄŸer kiÅŸilerin cihazlarıyla karşılaÅŸmalarınız günlüğe kaydedilir. BaÅŸka bir iÅŸlem yapmanız gerekmez."</string> + <string name="main_overview_body_tracing">"Maruz kalma günlüğü, uygulamanın üç temel özelliÄŸinden biridir. Bu özelliÄŸi etkinleÅŸtirdiÄŸinizde, diÄŸer kiÅŸilerin akıllı telefonlarıyla karşılaÅŸmalarınız günlüğe kaydedilir. BaÅŸka bir iÅŸlem yapmanız gerekmez."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"Enfeksiyon Riski"</string> <!-- YTXT: App overview body text about risk levels --> @@ -357,9 +365,9 @@ <item quantity="many">"En son %1$s gün önce, COVID-19 tanısı konan en az bir kiÅŸiyle daha uzun süreyle ve yakın mesafeden maruz kalma yaÅŸadığınız için enfeksiyon riskiniz daha yüksektir."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"Enfeksiyon riskiniz, cihazınızda yerel olarak bulunan maruz kalma günlüğü verileri (süre ve mesafe) kullanılarak hesaplanır. Enfeksiyon riskiniz baÅŸkaları tarafından görüntülenemez veya baÅŸkalarına aktarılmaz."</string> + <string name="risk_details_information_body_notice">"Enfeksiyon riskiniz, akıllı telefonunuzda yerel olarak bulunan maruz kalma günlüğü verileri (süre ve mesafe) kullanılarak hesaplanır. Enfeksiyon riskiniz baÅŸkaları tarafından görüntülenemez veya baÅŸkalarına aktarılmaz."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> - <string name="risk_details_information_body_notice_increased">"Bu nedenle enfeksiyon riskiniz artmış olarak derecelendirilmiÅŸtir. Enfeksiyon riskiniz, cihazınızda yerel olarak bulunan maruz kalma günlüğü verileri (süre ve mesafe) kullanılarak hesaplanır. Enfeksiyon riskiniz baÅŸkaları tarafından görüntülenemez veya baÅŸkalarına aktarılmaz. Eve gittiÄŸinizde lütfen aile fertleriniz veya ev arkadaÅŸlarınızla yakın temastan kaçının."</string> + <string name="risk_details_information_body_notice_increased">"Bu nedenle enfeksiyon riskiniz artmış olarak derecelendirilmiÅŸtir. Enfeksiyon riskiniz, akıllı telefonunuzda yerel olarak bulunan maruz kalma günlüğü verileri (süre ve mesafe) kullanılarak hesaplanır. Enfeksiyon riskiniz baÅŸkaları tarafından görüntülenemez veya baÅŸkalarına aktarılmaz. Eve gittiÄŸinizde lütfen aile fertleriniz veya ev arkadaÅŸlarınızla yakın temastan kaçının."</string> <!-- NOTR --> <string name="risk_details_button_update">@string/risk_card_button_update</string> <!-- NOTR --> @@ -415,7 +423,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"Sizin için ve hepimiz için daha fazla koruma. Corona-Warn-App uygulamasını kullanarak enfeksiyon zincirlerini çok daha kısa süre içinde kırabiliriz."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"Cihazınızı koronavirüs uyarı sistemine dönüştürün. Risk durumunuza iliÅŸkin genel bir bakış elde edin ve son 14 gün içinde COVID-19 tanısı konan herhangi biri ile yakın temasa geçip geçmediÄŸinizi öğrenin."</string> + <string name="onboarding_body">"Akıllı telefonunuzu koronavirüs uyarı sistemine dönüştürün. Risk durumunuza iliÅŸkin genel bir bakış elde edin ve son 14 gün içinde COVID-19 tanısı konan herhangi biri ile yakın temasa geçip geçmediÄŸinizi öğrenin."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"Uygulama kiÅŸilerin cihazları arasında ÅŸifrelenmiÅŸ rastgele kimlikleri paylaÅŸarak karşılaÅŸma günlüğü oluÅŸturur ve bu sırada hiçbir kiÅŸisel veriye eriÅŸim saÄŸlanmaz."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -452,7 +460,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"Geri"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Arka plan güncellemeleri devre dışı bırakıldı"</string> + <string name="onboarding_background_fetch_dialog_headline">"Arka planda uygulamayı yenileme devre dışı bırakıldı"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"Corona-Warn-App için arka plan güncellemelerini devre dışı bıraktınız. Otomatik maruz kalma günlüğü özelliÄŸini kullanmak için lütfen arka plan güncellemelerini etkinleÅŸtirin. Arka plan güncellemelerini etkinleÅŸtirmezseniz maruz kalma günlüğü özelliÄŸini yalnızca uygulamadan manüel olarak baÅŸlatabilirsiniz. Uygulamanın arka plan güncellemelerini cihazınızın ayarlarından etkinleÅŸtirebilirsiniz."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -474,7 +482,7 @@ <!-- XBUT: onboarding(tracing) - dialog about manual checking button --> <string name="onboarding_manual_required_dialog_button">"Tamam"</string> <!-- XACT: onboarding(tracing) - illustraction description, header image --> - <string name="onboarding_tracing_illustration_description">"Üç kiÅŸi cihazlarında maruz kalma günlüğünü etkinleÅŸtirdi ve birbirleri ile karşılaÅŸmaları günlüğe kaydedilecektir."</string> + <string name="onboarding_tracing_illustration_description">"Üç kiÅŸi akıllı telefonlarında maruz kalma günlüğünü etkinleÅŸtirdi ve birbirleri ile karşılaÅŸmaları günlüğe kaydedilecektir."</string> <!-- XHED: onboarding(tracing) - location explanation for bluetooth headline --> <string name="onboarding_tracing_location_headline">"Konum eriÅŸimine izin ver"</string> <!-- XTXT: onboarding(tracing) - location explanation for bluetooth body text --> @@ -671,7 +679,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"Robert Koch Institute (RKI), Almanya\'nın federal kamu saÄŸlığı kurumudur. RKI, Federal Hükûmet adına Corona-Warn-App uygulamasını yayınlamaktadır. Uygulama, daha önce açıklanan kamu saÄŸlığı önlemlerine iliÅŸkin dijital bir tamamlayıcı niteliÄŸindedir: sosyal mesafe, hijyen uygulamaları ve yüz maskeleri."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"Uygulamayı kullanan kiÅŸiler, enfeksiyon zincirlerinin takip edilmesine ve kırılmasına yardımcı olur. Uygulama, diÄŸer kiÅŸilerle karşılaÅŸmaları cihazınızda yerel olarak kaydeder. Daha sonra COVID-19 tanısı konan kiÅŸilerle karşılaÅŸmışsanız size bildirim gönderilir. KimliÄŸiniz ve gizliliÄŸiniz daima koruma altındadır."</string> + <string name="information_about_body">"Uygulamayı kullanan herkes, enfeksiyon zincirlerinin takip edilmesine ve kırılmasına yardımcı olur. Uygulama, diÄŸer kiÅŸilerle karşılaÅŸmaları akıllı telefonunuzda yerel olarak kaydeder. Daha sonra COVID-19 tanısı konan kiÅŸilerle karşılaÅŸmışsanız size bildirim gönderilir. KimliÄŸiniz ve gizliliÄŸiniz daima koruma altındadır."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"Bölgedeki bir grup insan akıllı telefonlarını kullanıyor."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -703,7 +711,7 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"Müşteri hizmetlerimiz size yardımcı olmaya hazır."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"Diller: Almanca, Ä°ngilizce, Türkçe\nMesai saatleri:"<xliff:g id="line_break">"\n"</xliff:g>"Pazartesi - Cumartesi: 7.00 - 22.00"<xliff:g id="line_break">"\n(ulusal tatiller hariçtir)"</xliff:g><xliff:g id="line_break">"\nAramalar ücretsizdir."</xliff:g></string> + <string name="information_contact_body_open">"Diller: Ä°ngilizce, Almanca, Türkçe\nMesai saatleri:"<xliff:g id="line_break">"\n"</xliff:g>"Pazartesi - Cumartesi: 7.00 - 22.00"<xliff:g id="line_break">"\n(ulusal tatiller hariçtir)"</xliff:g><xliff:g id="line_break">"\nAramalar ücretsizdir."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_other">"SaÄŸlıkla ilgili tüm sorularınız için lütfen aile hekiminizle veya tıbbi acil servis yardım hattı ile iletiÅŸime geçin. Telefon: 116 117."</string> <!-- XACT: describes illustration --> @@ -788,9 +796,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"Geri"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Testte hata var"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"QR kod artık geçerli deÄŸil"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"Testinizi deÄŸerlendirirken bir problem oluÅŸtu. QR kodunuzun süresi dolmuÅŸ."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"Testiniz 21 günden eski ve artık uygulamaya kaydedilemez. Ä°lerleyen zamanlarda yeniden test yaptırırsanız lütfen QR kodu alır almaz tarayın."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"Tamam"</string> @@ -865,15 +873,15 @@ <!-- XBUT: test result pending : refresh button --> <string name="submission_test_result_pending_refresh_button">"Güncelle"</string> <!-- XBUT: test result pending : remove the test button --> - <string name="submission_test_result_pending_remove_test_button">"Testi Sil"</string> + <string name="submission_test_result_pending_remove_test_button">"Testi kaldır"</string> <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Test Sonucunuz"</string> <!-- YTXT: Body text for next steps section of test negative result --> <string name="submission_test_result_negative_steps_negative_body">"Laboratuvar sonucuna göre koronavirüs SARS-CoV-2 olduÄŸunuza dair bir doÄŸrulama yok.\n\nGerekirse yeni bir test kodu kaydedebilmeniz için lütfen testi Corona-Warn-App\'ten silin."</string> <!-- XBUT: negative test result : remove the test button --> - <string name="submission_test_result_negative_remove_test_button">"Testi Sil"</string> + <string name="submission_test_result_negative_remove_test_button">"Testi kaldır"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"DiÄŸer Kullanıcıları Uyarma"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"DiÄŸer Kullanıcıları Uyarın"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"Rastgele kimliklerinizi paylaşın ve diÄŸer kullanıcıları uyarın.\nHerhangi bir koronavirüs semptomunu ne zaman ilk kez fark ettiÄŸinizi de belirterek diÄŸer kullanıcıların enfeksiyon riskini daha doÄŸru ÅŸekilde belirlemeye yardımcı olun."</string> <!-- XBUT: positive test result : continue button --> @@ -952,17 +960,17 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"Test belgenizin QR kodunu tarayarak testinizi kaydedin."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"Onay"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"Kabul Beyanı"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"\"Kabul Et\" seçeneÄŸine dokunarak Uygulamanın koronavirüs testinizin durumunu sorgulamasına ve Uygulamada görüntülemesine izin verirsiniz. Bu özelliÄŸi, QR kod aldıysanız ve test sonucunuzun Uygulamanın sunucu sistemine aktarılmasına onay verdiyseniz kullanabilirsiniz. Testi yapan laboratuvar test sonucunuzu sunucuya kaydettiÄŸi anda sonucu Uygulamada görüntüleyebilirsiniz. Ayrıca bildirimleri etkinleÅŸtirirseniz Uygulama, kullanmadığınız sırada test sonucunuzun alındığını belirten bir bildirim gönderir. Ancak gizlilik nedenleriyle testin sonucu yalnızca Uygulamada görüntülenecektir. Uygulamada test kaydınızı silerek dilediÄŸiniz zaman bu onayı geri çekebilirsiniz. Onayınızı geri çekmeniz, onayınızı geri çekmeden önce testi iÅŸlemenin hukuki niteliÄŸini etkilemeyecektir. Menüde \"Veri GizliliÄŸi\" baÅŸlığında daha fazla bilgiye eriÅŸebilirsiniz."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Kabul Et"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Ä°zin Ver"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Kabul Etme"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Ä°zin Verme"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"TAN"</string> <!-- YTXT: Body text for TAN code dispatcher option --> - <string name="submission_dispatcher_tan_code_card_text">"TAN\'yi manuel olarak girerek testinizi kaydedin."</string> + <string name="submission_dispatcher_tan_code_card_text">"TAN\'yi manuel olarak girerek kaydedin."</string> <!-- YTXT: Dispatcher text for TELE-TAN option --> <string name="submission_dispatcher_card_tan_tele">"TAN Talebi"</string> <!-- YTXT: Body text for TELE_TAN dispatcher option --> @@ -972,7 +980,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"DiÄŸer Kullanıcıları Uyarma"</string> + <string name="submission_positive_other_warning_title">"DiÄŸer Kullanıcıları Uyarın"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"Lütfen hepimize yardımcı olun!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -980,7 +988,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Kabul Et"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"Bir cihaz ÅŸifrelenmiÅŸ pozitif test tanısını sisteme aktarır."</string> + <string name="submission_positive_other_illustration_description">"Bir akıllı telefon ÅŸifrelenmiÅŸ pozitif test tanısını sisteme aktarır."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"AÅŸağıdaki ülkeler, ülkeler arası maruz kalma günlüğüne katılmaktadır:"</string> @@ -1046,7 +1054,7 @@ <!-- XBUT: symptom initial screen no button --> <string name="submission_symptom_negative_button">"Hayır"</string> <!-- XBUT: symptom initial screen no information button --> - <string name="submission_symptom_no_information_button">"Bilgi yok"</string> + <string name="submission_symptom_no_information_button">"Beyan yok"</string> <!-- XBUT: symptom initial screen continue button --> <string name="submission_symptom_further_button">"Sonraki"</string> @@ -1071,7 +1079,7 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Uygulamaya TAN girerek testi kaydedin."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Diller: \nAlmanca, Ä°ngilizce, Türkçe\n\nMesai saatleri:\nPazartesi - Pazar: 24 saat\n\nArama ücretsizdir."</string> + <string name="submission_contact_operating_hours_body">"Diller: \nÄ°ngilizce, Almanca, Türkçe\n\nMesai saatleri:\nPazartesi - Pazar: 24 saat\n\nArama ücretsizdir."</string> <!-- YTXT: Body text for technical contact and hotline information page --> <string name="submission_contact_body_other">"SaÄŸlıkla ilgili tüm sorularınız için lütfen aile hekiminizle veya tıbbi acil servis yardım hattı ile iletiÅŸime geçin. Telefon: 116 117."</string> @@ -1096,7 +1104,7 @@ <!-- XBUT: symptom calendar screen more than 2 weeks button --> <string name="submission_symptom_more_two_weeks">"2 haftadan uzun süre önce"</string> <!-- XBUT: symptom calendar screen verify button --> - <string name="submission_symptom_verify">"Bilgi yok"</string> + <string name="submission_symptom_verify">"Beyan yok"</string> <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> @@ -1201,7 +1209,10 @@ <string name="errors_google_update_needed">"Corona-Warn-App uygulamanız doÄŸru ÅŸekilde yüklendi ancak akıllı telefonunuzun iÅŸletim sisteminde \"COVID-19 Maruz Kalma Bildirimleri Sistemi\" yok. Bu, Corona-Warn-App\'i kullanamayacağınız anlamına geliyor. Daha fazla bilgi için lütfen SSS sayfamıza bakın: https://www.coronawarn.app/en/faq/"</string> <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"Corona-Warn-App doÄŸru ÅŸekilde çalışıyor ancak mevcut risk durumunuzu güncelleyemiyoruz. Maruz kalma günlüğü aktif ve doÄŸru ÅŸekilde çalışıyor. Daha fazla bilgi için lütfen SSS sayfamıza bakın: https://www.coronawarn.app/en/faq/"</string> - + <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_title">"Sınıra ulaşıldı"</string> + <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> + <string name="errors_risk_detection_limit_reached_description">"Ä°ÅŸletim sisteminizce tanımlanan günlük azami kontrol sayısına ulaÅŸtığınız için bugün daha fazla maruz kalma kontrolü yapılamaz. Lütfen risk durumunuzu yarın yeniden kontrol edin."</string> <!-- #################################### Generic Error Messages ###################################### --> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 266628ab2b4af25556ecb991a8911cff5a40eea2..35bfadc55443338cd197aaef22edde94a91473bf 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -117,9 +117,9 @@ <!-- XTXT: Notification body --> <string name="notification_body">"You have new messages from your Corona-Warn-App."</string> <!-- XHED: Notification title - Reminder to share a positive test result--> - <string name="notification_headline_share_positive_result">"Helfen Sie mit!"</string> + <string name="notification_headline_share_positive_result">"You can help!"</string> <!-- XTXT: Notification body - Reminder to share a positive test result--> - <string name="notification_body_share_positive_result">"Bitte warnen Sie andere und teilen Sie Ihr Testergebnis."</string> + <string name="notification_body_share_positive_result">"Please share your test result and warn others."</string> <!-- #################################### App Auto Update @@ -161,11 +161,9 @@ <!-- XTXT: risk card- tracing active for 14 out of 14 days --> <string name="risk_card_body_saved_days_full">"Exposure logging permanently active"</string> <!-- XTXT; risk card - no update done yet --> - <string name="risk_card_body_not_yet_fetched">"Exposures have not yet been checked."</string> + <string name="risk_card_body_not_yet_fetched">"Encounters have not yet been checked."</string> <!-- XTXT: risk card - last successful update --> <string name="risk_card_body_time_fetched">"Updated: %1$s"</string> - <!-- XTXT: risk card - next update --> - <string name="risk_card_body_next_update">"Updated daily"</string> <!-- XTXT: risk card - hint to open the app daily --> <string name="risk_card_body_open_daily">"Note: Please open the app daily to update your risk status."</string> <!-- XBUT: risk card - update risk --> @@ -196,7 +194,7 @@ <!-- XHED: risk card - tracing stopped headline, due to no possible calculation --> <string name="risk_card_no_calculation_possible_headline">"Exposure logging stopped"</string> <!-- XTXT: risk card - last successfully calculated risk level --> - <string name="risk_card_no_calculation_possible_body_saved_risk">"Last exposure logging:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> + <string name="risk_card_no_calculation_possible_body_saved_risk">"Last exposure check:"<xliff:g id="line_break">"\n"</xliff:g>"%1$s"</string> <!-- XHED: risk card - outdated risk headline, calculation isn't possible --> <string name="risk_card_outdated_risk_headline">"Exposure logging is not possible"</string> <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours --> @@ -204,11 +202,11 @@ <!-- XTXT: risk card - outdated risk manual, calculation couldn't be updated in the last 48 hours --> <string name="risk_card_outdated_manual_risk_body">"Your risk status has not been updated for more than 48 hours. Please update your risk status."</string> <!-- XHED: risk card - risk check failed headline, no internet connection --> - <string name="risk_card_check_failed_no_internet_headline" /> + <string name="risk_card_check_failed_no_internet_headline">"Exposure check failed"</string> <!-- XTXT: risk card - risk check failed, please check your internet connection --> - <string name="risk_card_check_failed_no_internet_body" /> + <string name="risk_card_check_failed_no_internet_body">"The synchronization of random IDs with the server failed. You can restart the synchronization manually."</string> <!-- XTXT: risk card - risk check failed, restart button --> - <string name="risk_card_check_failed_no_internet_restart_button" /> + <string name="risk_card_check_failed_no_internet_restart_button">"Restart"</string> <!-- #################################### Risk Card - Progress @@ -264,7 +262,7 @@ <!-- XHED: App overview subtitle for tracing explanation--> <string name="main_overview_subtitle_tracing">"Exposure Logging"</string> <!-- YTXT: App overview body text about tracing --> - <string name="main_overview_body_tracing">"Exposure logging is one of the three central features of the app. When you activate it, encounters with people\'s devices are logged. You don\'t have to do anything else."</string> + <string name="main_overview_body_tracing">"Exposure logging is one of three central features of the app. Once you activate it, encounters with people\'s smartphones are logged. You don\'t have to do anything else."</string> <!-- XHED: App overview subtitle for risk explanation --> <string name="main_overview_subtitle_risk">"Risk of Infection"</string> <!-- YTXT: App overview body text about risk levels --> @@ -374,9 +372,9 @@ <item quantity="many">"You have an increased risk of infection because you were last exposed %1$s days ago over a longer period of time and at close proximity to at least one person diagnosed with COVID-19."</item> </plurals> <!-- YTXT: risk details - risk calculation explanation --> - <string name="risk_details_information_body_notice">"Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your device. Your risk of infection cannot be seen by, or passed on to, anyone else."</string> + <string name="risk_details_information_body_notice">"Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your smartphone. Your risk of infection cannot be seen by, or passed on to, anyone else."</string> <!-- YTXT: risk details - risk calculation explanation for increased risk --> - <string name="risk_details_information_body_notice_increased">"Therefore, your risk of infection has been ranked as increased. Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your device. Your risk of infection cannot be seen by, or passed on to, anyone else. When you get home, please also avoid close contact with members of your family or household."</string> + <string name="risk_details_information_body_notice_increased">"Therefore, your risk of infection has been ranked as increased. Your risk of infection is calculated from the exposure logging data (duration and proximity) locally on your smartphone. Your risk of infection cannot be seen by, or passed on to, anyone else. When you get home, please also avoid close contact with members of your family or household."</string> <!-- NOTR --> <string name="risk_details_button_update">@string/risk_card_button_update</string> <!-- NOTR --> @@ -432,7 +430,7 @@ <!-- XHED: onboarding(together) - two/three line headline under an illustration --> <string name="onboarding_subtitle">"More protection for you and for us all. By using the Corona-Warn-App we can break infection chains much quicker."</string> <!-- YTXT: onboarding(together) - inform about the app --> - <string name="onboarding_body">"Turn your device into a coronavirus warning system. Get an overview of your risk status and find out whether you\'ve had close contact with anyone diagnosed with COVID-19 in the last 14 days."</string> + <string name="onboarding_body">"Turn your smartphone into a coronavirus warning system. Get an overview of your risk status and find out whether you\'ve had close contact with anyone diagnosed with COVID-19 in the last 14 days."</string> <!-- YTXT: onboarding(together) - explain application --> <string name="onboarding_body_emphasized">"The app logs encounters between individuals by exchanging encrypted, random IDs between their devices, whereby no personal data whatsoever is accessed."</string> <!-- XACT: onboarding(together) - illustraction description, header image --> @@ -469,7 +467,7 @@ <!-- XBUT: onboarding(tracing) - negative button (right) --> <string name="onboarding_tracing_dialog_button_negative">"Back"</string> <!-- XACT: onboarding(tracing) - dialog about background jobs header text --> - <string name="onboarding_background_fetch_dialog_headline">"Background updates deactivated"</string> + <string name="onboarding_background_fetch_dialog_headline">"Background app refresh deactivated"</string> <!-- YMSI: onboarding(tracing) - dialog about background jobs --> <string name="onboarding_background_fetch_dialog_body">"You have deactivated background updates for the Corona-Warn-App. Please activate background updates to use automatic exposure logging. If you do not activate background updates, you can only start exposure logging manually in the app. You can activate background updates for the app in your device settings."</string> <!-- XBUT: onboarding(tracing) - dialog about background jobs, open device settings --> @@ -491,7 +489,7 @@ <!-- XBUT: onboarding(tracing) - dialog about manual checking button --> <string name="onboarding_manual_required_dialog_button">"OK"</string> <!-- XACT: onboarding(tracing) - illustraction description, header image --> - <string name="onboarding_tracing_illustration_description">"Three people have activated exposure logging on their devices, which will log their encounters with each other."</string> + <string name="onboarding_tracing_illustration_description">"Three persons have activated exposure logging on their smartphones, which will log their encounters with each other."</string> <!-- XHED: onboarding(tracing) - location explanation for bluetooth headline --> <string name="onboarding_tracing_location_headline">"Allow location access"</string> <!-- XTXT: onboarding(tracing) - location explanation for bluetooth body text --> @@ -688,7 +686,7 @@ <!-- YTXT: Body text for about information page --> <string name="information_about_body_emphasized">"Robert Koch Institute (RKI) is Germany’s federal public health body. The RKI publishes the Corona-Warn-App on behalf of the Federal Government. The app is intended as a digital complement to public health measures already introduced: social distancing, hygiene, and face masks."</string> <!-- YTXT: Body text for about information page --> - <string name="information_about_body">"People who use the app help to trace and break chains of infection. The app saves encounters with other people locally on your device. You are notified if you have encountered people who were later diagnosed with COVID-19. Your identity and privacy are always protected."</string> + <string name="information_about_body">"Whoever uses the app helps to trace and break chains of infection. The app saves encounters with other persons locally on your smartphone. You are notified if you have encountered persons who were later diagnosed with COVID-19. Your identity and privacy are always protected."</string> <!-- XACT: describes illustration --> <string name="information_about_illustration_description">"A group of persons use their smartphones around town."</string> <!-- XHED: Page title for privacy information page, also menu item / button text --> @@ -720,9 +718,9 @@ <!-- XTXT: Body text for technical contact and hotline information page --> <string name="information_contact_body_phone">"Our customer service is here to help."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_open">"Languages: German, English, Turkish\nBusiness hours:"<xliff:g id="line_break">"\n"</xliff:g>"Monday to Saturday: 7am - 10pm"<xliff:g id="line_break">"\n(except national holidays)"</xliff:g><xliff:g id="line_break">"\nThe call is free of charge."</xliff:g></string> + <string name="information_contact_body_open">"Languages: English, German, Turkish\nBusiness hours:"<xliff:g id="line_break">"\n"</xliff:g>"Monday to Saturday: 7am - 10pm"<xliff:g id="line_break">"\n(except national holidays)"</xliff:g><xliff:g id="line_break">"\nThe call is free of charge."</xliff:g></string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="information_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the hotline for the medical emergency service, telephone: 116 117."</string> + <string name="information_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the medical emergency service hotline, telephone: 116 117."</string> <!-- XACT: describes illustration --> <string name="information_contact_illustration_description">"A man wears a headset while making a phone call."</string> <!-- XLNK: Menu item / hyper link / button text for navigation to FAQ website --> @@ -805,9 +803,9 @@ <string name="submission_error_dialog_web_tan_invalid_button_positive">"Back"</string> <!-- XHED: Dialog title for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_title">"Test has errors"</string> + <string name="submission_error_dialog_web_tan_redeemed_title">"QR code no longer valid"</string> <!-- XMSG: Dialog body for submission tan redeemed --> - <string name="submission_error_dialog_web_tan_redeemed_body">"There was a problem evaluating your test. Your QR code has already expired."</string> + <string name="submission_error_dialog_web_tan_redeemed_body">"Your test is more than 21 days old and can no longer be registered in the app. If you are tested again in future, please make sure to scan the QR code as soon as you get it."</string> <!-- XBUT: Positive button for submission tan redeemed --> <string name="submission_error_dialog_web_tan_redeemed_button_positive">"OK"</string> @@ -881,15 +879,15 @@ <!-- XBUT: test result pending : refresh button --> <string name="submission_test_result_pending_refresh_button">"Update"</string> <!-- XBUT: test result pending : remove the test button --> - <string name="submission_test_result_pending_remove_test_button">"Delete Test"</string> + <string name="submission_test_result_pending_remove_test_button">"Remove test"</string> <!-- XHED: Page headline for negative test result next steps --> <string name="submission_test_result_negative_steps_negative_heading">"Your Test Result"</string> <!-- YTXT: Body text for next steps section of test negative result --> <string name="submission_test_result_negative_steps_negative_body">"The laboratory result indicates no verification that you have coronavirus SARS-CoV-2.\n\nPlease delete the test from the Corona-Warn-App, so that you can save a new test code here if necessary."</string> <!-- XBUT: negative test result : remove the test button --> - <string name="submission_test_result_negative_remove_test_button">"Delete Test"</string> + <string name="submission_test_result_negative_remove_test_button">"Remove Test"</string> <!-- XHED: Page headline for other warnings screen --> - <string name="submission_test_result_positive_steps_warning_others_heading">"Warning Others"</string> + <string name="submission_test_result_positive_steps_warning_others_heading">"Warn Others"</string> <!-- YTXT: Body text for for other warnings screen--> <string name="submission_test_result_positive_steps_warning_others_body">"Share your random IDs and warn others.\nHelp determine the risk of infection for others more accurately by also indicating when you first noticed any coronavirus symptoms."</string> <!-- XBUT: positive test result : continue button --> @@ -968,13 +966,13 @@ <!-- YTXT: Body text for QR code dispatcher option --> <string name="submission_dispatcher_qr_card_text">"Register your test by scanning the QR code of your test document."</string> <!-- XHED: Dialog headline for dispatcher QR prviacy dialog --> - <string name="submission_dispatcher_qr_privacy_dialog_headline">"Consent"</string> + <string name="submission_dispatcher_qr_privacy_dialog_headline">"Declaration of Consent"</string> <!-- YTXT: Dialog Body text for dispatcher QR privacy dialog --> <string name="submission_dispatcher_qr_privacy_dialog_body">"By tapping “Acceptâ€, you consent to the App querying the status of your coronavirus test and displaying it in the App. This feature is available to you if you have received a QR code and have consented to your test result being transmitted to the App’s server system. As soon as the testing lab has stored your test result on the server, you will be able to see the result in the App. If you have enabled notifications, you will also receive a notification outside the App telling you that your test result has been received. However, for privacy reasons, the test result itself will only be displayed in the App. You can withdraw this consent at any time by deleting your test registration in the App. Withdrawing your consent will not affect the lawfulness of processing before its withdrawal. Further information can be found in the menu under “Data Privacyâ€."</string> <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_positive">"Allow"</string> <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) --> - <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Do Not Accept"</string> + <string name="submission_dispatcher_qr_privacy_dialog_button_negative">"Do Not Allow"</string> <!-- YTXT: Dispatcher text for TAN code option --> <string name="submission_dispatcher_card_tan_code">"TAN"</string> <!-- YTXT: Body text for TAN code dispatcher option --> @@ -988,7 +986,7 @@ <!-- Submission Positive Other Warning --> <!-- XHED: Page title for the positive result additional warning page--> - <string name="submission_positive_other_warning_title">"Warning Others"</string> + <string name="submission_positive_other_warning_title">"Warn Others"</string> <!-- XHED: Page headline for the positive result additional warning page--> <string name="submission_positive_other_warning_headline">"Please help all of us!"</string> <!-- YTXT: Body text for the positive result additional warning page--> @@ -996,7 +994,7 @@ <!-- XBUT: other warning continue button --> <string name="submission_positive_other_warning_button">"Accept"</string> <!-- XACT: other warning - illustration description, explanation image --> - <string name="submission_positive_other_illustration_description">"A device transmits an encrypted positive test diagnosis to the system."</string> + <string name="submission_positive_other_illustration_description">"A smartphone transmits an encrypted positive test diagnosis to the system."</string> <!-- XHED: Title for the interop country list--> <string name="submission_interoperability_list_title">"The following countries currently participate in transnational exposure logging:"</string> @@ -1062,7 +1060,7 @@ <!-- XBUT: symptom initial screen no button --> <string name="submission_symptom_negative_button">"No"</string> <!-- XBUT: symptom initial screen no information button --> - <string name="submission_symptom_no_information_button">"No answer"</string> + <string name="submission_symptom_no_information_button">"No statement"</string> <!-- XBUT: symptom initial screen continue button --> <string name="submission_symptom_further_button">"Next"</string> @@ -1087,9 +1085,9 @@ <!-- YTXT: Body text for step 2 of contact page--> <string name="submission_contact_step_2_body">"Register the test by entering the TAN in the app."</string> <!-- YTXT: Body text for operating hours in contact page--> - <string name="submission_contact_operating_hours_body">"Languages: \nGerman, English, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> + <string name="submission_contact_operating_hours_body">"Languages: \nEnglish, German, Turkish\n\nBusiness hours:\nMonday to Sunday: 24 hours\n\nThe call is free of charge."</string> <!-- YTXT: Body text for technical contact and hotline information page --> - <string name="submission_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the hotline for the medical emergency service, telephone: 116 117."</string> + <string name="submission_contact_body_other">"If you have any health-related questions, please contact your general practitioner or the medical emergency service hotline, telephone: 116 117."</string> <!-- XACT: Submission contact page title --> @@ -1113,7 +1111,7 @@ <!-- XBUT: symptom calendar screen more than 2 weeks button --> <string name="submission_symptom_more_two_weeks">"More than 2 weeks ago"</string> <!-- XBUT: symptom calendar screen verify button --> - <string name="submission_symptom_verify">"No answer"</string> + <string name="submission_symptom_verify">"No statement"</string> <!-- Submission Status Card --> <!-- XHED: Page title for the various submission status: fetching --> @@ -1174,7 +1172,7 @@ <!-- YTXT: invalid status text --> <string name="test_result_card_status_invalid">"Evaluation is not possible"</string> <!-- YTXT: pending status text --> - <string name="test_result_card_status_pending">"Your result is not available yet"</string> + <string name="test_result_card_status_pending">"Your result is not yet available"</string> <!-- XHED: Title for further info of test result negative --> <string name="test_result_card_negative_further_info_title">"Other information:"</string> <!-- YTXT: Content for further info of test result negative --> @@ -1219,9 +1217,9 @@ <!-- XTXT: error dialog - either Google API Error (10) or reached request limit per day --> <string name="errors_google_api_error">"The Corona-Warn-App is running correctly, but we cannot update your current risk status. Exposure logging remains active and is working correctly. For further information, please see our FAQ page: https://www.coronawarn.app/en/faq/"</string> <!-- XTXT: error dialog - Error title when the provideDiagnosisKeys quota limit was reached. --> - <string name="errors_risk_detection_limit_reached_title" /> + <string name="errors_risk_detection_limit_reached_title">"Limit already reached"</string> <!-- XTXT: error dialog - Error description when the provideDiagnosisKeys quota limit was reached. --> - <string name="errors_risk_detection_limit_reached_description" /> + <string name="errors_risk_detection_limit_reached_description">"No more exposure checks possible today, as you have reached the maximum number of checks per day defined by your operating system. Please check your risik status again tomorrow."</string> <!-- #################################### Generic Error Messages @@ -1380,7 +1378,7 @@ <!-- YMSG: Onboarding tracing step second section in interoperability after the title --> <string name="interoperability_onboarding_second_section">"When a user submits their random IDs to the exchange server jointly operated by the participating countries, users of the official corona apps in all these countries can be warned of potential exposure."</string> <!-- YMSG: Onboarding tracing step third section in interoperability after the title. --> - <string name="interoperability_onboarding_randomid_download_free">"The daily download of the list with the random IDs is usually free of charge for you. Specifically, this means that mobile network operators do not charge you for the data used by the app in this context, and nor do they apply roaming charges for this in other EU countries. Please contact your mobile network operator for more information."</string> + <string name="interoperability_onboarding_randomid_download_free">"The daily download of the list with the random IDs is usually free of charge for you. Specifically, this means that mobile network operators do not charge you for the data used by the app in this context, nor do they apply roaming charges for this in other EU countries. Please contact your mobile network operator for more information."</string> <!-- XTXT: Small header above the country list in the onboarding screen for interoperability. --> <string name="interoperability_onboarding_list_title">"The following countries currently participate:"</string> <!-- XTXT: Description of the expanded terms in delta interopoerability screen part 1 --> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/AppConfigProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/AppConfigProviderTest.kt index 8f5817cf7441619cc98c5d9296f7bafa0bbf8718..105844e8a11e9f93aca8769e161daf12ad6b8d47 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/AppConfigProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/AppConfigProviderTest.kt @@ -98,7 +98,7 @@ class AppConfigProviderTest : BaseIOTest() { } @Test - fun `appConfig uses WHILE_SUBSCRIBED mode`() = runBlockingTest2(ignoreActive = true) { + fun `appConfig uses LAZILY mode`() = runBlockingTest2(ignoreActive = true) { val instance = createInstance(this) val testCollector1 = instance.currentConfig.test(startOnScope = this) @@ -123,7 +123,7 @@ class AppConfigProviderTest : BaseIOTest() { advanceUntilIdle() testCollector4.cancel() - coVerify(exactly = 2) { source.retrieveConfig() } + coVerify(exactly = 1) { source.retrieveConfig() } } @Test diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetectorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetectorTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..e06b40b3ed38a7e8d3a194f27ad2a003749bd293 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/appconfig/ConfigChangeDetectorTest.kt @@ -0,0 +1,104 @@ +package de.rki.coronawarnapp.appconfig + +import de.rki.coronawarnapp.risk.RiskLevelData +import de.rki.coronawarnapp.task.TaskController +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.mockk +import io.mockk.mockkObject +import io.mockk.verify +import io.mockk.verifySequence +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.TestCoroutineScope +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import testhelpers.BaseTest + +class ConfigChangeDetectorTest : BaseTest() { + + @MockK lateinit var appConfigProvider: AppConfigProvider + @MockK lateinit var taskController: TaskController + @MockK lateinit var riskLevelData: RiskLevelData + + private val currentConfigFake = MutableStateFlow(mockConfigId("initial")) + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + + mockkObject(ConfigChangeDetector.RiskLevelRepositoryDeferrer) + every { ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() } just Runs + + every { taskController.submit(any()) } just Runs + every { appConfigProvider.currentConfig } returns currentConfigFake + } + + private fun mockConfigId(id: String): ConfigData { + return mockk<ConfigData>().apply { + every { identifier } returns id + } + } + + private fun createInstance() = ConfigChangeDetector( + appConfigProvider = appConfigProvider, + taskController = taskController, + appScope = TestCoroutineScope(), + riskLevelData = riskLevelData + ) + + @Test + fun `new identifier without previous one is ignored`() { + + every { riskLevelData.lastUsedConfigIdentifier } returns null + + createInstance().launch() + + verify(exactly = 0) { + taskController.submit(any()) + ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() + } + } + + @Test + fun `new identifier results in new risk level calculation`() { + every { riskLevelData.lastUsedConfigIdentifier } returns "I'm a new identifier" + + createInstance().launch() + + verifySequence { + ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() + taskController.submit(any()) + } + } + + @Test + fun `same idetifier results in no op`() { + every { riskLevelData.lastUsedConfigIdentifier } returns "initial" + + createInstance().launch() + + verify(exactly = 0) { + taskController.submit(any()) + ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() + } + } + + @Test + fun `new emissions keep triggering the check`() { + every { riskLevelData.lastUsedConfigIdentifier } returns "initial" + + createInstance().launch() + currentConfigFake.value = mockConfigId("Straw") + currentConfigFake.value = mockConfigId("berry") + + verifySequence { + ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() + taskController.submit(any()) + ConfigChangeDetector.RiskLevelRepositoryDeferrer.resetRiskLevel() + taskController.submit(any()) + } + } +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt index 44a4980d7826e632fd792e724dc1c8d8c807d308..c636f8180f546895c787bb8f807e2633c4aa894c 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt @@ -9,12 +9,12 @@ import de.rki.coronawarnapp.ui.main.home.HomeFragmentViewModel import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider import de.rki.coronawarnapp.ui.main.home.TracingHeaderState -import de.rki.coronawarnapp.ui.submission.ApiRequestState.SUCCESS import de.rki.coronawarnapp.ui.tracing.card.TracingCardState import de.rki.coronawarnapp.ui.tracing.card.TracingCardStateProvider import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE_TELETAN +import de.rki.coronawarnapp.util.NetworkRequestWrapper import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -128,7 +128,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive QR code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit @@ -142,7 +142,7 @@ class HomeFragmentViewModelTest : BaseTest() { @Test fun `positive test result notification is triggered on positive TeleTan code result`() { - val state = SubmissionCardState(PAIRED_POSITIVE_TELETAN, true, SUCCESS) + val state = SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(PAIRED_POSITIVE_TELETAN), true) every { submissionCardsStateProvider.state } returns flowOf(state) every { testResultNotificationService.schedulePositiveTestResultReminder() } returns Unit diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt index 37d908b103393884b0e18d7776bd7eae0d547377..e661eb23ae7b28ae3ee123f96ed067d076dd4e3e 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardStateTest.kt @@ -5,6 +5,7 @@ import de.rki.coronawarnapp.R import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -33,12 +34,18 @@ class SubmissionCardStateTest : BaseTest() { private fun instance( deviceUiState: DeviceUIState = mockk(), isDeviceRegistered: Boolean = true, - uiStateState: ApiRequestState = mockk() - ) = SubmissionCardState( - deviceUiState = deviceUiState, - isDeviceRegistered = isDeviceRegistered, - uiStateState = uiStateState - ) + uiStateState: ApiRequestState = ApiRequestState.SUCCESS + ) = + when (uiStateState) { + ApiRequestState.SUCCESS -> + SubmissionCardState(NetworkRequestWrapper.RequestSuccessful(deviceUiState), isDeviceRegistered) + ApiRequestState.FAILED -> + SubmissionCardState(NetworkRequestWrapper.RequestFailed(mockk()), isDeviceRegistered) + ApiRequestState.STARTED -> + SubmissionCardState(NetworkRequestWrapper.RequestStarted, isDeviceRegistered) + ApiRequestState.IDLE -> + SubmissionCardState(NetworkRequestWrapper.RequestIdle, isDeviceRegistered) + } @Test fun `risk card visibility`() { @@ -163,7 +170,7 @@ class SubmissionCardStateTest : BaseTest() { isFetchingCardVisible() shouldBe false } instance(isDeviceRegistered = true, uiStateState = ApiRequestState.FAILED).apply { - isFetchingCardVisible() shouldBe true + isFetchingCardVisible() shouldBe false } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt index 2eaac14f64ca80055b87cbfef053e197a6927306..b5bc2d4517aa1f4c8ec53b54553bc3bec1756228 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/SubmissionCardsStateProviderTest.kt @@ -5,8 +5,8 @@ import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.ui.main.home.SubmissionCardState import de.rki.coronawarnapp.ui.main.home.SubmissionCardsStateProvider -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations import io.mockk.clearAllMocks @@ -46,20 +46,19 @@ class SubmissionCardsStateProviderTest : BaseTest() { @Test fun `state is combined correctly`() = runBlockingTest { - every { SubmissionRepository.deviceUIStateFlow } returns flow { emit(DeviceUIState.PAIRED_POSITIVE) } - every { SubmissionRepository.uiStateStateFlow } returns flow { emit(ApiRequestState.SUCCESS) } + every { SubmissionRepository.deviceUIStateFlow } returns flow { + emit(NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>(DeviceUIState.PAIRED_POSITIVE)) + } every { LocalData.registrationToken() } returns "token" createInstance().apply { state.first() shouldBe SubmissionCardState( - deviceUiState = DeviceUIState.PAIRED_POSITIVE, - uiStateState = ApiRequestState.SUCCESS, + deviceUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), isDeviceRegistered = true ) verify { SubmissionRepository.deviceUIStateFlow - SubmissionRepository.uiStateStateFlow LocalData.registrationToken() } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorageTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorageTest.kt index fee9f63fa4177ddbb0fc6819d6788fe67535c514..702291ceaeaacdea384fe8f930a56caec0590ede 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorageTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTrackerStorageTest.kt @@ -130,4 +130,20 @@ class ExposureDetectionTrackerStorageTest : BaseIOTest() { storedData.getValue("b2b98400-058d-43e6-b952-529a5255248b").isCalculating shouldBe true storedData.getValue("aeb15509-fb34-42ce-8795-7a9ae0c2f389").isCalculating shouldBe false } + + @Test + fun `we catch empty json data and prevent unsafely initialized maps`() = runBlockingTest { + storageDir.mkdirs() + storageFile.writeText("") + + storageFile.exists() shouldBe true + + createStorage().apply { + val value = load() + value.size shouldBe 0 + value shouldBe emptyMap() + + storageFile.exists() shouldBe false + } + } } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelDataTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelDataTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..41a2b35177a6eab0a08331f6337a9ce6f991554d --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelDataTest.kt @@ -0,0 +1,40 @@ +package de.rki.coronawarnapp.risk + +import android.content.Context +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import testhelpers.BaseTest +import testhelpers.preferences.MockSharedPreferences + +class RiskLevelDataTest : BaseTest() { + + @MockK lateinit var context: Context + lateinit var preferences: MockSharedPreferences + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + preferences = MockSharedPreferences() + every { context.getSharedPreferences("risklevel_localdata", Context.MODE_PRIVATE) } returns preferences + } + + fun createInstance() = RiskLevelData(context = context) + + @Test + fun `update last used config identifier`() { + createInstance().apply { + lastUsedConfigIdentifier shouldBe null + lastUsedConfigIdentifier = "Banana" + lastUsedConfigIdentifier shouldBe "Banana" + preferences.dataMapPeek.containsValue("Banana") shouldBe true + + lastUsedConfigIdentifier = null + lastUsedConfigIdentifier shouldBe null + preferences.dataMapPeek.isEmpty() shouldBe true + } + } +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..889dc3a37d0ef6f84d25b84fa12616bbc28f2b41 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt @@ -0,0 +1,80 @@ +package de.rki.coronawarnapp.risk + +import android.content.Context +import android.net.ConnectivityManager +import android.net.Network +import android.net.NetworkCapabilities +import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.appconfig.ConfigData +import de.rki.coronawarnapp.nearby.ENFClient +import de.rki.coronawarnapp.task.Task +import de.rki.coronawarnapp.util.BackgroundModeStatus +import de.rki.coronawarnapp.util.TimeStamper +import io.mockk.MockKAnnotations +import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.just +import io.mockk.mockk +import io.mockk.verify +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.test.runBlockingTest +import org.joda.time.Instant +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import testhelpers.BaseTest + +class RiskLevelTaskTest : BaseTest() { + + @MockK lateinit var riskLevels: RiskLevels + @MockK lateinit var context: Context + @MockK lateinit var enfClient: ENFClient + @MockK lateinit var timeStamper: TimeStamper + @MockK lateinit var backgroundModeStatus: BackgroundModeStatus + @MockK lateinit var riskLevelData: RiskLevelData + @MockK lateinit var configData: ConfigData + @MockK lateinit var appConfigProvider: AppConfigProvider + + private val arguments: Task.Arguments = object : Task.Arguments {} + + private fun createTask() = RiskLevelTask( + riskLevels = riskLevels, + context = context, + enfClient = enfClient, + timeStamper = timeStamper, + backgroundModeStatus = backgroundModeStatus, + riskLevelData = riskLevelData, + appConfigProvider = appConfigProvider + ) + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + coEvery { appConfigProvider.getAppConfig() } returns configData + every { configData.identifier } returns "config-identifier" + + every { context.getSystemService(Context.CONNECTIVITY_SERVICE) } returns mockk<ConnectivityManager>().apply { + every { activeNetwork } returns mockk<Network>().apply { + every { getNetworkCapabilities(any()) } returns mockk<NetworkCapabilities>().apply { + every { hasCapability(any()) } returns true + } + } + } + + every { enfClient.isTracingEnabled } returns flowOf(true) + every { timeStamper.nowUTC } returns Instant.EPOCH + every { riskLevels.updateRepository(any(), any()) } just Runs + + every { riskLevelData.lastUsedConfigIdentifier = any() } just Runs + } + + @Test + fun `last used config ID is set after calculation`() = runBlockingTest { + every { riskLevels.calculationNotPossibleBecauseOfNoKeys() } returns true + val task = createTask() + task.run(arguments) + + verify { riskLevelData.lastUsedConfigIdentifier = "config-identifier" } + } +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/flow/HotDataFlowTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/flow/HotDataFlowTest.kt index 3de7010f7bf7105aa25a8738dbcd6772f0c140b4..9b23f5eca4035d5da1266bdc020f05dc3bb131fe 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/flow/HotDataFlowTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/flow/HotDataFlowTest.kt @@ -1,5 +1,6 @@ package de.rki.coronawarnapp.util.flow +import de.rki.coronawarnapp.util.mutate import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import io.kotest.matchers.types.instanceOf @@ -84,7 +85,7 @@ class HotDataFlowTest : BaseTest() { ) testScope.apply { - runBlockingTest2(permanentJobs = true) { + runBlockingTest2(ignoreActive = true) { hotData.data.first() shouldBe "Test" hotData.data.first() shouldBe "Test" } @@ -107,7 +108,7 @@ class HotDataFlowTest : BaseTest() { ) testScope.apply { - runBlockingTest2(permanentJobs = true) { + runBlockingTest2(ignoreActive = true) { hotData.data.first() shouldBe "Test" hotData.data.first() shouldBe "Test" } @@ -150,6 +151,48 @@ class HotDataFlowTest : BaseTest() { coVerify(exactly = 1) { valueProvider.invoke(any()) } } + data class TestData( + val number: Long = 1 + ) + + @Test + fun `check multi threading value updates with more complex data`() { + val testScope = TestCoroutineScope() + val valueProvider = mockk<suspend CoroutineScope.() -> Map<String, TestData>>() + coEvery { valueProvider.invoke(any()) } returns mapOf("data" to TestData()) + + val hotData = HotDataFlow( + loggingTag = "tag", + scope = testScope, + startValueProvider = valueProvider, + sharingBehavior = SharingStarted.Lazily + ) + + val testCollector = hotData.data.test(startOnScope = testScope) + testCollector.silent = true + + (1..10).forEach { _ -> + thread { + (1..400).forEach { _ -> + hotData.updateSafely { + mutate { + this["data"] = getValue("data").copy( + number = getValue("data").number + 1 + ) + } + } + } + } + } + + runBlocking { + testCollector.await { list, l -> list.size == 4001 } + testCollector.latestValues.map { it.values.single().number } shouldBe (1L..4001L).toList() + } + + coVerify(exactly = 1) { valueProvider.invoke(any()) } + } + @Test fun `only emit new values if they actually changed updates`() { val testScope = TestCoroutineScope() @@ -188,10 +231,10 @@ class HotDataFlowTest : BaseTest() { sharingBehavior = SharingStarted.Lazily ) - testScope.runBlockingTest2(permanentJobs = true) { - val sub1 = hotData.data.test().start(scope = this) - val sub2 = hotData.data.test().start(scope = this) - val sub3 = hotData.data.test().start(scope = this) + testScope.runBlockingTest2(ignoreActive = true) { + val sub1 = hotData.data.test(tag = "sub1", startOnScope = this) + val sub2 = hotData.data.test(tag = "sub2", startOnScope = this) + val sub3 = hotData.data.test(tag = "sub3", startOnScope = this) hotData.updateSafely { "A" } hotData.updateSafely { "B" } @@ -208,6 +251,49 @@ class HotDataFlowTest : BaseTest() { coVerify(exactly = 1) { valueProvider.invoke(any()) } } + @Test + fun `update queue is wiped on completion`() = runBlockingTest2(ignoreActive = true) { + val valueProvider = mockk<suspend CoroutineScope.() -> Long>() + coEvery { valueProvider.invoke(any()) } returns 1 + + val hotData = HotDataFlow( + loggingTag = "tag", + scope = this, + coroutineContext = this.coroutineContext, + startValueProvider = valueProvider, + sharingBehavior = SharingStarted.WhileSubscribed(replayExpirationMillis = 0) + ) + + val testCollector1 = hotData.data.test(tag = "collector1", startOnScope = this) + testCollector1.silent = false + + (1..10).forEach { _ -> + hotData.updateSafely { + this + 1L + } + } + + advanceUntilIdle() + + testCollector1.await { list, _ -> list.size == 11 } + testCollector1.latestValues shouldBe (1L..11L).toList() + + testCollector1.cancel() + testCollector1.awaitFinal() + + val testCollector2 = hotData.data.test(tag = "collector2", startOnScope = this) + testCollector2.silent = false + + advanceUntilIdle() + + testCollector2.cancel() + testCollector2.awaitFinal() + + testCollector2.latestValues shouldBe listOf(1L) + + coVerify(exactly = 2) { valueProvider.invoke(any()) } + } + @Test fun `blocking update is actually blocking`() = runBlocking { val testScope = TestCoroutineScope() diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt index c8310865349f45752a771fee79b85b6bfa4e74cc..c7f8e7b15f275e2a9b405de92603fa1531f8f7db 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelperTest.kt @@ -8,8 +8,8 @@ import android.text.style.ForegroundColorSpan import android.view.View import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.submission.ApiRequestState import de.rki.coronawarnapp.util.DeviceUIState +import de.rki.coronawarnapp.util.NetworkRequestWrapper import io.mockk.MockKAnnotations import io.mockk.every import io.mockk.impl.annotations.MockK @@ -74,52 +74,76 @@ class FormatterSubmissionHelperTest { every { context.getDrawable(R.drawable.ic_test_result_illustration_negative) } returns drawable } - private fun formatTestResultSpinnerVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultSpinnerVisible(uiStateState = oUiStateState) + private fun formatTestResultSpinnerVisibleBase( + oUiStateState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { + val result = formatTestResultSpinnerVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultVisibleBase(oUiStateState: ApiRequestState?, iResult: Int) { - val result = formatTestResultVisible(uiStateState = oUiStateState) + private fun formatTestResultVisibleBase( + oUiStateState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { + val result = formatTestResultVisible(uiState = oUiStateState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusTextBase(oUiState: DeviceUIState?, iResult: String) { + private fun formatTestResultStatusTextBase( + oUiState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: String + ) { val result = formatTestResultStatusText(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultStatusColorBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultStatusColorBase( + oUiState: NetworkRequestWrapper<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultStatusColor(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestStatusIconBase(oUiState: DeviceUIState?) { + private fun formatTestStatusIconBase(oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?) { val result = formatTestStatusIcon(uiState = oUiState) assertThat(result, `is`(drawable)) } - private fun formatTestResultPendingStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPendingStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultPendingStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultNegativeStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultNegativeStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultNegativeStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultPositiveStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultPositiveStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultPositiveStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultInvalidStepsVisibleBase(oUiState: DeviceUIState?, iResult: Int) { + private fun formatTestResultInvalidStepsVisibleBase( + oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?, + iResult: Int + ) { val result = formatTestResultInvalidStepsVisible(uiState = oUiState) assertThat(result, `is`(iResult)) } - private fun formatTestResultBase(oUiState: DeviceUIState?) { + private fun formatTestResultBase(oUiState: NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>?) { mockkConstructor(SpannableStringBuilder::class) val spannableStringBuilder1 = @@ -147,19 +171,19 @@ class FormatterSubmissionHelperTest { fun formatTestResultSpinnerVisible() { formatTestResultSpinnerVisibleBase(oUiStateState = null, iResult = View.VISIBLE) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.FAILED, + oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.IDLE, + oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.STARTED, + oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.VISIBLE ) formatTestResultSpinnerVisibleBase( - oUiStateState = ApiRequestState.SUCCESS, + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), iResult = View.GONE ) } @@ -167,10 +191,13 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResultVisible() { formatTestResultVisibleBase(oUiStateState = null, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.FAILED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.IDLE, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.STARTED, iResult = View.GONE) - formatTestResultVisibleBase(oUiStateState = ApiRequestState.SUCCESS, iResult = View.VISIBLE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestFailed(mockk()), iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestIdle, iResult = View.GONE) + formatTestResultVisibleBase(oUiStateState = NetworkRequestWrapper.RequestStarted, iResult = View.GONE) + formatTestResultVisibleBase( + oUiStateState = NetworkRequestWrapper.RequestSuccessful(mockk()), + iResult = View.VISIBLE + ) } @Test @@ -180,35 +207,35 @@ class FormatterSubmissionHelperTest { iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getString(R.string.test_result_card_status_negative) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getString(R.string.test_result_card_status_positive) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getString(R.string.test_result_card_status_invalid) ) formatTestResultStatusTextBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getString(R.string.test_result_card_status_invalid) ) } @@ -220,35 +247,35 @@ class FormatterSubmissionHelperTest { iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = context.getColor(R.color.colorTextSemanticGreen) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = context.getColor(R.color.colorTextSemanticRed) ) formatTestResultStatusColorBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = context.getColor(R.color.colorTextSemanticRed) ) } @@ -256,49 +283,49 @@ class FormatterSubmissionHelperTest { @Test fun formatTestStatusIcon() { formatTestStatusIconBase(oUiState = null) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestStatusIconBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestStatusIconBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestStatusIconBase(oUiState = DeviceUIState.UNPAIRED) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestStatusIconBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @Test fun formatTestResultPendingStepsVisible() { formatTestResultPendingStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.VISIBLE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPendingStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -307,35 +334,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultNegativeStepsVisible() { formatTestResultNegativeStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.VISIBLE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultNegativeStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -344,35 +371,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultPositiveStepsVisible() { formatTestResultPositiveStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.VISIBLE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultPositiveStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -381,35 +408,35 @@ class FormatterSubmissionHelperTest { fun formatTestResultInvalidStepsVisible() { formatTestResultInvalidStepsVisibleBase(oUiState = null, iResult = View.GONE) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NEGATIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_ERROR, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR), iResult = View.VISIBLE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_NO_RESULT, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_FINAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.SUBMITTED_INITIAL, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL), iResult = View.GONE ) formatTestResultInvalidStepsVisibleBase( - oUiState = DeviceUIState.UNPAIRED, + oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED), iResult = View.GONE ) } @@ -417,14 +444,14 @@ class FormatterSubmissionHelperTest { @Test fun formatTestResult() { formatTestResultBase(oUiState = null) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NEGATIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_ERROR) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_NO_RESULT) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE) - formatTestResultBase(oUiState = DeviceUIState.PAIRED_POSITIVE_TELETAN) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_FINAL) - formatTestResultBase(oUiState = DeviceUIState.SUBMITTED_INITIAL) - formatTestResultBase(oUiState = DeviceUIState.UNPAIRED) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NEGATIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_ERROR)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE_TELETAN)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_INITIAL)) + formatTestResultBase(oUiState = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)) } @After diff --git a/Corona-Warn-App/src/test/java/testhelpers/coroutines/FlowTest.kt b/Corona-Warn-App/src/test/java/testhelpers/coroutines/FlowTest.kt index 3fc56ce9a503dcd65c2afb6f91e657557776c2d8..5a19fa308a2f5ec037373528c26e0ea099810aa1 100644 --- a/Corona-Warn-App/src/test/java/testhelpers/coroutines/FlowTest.kt +++ b/Corona-Warn-App/src/test/java/testhelpers/coroutines/FlowTest.kt @@ -16,14 +16,17 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.test.TestCoroutineScope +import kotlinx.coroutines.withTimeout +import org.joda.time.Duration import timber.log.Timber fun <T> Flow<T>.test( tag: String? = null, - startOnScope: CoroutineScope -): TestCollector<T> = test(tag ?: "FlowTest").start(scope = startOnScope) + startOnScope: CoroutineScope = TestCoroutineScope() +): TestCollector<T> = createTest(tag ?: "FlowTest").start(scope = startOnScope) -fun <T> Flow<T>.test( +fun <T> Flow<T>.createTest( tag: String? = null ): TestCollector<T> = TestCollector(this, tag ?: "FlowTest") @@ -74,9 +77,14 @@ class TestCollector<T>( val latestValues: List<T> get() = collectedValues - fun await(condition: (List<T>, T) -> Boolean): T = runBlocking { - emissions().first { - condition(collectedValues, it) + fun await( + timeout: Duration = Duration.standardSeconds(10), + condition: (List<T>, T) -> Boolean + ): T = runBlocking { + withTimeout(timeMillis = timeout.millis) { + emissions().first { + condition(collectedValues, it) + } } } @@ -95,6 +103,8 @@ class TestCollector<T>( } fun cancel() { + if (job.isCompleted) throw IllegalStateException("Flow is already canceled.") + runBlocking { job.cancelAndJoin() } diff --git a/Corona-Warn-App/src/test/java/testhelpers/coroutines/TestExtensions.kt b/Corona-Warn-App/src/test/java/testhelpers/coroutines/TestExtensions.kt index 375adf36e462e42753b985160ba5062cbcdc3397..68d1ba19c174d4bb013eb4bcba609566a31cafdf 100644 --- a/Corona-Warn-App/src/test/java/testhelpers/coroutines/TestExtensions.kt +++ b/Corona-Warn-App/src/test/java/testhelpers/coroutines/TestExtensions.kt @@ -11,10 +11,10 @@ import kotlin.coroutines.EmptyCoroutineContext @ExperimentalCoroutinesApi // Since 1.2.1, tentatively till 1.3.0 fun TestCoroutineScope.runBlockingTest2( - permanentJobs: Boolean = false, + ignoreActive: Boolean = false, block: suspend TestCoroutineScope.() -> Unit ): Unit = runBlockingTest2( - ignoreActive = permanentJobs, + ignoreActive = ignoreActive, context = coroutineContext, testBody = block ) diff --git a/gradle.properties b/gradle.properties index 43acf78b7a8e600fcb0cc59815e1edecd3ed6cd4..cce1f15dbd414b6e337383eea977c01bb4f51384 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,4 @@ org.gradle.dependency.verification.console=verbose VERSION_MAJOR=1 VERSION_MINOR=8 VERSION_PATCH=0 -VERSION_BUILD=2 +VERSION_BUILD=3