diff --git a/components/Alert.tsx b/components/Alert.tsx index 7ee7465..4fffdfb 100644 --- a/components/Alert.tsx +++ b/components/Alert.tsx @@ -10,7 +10,7 @@ function Alert(props: AlertProps): JSX.Element { return (
- {props.errorMessage} + {props.errorMessage} diff --git a/components/Form.tsx b/components/Form.tsx index fee3978..e053b42 100644 --- a/components/Form.tsx +++ b/components/Form.tsx @@ -29,6 +29,11 @@ function Form(): JSX.Element { // Check if there is a translation and replace message accordingly const setErrorMessage = (message: string) => { + if (message == undefined) { + _setErrorMessage(undefined); + return; + } + const translation = t('errors:'.concat(message)); _setErrorMessage(translation !== message ? translation : message); }; @@ -68,7 +73,20 @@ function Form(): JSX.Element { const codeReader = new BrowserQRCodeReader(); // Needs to be called before any camera can be accessed - await BrowserQRCodeReader.listVideoInputDevices(); + let deviceList: MediaDeviceInfo[]; + + try { + deviceList = await BrowserQRCodeReader.listVideoInputDevices(); + } catch (e) { + setErrorMessage('noCameraAccess'); + return; + } + + // Check if camera device is present + if (deviceList.length == 0) { + setErrorMessage("noCameraFound"); + return; + } // Get preview Element to show camera stream const previewElem: HTMLVideoElement = document.querySelector('#cameraPreview'); @@ -89,6 +107,9 @@ function Form(): JSX.Element { setGlobalControls(undefined); setIsCameraOpen(false); } + if (error !== undefined) { + setErrorMessage(error.message); + } } ) ); @@ -101,6 +122,12 @@ function Form(): JSX.Element { event.preventDefault(); setLoading(true); + if(navigator.userAgent.match('CriOS')) { + setErrorMessage('safariSupportOnly'); + setLoading(false); + return; + } + if (!file && !qrCode) { setErrorMessage('noFileOrQrCode') setLoading(false); @@ -228,7 +255,7 @@ function Form(): JSX.Element { {t('index:addToWallet')}
- +
  • {t('privacy:generalInfoProvider')} -   {t('privacy:privacyPolicy')} -   +   {t('privacy:andThe')}   diff --git a/public/locales/de/errors.yml b/public/locales/de/errors.yml index 671a679..6933e7a 100644 --- a/public/locales/de/errors.yml +++ b/public/locales/de/errors.yml @@ -14,4 +14,7 @@ couldNotFindQrCode: QR-Code konnte in der ausgewählten Datei nicht gefunden wer invalidQrCode: Ungültiger QR-Code certificateType: Kein gültiger Zertifikatstyp gefunden invalidTestResult: Ungültiges Testergebnis -invalidTestType: Ungültiger Testtyp \ No newline at end of file +invalidTestType: Ungültiger Testtyp +noCameraAccess: Kein Zugriff auf die Kamera möglich. Überprüfe die Berechtigungen unter Einstellungen > Safari > Kamera. +noCameraFound: Keine Kamera gefunden. +safariSupportOnly: Bitte verwende unter iOS den Safari Browser. \ No newline at end of file diff --git a/public/locales/en/errors.yml b/public/locales/en/errors.yml index 828ec38..0dcc155 100644 --- a/public/locales/en/errors.yml +++ b/public/locales/en/errors.yml @@ -14,4 +14,7 @@ couldNotFindQrCode: Could not find QR Code in provided file invalidQrCode: Invalid QR code certificateType: No valid certificate type found invalidTestResult: Invalid test result -invalidTestType: Invalid test type \ No newline at end of file +invalidTestType: Invalid test type +noCameraAccess: Could not access camera. Check permissions under Settings > Safari > Camera. +noCameraFound: Could not find camera. +safariSupportOnly: On iOS, please use the Safari Browser. \ No newline at end of file diff --git a/public/locales/en/privacy.yml b/public/locales/en/privacy.yml index 65c62a4..553a9c4 100644 --- a/public/locales/en/privacy.yml +++ b/public/locales/en/privacy.yml @@ -21,7 +21,7 @@ dataPrivacyFaq: data privacy FAQ contact: Contact email: Email website: Website -process: Simplified of the process +process: Simplified explanation of the process processFirst: First, the following steps happen locally in your browser processSecond: Second, the following steps happen on our server processThird: Finally, the following steps happen locally in your browser diff --git a/public/locales/fi-FI b/public/locales/fi-FI new file mode 120000 index 0000000..5f9399c --- /dev/null +++ b/public/locales/fi-FI @@ -0,0 +1 @@ +fi \ No newline at end of file diff --git a/public/locales/fi/common.yml b/public/locales/fi/common.yml new file mode 100644 index 0000000..70df300 --- /dev/null +++ b/public/locales/fi/common.yml @@ -0,0 +1,5 @@ +title: CovidPass +subtitle: Lisää EU:n koronatodistus suosikkilompakkosovellukseesi. +privacyPolicy: Tietosuojaseloste +gitHub: GitHub +imprint: Imprint \ No newline at end of file diff --git a/public/locales/fi/errors.yml b/public/locales/fi/errors.yml new file mode 100644 index 0000000..35ab1fd --- /dev/null +++ b/public/locales/fi/errors.yml @@ -0,0 +1,20 @@ +noFileOrQrCode: Skannaa QR koodi tai valitse tiedosto +signatureFailed: Virhe allekirjoitettaessa passia palvelimella +decodingFailed: QR-koodin hyötykuorman purkaminen epäonnistui +invalidColor: Väärä väri +certificateData: Varmenteen tietojen lukeminen epäonnistui +nameMissing: Nimen lukeminen epäonnistui +dobMissing: Syntymäaikaa ei onnistuttu lukemaan +invalidMedicalProduct: Virheellinen lääkevalmiste +invalidCountryCode: Virheellinen maakoodi +invalidManufacturer: Virheellinen valmistaja +invalidFileType: Virheellinen tiedostotyyppi +couldNotDecode: QR-koodia ei voitu purkaa tiedostosta +couldNotFindQrCode: QR-koodia ei löytynyt annetusta tiedostosta +invalidQrCode: Virheellinen QR-koodi +certificateType: Kelvollista varmennetyyppiä ei löytynyt +invalidTestResult: Virheellinen testitulos +invalidTestType: Virheellinen testityyppi +noCameraAccess: Kameraan ei päässyt käsiksi. Tarkista käyttöoikeudet kohdasta Asetukset > Safari > Kamera. +noCameraFound: En löytänyt kameraa. +safariSupportOnly: Käytä iOS:ssä Safari-selainta. \ No newline at end of file diff --git a/public/locales/fi/imprint.yml b/public/locales/fi/imprint.yml new file mode 100644 index 0000000..7055a98 --- /dev/null +++ b/public/locales/fi/imprint.yml @@ -0,0 +1,27 @@ +heading: TMG 5 §:n mukaiset tiedot +contact: Yhteystiedot +euDisputeResolution: EU:n riidanratkaisu +euDisputeResolutionParagraph: | + Euroopan komissio tarjoaa foorumin verkkovälitteistä riidanratkaisua varten https://ec.europa.eu/consumers/odr. + Sähköpostiosoitteemme löytyy yllä olevasta painatuksesta. +consumerDisputeResolution: Kuluttajariitojen ratkaiseminen / yleinen välimieslautakunta +consumerDisputeResolutionParagraph: Emme ole halukkaita tai velvollisia osallistumaan riidanratkaisumenettelyyn kuluttajasovittelulautakunnassa. +liabilityForContents: Vastuu sisällöstä +liabilityForContentsParagraph: | + Palveluntarjoajana olemme yleisten lakien 7 §:n 1 momentin TMG:n mukaisesti vastuussa näiden sivujen sisällöstä. + TMG:n 8-10 §:n mukaan emme ole velvollisia valvomaan siirrettyjä tai tallennettuja tietoja tai tutkimaan olosuhteita, jotka viittaavat laittomaan toimintaan. + Yleisten lakien mukaiset velvollisuudet poistaa tai estää tietojen käyttö säilyvät ennallaan. + Vastuu tässä suhteessa on kuitenkin mahdollista vasta siitä hetkestä alkaen, kun konkreettinen lain rikkominen tulee tietoon. + Jos saamme tietää tällaisista rikkomuksista, poistamme asianomaisen sisällön välittömästi. +liabilityForLinks: Vastuu linkeistä +liabilityForLinksParagraph: | + Tarjouksemme sisältää linkkejä kolmansien osapuolten ulkoisille verkkosivustoille, joiden sisältöön emme voi vaikuttaa. + Siksi emme voi ottaa vastuuta näistä ulkoisista sisällöistä. + Linkitettyjen sivustojen sisällöstä on aina vastuussa kyseisten sivustojen tarjoaja tai ylläpitäjä. + Linkitetyt sivut on tarkistettu mahdollisten lainrikkomusten varalta linkittämishetkellä. + Laitonta sisältöä ei ollut tunnistettavissa linkittämishetkellä. + Linkitettyjen sivujen sisällön jatkuva valvonta ei kuitenkaan ole järkevää ilman konkreettisia todisteita lainrikkomuksesta. + Jos saamme tietoiseksi rikkomuksista, poistamme tällaiset linkit välittömästi. +credits: Kiitokset +creditsSource: Otteita osoitteesta https://www.e-recht24.de/impressum-generator.html +creditsTranslation: Käännetty osoitteella https://www.DeepL.com/Translator (ilmainen versio). \ No newline at end of file diff --git a/public/locales/fi/index.yml b/public/locales/fi/index.yml new file mode 100644 index 0000000..b5f1c52 --- /dev/null +++ b/public/locales/fi/index.yml @@ -0,0 +1,26 @@ +iosHint: Käytä iOS:ssä Safari-selainta. +errorClose: Sulje +selectCertificate: Valitse todistus +selectCertificateDescription: | + Skannaa todistuksessa oleva QR-koodi tai valitse kuvakaappaus tai PDF-sivu, jossa on QR-koodi. + Huomaa, että tiedoston valitsemista suoraan kamerasta ei tueta. +stopCamera: Lopeta Kamera +startCamera: Käynnistä Kamera +openFile: Valitse Tiedosto +foundQrCode: QR koodi löytyi! +pickColor: Valitse väri +pickColorDescription: Valitse passisi taustaväri. +colorWhite: Valkoinen +colorBlack: Musta +colorGrey: Harmaa +colorGreen: Vihreä +colorIndigo: Indigonsininen +colorBlue: Sininen +colorPurple: Purppura +colorTeal: Sinivihreä +addToWallet: Lisää lompakkoon. +dataPrivacyDescription: | + Tietosuoja on erityisen tärkeää, kun käsitellään terveyteen liittyviä tietoja. + Jotta voisit tehdä tietoon perustuvan päätöksen, lue seuraavat tiedot +iAcceptThe: Hyväksyn +privacyPolicy: Tietosuojaselosteen \ No newline at end of file diff --git a/public/locales/fi/privacy.yml b/public/locales/fi/privacy.yml new file mode 100644 index 0000000..728d804 --- /dev/null +++ b/public/locales/fi/privacy.yml @@ -0,0 +1,56 @@ +gdprNotice: | + Tietosuojakäytäntömme perustuu Euroopan lainsäätäjän yleisen tietosuoja-asetuksen (GDPR) hyväksymisen yhteydessä käyttämiin termeihin. +generalInfo: Yleistä tietoa +generalInfoProcess: | + Koko passitiedoston luomisprosessi tapahtuu paikallisesti selaimessasi. + Allekirjoitusvaihetta varten palvelimelle lähetetään vain hashed versio tiedoistasi. +generalInfoStoring: Tietojasi ei tallenneta aktiivisen selainistunnon jälkeen, eikä sivusto käytä evästeitä. +generalInfoThirdParties: Tietoja ei lähetetä kolmansille osapuolille. +generalInfoHttps: Lähetämme tietosi turvallisesti https:n kautta. +generalInfoLocation: Palvelimemme sijaitsee Tuusulassa. +generalInfoGitHub: The source code of this site is available on +generalInfoLockScreen: Oletusarvoisesti Apple Wallet -passit ovat käytettävissä lukitusnäytöstä. Tämän voi muuttaa +settings: asetukissa +generalInfoProvider: | + Palveluntarjoaja käsittelee tietoja tämän sivuston tarjoamiseksi. + Jotta ymmärtäisit paremmin, mitä toimenpiteitä he toteuttavat tietojesi suojaamiseksi, lue myös heidän palveluntarjoajansa tiedot. +privacyPolicy: tietosuojakäytäntö +andThe: ja +dataPrivacyFaq: tietosuoja FAQ +contact: Yhteystiedot +email: Email +website: Verkkosivu +process: Prosessin yksinkertaistaminen +processFirst: Seuraavat vaiheet tapahtuvat ensin paikallisesti selaimessasi. +processSecond: Toiseksi palvelimellamme suoritetaan seuraavat vaiheet +processThird: Lopuksi seuraavat vaiheet tapahtuvat paikallisesti selaimessasi +processRecognizing: QR-koodin tietojen tunnistaminen ja poimiminen valitusta varmenteesta. +processDecoding: Henkilökohtaisten ja terveyteen liittyvien tietojen purkaminen QR-koodin hyötykuormasta. +processAssembling: Epätäydellisen syötetiedoston kokoaminen omista tiedoistasi +processGenerating: Luodaan tiedosto, joka sisältää passitiedostoon tallennettujen tietojen hashit. +processSending: Lähetetään palvelimellemme vain hasheja sisältävä tiedosto. +processReceiving: Paikallisesti luotujen hashien vastaanottaminen ja tarkistaminen. +processSigning: Hashit sisältävän tiedoston allekirjoittaminen +processSendingBack: Allekirjoituksen lähettäminen takaisin +processCompleting: Allekirjoitetun passitiedoston kokoaminen paikallisesti luodusta epätäydellisestä tiedostosta ja allekirjoituksesta. +processSaving: Tiedoston tallentaminen laitteeseen +locallyProcessedData: Paikallisesti käsitellyt tiedot +the: The +schema: Digitaalisen Covid-varmenteen skeema +specification: sisältää yksityiskohtaisen määrittelyn siitä, mitä tietoja QR-koodi voi sisältää ja mitä tietoja selaimesi käsittelee. +serverProvider: Palveluntarjoaja +serverProviderIs: Meidän palveluntarjoaja on +logFiles: Palvelimen lokitiedostoihin voidaan kerätä ja tallentaa seuraavia tietoja +logFilesBrowser: Käytetty selaintyyppi ja -versio +logFilesOs: Käyttöjärjestelmä +logFilesReferrer: Verkkosivusto, josta käyttäjä saapuu verkkosivustollemme (ns. viittaajat). +logFilesTime: Päivämäärä ja kellonaika +logFilesIpAddress: Pseudonymisoidut IP-osoitteet +rights: Sinun oikeutesi +rightsGranted: Yleisen tietosuoja-asetuksen mukaisesti sinulla on seuraavat oikeudet +rightsAccess: Oikeus tutustua tietoihin; Sinulla on oikeus tietää, mitä tietoja sinusta on kerätty ja miten niitä on käsitelty. +rightsErasure: Oikeus tulla unohdetuksi; henkilötietojesi poistaminen. +rightsRectification: Oikaisuoikeus; Sinulla on oikeus korjata virheelliset tiedot. +rightsPortability: Oikeus tietojen siirrettävyyteen; Sinulla on oikeus siirtää tietosi käsittelyjärjestelmästä toiseen. +thirdParties: Kolmannet osapuolet +appleSync: Apple saattaa synkronoida koronapassisi iCloudin kautta \ No newline at end of file diff --git a/public/locales/fr/errors.yml b/public/locales/fr/errors.yml index 3149029..dc3119e 100644 --- a/public/locales/fr/errors.yml +++ b/public/locales/fr/errors.yml @@ -2,7 +2,7 @@ noFileOrQrCode: Veuillez scanner un QR Code ou sélectionner un fichier signatureFailed: Erreur lors de la signature du pass sur le serveur decodingFailed: Échec du décodage du QR Code invalidColor: Couleur non valide -vaccinationInfo: Échec de la lecture des informations de vaccination +certificateData: Échec de la lecture des données du certificat nameMissing: Échec de la lecture du nom dobMissing: Échec de la lecture de la date de naissance invalidMedicalProduct: Produit vaccinal non valide @@ -12,3 +12,9 @@ invalidFileType: Type de fichier non valide couldNotDecode: Impossible de décoder le QR Code du fichier couldNotFindQrCode: Impossible de trouver le QR Code dans le fichier fourni invalidQrCode: QR Code non valide +certificateType: Aucun type de certificat valide n'a été trouvé +invalidTestResult: Résultat du test non valide +invalidTestType: Type de test non valide +noCameraAccess: Impossible d'accéder à la caméra. Vérifiez les autorisations sous Paramètres > Safari > Appareil photo. +noCameraFound: Impossible de trouver la caméra. +safariSupportOnly: Sur iOS, veuillez utiliser le navigateur Safari. \ No newline at end of file diff --git a/public/locales/fr/index.yml b/public/locales/fr/index.yml index ba922f2..83e59d2 100644 --- a/public/locales/fr/index.yml +++ b/public/locales/fr/index.yml @@ -7,7 +7,7 @@ selectCertificateDescription: | stopCamera: Arrêter l'appareil photo startCamera: Démarrer l'appareil photo openFile: Sélectionner un fichier -foundQrCode: Code QR trouvé! +foundQrCode: Code QR trouvé ! pickColor: Choisissez une couleur pickColorDescription: Choisissez une couleur de fond pour votre passe. colorWhite: blanc diff --git a/public/locales/fr/privacy.yml b/public/locales/fr/privacy.yml index cbcf051..c4a4582 100644 --- a/public/locales/fr/privacy.yml +++ b/public/locales/fr/privacy.yml @@ -21,7 +21,7 @@ dataPrivacyFaq: FAQ sur la confidentialité des données contact: Contact email: Email website: Site web -process: Simplification du processus +process: Explication simplifiée du processus processFirst: Premièrement, les étapes suivantes se déroulent localement dans votre navigateur. processSecond: Ensuite, les étapes suivantes se déroulent sur notre serveur processThird: Enfin, les étapes suivantes se déroulent localement dans votre navigateur @@ -49,9 +49,9 @@ logFilesTime: La date et l'heure de l'accès. logFilesIpAddress: Les adresses IP pseudonymisées rights: Vos droits rightsGranted: Conformément au RGPD, vous disposez des droits suivants -rightsAccess: Droit d'accès à vos données; Vous avez le droit de savoir quelles données ont été collectées à votre sujet et comment elles ont été traitées. -rightsErasure: Droit à l'oubli; Effacement de vos données personnelles. -rightsRectification: Droit de rectification; Vous avez le droit de corriger des données inexactes. -rightsPortability: Droit à la portabilité des données; Vous avez le droit de transférer vos données d'un système de traitement à un autre. +rightsAccess: Droit d'accès à vos données ; Vous avez le droit de savoir quelles données ont été collectées à votre sujet et comment elles ont été traitées. +rightsErasure: Droit à l'oubli ; Effacement de vos données personnelles. +rightsRectification: Droit de rectification ; Vous avez le droit de corriger des données inexactes. +rightsPortability: Droit à la portabilité des données ; Vous avez le droit de transférer vos données d'un système de traitement à un autre. thirdParties: Tiers liés appleSync: Apple peut synchroniser vos passes via iCloud. diff --git a/public/locales/nl-BE b/public/locales/nl-BE new file mode 120000 index 0000000..d5f5c2a --- /dev/null +++ b/public/locales/nl-BE @@ -0,0 +1 @@ +nl \ No newline at end of file diff --git a/public/locales/nl-NL b/public/locales/nl-NL new file mode 120000 index 0000000..d5f5c2a --- /dev/null +++ b/public/locales/nl-NL @@ -0,0 +1 @@ +nl \ No newline at end of file diff --git a/public/locales/nl/common.yml b/public/locales/nl/common.yml new file mode 100644 index 0000000..bde9e35 --- /dev/null +++ b/public/locales/nl/common.yml @@ -0,0 +1,6 @@ +title: CovidPass +subtitle: Voeg uw EU Digitaal COVID-certificaten toe aan uw favoriete wallet-apps. +privacyPolicy: Privacybeleid +donate: Doneer +gitHub: GitHub +imprint: Over \ No newline at end of file diff --git a/public/locales/nl/errors.yml b/public/locales/nl/errors.yml new file mode 100644 index 0000000..1677032 --- /dev/null +++ b/public/locales/nl/errors.yml @@ -0,0 +1,20 @@ +noFileOrQrCode: Scan een QR-code of selecteer een bestand +signatureFailed: Fout bij het ondertekenen van de pass op de server +decodingFailed: Kan de payload van de QR-code niet decoderen +invalidColor: Ongeldige kleur +certificateData: Kan certificaatgegevens niet lezen +nameMissing: Kan naam niet lezen +dobMissing: Kan geboortedatum niet lezen +invalidMedicalProduct: Ongeldig medisch product +invalidCountryCode: Ongeldige landcode +invalidManufacturer: Ongeldige fabrikant +invalidFileType: Ongeldig bestandstype +couldNotDecode: Kon QR-code niet uit bestand decoderen +couldNotFindQrCode: Kon de QR-code niet vinden in het verstrekte bestand +invalidQrCode: Ongeldige QR-code +certificateType: Geen geldig certificaattype gevonden +invalidTestResult: Ongeldig testresultaat +invalidTestType: Ongeldig testtype +noCameraAccess: Kon geen toegang krijgen tot de camera. Controleer de machtigingen onder Instellingen > Safari > Camera. +noCameraFound: Ik kon de camera niet vinden. +safariSupportOnly: Gebruik op iOS de Safari-browser. \ No newline at end of file diff --git a/public/locales/nl/imprint.yml b/public/locales/nl/imprint.yml new file mode 100644 index 0000000..31609ed --- /dev/null +++ b/public/locales/nl/imprint.yml @@ -0,0 +1,27 @@ +heading: Informatie volgens § 5 TMG +contact: Contact +euDisputeResolution: EU-geschillenbeslechting +euDisputeResolutionParagraph: | + De Europese Commissie biedt een platform voor online geschillenbeslechting (OS) https://ec.europa.eu/consumers/odr. + U vindt ons e-mailadres in de conrtactgegevens hierboven. +consumerDisputeResolution: Beslechting van consumentengeschillen / universele arbitragecommissie +consumerDisputeResolutionParagraph: We zijn niet bereid of verplicht om deel te nemen aan geschillenbeslechtingsprocedures voor een arbitragecommissie voor consumenten. +liabilityForContents: Aansprakelijkheid voor inhoud +liabilityForContentsParagraph: | + Als dienstverlener zijn wij verantwoordelijk voor onze eigen inhoud op deze pagina's in overeenstemming met § 7 lid 1 TMG onder de algemene wetten. + Volgens §§ 8 tot 10 TMG zijn wij niet verplicht om verzonden of opgeslagen informatie te controleren of omstandigheden te onderzoeken die wijzen op illegale activiteiten. + Verplichtingen tot het verwijderen of blokkeren van het gebruik van informatie onder de algemene wetten blijven onaangetast. + Aansprakelijkheid ter zake is echter pas mogelijk vanaf het moment dat een concrete wetsovertreding bekend wordt. + Als we kennis krijgen van dergelijke inbreuken, zullen we de relevante inhoud onmiddellijk verwijderen. +liabilityForLinks: Aansprakelijkheid voor links +liabilityForLinksParagraph: | + Ons aanbod bevat links naar externe websites van derden, op wiens inhoud wij geen invloed hebben. + Daarom kunnen wij voor deze externe inhoud geen aansprakelijkheid aanvaarden. + De respectievelijke aanbieder of exploitant van de sites is altijd verantwoordelijk voor de inhoud van de gelinkte sites. + De gelinkte pagina's werden op het moment van linken gecontroleerd op mogelijke juridische overtredingen. + Illegale inhoud was op het moment van linken niet herkenbaar. + Een permanente controle van de inhoud van de gelinkte pagina's is echter niet redelijk zonder concreet bewijs van een overtreding van de wet. + Als we inbreuken vaststellen, zullen we dergelijke links onmiddellijk verwijderen. +credits: Credits +creditsSource: Met fragmenten van https://www.e-recht24.de/impressum-generator.html +creditsTranslation: Vertaald met https://www.DeepL.com/Translator (gratis versie) \ No newline at end of file diff --git a/public/locales/nl/index.yml b/public/locales/nl/index.yml new file mode 100644 index 0000000..847c658 --- /dev/null +++ b/public/locales/nl/index.yml @@ -0,0 +1,26 @@ +iosHint: Gebruik op iOS de Safari-browser. +errorClose: Sluiten +selectCertificate: Selecteer Certificaat +selectCertificateDescription: | + Scan de QR-code op uw certificaat of selecteer een screenshot of pdf-pagina met de QR-code. + Merk op dat het rechtstreeks vanaf de camera selecteren van een bestand niet wordt ondersteund. +stopCamera: Stop Camera +startCamera: Start Camera +openFile: Selecteer Bestand +foundQrCode: QR-code gevonden! +pickColor: Kies een kleur +pickColorDescription: Kies een achtergrondkleur voor je pas. +colorWhite: wit +colorBlack: zwart +colorGrey: grijs +colorGreen: groen +colorIndigo: indigo +colorBlue: blauw +colorPurple: paars +colorTeal: groenblauw +addToWallet: Toevoegen aan Wallet +dataPrivacyDescription: | + Gegevensprivacy is van bijzonder belang bij de verwerking van gezondheidsgerelateerde gegevens. + Om een weloverwogen beslissing te kunnen nemen, lees a.u.b. de +iAcceptThe: Ik accepteer het +privacyPolicy: Privacybeleid \ No newline at end of file diff --git a/public/locales/nl/privacy.yml b/public/locales/nl/privacy.yml new file mode 100644 index 0000000..a0e7b24 --- /dev/null +++ b/public/locales/nl/privacy.yml @@ -0,0 +1,57 @@ +gdprNotice: | + Ons privacybeleid is gebaseerd op de voorwaarden die worden gebruikt door de Europese wetgever + voor de vaststelling van de Algemene Verordening Gegevensbescherming (AVG). +generalInfo: Algemene informatie +generalInfoProcess: | + Het hele proces van het genereren van het pass-bestand gebeurt lokaal in uw browser. + Voor de ondertekeningsstap wordt alleen een gehashte weergave van uw gegevens naar de server gestuurd. +generalInfoStoring: Uw gegevens worden niet opgeslagen buiten de actieve browsersessie en de site maakt geen gebruik van cookies. +generalInfoThirdParties: Er worden geen gegevens naar derden verzonden. +generalInfoHttps: Wij verzenden uw gegevens veilig via https. +generalInfoLocation: Onze server wordt gehost in Neurenberg, Duitsland. +generalInfoGitHub: De broncode van deze site is beschikbaar op +generalInfoLockScreen: Standaard zijn Apple Wallet-passen toegankelijk vanaf het vergrendelingsscherm. Dit kan worden gewijzigd in de +settings: settings +generalInfoProvider: | + De serverprovider verwerkt gegevens om deze site ter beschikking te stellen. + Om beter te begrijpen welke maatregelen zij nemen om uw gegevens te beschermen, leest u ook hun +privacyPolicy: privacybeleid +andThe: en de +dataPrivacyFaq: veelgestelde vragen over gegevensprivacy +contact: Contact +email: E-mail +website: Website +process: Vereenvoudigde uitleg van het proces +processFirst: Ten eerste gebeuren de volgende stappen lokaal in uw browser +processSecond: Ten tweede gebeuren de volgende stappen op onze server +processThird: Ten slotte gebeuren de volgende stappen lokaal in uw browser +processRecognizing: Herkennen en extraheren van de QR-codegegevens van uw geselecteerde certificaat +processDecoding: Het decoderen van uw persoonlijke en gezondheidsgerelateerde gegevens uit de QR-code payload +processAssembling: Een onvolledig pasbestand samenstellen uit uw gegevens +processGenerating: Een bestand genereren dat hashes bevat van de gegevens die zijn opgeslagen in het pasbestand +processSending: Alleen het bestand met de hashes naar onze server verzenden +processReceiving: De hashes ontvangen en controleren die lokaal zijn gegenereerd +processSigning: Het bestand met de hashes ondertekenen +processSendingBack: De handtekening terugsturen +processCompleting: Het getekende pass-bestand samenstellen uit het onvolledige bestand dat lokaal is gegenereerd en de handtekening +processSaving: Het bestand op uw apparaat opslaan +locallyProcessedData: Lokaal verwerkte gegevens +the: Het +schema: Digitaal Covid Certificate Schema +specification: bevat een gedetailleerde specificatie van welke gegevens in de QR-code kunnen staan en in uw browser worden verwerkt. +serverProvider: Serverprovider +serverProviderIs: Onze serverprovider is +logFiles: De volgende gegevens kunnen worden verzameld en opgeslagen in de serverlogbestanden +logFilesBrowser: De gebruikte browsertypes en -versies +logFilesOs: Het besturingssysteem dat wordt gebruikt door het toegangssysteem +logFilesReferrer: De website van waaruit een toegangssysteem onze website bereikt (zogenaamde verwijzers) +logFilesTime: De datum en tijd van bezoek +logFilesIpAddress: De gepseudonimiseerde IP-adressen +rights: Jou rechten +rightsGranted: Conform de AVG heeft u de volgende rechten +rightsAccess: Recht op toegang tot uw gegevens; U hebt het recht om te weten welke gegevens over u zijn verzameld en hoe deze zijn verwerkt. +rightsErasure: Recht om vergeten te worden; Wissen van uw persoonsgegevens. +rightsRectification: Recht op rectificatie; U heeft het recht om onjuiste gegevens te corrigeren. +rightsPortability: Recht op gegevensoverdraagbaarheid; U heeft het recht om uw gegevens over te dragen van het ene verwerkingssysteem naar het andere. +thirdParties: Derden gekoppeld +appleSync: Apple kan uw passen synchroniseren via iCloud \ No newline at end of file diff --git a/src/payload.ts b/src/payload.ts index e45d882..6e7f6b7 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -2,7 +2,7 @@ import {ValueSets} from "./value_sets"; import {Constants} from "./constants"; enum CertificateType { - Vaccination = 'Vaccination', + Vaccine = 'Vaccine', Test = 'Test', Recovery = 'Recovery', } @@ -63,25 +63,35 @@ export class Payload { throw new Error('certificateData'); } - // Get name and date of birth information + // Get name information const nameInformation = covidCertificate['nam']; - const dateOfBirthInformation = covidCertificate['dob']; if (nameInformation == undefined) { throw new Error('nameMissing'); } - if (dateOfBirthInformation == undefined) { - throw new Error('dobMissing'); - } - const name = `${nameInformation['fn']}, ${nameInformation['gn']}`; - const dateOfBirth = dateOfBirthInformation; + const firstName = nameInformation['gn']; + const lastName = nameInformation['fn']; + + const transliteratedFirstName = nameInformation['gnt']; + const transliteratedLastName = nameInformation['fnt']; + + // Check if name contains non-latin characters + const nameRegex = new RegExp('^(\\p{Script=Latin}|[ -\'`´])+$', 'u'); + + let name: string; + + if (nameRegex.test(firstName) && nameRegex.test(lastName)) { + name = `${firstName} ${lastName}`; + } else { + name = `${transliteratedFirstName} ${transliteratedLastName}`; + } let properties: object; // Set certificate type and properties if (covidCertificate['v'] !== undefined) { - this.certificateType = CertificateType.Vaccination; + this.certificateType = CertificateType.Vaccine; properties = covidCertificate['v'][0]; } if (covidCertificate['t'] !== undefined) { @@ -96,23 +106,16 @@ export class Payload { throw new Error('certificateType') } - // Get country code, identifier and issuer - const countryCode = properties['co']; + // Get identifier and issuer const uvci = properties['ci']; const certificateIssuer = properties['is']; - if (!(countryCode in valueSets.countryCodes)) { - throw new Error('invalidCountryCode'); - } - - const country = valueSets.countryCodes[countryCode].display; - const generic: PassDictionary = { headerFields: [ { key: "type", - label: "Certificate Type", - value: this.certificateType + label: "EU Digital COVID", + value: this.certificateType + " Certificate" } ], primaryFields: [ @@ -123,14 +126,7 @@ export class Payload { } ], secondaryFields: [], - auxiliaryFields: [ - { - key: "dob", - label: "Date of Birth", - value: dateOfBirth, - textAlignment: TextAlignment.right - } - ], + auxiliaryFields: [], backFields: [ { key: "uvci", @@ -141,11 +137,6 @@ export class Payload { key: "issuer", label: "Certificate Issuer", value: certificateIssuer - }, - { - key: "country", - label: "Country", - value: country } ] } @@ -164,8 +155,17 @@ export class Payload { } static fillPassData(type: CertificateType, data: PassDictionary, properties: Object, valueSets: ValueSets): PassDictionary { + // Get country name + const countryCode = properties['co']; + + if (!(countryCode in valueSets.countryCodes)) { + throw new Error('invalidCountryCode'); + } + + const country = valueSets.countryCodes[countryCode].display; + switch (type) { - case CertificateType.Vaccination: + case CertificateType.Vaccine: const dose = `${properties['dn']}/${properties['sd']}`; const dateOfVaccination = properties['dt']; const medialProductKey = properties['mp']; @@ -178,7 +178,7 @@ export class Payload { throw new Error('invalidManufacturer') } - const vaccineName = valueSets.medicalProducts[medialProductKey].display; + const vaccineName = valueSets.medicalProducts[medialProductKey].display.replace(/\s*\([^)]*\)\s*/g, ""); const manufacturer = valueSets.manufacturers[manufacturerKey].display; data.secondaryFields.push(...[ @@ -194,11 +194,19 @@ export class Payload { textAlignment: TextAlignment.right } ]); - data.auxiliaryFields.splice(0, 0, { - key: "vaccine", - label: "Vaccine", - value: vaccineName - }); + data.auxiliaryFields.push(...[ + { + key: "vaccine", + label: "Vaccine", + value: vaccineName + }, + { + key: "cov", + label: "Country of Vaccination", + value: country, + textAlignment: TextAlignment.right + } + ]); data.backFields.push(...[ { key: "manufacturer", @@ -234,7 +242,7 @@ export class Payload { data.secondaryFields.push(...[ { key: "result", - label: "Result", + label: "Test Result", value: testResult }, { @@ -244,7 +252,6 @@ export class Payload { textAlignment: TextAlignment.right } ]); - data.auxiliaryFields.pop(); data.auxiliaryFields.push(...[ { key: "test", @@ -258,6 +265,11 @@ export class Payload { textAlignment: TextAlignment.right }, ]); + data.backFields.push({ + key: "cot", + label: "Country of Test", + value: country + }); if (testingCentre !== undefined) data.backFields.push({ key: "centre", @@ -276,29 +288,28 @@ export class Payload { const validUntil = properties['du']; data.secondaryFields.push(...[ - { - key: "result", - label: "Test Result", - value: "Detected" - }, { key: "from", label: "Valid From", value: validFrom, + }, + { + key: "dov", + label: "Date of positive Test", + value: firstPositiveTestDate, textAlignment: TextAlignment.right } ]); - data.auxiliaryFields.pop(); data.auxiliaryFields.push(...[ - { - key: "testdate", - label: "Test Date", - value: firstPositiveTestDate - }, { key: "until", label: "Valid Until", value: validUntil, + }, + { + key: "cov", + label: "Country of Test", + value: country, textAlignment: TextAlignment.right }, ]);