Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • startuplab/courses/tjts5901-continuous-software-engineering/TJTS5901-K23_template
  • planet-of-the-apes/tjts-5901-apeuction
  • uunot-yliopiston-leivissa/tjts-5901-uunot
  • contain-the-cry/tjts-5901-auction-system
  • avengers/avengers
  • cse6/cse-6
  • 13th/13-sins-of-gitlab
  • fast-and-furious/fast-and-furious
  • back-to-the-future/delorean-auction
  • monty-pythons-the-meaning-of-life/the-meaning-of-life
  • team-atlantis/the-empire
  • code-with-the-wind/auction-project
  • the-pirates/the-pirates
  • do-the-right-thing/do-the-right-thing
  • inception/inception
  • the-social-network-syndicate/the-social-auction-network
  • team-the-hunt-for-red-october/tjts-5901-k-23-red-october
  • good-on-paper/good-paper-project
  • desperados/desperados
19 results
Show changes
msgid ""
msgstr ""
"Project-Id-Version: TJTS5901-K23\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-02-19 12:49+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fi\n"
"Language-Team: fi <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.11.0\n"
#: src/tjts5901/app.py:42
msgid "Hill Valley DMC dealership"
msgstr "Hill Valley DMC -liike"
#: src/tjts5901/app.py:78 tests/test_i18n.py:79 tests/test_i18n.py:103
msgid "Hello, World!"
msgstr "Hei Maailma!"
#: src/tjts5901/auth.py:255
msgid "Required field missing"
msgstr "Pakollinen kenttä puuttuu"
#: src/tjts5901/auth.py:258
#, python-format
msgid "Error creating token: %s"
msgstr "Virhe luotaessa tunnistetta: %s"
#: src/tjts5901/auth.py:260
#, python-format
msgid "Created token: %s"
msgstr "Luotu tunniste: %s"
#: src/tjts5901/items.py:187
#, python-format
msgid "Starting bid must be greater than %(amount)s."
msgstr "Huudon tulee olla vähintään %(amount)s"
#: src/tjts5901/items.py:203
msgid "Item listed successfully!"
msgstr "Tuote lisätty onnistuneesti!"
#: src/tjts5901/items.py:206
#, python-format
msgid "Error creating item: %(exc)s"
msgstr "Virhe luotaessa tuotetta: %(exc)s"
#: src/tjts5901/items.py:251
msgid "Congratulations! You won the auction!"
msgstr "Onnittelut! Voitit huutokaupan!"
#: src/tjts5901/items.py:253 src/tjts5901/items.py:423
msgid "This item is no longer on sale."
msgstr "Tämä tuote ei ole enää myynnissä"
#: src/tjts5901/items.py:256
msgid "This item is closing soon! Act now! Now! Now!"
msgstr "Tämä tuote sulkeutuu pian! Toimi nyt! Heti! Nyt!"
#: src/tjts5901/items.py:275
msgid "Title is required."
msgstr "Otsikko on pakollinen."
#: src/tjts5901/items.py:282
#, python-format
msgid "Error updating item: %(exc)s"
msgstr "Virhe päivitettäessä tuotetta: %(exc)s"
#: src/tjts5901/items.py:287
msgid "Item updated successfully!"
msgstr "Tuote päivitetty onnistuneesti!"
#: src/tjts5901/items.py:306
#, python-format
msgid "Error deleting item: %(exc)s"
msgstr "Virhe poistaessa tuotetta: %(exc)s"
#: src/tjts5901/items.py:308
msgid "Item deleted successfully!"
msgstr "Tuote poistettu onnistuneesti!"
#: src/tjts5901/items.py:334 src/tjts5901/items.py:417
#, python-format
msgid "Bid must be at least %(min_amount)s"
msgstr "Huudon tulee olla vähintään %(min_amount)s"
#: src/tjts5901/items.py:351 src/tjts5901/items.py:442
#, python-format
msgid "Error placing bid: %(exc)s"
msgstr "Virhe asettaessa huutoa: %(exc)s"
#: src/tjts5901/items.py:353
msgid "Bid placed successfully!"
msgstr "Huuto asetettu onnistuneesti!"
#: src/tjts5901/items.py:401
#, python-format
msgid "Missing required argument %(argname)s"
msgstr "Tarvittava argumentti %(argname)s puuttuu"
#: src/tjts5901/items.py:406
#, python-format
msgid "Invalid value for argument %(argname)s"
msgstr "Virheellinen arvo argumentille %(argname)s"
#: src/tjts5901/items.py:411
#, python-format
msgid "Error parsing argument %(argname)s: %(exc)s"
msgstr "Virhe käsiteltäessä argumenttia %(argname)s: %(exc)s"
#: src/tjts5901/templates/base.html:48
msgid "Home"
msgstr "Etusivu"
#: src/tjts5901/templates/base.html:51
msgid "Sell"
msgstr "Myy"
#: src/tjts5901/templates/base.html:54
msgid "About"
msgstr "Tietoa"
#: src/tjts5901/templates/base.html:61
msgid "Language"
msgstr "Kieli"
#: src/tjts5901/templates/base.html:72
msgid "Log Out"
msgstr "Kirjaudu ulos"
#: src/tjts5901/templates/base.html:74
msgid "Register"
msgstr "Rekisteröidy"
#: src/tjts5901/templates/base.html:75
msgid "Log In"
msgstr "Kirjaudu sisään"
#: src/tjts5901/templates/base.html:80
msgid "Search"
msgstr "Etsi"
#: src/tjts5901/templates/base.html:103
msgid "Message"
msgstr "Viesti"
#: src/tjts5901/templates/base.html:105
msgid "Close"
msgstr "Sulje"
#: src/tjts5901/templates/auth/login.html:25
msgid "Sign in to our platform"
msgstr "Kirjaudu palveluun"
#: src/tjts5901/templates/auth/login.html:32
#: src/tjts5901/templates/auth/register.html:31
msgid "Email"
msgstr "Sähköposti"
#: src/tjts5901/templates/auth/login.html:33
msgid "Your email"
msgstr "Sähköpostisi"
#: src/tjts5901/templates/auth/login.html:40
#: src/tjts5901/templates/auth/register.html:38
msgid "Password"
msgstr "Salasana"
#: src/tjts5901/templates/auth/login.html:42
msgid "Your password"
msgstr "Salasanasi"
#: src/tjts5901/templates/auth/login.html:51
msgid "Remember me"
msgstr "Muista minut"
#: src/tjts5901/templates/auth/login.html:54
msgid "Lost password?"
msgstr "Salasana unohtunut?"
#: src/tjts5901/templates/auth/login.html:57
msgid "Login"
msgstr "Kirjaudu"
#: src/tjts5901/templates/auth/login.html:61
msgid "Not registered?"
msgstr "Ei vielä tunnuksia?"
#: src/tjts5901/templates/auth/login.html:62
msgid "Create an account"
msgstr "Luo tunnus"
#: src/tjts5901/templates/auth/profile.html:37
msgid "My items"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:44
msgid "Purchase date"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:49
msgid "Item ID"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:53
#: src/tjts5901/templates/items/index.html:34
msgid "Seller"
msgstr "Myyjä"
#: src/tjts5901/templates/auth/profile.html:59
#, python-format
msgid "Product image for %(title)s"
msgstr ""
#: src/tjts5901/templates/auth/register.html:24
msgid "Register on our platform"
msgstr "Rekisteröidy palveluun"
#: src/tjts5901/templates/auth/register.html:42
msgid "Confirm password"
msgstr "Vahvista salasana"
#: src/tjts5901/templates/auth/register.html:53
#, python-format
msgid "I agree to the %(terms)s"
msgstr "Hyväksyn %(terms)s"
#: src/tjts5901/templates/auth/register.html:53
msgid "terms and conditions"
msgstr "käyttöehdot"
#: src/tjts5901/templates/auth/register.html:58
msgid "Register account"
msgstr "Rekisteröi tunnus"
#: src/tjts5901/templates/auth/register.html:62
msgid "Already have an account?"
msgstr "Onko sinulla jo tunnus?"
#: src/tjts5901/templates/auth/register.html:63
msgid "Login here"
msgstr "Kirjaudu tästä"
#: src/tjts5901/templates/auth/tokens.html:11
msgid "Personal Access Tokens"
msgstr "Henkilökohtaiset poletit"
#: src/tjts5901/templates/auth/tokens.html:13
msgid ""
"Personal access tokens allow third-party services to authenticate with "
"our application on your behalf."
msgstr ""
"Henkilökohtaiset poletit mahdollistavat kolmannen osapuolen "
"palveluidenautentikoinnin sovelluksen puolesta."
#: src/tjts5901/templates/auth/tokens.html:19
msgid "Your new personal access token"
msgstr "Uusi henkilökohtainen poletti"
#: src/tjts5901/templates/auth/tokens.html:21
msgid ""
"Your new personal access token is shown below. You may now use this token"
" to make API requests."
msgstr ""
"Uusi henkilökohtainen poletti näkyy alla. Voit nyt käyttää tätä "
"polettiaAPI-pyyntöihin."
#: src/tjts5901/templates/auth/tokens.html:25
msgid "Copy"
msgstr "Kopioi"
#: src/tjts5901/templates/auth/tokens.html:35
msgid "Make sure to copy your new token now. You won't be able to see it again!"
msgstr "Varmista, että kopioit uuden poletin. Et voi nähdä sitä uudelleen!"
#: src/tjts5901/templates/auth/tokens.html:41
#: src/tjts5901/templates/auth/tokens.html:54
msgid "Create access token"
msgstr "Luo poletti"
#: src/tjts5901/templates/auth/tokens.html:45
msgid "Name"
msgstr "Nimi"
#: src/tjts5901/templates/auth/tokens.html:46
msgid " Enter token name"
msgstr "Anna poletin nimi"
#: src/tjts5901/templates/auth/tokens.html:47
msgid ""
"Give your token a descriptive name so you can easily identify it in the "
"future."
msgstr ""
"Anna poletille kuvaava nimi, jotta voit helposti tunnistaa sen "
"tulevaisuudessa."
#: src/tjts5901/templates/auth/tokens.html:50
msgid "Expires at"
msgstr "Vanhenee"
#: src/tjts5901/templates/auth/tokens.html:52
msgid "Leave blank to never expire."
msgstr "Jätä tyhjäksi, jos et halua poletin vanhentuman."
#: src/tjts5901/templates/auth/tokens.html:64
msgid "Active Access Tokens"
msgstr "Aktiiviset poletit"
#: src/tjts5901/templates/auth/tokens.html:68
msgid "Token name"
msgstr "Poletin nimi"
#: src/tjts5901/templates/auth/tokens.html:69
msgid "Created"
msgstr "Luotu"
#: src/tjts5901/templates/auth/tokens.html:70
msgid "Last used"
msgstr "Viimeksi käytetty"
#: src/tjts5901/templates/auth/tokens.html:71
msgid "Expires"
msgstr "Vanhenee"
#: src/tjts5901/templates/auth/tokens.html:72
msgid "Actions"
msgstr "Toiminnot"
#: src/tjts5901/templates/auth/tokens.html:83
#: src/tjts5901/templates/auth/tokens.html:89
msgid "Never"
msgstr "Ei koskaan"
#: src/tjts5901/templates/auth/tokens.html:95
#: src/tjts5901/templates/items/update.html:31
msgid "Delete"
msgstr "Poista"
#: src/tjts5901/templates/items/index.html:20
msgid "Items on sale"
msgstr "Myynnissä olevat tuotteet"
#: src/tjts5901/templates/items/index.html:31
#: src/tjts5901/templates/items/sell.html:15
#: src/tjts5901/templates/items/update.html:17
msgid "Title"
msgstr "Otsikko"
#: src/tjts5901/templates/items/index.html:32
#: src/tjts5901/templates/items/sell.html:19
#: src/tjts5901/templates/items/update.html:21
msgid "Description"
msgstr "Kuvaus"
#: src/tjts5901/templates/items/index.html:33
#: src/tjts5901/templates/items/sell.html:24
msgid "Starting Bid"
msgstr "Aloitushinta"
#: src/tjts5901/templates/items/index.html:35
msgid "Created At"
msgstr "Luotu"
#: src/tjts5901/templates/items/index.html:36
msgid "Closes At"
msgstr "Sulkeutuu"
#: src/tjts5901/templates/items/sell.html:4
msgid "Sell an Item"
msgstr "Lisää tuote myyntiin"
#: src/tjts5901/templates/items/sell.html:12
msgid "Add Item"
msgstr "Lisää tuote"
#: src/tjts5901/templates/items/sell.html:28
msgid "Currency"
msgstr "Valuutta"
#: src/tjts5901/templates/items/sell.html:40
msgid "Flash sale!"
msgstr "Salamakauppa!"
#: src/tjts5901/templates/items/sell.html:46
msgid "Add to listing"
msgstr "Lisää myyntiin"
#: src/tjts5901/templates/items/update.html:25
msgid "Starting Price"
msgstr "Aloitushinta"
#: src/tjts5901/templates/items/update.html:30
msgid "Update listing"
msgstr "Päivitä myynti-ilmoitus"
#: src/tjts5901/templates/items/update.html:31
msgid "Are you sure?"
msgstr "Oletko varma?"
#: src/tjts5901/templates/items/view.html:21
#, python-format
msgid "%(item)s by %(seller)s"
msgstr "%(item)s, myyjänä %(seller)s"
#: src/tjts5901/templates/items/view.html:27
msgid "Closes at"
msgstr "Sulkeutuu"
#: src/tjts5901/templates/items/view.html:35
msgid "Added at"
msgstr "Lisätty"
#: src/tjts5901/templates/items/view.html:45
msgid "Starting bid"
msgstr "Aloitushinta"
#: src/tjts5901/templates/items/view.html:56
msgid "Bid amount"
msgstr "Tarjous"
#: src/tjts5901/templates/items/view.html:62
#, python-format
msgid "Minimum bid is %(min_bid)s"
msgstr "Vähimmäistarjous on %(min_bid)s"
#: src/tjts5901/templates/items/view.html:66
msgid "Bid"
msgstr "Tarjoa"
#: src/tjts5901/templates/items/view.html:72
msgid "Congratulations!"
msgstr "Onnittelut!"
#: src/tjts5901/templates/items/view.html:72
msgid "You won the bid!"
msgstr "Voitit huutokisan!"
#: src/tjts5901/templates/items/view.html:80
msgid "Final price"
msgstr "Lopullinen hinta"
#: src/tjts5901/templates/items/view.html:84
#, python-format
msgid "You won this item at %(closes_at)s"
msgstr "Voitit tämän tuotteen %(closes_at)s"
#: src/tjts5901/templates/items/view.html:90
msgid "Pay"
msgstr "Maksa"
#: src/tjts5901/templates/items/view.html:97
msgid "Item is no longer at sale."
msgstr "Myynti on päättynyt."
#: src/tjts5901/templates/items/view.html:97
msgid "Next time, act faster!"
msgstr "Jatkossa toimi nopeammin!"
#: src/tjts5901/templates/items/view.html:105
#, python-format
msgid "%(icon)s Contact seller"
msgstr "%(icon)s Ota yhteyttä myyjään"
#: src/tjts5901/templates/items/view.html:106
#, python-format
msgid "%(icon)s Call seller"
msgstr "%(icon)s Soita myyjälle"
#: src/tjts5901/templates/items/view.html:121
msgid "Elon-senpai notice me!"
msgstr "Elon-senpai huomioi minut!"
#: src/tjts5901/templates/items/view.html:125
msgid "Zuckdaddy, you so alpha!"
msgstr "Zuckdaddy, olet niin alpha!"
#: src/tjts5901/templates/items/view.html:129
msgid "Email to a friend"
msgstr "Lähetä ystävälle"
#~ msgid "Your item was not sold"
#~ msgstr "Tuotetteesi ei käynyt kaupaksi"
#~ msgid "Your item <a href=\"%(url)s\">%(title)s</a> was not sold."
#~ msgstr "Tuotteesi <a href=\"%(url)s\">%(title)s</a> ei käynyt kaupaksi."
msgid ""
msgstr ""
"Project-Id-Version: TJTS5901-K23\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2023-02-19 12:49+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: sv\n"
"Language-Team: sv <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.11.0\n"
#: src/tjts5901/app.py:42
msgid "Hill Valley DMC dealership"
msgstr "Hill Valley DMC återförsäljare"
#: src/tjts5901/app.py:78 tests/test_i18n.py:79 tests/test_i18n.py:103
msgid "Hello, World!"
msgstr "Hej världen!"
#: src/tjts5901/auth.py:255
msgid "Required field missing"
msgstr "Obligatoriskt fält saknas"
#: src/tjts5901/auth.py:258
#, python-format
msgid "Error creating token: %s"
msgstr "Fel vid skapande av token: %s"
#: src/tjts5901/auth.py:260
#, python-format
msgid "Created token: %s"
msgstr "Skapad token: %s"
#: src/tjts5901/items.py:187
#, python-format
msgid "Starting bid must be greater than %(amount)s."
msgstr "Budet måste vara minst %(amount)s"
#: src/tjts5901/items.py:203
msgid "Item listed successfully!"
msgstr "Objektet listades framgångsrikt!"
#: src/tjts5901/items.py:206
#, python-format
msgid "Error creating item: %(exc)s"
msgstr "Fel vid skapandet av objektet: %(exc)s"
#: src/tjts5901/items.py:251
msgid "Congratulations! You won the auction!"
msgstr "Grattis! Du har vunnit auktionen!"
#: src/tjts5901/items.py:253 src/tjts5901/items.py:423
msgid "This item is no longer on sale."
msgstr "Denna vara är inte längre till rea."
#: src/tjts5901/items.py:256
msgid "This item is closing soon! Act now! Now! Now!"
msgstr "Detta objekt stänger snart! Handla nu! Nu! Nu!"
#: src/tjts5901/items.py:275
msgid "Title is required."
msgstr "Titel krävs."
#: src/tjts5901/items.py:282
#, python-format
msgid "Error updating item: %(exc)s"
msgstr "Fel vid uppdatering av objekt: %(exc)s"
#: src/tjts5901/items.py:287
msgid "Item updated successfully!"
msgstr "Artikeln har uppdaterats framgångsrikt!"
#: src/tjts5901/items.py:306
#, python-format
msgid "Error deleting item: %(exc)s"
msgstr "Fel vid radering av objekt: %(exc)s"
#: src/tjts5901/items.py:308
msgid "Item deleted successfully!"
msgstr "Föremålet har tagits bort framgångsrikt!"
#: src/tjts5901/items.py:334 src/tjts5901/items.py:417
#, python-format
msgid "Bid must be at least %(min_amount)s"
msgstr "Budet måste vara minst %(min_amount)s"
#: src/tjts5901/items.py:351 src/tjts5901/items.py:442
#, python-format
msgid "Error placing bid: %(exc)s"
msgstr "Fel i budgivningen: %(exc)s"
#: src/tjts5901/items.py:353
msgid "Bid placed successfully!"
msgstr "Budet har placerats framgångsrikt!"
#: src/tjts5901/items.py:401
#, python-format
msgid "Missing required argument %(argname)s"
msgstr "Det obligatoriska argumentet %(argname)s saknas"
#: src/tjts5901/items.py:406
#, python-format
msgid "Invalid value for argument %(argname)s"
msgstr "Ogiltigt värde för argument %(argname)s"
#: src/tjts5901/items.py:411
#, python-format
msgid "Error parsing argument %(argname)s: %(exc)s"
msgstr "Fel vid analys av argument %(argname)s: %(exc)s"
#: src/tjts5901/templates/base.html:48
msgid "Home"
msgstr "Hem"
#: src/tjts5901/templates/base.html:51
msgid "Sell"
msgstr "Sälja"
#: src/tjts5901/templates/base.html:54
msgid "About"
msgstr "Handla om"
#: src/tjts5901/templates/base.html:61
msgid "Language"
msgstr "Språk"
#: src/tjts5901/templates/base.html:72
msgid "Log Out"
msgstr "Logga ut"
#: src/tjts5901/templates/base.html:74
msgid "Register"
msgstr "Registrera"
#: src/tjts5901/templates/base.html:75
msgid "Log In"
msgstr "Logga in"
#: src/tjts5901/templates/base.html:80
msgid "Search"
msgstr "Sök"
#: src/tjts5901/templates/base.html:103
msgid "Message"
msgstr "Meddelande"
#: src/tjts5901/templates/base.html:105
msgid "Close"
msgstr "Stänga"
#: src/tjts5901/templates/auth/login.html:25
msgid "Sign in to our platform"
msgstr "Logga in på vår plattform"
#: src/tjts5901/templates/auth/login.html:32
#: src/tjts5901/templates/auth/register.html:31
msgid "Email"
msgstr "E-post"
#: src/tjts5901/templates/auth/login.html:33
msgid "Your email"
msgstr "Din email"
#: src/tjts5901/templates/auth/login.html:40
#: src/tjts5901/templates/auth/register.html:38
msgid "Password"
msgstr "Lösenord"
#: src/tjts5901/templates/auth/login.html:42
msgid "Your password"
msgstr "Ditt lösenord"
#: src/tjts5901/templates/auth/login.html:51
msgid "Remember me"
msgstr "Kom ihåg mig"
#: src/tjts5901/templates/auth/login.html:54
msgid "Lost password?"
msgstr "Glömt lösenord?"
#: src/tjts5901/templates/auth/login.html:57
msgid "Login"
msgstr "Logga in"
#: src/tjts5901/templates/auth/login.html:61
msgid "Not registered?"
msgstr "Inte registrerad?"
#: src/tjts5901/templates/auth/login.html:62
msgid "Create an account"
msgstr "Skapa ett konto"
#: src/tjts5901/templates/auth/profile.html:37
msgid "My items"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:44
msgid "Purchase date"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:49
msgid "Item ID"
msgstr ""
#: src/tjts5901/templates/auth/profile.html:53
#: src/tjts5901/templates/items/index.html:34
msgid "Seller"
msgstr "Säljare"
#: src/tjts5901/templates/auth/profile.html:59
#, python-format
msgid "Product image for %(title)s"
msgstr ""
#: src/tjts5901/templates/auth/register.html:24
msgid "Register on our platform"
msgstr "Registrera dig på vår plattform"
#: src/tjts5901/templates/auth/register.html:42
msgid "Confirm password"
msgstr "Bekräfta lösenord"
#: src/tjts5901/templates/auth/register.html:53
#, python-format
msgid "I agree to the %(terms)s"
msgstr "Jag godkänner %(terms)s"
#: src/tjts5901/templates/auth/register.html:53
msgid "terms and conditions"
msgstr "Villkor"
#: src/tjts5901/templates/auth/register.html:58
msgid "Register account"
msgstr "Registrera konto"
#: src/tjts5901/templates/auth/register.html:62
msgid "Already have an account?"
msgstr "Har du redan ett konto?"
#: src/tjts5901/templates/auth/register.html:63
msgid "Login here"
msgstr "Logga in här"
#: src/tjts5901/templates/auth/tokens.html:11
msgid "Personal Access Tokens"
msgstr "Personliga åtkomsttokens"
#: src/tjts5901/templates/auth/tokens.html:13
msgid ""
"Personal access tokens allow third-party services to authenticate with "
"our application on your behalf."
msgstr ""
"Personliga åtkomsttokens tillåter tredjepartstjänster att autentisera med"
" vår applikation å dina vägnar."
#: src/tjts5901/templates/auth/tokens.html:19
msgid "Your new personal access token"
msgstr "Din nya personliga åtkomsttoken"
#: src/tjts5901/templates/auth/tokens.html:21
msgid ""
"Your new personal access token is shown below. You may now use this token"
" to make API requests."
msgstr ""
"Din nya personliga åtkomsttoken visas nedan. Du kan nu använda denna "
"token för att göra API-förfrågningar."
#: src/tjts5901/templates/auth/tokens.html:25
msgid "Copy"
msgstr "Kopiera"
#: src/tjts5901/templates/auth/tokens.html:35
msgid "Make sure to copy your new token now. You won't be able to see it again!"
msgstr ""
"Se till att kopiera din nya token nu. Du kommer inte att kunna se den "
"igen!"
#: src/tjts5901/templates/auth/tokens.html:41
#: src/tjts5901/templates/auth/tokens.html:54
msgid "Create access token"
msgstr "Skapa åtkomsttoken"
#: src/tjts5901/templates/auth/tokens.html:45
msgid "Name"
msgstr "namn"
#: src/tjts5901/templates/auth/tokens.html:46
msgid " Enter token name"
msgstr " Ange tokennamn"
#: src/tjts5901/templates/auth/tokens.html:47
msgid ""
"Give your token a descriptive name so you can easily identify it in the "
"future."
msgstr ""
"Ge din token ett beskrivande namn så att du enkelt kan identifiera den i "
"framtiden."
#: src/tjts5901/templates/auth/tokens.html:50
msgid "Expires at"
msgstr "Går ut kl"
#: src/tjts5901/templates/auth/tokens.html:52
msgid "Leave blank to never expire."
msgstr "Lämna tomt för att aldrig upphöra."
#: src/tjts5901/templates/auth/tokens.html:64
msgid "Active Access Tokens"
msgstr "Active Access Tokens"
#: src/tjts5901/templates/auth/tokens.html:68
msgid "Token name"
msgstr "Tokennamn"
#: src/tjts5901/templates/auth/tokens.html:69
msgid "Created"
msgstr "Skapad"
#: src/tjts5901/templates/auth/tokens.html:70
msgid "Last used"
msgstr "Senast använd"
#: src/tjts5901/templates/auth/tokens.html:71
msgid "Expires"
msgstr "Upphör att gälla"
#: src/tjts5901/templates/auth/tokens.html:72
msgid "Actions"
msgstr "Handlingar"
#: src/tjts5901/templates/auth/tokens.html:83
#: src/tjts5901/templates/auth/tokens.html:89
msgid "Never"
msgstr "Aldrig"
#: src/tjts5901/templates/auth/tokens.html:95
#: src/tjts5901/templates/items/update.html:31
msgid "Delete"
msgstr "Radera"
#: src/tjts5901/templates/items/index.html:20
msgid "Items on sale"
msgstr "Föremål till försäljning"
#: src/tjts5901/templates/items/index.html:31
#: src/tjts5901/templates/items/sell.html:15
#: src/tjts5901/templates/items/update.html:17
msgid "Title"
msgstr "Titel"
#: src/tjts5901/templates/items/index.html:32
#: src/tjts5901/templates/items/sell.html:19
#: src/tjts5901/templates/items/update.html:21
msgid "Description"
msgstr "Beskrivning"
#: src/tjts5901/templates/items/index.html:33
#: src/tjts5901/templates/items/sell.html:24
msgid "Starting Bid"
msgstr "Startbud"
#: src/tjts5901/templates/items/index.html:35
msgid "Created At"
msgstr "Skapad vid"
#: src/tjts5901/templates/items/index.html:36
msgid "Closes At"
msgstr "Stänger kl"
#: src/tjts5901/templates/items/sell.html:4
msgid "Sell an Item"
msgstr "Sälja ett föremål"
#: src/tjts5901/templates/items/sell.html:12
msgid "Add Item"
msgstr "Lägg till vara"
#: src/tjts5901/templates/items/sell.html:28
msgid "Currency"
msgstr "Valuta"
#: src/tjts5901/templates/items/sell.html:40
msgid "Flash sale!"
msgstr "Flash rea!"
#: src/tjts5901/templates/items/sell.html:46
msgid "Add to listing"
msgstr "Lägg till i annonsen"
#: src/tjts5901/templates/items/update.html:25
msgid "Starting Price"
msgstr "Startpris"
#: src/tjts5901/templates/items/update.html:30
msgid "Update listing"
msgstr "Uppdatera lista"
#: src/tjts5901/templates/items/update.html:31
msgid "Are you sure?"
msgstr "Är du säker?"
#: src/tjts5901/templates/items/view.html:21
#, python-format
msgid "%(item)s by %(seller)s"
msgstr "%(item)s av %(seller)s"
#: src/tjts5901/templates/items/view.html:27
msgid "Closes at"
msgstr "Stänger kl."
#: src/tjts5901/templates/items/view.html:35
msgid "Added at"
msgstr "Tillagd på"
#: src/tjts5901/templates/items/view.html:45
msgid "Starting bid"
msgstr "Startbud"
#: src/tjts5901/templates/items/view.html:56
msgid "Bid amount"
msgstr "Budbelopp"
#: src/tjts5901/templates/items/view.html:62
#, python-format
msgid "Minimum bid is %(min_bid)s"
msgstr "Minsta bud är %(min_bid)s"
#: src/tjts5901/templates/items/view.html:66
msgid "Bid"
msgstr "Anbud"
#: src/tjts5901/templates/items/view.html:72
msgid "Congratulations!"
msgstr "Grattis!"
#: src/tjts5901/templates/items/view.html:72
msgid "You won the bid!"
msgstr "Du vann budet!"
#: src/tjts5901/templates/items/view.html:80
msgid "Final price"
msgstr "Slutgiltigt pris"
#: src/tjts5901/templates/items/view.html:84
#, python-format
msgid "You won this item at %(closes_at)s"
msgstr "Du vann detta föremål på %(closes_at)s"
#: src/tjts5901/templates/items/view.html:90
msgid "Pay"
msgstr "Betala"
#: src/tjts5901/templates/items/view.html:97
msgid "Item is no longer at sale."
msgstr "Föremålet är inte längre till salu."
#: src/tjts5901/templates/items/view.html:97
msgid "Next time, act faster!"
msgstr "Nästa gång, agera snabbare!"
#: src/tjts5901/templates/items/view.html:105
#, python-format
msgid "%(icon)s Contact seller"
msgstr "%(icon)s Kontakta säljaren"
#: src/tjts5901/templates/items/view.html:106
#, python-format
msgid "%(icon)s Call seller"
msgstr "%(icon)s Ring till säljaren"
#: src/tjts5901/templates/items/view.html:121
msgid "Elon-senpai notice me!"
msgstr "Elon-senpai lägger märke till mig!"
#: src/tjts5901/templates/items/view.html:125
msgid "Zuckdaddy, you so alpha!"
msgstr "Zuckdaddy, du är så alfa!"
#: src/tjts5901/templates/items/view.html:129
msgid "Email to a friend"
msgstr "Skicka e-post till en vän"
#~ msgid "Your item was not sold"
#~ msgstr "Din vara såldes inte"
#~ msgid "Your item <a href=\"%(url)s\">%(title)s</a> was not sold."
#~ msgstr "Din vara <a href=\"%(url)s\">%(title)s</a> såldes inte."
This diff is collapsed.
"""
Basic views for Application
===========================
"""
from flask import Blueprint, render_template, send_from_directory
# Main blueprint.
bp = Blueprint('views', __name__)
# Blueprint for documentation.
docs_bp = Blueprint('docs', __name__)
@bp.route("/")
def index() -> str:
"""
Index page.
"""
# Render template file. Template file is using Jinja2 syntax, and can be passed an arbitrary number
# of arguments to be used in the template. The template file is located in the templates directory.
html = render_template("index.html.j2", title="TJTS5901 Example. I should be changed.")
return html
from os import environ
import pytest
from flask import Flask
from faker import Faker
from werkzeug.security import generate_password_hash
# Disable Flask debug mode for testing
environ["FLASK_DEBUG"] = "0"
def pytest_addoption(parser: pytest.Parser):
"""
Callback to add command-line options for pytest.
Add option to define environment url to test.
Usage example from agruments::
$ pytest --environment-url "https://example.com"
Note: GitLab CI automatically sets environment variable `CI_ENVIRONMENT_URL`
to the address of environment to test.
Usage example from environment variable::
$ CI_ENVIRONMENT_URL="https://example.com" pytest
Note: If you want to test locally, you can define environment variable in
.env file.
"""
parser.addoption("--environment-url",
dest="CI_ENVIRONMENT_URL",
help="Deployment webaddress",
default=environ.get("CI_ENVIRONMENT_URL"))
@pytest.fixture(scope="session")
def app():
"""
Application fixture.
Every test that requires `app` as parameter can use this fixture.
Example:
>>> def test_mytest(app: Flask):
>>> ...
"""
from tjts5901.app import create_app
flask_app = create_app({
'TESTING': True,
'DEBUG': False,
# We need to set SERVER_NAME and PREFERRED_URL_SCHEME for testing.
'SERVER_NAME': 'localhost.localdomain',
'PREFERRED_URL_SCHEME': 'http',
})
# If you have done ties4080 course and have used Flask-WTF, you might
# have noticed that CSRF protection is enabled by default. This is
# problematic for testing, because we don't have a browser to generate
# CSRF tokens. We can disable CSRF protection for testing, but we need
# to make sure that we don't have CSRF protection enabled in production.
# flask_app.config['WTF_CSRF_ENABLED'] = False
# flask_app.config['WTF_CSRF_METHODS'] = []
# flask_app.config['WTF_CSRF_CHECK_DEFAULT'] = False
flask_app.testing = True
yield flask_app
# Do some cleanup here if needed.
...
@pytest.fixture
def client(app):
return app.test_client()
@pytest.fixture(scope='session', autouse=True)
def faker_session_locale(app: Flask):
"""
Fixture to set faker locale.
Compares the available locales in the application with the locales
available in faker. If there is a match, the locale is set to the
application locale.
This fixture is autouse, so it will be applied to all tests.
"""
from faker.config import AVAILABLE_LOCALES, DEFAULT_LOCALE
languages = []
with app.app_context():
for locale in app.extensions['babel'].instance.list_translations():
locale_code = str(locale)
if locale_code in AVAILABLE_LOCALES:
languages.append(locale_code)
if len(languages) == 0:
languages = [DEFAULT_LOCALE]
return languages
@pytest.fixture()
def user(app: Flask, faker: Faker):
"""
User fixture.
Creates a user into database and returns it.
"""
from tjts5901.models import User
print(faker.locales[0])
with app.app_context():
password = faker.password()
user = User(
email=faker.email(),
password=generate_password_hash(password),
locale=f"{faker.locales[0]}.UTF-8",
)
user.save()
setattr(user, '_plaintext_password', password)
yield user
user.delete()
"""
Flask based tests
=================
Uses the flask testclient to retrieve and post pages in application.
"""
import pytest
from flask.testing import FlaskClient
# This is the string we are looking for in the frontpage.
IN_TITLE = "DMC"
def test_fetch_mainpage(client: FlaskClient):
"""
Fetch frontpage and check that it has <title>.
:param client: Flask test client. See conftest.py for more info how it is
created.
"""
# Request frontpage
page = client.get('/')
# Check that page contains something.
# Note about assert; assert is special kind of keyword. By default
# assert statements are run, but if they are deemed too costly, python
# interepter can be defined to pass them with `python -O` flag.
# If assert statement return False, new assert exception is raised, and
# and test is deemed to fail. After first statement - condition - human
# readable reason for failure can be provided.
# >>> assert (condition-for-failure, "human readable reason")
assert page, "Did not get anything"
assert IN_TITLE.encode() in page.data, f"Page didn't have {IN_TITLE}"
from tjts5901 import create_app
def test_config():
assert not create_app().testing
assert create_app({'TESTING': True}).testing
def test_hello(client):
response = client.get('/hello', headers={'Accept-Language': 'en_US'})
assert response.data == b'Hello, World!'
This diff is collapsed.
"""
Test the notifications module.
"""
import pytest
from flask import Flask, flash, url_for
from flask.testing import FlaskClient
from tjts5901.models import Notification, User
from tjts5901.notification import send_notification, get_notifications
def test_send_notification(user: User):
"""
Test that a notification can be sent to a user.
"""
send_notification(user, "Test message", "message", "Test title")
# Check that the notification was saved to the database.
notifications = Notification.objects(user=user)
assert len(notifications) == 1, "Notification was not saved to the database."
# Check that the notification has the correct values.
notification = notifications.first()
assert notification.message == "Test message"
assert notification.category == "message"
assert notification.title == "Test title"
def test_flash_messages(user: User, app: Flask):
"""
Test that flask.flash() can be used to send notifications.
"""
with app.test_request_context():
flash("Test message", "message")
notifications = get_notifications(user)
assert len(notifications) == 1, "Flash message was returned."
notification = notifications.pop()
assert notification.message == "Test message"
assert notification.category == "message"
def test_notifications_view(client: FlaskClient, user: User):
"""
Test that the notifications view works.
"""
# Send a notification to the user.
db_notification = {
"message": "This is a database message",
"category": "message",
}
send_notification(user, **db_notification)
with client:
# Log in as the user.
client.post(
url_for("auth.login"),
data={"email": user.email, "password": user._plaintext_password},
follow_redirects=False,
)
# Check that the notification is shown on the page.
response = client.get(url_for('notification.user_notifications'))
assert response.status_code == 200
assert response.is_json
assert db_notification['message'] in [msg['message'] for msg in response.json['notifications']], \
"Database message was not returned."
"""
Smoketests
==========
Thease are tests that run in gitlab runner, but they target review or staging
environment.
"""
import requests
import pytest
@pytest.fixture
def deployment_address(pytestconfig: pytest.Config):
"""
Get the address for environment to check.
Define it in either in environment variable `CI_ENVIRONMENT_URL`,
or as pytest argument `--environment url <address>`.
To test locally setup in .env::
CI_ENVIRONMENT_URL="http://localhost:5000/"
"""
url = pytestconfig.getoption("CI_ENVIRONMENT_URL")
if not url:
return pytest.skip("Could not determine environment url. Please check that container contains variable CI_ENVIRONMENT_URL or define `--environment-url <address>`")
return url
def test_server_status(deployment_address: str, path="/server-info"):
"""
Fetch server status page and checks for Falsies.
"""
deployment_address = deployment_address.rstrip("/")
resp = requests.get(deployment_address + path, timeout=5)
assert resp.status_code == 200
assert resp.headers['Content-Type'] == 'application/json'
data = resp.json()
assert data['sentry_available'] is True, "App reporting that the sentry is not available"
assert data['database_connectable'] is True, "App reporting that the database is not available"
def test_404(deployment_address, path="/_404"):
"""
Anti-thesis: Check that the correct error code - 404 - is returned for missing page (:param:`path`)
"""
deployment_address = deployment_address.rstrip("/")
resp = requests.get(deployment_address + path, timeout=5)
assert resp.status_code == 404, f"Expected to receive 404 for path {path}"
# QED
def test_fronpage_loading(deployment_address):
"""
Fetch fronpage of our application, and check for known string.
"""
from test_app import IN_TITLE # pylint: disable=import-outside-toplevel
resp = requests.get(deployment_address, timeout=5)
assert resp.status_code == 200, f"Failed to fetch page {deployment_address}"
assert IN_TITLE.encode() in resp.content