I React-applikasjoner spiller tilstand (state) en avgjørende rolle, da det representerer den dynamiske aspekten av applikasjonen. Når tilstanden endres, reagerer komponentene på disse endringene, og det er dette som driver UI-oppdateringene. Uten tilstand vil applikasjonen ikke være noe mer enn en statisk HTML-mal. Vanligvis skjer tilstandsoppdateringer raskt, og tiden som kreves for at endringene skal gjenspeiles på skjermen er nesten ikke merkbar for brukeren. Likevel kan komplekse tilstandsoppdateringer føre til merkbare forsinkelser, og dette er noe utviklere må være bevisste på for å sikre en jevn og effektiv brukeropplevelse.
Et av de største problemene som kan oppstå ved tilstandsoppdateringer er overdreven re-rendering. Når flere tilstandsoppdateringer skjer raskt etter hverandre, kan dette føre til unødvendige renderinger av komponentene, noe som kan redusere applikasjonens ytelse. React 18 har introdusert noen effektive teknikker for å håndtere dette problemet.
Batching av tilstandsoppdateringer
En av hovedstrategiene som React bruker for å forbedre ytelsen er batching, eller gruppering, av tilstandsoppdateringer. Når flere tilstandsoppdateringer skjer samtidig, kan React gruppere disse endringene og bare utføre én re-rendering, i stedet for å gjenta prosessen for hver enkelt oppdatering. Dette kan drastisk redusere mengden arbeid som nettleseren må gjøre, og dermed forbedre applikasjonens responstid og ytelse.
For eksempel, anta at du har en komponent som håndterer en "name"-tilstand, og du endrer denne tilstanden flere ganger på rad – for eksempel fra "Adam" til "Ashley", deretter til "Andrew", og så videre. Uten batching, ville React ha rendert komponenten på nytt etter hver eneste endring. I dette scenariet ville den slutte opp med å rendere komponenten fem ganger før tilstanden til slutt returnerte til den opprinnelige verdien. Denne unødvendige re-renderingen kan føre til betydelig ytelsestap, spesielt i komplekse applikasjoner.
Endringer i React 18
I React 18 har håndtering av batching blitt forbedret. Tidligere, i React 17, ble automatisk batching kun utført innenfor event-håndteringsfunksjoner, som for eksempel når en bruker klikket på en knapp som utløste flere tilstandsoppdateringer. Men hvis en tilstandsoppdatering ble utført etter et asynkront kall, som for eksempel en datahenting fra en API, ble ikke oppdateringene automatisk gruppert, og flere re-renders kunne forekomme.
Med React 18 har denne begrensningen blitt fjernet, og batching skjer nå automatisk selv i asynkrone scenarioer. Dette gjør at React kan håndtere mange tilstandsoppdateringer effektivt, selv når de ikke skjer direkte i event-handlerne, men i for eksempel asynkrone tilbakekallingsfunksjoner.
Eksempel: Batching i praksis
La oss se på et konkret eksempel. Anta at vi har en knapp som, når den trykkes, utfører 100 tilstandsoppdateringer asynkront ved hjelp av setTimeout(). I React 17, uten automatisk batching, vil hver oppdatering føre til en re-render, og dermed vil applikasjonen måtte håndtere 100 separate re-renders. Dette kan føre til betydelige ytelsesproblemer. Med React 18, derimot, vil bare den siste oppdateringen føre til en re-render, og dette vil dramatisk forbedre ytelsen.
Prioritering av tilstandsoppdateringer
Et annet viktig aspekt ved ytelsesoptimalisering i React er prioritering av tilstandsoppdateringer. Når flere tilstandsoppdateringer skjer på en gang, kan det være nødvendig å sørge for at de viktigste oppdateringene skjer først. Dette er spesielt viktig i interaktive applikasjoner, der enkelte UI-oppdateringer, som endring av tekstinnhold eller synlige elementer, har større betydning for brukeropplevelsen enn andre. Ved å bruke prioritetsstyring kan man sikre at applikasjonen alltid viser de viktigste delene av grensesnittet først, og unngår at mindre viktige oppdateringer blokkerer viktige prosesser.
For eksempel kan en React-applikasjon som håndterer datahenting og visning av resultater prioritere visningen av de første resultatene, mens videre data kan lastes inn i bakgrunnen uten å forstyrre brukerens opplevelse. Dette kan oppnås ved å implementere prioriteringsstrategier som gjør at React først oppdaterer visuelle komponenter som direkte påvirker brukerinteraksjonen.
Asynkrone operasjoner og batching
I virkeligheten er mange applikasjoner avhengige av asynkrone operasjoner, som API-kall, tidsavbrudd (timeouts) eller intervaller. Disse operasjonene kan føre til at tilstandsoppdateringer skjer utenfor event-håndteringsfunksjoner, og tidligere var det en utfordring at disse ikke ble batchet automatisk. I React 18 er dette endret, og nå kan også asynkrone oppdateringer behandles effektivt ved hjelp av batching. Dette gjør at utviklere kan bygge mer responsive applikasjoner uten å måtte bekymre seg for at asynkrone operasjoner forårsaker unødvendige re-renders.
Viktige betraktninger
Det er viktig å forstå at selv om React 18 gjør mye for å optimere tilstandsoppdateringene, betyr det ikke at utviklere kan ignorere hvordan tilstandsoppdateringer håndteres. Effektiv tilstandshåndtering krever at man nøye vurderer hvordan komponentene er designet og hvordan tilstandslogikken er implementert. Å forstå Reacts tilstandshåndteringssystem og hvordan det fungerer sammen med andre mekanismer som batching og prioritering, er essensielt for å bygge applikasjoner som er både raskere og mer effektive.
Til tross for at React håndterer mye av ytelsesoptimaliseringen automatisk, er det fortsatt viktig at utvikleren tar ansvar for å strukturere koden på en måte som minimerer unødvendige re-renders. Dette kan for eksempel innebære å bruke useMemo eller React.memo for å hindre at komponenter re-rendres med mindre det er nødvendig, samt å sørge for at tilstandsoppdateringer er optimalisert for både ytelse og brukeropplevelse.
Hvordan hente data fra servere: Fra HTTP til moderne verktøy
I webutvikling har prosessen med å hente data fra servere gjennomgått en bemerkelsesverdig utvikling. På begynnelsen av 90-tallet, da webben var i sin barndom med HTTP 1.0, startet kommunikasjonen mellom server og klient. Websidene var statiske, og HTTP-forespørsler var enkle, der hele sider eller statiske ressurser ble hentet. Hver forespørsel førte til at en ny tilkobling måtte opprettes, og interaktivitet var minimal, med HTML-skjemaer som de viktigste interaksjonsformene. Sikkerheten var også grunnleggende, i tråd med webens tidlige stadier.
Mot slutten av 90-tallet og begynnelsen av 2000-tallet fikk weben en ny dimensjon med introduksjonen av Asynchronous JavaScript and XML (AJAX), som revolusjonerte interaktiviteten. Det var nå mulig for webapplikasjoner å kommunisere med serveren i bakgrunnen uten å måtte laste inn hele siden på nytt. Dette ble mulig gjennom XMLHttpRequest-objektet, som ga en mekanisme for asynkrone forespørsler.
Et eksempel på hvordan XMLHttpRequest kan brukes til å hente data:
Denne koden viser hvordan forespørsler ble gjort i AJAX-tiden, med callbacks som håndterte både suksess og feil. Denne metoden ble senere forbedret med HTTP 1.1, som introduserte vedvarende tilkoblinger og standardiserte RESTful API-er. RESTful API-er tillot utviklere å bruke standard HTTP-metoder og organisere serverressurser rundt identifiserbare objekter, noe som forbedret skalerbarhet og produktivitet.
Neste steg i utviklingen var introduksjonen av Fetch API, som bygget på en mer moderne og fleksibel måte å håndtere HTTP-forespørsler på. Fetch API er basert på promises, som gjør det enklere å håndtere asynkrone forespørsler på en mer lesbar og vedlikeholdbar måte.
Et eksempel på hvordan Fetch API kan brukes:
Fetch API er en forbedring sammenlignet med XMLHttpRequest, men for større applikasjoner er det ofte behov for ytterligere verktøy som Axios, GraphQL eller React Query for å håndtere datainnhenting mer effektivt.
Axios, for eksempel, er en moderne HTTP-klient som bruker promises og tilbyr flere praktiske funksjoner, som muligheten til å sette opp interceptors for å modifisere forespørsler før de sendes, eller responsene før de håndteres. Dette gjør Axios svært nyttig i komplekse applikasjoner der man må håndtere flere typer autentisering eller annen tilpasset logikk.
Et eksempel på hvordan Axios kan brukes til å hente data:
Selv om Fetch API og Axios kan være nok i mange situasjoner, har GraphQL åpnet en ny æra for datahenting. Med GraphQL kan klienter spesifisere nøyaktig hvilke data de trenger, noe som eliminerer både overfetching og underfetching av data. I stedet for å hente data fra flere endepunkter, kan en klient sende en enkelt forespørsel til serveren og få tilbake akkurat det de trenger.
Her er et eksempel på hvordan GraphQL kan brukes:
I dette eksemplet forespør vi kun de nødvendige feltene, som navn og e-post, og GraphQL-serveren vil svare med akkurat disse feltene, uavhengig av størrelsen på brukerobjektet.
En annen viktig utvikling innen serverkommunikasjon er WebSockets, som muliggjør sanntids, toveis kommunikasjon mellom klient og server. Dette er spesielt nyttig i applikasjoner som krever live oppdateringer, som chat-applikasjoner eller handelsplattformer.
Et grunnleggende eksempel på bruk av WebSockets:
WebSockets introduserte en modell der kommunikasjon kan skje i begge retninger, og gir et mer interaktivt alternativ til de tradisjonelle HTTP-forespørslene.
Den siste viktige teknologien som forenkler datahåndtering i React-applikasjoner, er React Query. Denne biblioteket håndterer både datainnhenting og tilstandshåndtering på en effektiv måte. Det abstrakterer bort kompleksiteten ved å håndtere bakgrunnsoppdateringer og cachere data, og gjør det mulig for utviklere å fokusere på selve applikasjonen.
Eksempel på bruk av React Query:
React Query gjør det enklere å håndtere data fra servere med minimal kode, samtidig som det tar seg av vanlige utfordringer som håndtering av feilmeldinger, lastestatus og caching.
Med fremveksten av disse verktøyene har webutvikling blitt langt mer strømlinjeformet og kraftig. Verktøy som Fetch, Axios, GraphQL, WebSockets, og React Query har ikke bare forenklet datainnhenting, men de har også hevet standardene for hvordan applikasjoner skal håndtere asynkrone operasjoner og dataflyt.
I tillegg til verktøyene som er beskrevet, er det viktig for utviklere å ha en grundig forståelse av hvordan disse teknologiene kan brukes effektivt i ulike scenarier, og hvordan de kan integreres med eksisterende applikasjoner for å forbedre ytelse, brukeropplevelse og vedlikeholdbarhet. Tenk på hvordan du strukturerer dataflyten i applikasjonen din, og vær oppmerksom på aspekter som sikkerhet, caching og optimalisering for å unngå potensielle flaskehalser i datainnhenting.
Hvordan hente data fra serveren: Forskjellige verktøy og teknikker
I dagens webutvikling er det å hente data fra servere en sentral funksjon, spesielt når man utvikler interaktive og dynamiske applikasjoner. En av de mest vanlige måtene å gjøre dette på er å bruke API-er (Application Programming Interfaces). I denne sammenhengen ser vi på forskjellige verktøy og teknikker for å hente data fra serveren, med hovedfokus på GitHub REST API, Fetch API, Axios, TanStack Query (tidligere kjent som React Query), og GraphQL.
En viktig del av ethvert moderne webprosjekt er å hente data fra eksterne kilder. I dette eksempelet bruker vi GitHub som et eksempel på en ekstern tjeneste der vi henter informasjon om brukere ved hjelp av GitHub REST API. Det første steget i prosessen er å forstå strukturen på dataene vi henter.
GitHub API og Fetch API
GitHub tilbyr en REST API som gir tilgang til informasjon om brukere, repositorier, gists, og mye mer. For eksempel kan man hente brukerdata som profilinformasjon, antall følgere, og offentlig tilgjengelige repositorier. Dette gjøres ved å sende en GET-forespørsel til GitHub API, og i vårt tilfelle kan vi bruke Fetch API for å hente dataene.
Her ser vi hvordan vi kan hente og vise informasjon om en GitHub-bruker:
I dette eksemplet rendrer vi brukerens avatar og noen nyttige detaljer, inkludert en lenke til GitHub-profilen deres. Ved å bruke fetch kan vi hente data fra serveren:
I dette tilfellet bruker vi useState for å lagre brukerdataene og en useEffect-hook for å hente dataene fra serveren når komponenten lastes inn. Dette er en enkel og effektiv tilnærming til å hente og vise data, men vi kan gjøre forbedringer i koden ved hjelp av mer avanserte verktøy som Axios og TanStack Query.
Axios
Axios er et populært bibliotek for å håndtere HTTP-forespørsler og gir flere funksjoner som ikke er tilgjengelige i Fetch API. En av de største fordelene med Axios er muligheten til å lage forhåndskonfigurerte instanser som gjør det lettere å håndtere flere forespørsler.
Først installerer vi Axios:
Deretter kan vi lage en API-klasse som håndterer alle serverforespørslene:
Denne klassen skaper en Axios-instans med en forhåndsdefinert base URL og interceptorer som loggfører forespørsler og svar. Deretter bruker vi denne klassen i komponenten vår for å hente GitHub-brukerinformasjon.
Axios gir flere fordeler, som automatisk håndtering av JSON-data og muligheten for å legge til globale konfigurasjoner som headers og autentisering. Dette gjør det til et kraftig verktøy for mer komplekse applikasjoner.
TanStack Query
TanStack Query (tidligere kjent som React Query) er et bibliotek som revolusjonerer hvordan vi håndterer serverforespørsler. Det gir innebygde funksjoner for caching, synkronisering, og håndtering av forespørselsstatus, som gjør det lettere å bygge robuste applikasjoner.
For å bruke TanStack Query, installerer vi biblioteket først:
Deretter setter vi opp en QueryClient som håndterer alle forespørsler:
Nå kan vi bruke useQuery-hooken for å hente data, som forenkler koden betydelig:
Med TanStack Query trenger vi ikke lenger å håndtere tilstander som loading eller error manuelt; biblioteket gjør alt dette for oss. Det gir også muligheten til å cache forespørsler, som reduserer antall serverforespørsler og forbedrer ytelsen.
GraphQL
GraphQL er en annen tilnærming til å hente data fra serveren, og det skiller seg betydelig fra REST API-er. I stedet for å gjøre flere separate forespørsler for ulike ressurser, kan du spesifisere eksakt hvilke data du trenger i én enkelt forespørsel. Dette gjør det enklere å optimalisere og redusere nettverksbelastningen.
GraphQL gir stor fleksibilitet ved at du kan spørre etter nøyaktig de dataene du trenger, i stedet for å få tilbake hele objekter med unødvendig informasjon. Denne teknikken er spesielt nyttig når du jobber med store og komplekse datastrukturer.
Hva er React Native, og hvorfor bør du vurdere det for utvikling av mobile apper?
React Native representerer en revolusjon innen utvikling av mobilapplikasjoner. Den lar utviklere bygge apper som kjører på både iOS og Android ved hjelp av JavaScript og React, uten å måtte skrive separate apper for hvert operativsystem. Denne løsningen har raskt blitt populær blant utviklere, ettersom den kombinerer de beste aspektene fra web- og mobilutvikling i én plattform. Men hva gjør React Native så attraktivt, og hvordan fungerer det?
For å forstå React Native, må vi først ta et skritt tilbake og se på hvordan tradisjonell webutvikling fungerer. Når du skriver en React-applikasjon for nettet, kommuniserer komponentene dine med Document Object Model (DOM), som er den representasjonen av nettsidens struktur. Dette skjer synkront, og React sørger for at endringer på nettsiden skjer raskt og effektivt. Men når du tar steget til mobilutvikling, blir situasjonen mer kompleks. Hver mobilplattform (Android og iOS) har sitt eget sett med native UI-elementer som utviklere må forholde seg til. På Android bruker utviklere Java eller Kotlin, mens iOS krever kunnskap om Objective-C eller Swift.
Her ligger kjernen i React Native. Ved å introdusere en ny «render target» – som i stedet for å bruke DOM, benytter native UI-widgets – gjør React Native det mulig for React-komponenter å kjøre på mobile operativsystemer. Denne løsningen bruker asynkrone API-kall til å kommunisere med de underliggende operativsystemene, og resultatet er en applikasjon som ser ut og føles som en ekte mobilapp, men som er utviklet med webteknologi.
En viktig forskjell mellom tradisjonelle mobilapper og webapper ligger i brukeropplevelsen. Webapplikasjoner er ofte begrenset i sine evner, spesielt når det gjelder å reprodusere native widgets. For eksempel kan et datovelger-element i en webapplikasjon se annerledes ut enn de native datovelgerne på en enhet, noe som skaper inkonsekvens og forvirring. Native apper derimot, bruker systemets egne komponenter, som gir et konsistent og intuitivt brukergrensesnitt.
React Native overkommer også utfordringene ved berøringsbasert interaksjon. Mobilenheter har et helt annet brukergrensesnitt enn desktop, der mus og tastatur er de primære inngangene. På mobil er det berøring og geststyring som gjelder. React Native er i stand til å håndtere denne dynamikken på en mer naturlig måte enn en vanlig webapp kan. For eksempel, der en webapplikasjon kanskje ikke vil kunne håndtere multitouch-gestene til en mobilbruker på en smidig måte, takler React Native disse med letthet.
I tillegg til å forenkle utviklingen for både iOS og Android, gjør React Native det mulig for utviklere å bygge apper som kjører på flere plattformer med minimal koding på tvers av systemene. Tidligere måtte utviklere lære flere programmeringsspråk og plattformer for å kunne utvikle apper for både Android og iOS. Med React Native kan utviklere i stedet fokusere på å lage én kodebase som fungerer på tvers av begge plattformene. I tillegg er verktøy som Expo og Tamagui UI-kit blitt utviklet for å gjøre dette enda lettere, og gir nå støtte for både web- og mobilutvikling med én og samme kodebase.
Det er imidlertid viktig å merke seg at til tross for at React Native muliggjør plattformspesifikke widgets, er Android og iOS fundamentalt forskjellige på flere nivåer, både i hvordan operativsystemene fungerer og hvordan de håndterer brukergrensesnitt. Mens ideen bak React Native er å «lære én gang, skrive hvor som helst», er det ofte tilfeller der du kan dra nytte av plattformspesifikke elementer for å skape en mer effektiv brukeropplevelse.
De forskjellige designfilosofiene mellom Android og iOS gjør at utviklere kan ha behov for å justere apper for å tilpasse dem til de spesifikke egenskapene ved hvert operativsystem. For eksempel, mens iOS fremmer et minimalistisk grensesnitt, kan Android være mer fleksibel med tanke på tilpasning. I slike tilfeller kan React Native hjelpe ved å bygge en applikasjon som føles helt naturlig på både Android og iOS, samtidig som utvikleren kan dele mesteparten av koden.
En annen interessant utvikling i React Native-økosystemet er muligheten for å utvikle apper som kan kjøre på web, Android og iOS ved å bruke verktøy som React Native for Web. Dette gir enda flere muligheter for å utvikle apper som fungerer på flere plattformer uten at du trenger å lære flere forskjellige teknologier eller skrive flere versjoner av applikasjonen.
Så hva er det viktigste å forstå om React Native? Først og fremst gjør det mulig å bygge applikasjoner som ser og føles ut som native apper, samtidig som du bruker teknologiene og ferdighetene du allerede har. For utviklere som er vant til React, gir det en smidig overgang til mobilutvikling uten behov for å lære nye programmeringsspråk eller plattformer. Det er også en kostnadseffektiv løsning, da det gir mulighet for å bygge apper for både Android og iOS med én kodebase. Samtidig bør man ikke glemme at, til tross for disse fordelene, finnes det fortsatt nyanserte forskjeller mellom plattformene som krever tilpasninger.
React Native er ikke en løsning som passer for alt, men for mange utviklingsprosjekter, spesielt de som ønsker å støtte både mobil og web, kan det være en utmerket løsning. Når plattformspesifikke utfordringer håndteres på riktig måte, kan React Native tilby en robust og effektiv utviklingsopplevelse for både iOS og Android-brukere.
Hvordan håndtere offline-funksjonalitet i React Native-applikasjoner
Når man utvikler applikasjoner for mobile enheter, er det avgjørende at applikasjonen fungerer godt også under forhold med dårlig eller ingen nettverksforbindelse. Brukere forventer at applikasjoner skal kunne håndtere slike situasjoner sømløst, uten at funksjonaliteten blir svekket eller ødelagt. Hvis applikasjonen din ikke kan håndtere problemer med nettverkstilkoblinger, vil brukerne trolig finne seg en annen app som fungerer bedre under slike forhold.
En viktig del av denne prosessen er å sørge for at applikasjonen kan lagre data lokalt på enheten, slik at når nettverket blir tilgjengelig igjen, kan appen synkronisere de lokal lagrede dataene med serveren. Dette er spesielt viktig for applikasjoner som trenger å fungere uavhengig av nettverksstatus, eller for applikasjoner som trenger å lagre data midlertidig mens brukeren er offline.
I denne delen vil vi utforske hvordan man kan oppdage nettverksstatusen i en React Native-applikasjon, hvordan man kan lagre data lokalt på enheten, og hvordan man kan synkronisere denne dataen når nettverket blir tilgjengelig igjen.
Oppdage nettverksstatus
Først og fremst er det viktig å kunne oppdage når nettverksstatusen endres. Dette kan gjøres ved hjelp av pakken @react-native-community/netinfo, som gir oss muligheten til å registrere når applikasjonen går fra å være tilkoblet til å være frakoblet, og omvendt. Dette gjør det mulig å informere brukeren om tilstanden på nettverket, slik at de kan tilpasse handlingene sine i appen.
En måte å implementere dette på er ved å bruke en enkel komponent som overvåker nettverksstatusen og viser en melding til brukeren. Koden for dette kan se slik ut:
Denne komponenten viser statusen til nettverket ved å bruke connectedMap, som inneholder forskjellige nettverkstyper og deres tilstand. Når nettverket endres, vil komponenten oppdatere seg selv og vise den aktuelle tilstanden, som for eksempel "Connected" eller "Disconnected". Dette gjør at brukeren får en visuell indikasjon på om de er tilkoblet nettet eller ikke.
Lagring av applikasjonsdata lokalt
Når applikasjonen er offline, kan det være nødvendig å lagre data lokalt på enheten, slik at de senere kan synkroniseres med serveren når nettverket er tilgjengelig igjen. React Native tilbyr et verktøy som heter AsyncStorage for å lagre små mengder data på enheten, som nøkkel/verdi-par. Dette er en enkel og effektiv måte å lagre data midlertidig på, uten å være avhengig av nettverksforbindelsen.
For å installere AsyncStorage, kan du bruke følgende kommando:
Når AsyncStorage er installert, kan du bruke det til å lagre, hente og slette data på enheten. Et eksempel på hvordan dette kan implementeres, er som følger:
I dette eksempelet gir vi brukeren muligheten til å legge inn et nøkkel/verdi-par, som lagres lokalt ved hjelp av AsyncStorage. Appen viser også en liste over lagrede elementer som kan lastes inn og slettes ved hjelp av knapper.
Synkronisering av data
En annen viktig funksjon er synkronisering av data når nettverket blir tilgjengelig igjen. Når applikasjonen er offline og lagrer data lokalt, er det nødvendig å sørge for at disse dataene blir sendt til serveren når en nettverkstilkobling er etablert. Dette kan gjøres ved å implementere en mekanisme som sjekker nettverksstatusen regelmessig, og synkroniserer lokal data med serveren når det er mulig.
I praksis kan dette gjøres ved å opprette en funksjon som prøver å sende data til serveren, og hvis det oppstår en feil på grunn av manglende nettverkstilkobling, kan dataene lagres lokalt for senere synkronisering. Når nettverket er tilbake, kan applikasjonen automatisk sende de lagrede dataene til serveren.
Det er viktig å merke seg at en god brukeropplevelse krever at synkroniseringen skjer uten at brukeren trenger å gjøre noe ekstra. For eksempel kan en animasjon eller en bakgrunnsprosess indikere at applikasjonen er i ferd med å synkronisere data, eller en enkel melding kan informere brukeren om at synkroniseringen er i gang.
Hvordan lage interessante grønne nyanser med pasteller: teknikker og tips
Hvordan stokkastisk geometri kan optimalisere rom-, luft- og bakkebaserte nettverk
Hvordan Fokker-Planck-Kolmogorov-likningen beskriver stokastiske prosesser og deres anvendelser

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский