MAJ terminée. Nous sommes passés en version 14.6.2 . Pour consulter les "releases notes" associées c'est ici :

https://about.gitlab.com/releases/2022/01/11/security-release-gitlab-14-6-2-released/
https://about.gitlab.com/releases/2022/01/04/gitlab-14-6-1-released/

Commit 2022f41e authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com
Browse files

Update to 2.1.2

parent 4019f91f
......@@ -13,6 +13,7 @@ package com.lunabeestudio.stopcovid.coreui.fastitem
import android.view.Gravity
import android.view.View
import android.widget.TextView
import androidx.annotation.StyleRes
import androidx.recyclerview.widget.RecyclerView
import com.lunabeestudio.stopcovid.coreui.R
import com.lunabeestudio.stopcovid.coreui.extension.safeEmojiSpanify
......@@ -23,10 +24,19 @@ class CaptionItem : BaseItem<CaptionItem.ViewHolder>(
var text: String? = null
var gravity: Int = Gravity.NO_GRAVITY
@StyleRes
var textAppearance: Int = R.style.TextAppearance_StopCovid_Caption
override fun bindView(holder: ViewHolder, payloads: List<Any>) {
super.bindView(holder, payloads)
holder.textView.text = text.safeEmojiSpanify()
holder.textView.gravity = gravity
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
holder.textView.setTextAppearance(textAppearance)
} else {
@Suppress("DEPRECATION")
holder.textView.setTextAppearance(holder.textView.context, textAppearance)
}
}
class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
......
......@@ -56,18 +56,35 @@ abstract class BaseFragment : Fragment() {
return when {
now - this <= 1.minutes -> strings["common.justNow"]
now - this <= 1.days -> DateUtils.getRelativeTimeSpanString(
this.coerceAtMost(now - 1.minutes).toLongMilliseconds(),
now.toLongMilliseconds(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR or DateUtils.FORMAT_ABBREV_MONTH,
).toString()
this.coerceAtMost(now - 1.minutes).toLongMilliseconds(),
now.toLongMilliseconds(),
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR or DateUtils.FORMAT_ABBREV_MONTH,
)
.toString()
.fixQuoteInString()
else -> DateUtils.getRelativeDateTimeString(
context,
this.toLongMilliseconds(),
DateUtils.DAY_IN_MILLIS,
DateUtils.WEEK_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR or DateUtils.FORMAT_ABBREV_MONTH,
).toString()
context,
this.toLongMilliseconds(),
DateUtils.DAY_IN_MILLIS,
DateUtils.WEEK_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR or DateUtils.FORMAT_ABBREV_MONTH,
)
.toString()
.fixQuoteInString()
}
}
@OptIn(ExperimentalTime::class)
protected fun Duration.getRelativeDateString(context: Context): String? {
return DateUtils.getRelativeTimeSpanString(
this.toLongMilliseconds(),
System.currentTimeMillis(),
DateUtils.DAY_IN_MILLIS,
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_SHOW_YEAR or DateUtils.FORMAT_ABBREV_MONTH)
.toString()
}
// Dirty hack to fix strange display of quotes on some Android devices
private fun String.fixQuoteInString(): String = replace("'", "")
}
......@@ -46,13 +46,13 @@ abstract class ServerManager {
}
}
protected suspend fun <T> loadLocal(context: Context, forceRefresh: Boolean): T? {
protected suspend fun <T> loadLocal(context: Context): T? {
val currentLanguage = Locale.getDefault().language
val result: T? = loadLocal(context, currentLanguage) ?: loadAssetFile(context, currentLanguage)
if (result == null && (shouldRefresh(context) || forceRefresh)) {
fetchLast(context, UiConstants.DEFAULT_LANGUAGE)
}
return result ?: loadLocal(context, UiConstants.DEFAULT_LANGUAGE) ?: loadAssetFile(context, UiConstants.DEFAULT_LANGUAGE)
return loadFromFiles(context, currentLanguage)
?: loadFromAssets(context, currentLanguage)
?: loadFromFiles(context, UiConstants.DEFAULT_LANGUAGE)
?: loadFromAssets(context, UiConstants.DEFAULT_LANGUAGE)
}
private suspend fun fetchLast(context: Context, languageCode: String): Boolean {
......@@ -67,7 +67,7 @@ abstract class ServerManager {
}
}
private suspend fun <T> loadLocal(context: Context, languageCode: String): T? {
private suspend fun <T> loadFromFiles(context: Context, languageCode: String): T? {
val fileName = "${prefix(context)}$languageCode${extension()}"
val file = File(context.filesDir, fileName)
return if (!file.exists()) {
......@@ -86,7 +86,7 @@ abstract class ServerManager {
}
}
private suspend fun <T> loadAssetFile(context: Context, languageCode: String): T? {
private suspend fun <T> loadFromAssets(context: Context, languageCode: String): T? {
val fileName = "${prefix(context)}$languageCode${extension()}"
@Suppress("BlockingMethodInNonBlockingContext")
return withContext(Dispatchers.IO) {
......
......@@ -38,17 +38,24 @@ object StringsManager : ServerManager() {
suspend fun initialize(context: Context) {
prevLanguage = Locale.getDefault().language
loadLocal<HashMap<String, String>>(context, false)?.let {
loadLocal<HashMap<String, String>>(context)?.let {
strings = it
}
}
suspend fun onAppForeground(context: Context) {
val forceRefresh = prevLanguage != Locale.getDefault().language
val hasFetch = fetchLast(context, forceRefresh)
if (hasFetch || forceRefresh) {
loadLocal<HashMap<String, String>>(context, forceRefresh)?.let {
prevLanguage = Locale.getDefault().language
val languageHasChanged = prevLanguage != Locale.getDefault().language
prevLanguage = Locale.getDefault().language
if (languageHasChanged) {
loadLocal<HashMap<String, String>>(context)?.let {
strings = it
}
}
val hasFetch = fetchLast(context, languageHasChanged)
if (hasFetch) {
loadLocal<HashMap<String, String>>(context)?.let {
strings = it
}
}
......
......@@ -60,6 +60,10 @@
<item name="android:textSize">@dimen/small_caption_font_size</item>
</style>
<style name="TextAppearance.StopCovid.Caption.Small.Grey">
<item name="android:textColor">@android:color/darker_gray</item>
</style>
<style name="TextAppearance.StopCovid.Title.Circle">
<item name="android:textSize">@dimen/circle_font_size</item>
<item name="android:textColor">?attr/colorOnPrimary</item>
......
......@@ -78,8 +78,8 @@
<item name="boxCornerRadiusTopEnd">@dimen/corner_radius</item>
<item name="boxCornerRadiusBottomStart">@dimen/corner_radius</item>
<item name="boxCornerRadiusBottomEnd">@dimen/corner_radius</item>
<item name="android:layout_marginStart">@dimen/spacing_xlarge</item>
<item name="android:layout_marginEnd">@dimen/spacing_xlarge</item>
<item name="android:layout_marginStart">@dimen/spacing_large</item>
<item name="android:layout_marginEnd">@dimen/spacing_large</item>
<item name="errorIconDrawable">@null</item>
<item name="errorEnabled">true</item>
</style>
......
......@@ -44,6 +44,7 @@ import java.util.UUID
abstract class RobertProximityService : ProximityNotificationService() {
abstract val robertManager: RobertManager
protected abstract fun sendErrorBluetoothNotification()
private var payloadUpdateSchedulerScope: CoroutineScope = CoroutineScope(Dispatchers.IO)
......@@ -74,6 +75,11 @@ abstract class RobertProximityService : ProximityNotificationService() {
payloadUpdateSchedulerScope.cancel("Proximity service has been stopped")
}
override fun onBluetoothDisabled() {
super.onBluetoothDisabled()
sendErrorBluetoothNotification()
}
override val bleSettings: BleSettings
get() {
Timber.v("Fetch new BLE settings")
......
......@@ -553,6 +553,25 @@ class SecureKeystoreDataSource(context: Context, private val cryptoManager: Loca
}
}
override var qrCodeFormattedStringDisplayed: String?
get() {
val encryptedText = sharedPreferences.getString(SHARED_PREF_KEY_QR_CODE_FORMATTED_STRING_DISPLAYED, null)
return if (encryptedText != null) {
cryptoManager.decryptToString(encryptedText)
} else {
null
}
}
set(value) {
if (value != null) {
sharedPreferences.edit()
.putString(SHARED_PREF_KEY_QR_CODE_FORMATTED_STRING_DISPLAYED, cryptoManager.encryptToString(value))
.apply()
} else {
sharedPreferences.edit().remove(SHARED_PREF_KEY_QR_CODE_FORMATTED_STRING_DISPLAYED).apply()
}
}
override var qrCodeFooterString: String?
get() {
val encryptedText = sharedPreferences.getString(SHARED_PREF_KEY_QR_CODE_FOOTER_STRING, null)
......@@ -680,6 +699,7 @@ class SecureKeystoreDataSource(context: Context, private val cryptoManager: Loca
private const val SHARED_PREF_KEY_QR_CODE_DELETION_HOURS = "shared.pref.qr_code_deletion_hours"
private const val SHARED_PREF_KEY_QR_CODE_EXPIRED_HOURS = "shared.pref.qr_code_expired_hours"
private const val SHARED_PREF_KEY_QR_CODE_FORMATTED_STRING = "shared.pref.qr_code_formatted_string"
private const val SHARED_PREF_KEY_QR_CODE_FORMATTED_STRING_DISPLAYED = "shared.pref.qr_code_formatted_string_displayed"
private const val SHARED_PREF_KEY_QR_CODE_FOOTER_STRING = "shared.pref.qr_code_footer_string"
private const val SHARED_PREF_KEY_SAVE_ATTESTATION_DATA = "shared.pref.save_attestation_data"
private const val SHARED_PREF_KEY_SAVED_ATTESTATION_DATA = "shared.pref.saved_attestation_data"
......
......@@ -34,6 +34,7 @@ object RobertConstant {
const val QR_CODE_DELETION_HOURS: Float = 24F
const val QR_CODE_EXPIRED_HOURS: Float = 1F
const val QR_CODE_FORMATTED_STRING: String = "Cree le: <creationDate> a <creationHour>;\nNom: <lastname>;\nPrenom: <firstname>;\nNaissance: <dob> a <cityofbirth>;\nAdresse: <address> <zip> <city>;\nSortie: <datetime-day> a <datetime-hour>;\nMotif: <reason-code>"
const val QR_CODE_FORMATTED_STRING_DISPLAYED: String = "Créé le <creationDate> à <creationHour>\nNom : <lastname>\nPrénom : <firstname>\nNaissance : <dob> à <cityofbirth>\nAdresse : <address> <zip> <city>\nSortie : <datetime-day> à <datetime-hour>\nMotif: <reason-code>"
const val QR_CODE_FOOTER_STRING: String = "<firstname> - <datetime-day>, <datetime-hour>\n<reason-shortlabel>"
object CONFIG {
......@@ -57,6 +58,7 @@ object RobertConstant {
const val QR_CODE_DELETION_HOURS: String = "app.qrCode.deletionHours"
const val QR_CODE_EXPIRED_HOURS: String = "app.qrCode.expiredHours"
const val QR_CODE_FORMATTED_STRING: String = "app.qrCode.formattedString"
const val QR_CODE_FORMATTED_STRING_DISPLAYED: String = "app.qrCode.formattedStringDisplayed"
const val QR_CODE_FOOTER_STRING: String = "app.qrCode.footerString"
}
......
......@@ -67,6 +67,8 @@ interface RobertManager {
val qrCodeFormattedString: String
val qrCodeFormattedStringDisplayed: String
val qrCodeFooterString: String
val displayDepartmentLevel: Boolean
......
......@@ -167,6 +167,9 @@ class RobertManagerImpl(
override val qrCodeFormattedString: String
get() = keystoreRepository.qrCodeFormattedString ?: RobertConstant.QR_CODE_FORMATTED_STRING
override val qrCodeFormattedStringDisplayed: String
get() = keystoreRepository.qrCodeFormattedStringDisplayed ?: RobertConstant.QR_CODE_FORMATTED_STRING_DISPLAYED
override val qrCodeFooterString: String
get() = keystoreRepository.qrCodeFooterString ?: RobertConstant.QR_CODE_FOOTER_STRING
......@@ -343,6 +346,11 @@ class RobertManagerImpl(
}?.value as? String)?.let { formattedString ->
keystoreRepository.qrCodeFormattedString = formattedString
}
(configuration?.firstOrNull {
it.name == RobertConstant.CONFIG.QR_CODE_FORMATTED_STRING_DISPLAYED
}?.value as? String)?.let { formattedStringDisplayed ->
keystoreRepository.qrCodeFormattedStringDisplayed = formattedStringDisplayed
}
(configuration?.firstOrNull {
it.name == RobertConstant.CONFIG.QR_CODE_FOOTER_STRING
}?.value as? String)?.let { footerString ->
......
......@@ -41,6 +41,7 @@ interface LocalKeystoreDataSource {
var qrCodeDeletionHours: Float?
var qrCodeExpiredHours: Float?
var qrCodeFormattedString: String?
var qrCodeFormattedStringDisplayed: String?
var qrCodeFooterString: String?
var displayDepartmentLevel: Boolean?
}
......@@ -184,6 +184,12 @@ internal class KeystoreRepository(
keystoreDataSource.qrCodeFormattedString = value
}
var qrCodeFormattedStringDisplayed: String?
get() = keystoreDataSource.qrCodeFormattedStringDisplayed
set(value) {
keystoreDataSource.qrCodeFormattedStringDisplayed = value
}
var qrCodeFooterString: String?
get() = keystoreDataSource.qrCodeFooterString
set(value) {
......
......@@ -44,8 +44,8 @@ android {
applicationId "fr.gouv.android.stopcovid"
minSdkVersion 21
targetSdkVersion 30
versionCode 84
versionName "2.1.1"
versionCode 86
versionName "2.1.2"
testInstrumentationRunner = 'com.lunabeestudio.stopcovid.TestRunner'
......
......@@ -2,11 +2,11 @@
"config": [
{
"name": "lastUpdate",
"value": "28 October 2020"
"value": "3 november 2020"
},
{
"name": "version",
"value": 3
"value": 5
},
{
"name": "app.apiVersion",
......@@ -34,7 +34,7 @@
},
{
"name": "app.qrCode.expiredHours",
"value": 12.0
"value": 8.0
},
{
"name": "app.qrCode.formattedString",
......
......@@ -290,7 +290,7 @@
"myHealthController.yourDepartment.title": "Your department of France",
"myHealthController.yourDepartment.subtitle": "You can check the status of the COVID-19 pandemic in your department of France.",
"myHealthController.yourDepartment.buttonTitle": "Learn more",
"myHealthController.yourDepartment.url": "https://geodes.santepubliquefrance.fr/#c=indicator&i=sp_ti_tp_7j.tx_pe_gliss&s=2020-09-07-2020-09-13&t=a01&view=map2",
"myHealthController.yourDepartment.url":"https://geodes.santepubliquefrance.fr/#view=map2&c=indicator",
"myHealthController.notification.title": "Risk alert",
"myHealthController.notification.subtitle": "You will be alerted if you have been in close contact with a user who is reported with a COVID-19 diagnosis (exposure at less than one metre lasting 15 minutes or more). Your status is checked every 24h.\n\nTousAntiCovid will then give you the recommendations from the Ministry for Solidarity and Health.",
"myHealthController.alert.atitudeToAdopt": "What to do",
......@@ -456,7 +456,7 @@
"attestationsController.attestationWebSite": "Certificate website",
"attestationsController.termsOfUse.alert.title": "Terms",
"attestationsController.termsOfUse.alert.message": "The manager of the \"TousAntiCovid\" app does not process any of the information entered into the certificate generator.",
"attestationsController.termsOfUse.url": "https://bonjour.tousanticovid.gouv.fr/privacy.html",
"attestationsController.termsOfUse.url": "https://bonjour.tousanticovid.gouv.fr/privacy.html#attestation",
"newAttestationController.title": "New certificate",
"newAttestationController.generate": "Generate",
"newAttestationController.saveMyData": "Remember me",
......@@ -472,7 +472,7 @@
"attestationsController.menu.delete.alert.message": "Are you sure you want to delete this exemption certificate?",
"attestationFieldItemChoiceController.title": "Choose a reason",
"newAttestationController.generate.alert.title": "Important",
"newAttestationController.generate.alert.message": "I hereby certify that my reason for going out is one of the authorised reasons under the terms of the general measures required to cope with the COVID-19 pandemic as part of the health state of emergency.",
"newAttestationController.generate.alert.message": "Je certifie que mon déplacement est lié au motif suivant autorisé par le décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l'épidémie de Covid19 dans le cadre de l'état d'urgence sanitaire.",
"newAttestationController.generate.alert.validate": "I hereby certify",
"newAttestationController.missingInfo.alert.title": "Attention",
"newAttestationController.missingInfo.alert.message": "All fields must be completed to generate a certificate.",
......@@ -483,13 +483,21 @@
"attestationsController.expiredSection.subtitle": "These exemption certificates will be deleted from your phone automatically.",
"attestationsController.menu.share": "Share the certificate",
"attestationsController.menu.share.text": "Here is a #TousAntiCovid exemption certificate",
"newAttestationController.header": "",
"attestationController.footer.noAttestations": "attestationController.footer.noAttestations",
"newAttestationController.header": "En application du décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l'épidémie de Covid19 dans le cadre de l'état d'urgence sanitaire",
"supportController.departmentLevel": "Display by Département",
"supportController.departmentLevel.activate": "Activate",
"supportController.departmentLevel.deactivate": "Deactivate",
"newAttestationController.generate.error.alert.title": "Attention",
"newAttestationController.generate.error.alert.message": "An error occurred when generating the certificate",
"accessibility.hint.otherActions": "Other actions"
"accessibility.hint.otherActions": "Other actions",
"attestationFieldItemChoiceController.footer": "- Les personnes souhaitant bénéficier de l'une de ces exceptions doivent se munir s'il y a lieu, lors de leurs déplacements hors de leur domicile, d'un document leur permettant de justifier que le déplacement considéré entre dans le champ de l'une de ces exceptions.\n- Déplacements professionnels ne pouvant être différés : à utiliser par les travailleurs non-salariés, lorsqu'ils ne peuvent disposer d'un justificatif de déplacement établi par leur employeur.\n- Achats de première nécessité : y compris les acquisitions à titre gratuit (distribution de denrées alimentaires...) et les déplacements liés à la perception de prestations sociales et au retrait d'espèces.",
"keyFiguresController.explanation": "Key figures updates",
"keyFiguresController.explanation.alert.title": "Key figures updates",
"keyFiguresController.explanation.alert.message": "Les données sur le R Effectif sont mises à jour deux fois par semaines (le mardi et vendredi), et le nombre de nouveaux cas, le taux d'incidence, le taux de positivité et le taux d’occupation sont mis à jour une fois par jour, après consolidation par Santé Publique France et le Ministère des Solidarités et de la Santé.",
"keyFiguresController.explanation.alert.button": "Ok, got it",
"notification.ultimateStatus.title":"TousAntiCovid a besoin de vous",
"notification.ultimateStatus.message":"Relancez TousAntiCovid dès que possible pour assurer son bon fonctionnement. Merci !"
}
......@@ -34,7 +34,7 @@
"onboarding.batteryController.mainMessage.subtitle":"Pour que TousAntiCovid fonctionne de manière continue en arrière-plan, acceptez de désactiver l’optimisation de la batterie pour TousAntiCovid seulement.",
"onboarding.batteryController.accept":"Accepter",
"sickController.message.testedPositive.title":"Vous avez été diagnostiqué comme un cas de COVID-19 ?",
"sickController.message.testedPositive.subtitle":"Vous avez reçu un code (QR code ou code à 6 chiffres) avec votre résultat de test, de votre médecin ou du professionnel de santé ayant réalisé le test : merci de le scanner ou le saisir pour que les utilisateurs qui ont été à proximité soient alertés. Merci !",
"sickController.message.testedPositive.subtitle":"Vous avez reçu un code (QR code ou code à 6 caractères) avec votre résultat de test, de votre médecin ou du professionnel de santé ayant réalisé le test : merci de le scanner ou le saisir pour que les utilisateurs qui ont été à proximité soient alertés. Merci !",
"sickController.message.youHaveSymptoms.title":"Vous pensez avoir des symptômes",
"sickController.message.youHaveSymptoms.subtitle":"Vous souhaitez savoir quel comportement adopter ?\nCe questionnaire est là pour vous orienter.",
"sickController.button.flash":"Scanner le QR code",
......@@ -50,7 +50,7 @@
"sickController.state.nothing.title":"Vous n'avez pas été à proximité d’un utilisateur diagnostiqué comme un cas de COVID-19",
"sickController.state.nothing.subtitle":"N'oubliez pas pour autant les mesures barrières et les recommandations de santé publique",
"sickController.state.contact.title":"Vous avez été exposé à au moins un utilisateur diagnostiqué comme un cas de COVID-19 ces derniers jours, vous êtes un contact à risque ",
"sickController.state.contact.subtitle":"Contactez votre médecin en l’informant que vous avez été notifié comme contact à risque et isolez-vous.",
"sickController.state.contact.subtitle":"Isolez-vous, contactez votre médecin en l’informant que vous avez été notifié comme contact à risque et faites-vous tester.",
"sickController.state.deleteNotification":"Supprimer la notification",
"sickController.state.deleteNotification.alert.title":"Voulez-vous vraiment supprimer la notification ?",
"sharingController.title":"Partager",
......@@ -96,15 +96,15 @@
"informationController.step.beCareful.nothing.title":"%d. Restez attentif à l'apparition de symptômes",
"informationController.step.beCareful.nothing.subtitle":"En cas de doute, consultez votre médecin si vous pensez avoir des symptômes. Et n’hésitez pas à effectuer le questionnaire d'orientation sur Mes Conseils Covid",
"informationController.step.beCareful.buttonTitle":"Questionnaire d'orientation",
"informationController.step.appointment.title":"%d. Appelez votre médecin",
"informationController.step.appointment.subtitle":"Contactez votre médecin traitant. Si vous n’avez pas de médecin, appelez le numéro suivant afin d’être orienté vers un médecin (service gratuit + appel gratuit)",
"informationController.step.appointment.title":"%d. Appelez votre médecin et faites-vous tester",
"informationController.step.appointment.subtitle":"Contactez votre médecin traitant et faites-vous tester dès aujourd’hui grâce à un accès prioritaire. Si vous n’avez pas de médecin, appelez le numéro suivant afin d’être orienté vers un médecin (service gratuit + appel gratuit)",
"informationController.step.appointment.buttonTitle":"Appeler le 0 800 130 000",
"informationController.step.moreInfo.title":"%d. Plus d'informations",
"informationController.step.moreInfo.subtitle":"Pour avoir des recommandations personnalisées pour votre santé et celle de vos proches.",
"informationController.step.moreInfo.buttonTitle":"Les conseils COVID-19",
"informationController.step.moreInfo.url":"https://mesconseilscovid.sante.gouv.fr/",
"enterCodeController.title":"Votre code",
"enterCodeController.mainMessage.title":"Veuillez saisir le code que vous avez reçu avec votre résultat de test (sous votre QR code) ou par votre médecin (code à 6 caractères valable 1h).",
"enterCodeController.mainMessage.title":"Veuillez utiliser le code que vous avez reçu avec votre résultat de test (sous votre QR code) ou par votre médecin ou professionnel de santé ayant réalisé le test (code à 6 caractères valable 1h).",
"enterCodeController.mainMessage.subtitle":"Ces codes sont aléatoires et ne contiennent aucune information personnelle.",
"enterCodeController.button.validate":"Valider",
"enterCodeController.textField.placeholder":"Saisir le code ici",
......@@ -154,7 +154,7 @@
"captchaController.mainMessage.subtitle":"En répondant à ces quelques questions",
"captchaController.mainMessage.action":"Veuillez appuyer sur la photo de",
"notification.proximityServiceRunning.title":"TousAntiCovid est activé",
"notification.proximityServiceRunning.message":"Merci de participer à la lutte contre la propagation de la COVID-19 !",
"notification.proximityServiceRunning.message":"Merci de participer à la lutte contre la COVID-19 !",
"notification.channel.title":"TousAntiCovid est activé",
"notification.channel.atRisk.title":"Risque d’exposition à la COVID-19",
"notification.atRisk.title":"Risque d’exposition à un cas de COVID-19",
......@@ -291,7 +291,7 @@
"myHealthController.yourDepartment.title":"Mon département",
"myHealthController.yourDepartment.subtitle":"Vous pouvez connaître l'état de la pandémie de COVID-19 dans votre département.",
"myHealthController.yourDepartment.buttonTitle":"En savoir plus",
"myHealthController.yourDepartment.url":"https://geodes.santepubliquefrance.fr/#c=indicator&i=sp_ti_tp_7j.tx_pe_gliss&s=2020-09-07-2020-09-13&t=a01&view=map2",
"myHealthController.yourDepartment.url":"https://geodes.santepubliquefrance.fr/#view=map2&c=indicator",
"myHealthController.notification.title":"Notification en cas de risque",
"myHealthController.notification.subtitle":"Vous serez averti si vous avez été à proximité d'un utilisateur déclaré comme un cas de COVID-19 (distance estimée à moins d'un mètre et pendant au moins 15 minutes). La vérification de votre état se fait toutes les 24h.\n\nTousAntiCovid vous donnera alors les recommandations du ministère des Solidarités et de la Santé.",
"myHealthController.alert.atitudeToAdopt":"Comment se protéger",
......@@ -369,22 +369,30 @@
"keyfigure.nombrecas.shortLabel":"Nouveaux cas",
"keyfigure.nombrecas.description":"Ce nombre correspond au nombre de nouveaux cas confirmés par un test positif, sur les dernières 24 heures. Les données du week-end sont souvent moins élevées en raison d’une diminution des activités liées au dépistage le week-end.",
"keyfigure.registered.colorCode.dark":"#FB4B56",
"keyfigure.registered.colorCode.light":"#E1000F",
"keyfigure.notification.colorCode.dark":"#85BBFF",
"keyfigure.notification.colorCode.light":"#000091",
"keyfigure.qrcodes.colorCode.dark":"#FF8D7E",
"keyfigure.qrcodes.colorCode.light":"#FF8D7E",
"keyfigure.reffectif.colorCode.dark":"#FF6F4D",
"keyfigure.reffectif.colorCode.light":"#FF6F4D",
"keyfigure.tauxincidence.colorCode.dark":"#72E1EB",
"keyfigure.tauxincidence.colorCode.light":"#2C959E",
"keyfigure.tauxpositivite.colorCode.dark":"#7090F0",
"keyfigure.tauxpositivite.colorCode.light":"#5770BE",
"keyfigure.nombrecas.colorCode.dark":"#B693C4",
"keyfigure.nombrecas.colorCode.light":"#650F85",
"keyfigure.tauxoccupation.colorCode.dark":"#FED042",
"keyfigure.tauxoccupation.colorCode.light":"#A26959",
"keyfigure.nombrecas.colorCode.light":"#8944AB",
"keyfigure.nombrecas.colorCode.dark":"#DA8FFF",
"keyfigure.reffectif.colorCode.light":"#0141DD",
"keyfigure.reffectif.colorCode.dark":"#429DFF",
"keyfigure.tauxincidence.colorCode.light":"#A05A03",
"keyfigure.tauxincidence.colorCode.dark":"#FED708",
"keyfigure.tauxpositivite.colorCode.light":"#3734A3",
"keyfigure.tauxpositivite.colorCode.dark":"#7D7BFF",
"keyfigure.tauxoccupation.colorCode.light":"#0271A4",
"keyfigure.tauxoccupation.colorCode.dark":"#70D8FF",
"keyfigure.registered.colorCode.light":"#FF2C55",
"keyfigure.registered.colorCode.dark":"#FF395F",
"keyfigure.notification.colorCode.light":"#007AFF",
"keyfigure.notification.colorCode.dark":"#0B84FF",
"keyfigure.qrcodes.colorCode.light":"#34C859",
"keyfigure.qrcodes.colorCode.dark":"#31D158",
"keyFiguresController.title":"Chiffres clés",
"keyFiguresController.section.health":"Situation sanitaire",
......@@ -427,7 +435,7 @@
"keyFigures.update":"Donnée du : %@",
"declareController.codeNotReceived.buttonTitle": "Je n'ai pas reçu le code",
"declareController.codeNotReceived.alert.title": "Votre code",
"declareController.codeNotReceived.alert.message": "Vérifiez vos e-mails et votre courrier postal. Si vous ne l'avez pas, vous pouvez aussi contacter votre médecin ou le professionnel de santé qui a réalisé le test pour qu’il vous délivre un code à 6 chiffres.",
"declareController.codeNotReceived.alert.message": "Vérifiez vos e-mails et votre courrier postal. Si vous ne l'avez pas, vous pouvez aussi contacter votre médecin ou le professionnel de santé qui a réalisé le test pour qu’il vous délivre un code à 6 caractères.",
"keyFigure.sharing.national": "%1$@ (France): %2$@. Retrouve tous les chiffres clés dans l'appli TousAntiCovid https://bonjour.tousanticovid.gouv.fr",
"keyFigure.sharing.department": "%1$@ (%2$@): %3$@. %4$@ (France): %5$@. Retrouve tous les chiffres clés dans l'appli TousAntiCovid https://bonjour.tousanticovid.gouv.fr",
......@@ -466,7 +474,7 @@
"attestation.form.sport_animaux.shortLabel":"Activité individuelle ou animaux de compagnie",
"attestation.form.sport_animaux.longLabel":"Déplacements brefs, dans la limite d'une heure quotidienne et dans un rayon maximal d'un kilomètre autour du domicile, liés soit à l'activité physique individuelle des personnes, à l'exclusion de toute pratique sportive collective et de toute proximité avec d'autres personnes, soit à la promenade avec les seules personnes regroupées dans un même domicile, soit aux besoins des animaux de compagnie",
"attestation.form.missions.shortLabel":"Missions d'intérêt général",
"attestation.form.missions.longLabel":"Déplacements pour participer à des missions d'intérêt général sur demande de l'autorité administrative",
"attestation.form.missions.longLabel":"Participation à des missions d'intérêt général sur demande de l'autorité administrative",
"attestation.form.enfants.shortLabel":"Enfants à l’école",
"attestation.form.enfants.longLabel":"Déplacement pour chercher les enfants à l’école et à l’occasion de leurs activités périscolaires",
......@@ -484,7 +492,7 @@
"attestationsController.attestationWebSite": "Site web attestation",
"attestationsController.termsOfUse.alert.title": "Conditions d'utilisation",
"attestationsController.termsOfUse.alert.message": "Les informations saisies dans ce générateur d’attestation de déplacement ne font l’objet d’aucun traitement par le responsable de l’application \"TousAntiCovid\".",
"attestationsController.termsOfUse.url": "https://bonjour.tousanticovid.gouv.fr/privacy.html",
"attestationsController.termsOfUse.url": "https://bonjour.tousanticovid.gouv.fr/privacy.html#attestation",
"newAttestationController.title": "Nouvelle attestation",
"newAttestationController.generate": "Générer",
"newAttestationController.saveMyData": "Sauvegarder mes données",
......@@ -501,21 +509,28 @@
"attestationsController.menu.delete.alert.message": "Êtes-vous sûr de vouloir supprimer cette attestation de déplacement ?",
"attestationFieldItemChoiceController.title": "Choisir le motif",
"newAttestationController.generate.alert.title": "Important",
"newAttestationController.generate.alert.message": "Je certifie que mon déplacement est lié au motif autorisé en application des mesures générales nécessaires pour faire face à l'épidémie de COVID-19 dans le cadre de l'état d'urgence sanitaire.",
"newAttestationController.generate.alert.message": "Je certifie que mon déplacement est lié au motif suivant autorisé par le décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l'épidémie de Covid19 dans le cadre de l'état d'urgence sanitaire.",
"newAttestationController.generate.alert.validate": "Je certifie",
"newAttestationController.missingInfo.alert.title": "Attention",
"newAttestationController.missingInfo.alert.message": "Vous devez remplir tous les champs pour pouvoir générer une attestation.",
"attestationController.footer": "Ou vous pouvez également utiliser le site web du Ministère de l’Intérieur pour générer l’attestation PDF :",
"attestationsController.validAttestationsSection.title": "Mes attestations",
"attestationsController.validAttestationsSection.subtitle": "Ces attestations sont valides.",
"attestationsController.validAttestationsSection.subtitle": "Pour le motif \"Activité individuelle ou animaux de compagnie\", l'attestation n'est valide qu'une heure.",
"attestationsController.expiredSection.title": "Expirées",
"attestationsController.expiredSection.subtitle": "Ces attestations de déplacement seront supprimées automatiquement de votre téléphone (dans 24h minimum, à la prochaine ouverture), sans action nécessaire de votre part.",
"attestationsController.menu.share": "Partager l'attestation",
"attestationsController.menu.share.text": "Voici une attestation de déplacement de #TousAntiCovid",
"newAttestationController.header": "",
"newAttestationController.header": "En application du décret n°2020-1310 du 29 octobre 2020 prescrivant les mesures générales nécessaires pour faire face à l'épidémie de Covid19 dans le cadre de l'état d'urgence sanitaire",
"newAttestationController.generate.error.alert.title": "Attention",
"newAttestationController.generate.error.alert.message": "Il y a eu une erreur lors de la génération de l'attestation",
"accessibility.hint.otherActions": "Autres actions"
"accessibility.hint.otherActions": "Autres actions",
"attestationFieldItemChoiceController.footer": "- Les personnes souhaitant bénéficier de l'une de ces exceptions doivent se munir s'il y a lieu, lors de leurs déplacements hors de leur domicile, d'un document leur permettant de justifier que le déplacement considéré entre dans le champ de l'une de ces exceptions.\n- Déplacements professionnels ne pouvant être différés : à utiliser par les travailleurs non-salariés, lorsqu'ils ne peuvent disposer d'un justificatif de déplacement établi par leur employeur.\n- Achats de première nécessité : y compris les acquisitions à titre gratuit (distribution de denrées alimentaires...) et les déplacements liés à la perception de prestations sociales et au retrait d'espèces.",
"keyFiguresController.explanation": "Mise à jour des données",
"keyFiguresController.explanation.alert.title": "Mise à jour des données",
"keyFiguresController.explanation.alert.message": "Les données sur le R Effectif sont mises à jour deux fois par semaines (le mardi et vendredi), et le nombre de nouveaux cas, le taux d'incidence, le taux de positivité et le taux d’occupation sont mis à jour une fois par jour, après consolidation par Santé Publique France et le Ministère des Solidarités et de la Santé.",
"keyFiguresController.explanation.alert.button": "Ok, j'ai compris",
"notification.ultimateStatus.title":"TousAntiCovid a besoin de vous",
"notification.ultimateStatus.message":"Relancez TousAntiCovid dès que possible pour assurer son bon fonctionnement. Merci !"
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment