Gå til innhold

Problemer med æøå / skandinaviske tegn? Klikk her!


Gjest Slettet-rXRozPkg

Anbefalte innlegg

Gjest Slettet-rXRozPkg

Etter å ha svart på en del tråder med ÆØÅ-problematikk og andre særskandinaviske tegn, så tenkte jeg det kunne vært en fordel å lage en tråd med generell informasjon om dette. Forslag, forbedringer og feilrettinger vil bli tatt med fortløpende.

 

Here goes:

 

Har du problemer med norske tegn, ÆØÅ, eller andre særskandinaviske tegn i ditt PHP-script eller din PHP-applikasjon?

 

- Vises dine norske, eller skandinaviske tegn som spørsmålstegn eller firkanter istedenfor ÆØÅ, så er antagentligvis problemet at dine data er i iso-8859-1-format, mens nettleseren prøver å vise fram dataene i utf-8-format.

- Vises dine norske, eller skandinaviske tegn som en kombinasjon av to tegn, f.eks ø istedenfor ø, så er antagentligvis problemet at dine data er i utf-8-format, mens nettleseren prøver å vise fram dataene i iso-8859-1-format.

 

Hvorfor prøver så nettleseren å vise fram i "feil" tegnsett?

 

1. Har du angitt tegnsett i HTML-headeren?

 

- Ja:

Sjekk om siden virker skikkelig hvis du overstyrer tegnsettet nettleseren bruker.

Dette kan gjøres i IE7, FireFox og Opera med letthet (klikk for større bilde):

 

Internet Explorer 7:

charenc_ie_lite.png

 

FireFox 1.5/2:

charenc_ff_lite.png

 

Opera 9:

charenc_opera_lite.png

 

Ser siden din pluttselig bra ut hvis du velger UTF-8 eller ISO-8859-1 manuelt her? Da kan du lese vidre under "Nei".

Ser siden fortsatt rar ut, gå vidre til punkt 2. Hvis du ikke finner svaret der, skriv en post i denne tråden.

 

- Nei / Vet ikke:

 

Sjekk kildekoden til din nettside. Noe tilsvarende dette skal ligge inne i <head> tag'en:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

eller:

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />

 

To eksempler på fulle headere i XHTML og HTML:

 

Full header i XHTML 1.0 Transitional:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Jeg skal vise deg ÆØÅ jeg!</title>
<link href="style.css" rel="stylesheet" type="text/css" media="all" />
</head>

 

Full header i HTML 4.01:

 

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Jeg skal vise deg ÆØÅ jeg!</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>

 

Har du fortsatt ikke funnet løsningen, les vidre på punkt 2:

 

2. Blander du statisk og dynamisk data?

 

Hvis f.eks. siden din består av artikler som blir hentet ut fra en database, og en meny som er statisk, så er svaret her ja.

Svarte du ja i punkt 1, så les hele punkt 2 for tips på hvordan du kan finne rett tegnsett for dine data.

 

- Ja:

 

Er du sikker på at begge kildene bruker samme tegnsett?

 

Statiske data, som HTML lagret rett i en PHP-fil, eller f.eks. en include()/require() er ofte laget i en teksteditor.

Når man lagrer filene, så er det også her viktig å tenke på tegnsett. Til og med Notepad lar deg velge tegnsett (ANSI og tre varianter av unicode, der UTF-8 er den mest brukbare).

(include()/require() kan selvsagt også brukes til dynamiske data)

 

Pass altså på å lagre statisk innhold i PHP-/tekstfiler med rett tegnsett i forhold til det som står nevnt i punkt 1. Støtter ikke din editor dette, så burde du seriøst vurdere å bytte.

 

- Nei:

 

Hvis svaret er nei, så er det meste av innholdet på siden hentet ut i fra en eller annen database.

 

Igjen er det viktigste å finne ut av hva slags tegnsett er det faktisk dataene har.

Bruker man MySQL 4.1 eller 5, så har man skikkelig støtte for tegnsett. Under viser jeg et eksempel på en MySQL-tabell, og hvordan man kan se hva slags tegnsett som blir brukt:

 

mysql> SHOW FULL COLUMNS FROM table; +---------+---------------+----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field   | Type          | Collation      | Null | Key | Default | Extra          | Privileges                      | Comment |
+---------+---------------+----------------+------+-----+---------+----------------+---------------------------------+---------+
| id      | int(11)       | NULL           | NO   | PRI | NULL    | auto_increment | select,insert,update,references |         |
| prefix  | varchar(20)   | utf8_danish_ci | NO   |     |         |                | select,insert,update,references |         |
| field   | varchar(255)  | utf8_danish_ci | NO   |     |         |                | select,insert,update,references |         |
+---------+---------------+----------------+------+-----+---------+----------------+---------------------------------+---------+

'utf8_danish_ci' er brukt her, som dekker det som trengs av norske spesialtegn. Man kan også bruke 'utf8_general_ci', men det kan få konsekvenser for sortering etter alfabetisk rekkefølge.

Tilsvarende for iso-8859-1 i MySQL-verdenen er 'latin1_danish_ci'

 

Bruker du phpMyAdmin, så kan du enkelt lage nye databaser, og endre tegnsett. Klikk for større bilder.

 

Ny database:

phpmyadmin_ny_db_lite.jpg

 

Eksisterende tabell, man kan stille inn tegnsett per kolonne.

phpmyadmin_eksisterende_db_lite.jpg

 

Her er et eksempel på hvordan du kan lage en ny database, og sette rett tegnsett med kommandolinjeklienten:

 

UTF-8:

CREATE DATABASE dbnavn CHARACTER SET utf8 COLLATE utf8_danish_ci;

ISO-8859-1:

CREATE DATABASE dbnavn CHARACTER SET latin1 COLLATE latin1_danish_ci;

(etter dette kommer tilganger/passord osv, men det har ikke noe med tegnsett å gjøre)

 

Har du allerede en eksisterende database med data, kan du bruke mysqldump, opprette databasen på nytt som over, og legge til 'SET NAMES utf8' eller 'SET NAMES latin1' helt i toppen (første linje) av dumpen. Søk også igjennom, og se at SET NAMES ikke forekommer mer enn helt i toppen.

 

Uansett om svaret er ja eller nei, så kan man alltids konvertere mellom to forskjellige tegnsett.

Konvertering fra ISO-8859-1 til UTF-8 eller omvendt kan gjøres med PHP-funksjonene utf8_encode() og utf8_decode().

 

Hvis du har mbstring-utvidelsen installert (sjekk med phpinfo()), så kan en variant av denne funksjonen brukes til å konvertere fra et tegnsett til et annet:

 

function convertCharacterEncoding($content) {
// Convert encoding from charset X to utf8 if needed.
 $characterEncoding = mb_detect_encoding($content, 'UTF-8, UTF-16, ISO-8859-1, ISO-8859-15, Windows-1252, ASCII');
 
switch ($characterEncoding) {
 case "UTF-8":
   // Do nothing
   break;	
 case "ISO-8859-1":
   $content = utf8_encode($content);    
   break;
 default:
   $content = mb_convert_encoding($content,"UTF-8",$characterEncoding);
   break;
}

return $content;

}

 

Er du usikker på hvilket tegnsett dataene dine har, så kan du også bruke mbstring til å lage en funksjon som dette:

 

function detectCharacterEncoding($string) {
 $characterEncoding = mb_detect_encoding($string, 'UTF-8, UTF-16, ISO-8859-1, ISO-8859-15, Windows-1252, ASCII');
 return $characterEncoding;
}

 

I begge funksjonene over har jeg tatt med et utvalg av vanlige tegnsett. I noen tilfeller kan utf-8 bli returnert hvis PHP ikke finner ut av tegnsettet (det ligger ikke i listen). For å legge til flere tegnsett, er det bare å ta en kikk på listen her (Supported Character Encodings), og legge til i funksjonene.

 

Har du ikke mbstring-utvidelsen, så kan det hende at iconv er tilgjengelig. Denne utvidelsen kan også konvertere mellom forskjellige tegnsett.

 

En siste mulighet er å bruke selve databasen til å bytte mellom tegnsett.

MySQL har muligheten til å sette tegnsettet data returneres med ved å bruke SET NAMES (nevnt tidligere) eller SET CHARACTER SET. Dette kan du lese mer om her.

 

Ninjatriks: Kjør mysql_query("SET NAMES 'utf8'"); eller mysqli_query("SET NAMES 'utf8'" ); rett etter du har koblet deg til databasen.

 

3. Jeg genererer filer, som f.eks. .xml eller .pdf med PHP og sender dette direkte til nettleseren, og har problemer med tegnsett.

 

Igjen så bør du finne ut av hva slags data det er du prøver å sende til nettleseren. Når du har funnet ut av dette, så må du angi det rette tegnsettet i headeren.

Dette gjøres på en annen måte enn i HTML, ved bruk av header().

 

Eksempler:

header("Content-Type: *mimetype*; charset=UTF-8");

eller

header("Content-Type: *mimetype*; charset=ISO-8859-1");

 

*mimetype* skal selvsagt byttes ut med mimetypen du skal sende.

 

Siden header() også kan brukes til å sette tegnsett på vanlige HTML/XHTML-dokumenter, må man passe på at man ikke lager en (mulig) konflikt med det som står i <head>-taggen i dokumentet!

For å se hva slags HTTP-headere som sendes til og fra nettleseren, kan du bruke Live HTTP headers-utvidelsen til FireFox. Under er et screenshot av denne utvidelsen etter et besøk på en tilfeldig artikkel fra HW.no (klikk for større bilde):

 

headers_lite.png

Jeg har markert to viktige ting med røde piler. Pil 1 viser hva slags tegnsett som nettleseren sier den søtter til webserveren. Pil 2 viser hva slags tegnsett som blir brukt på det som webserveren sender tilbake til nettleseren.

 

Andre grunner til at dine data blir vist med feil tegnsett kan være:

 

PHP:

 

I konfigurasjonsfila til PHP (php.ini), kan man sette standard tegnsett og standard mimetype.

Som standard er dette ikke tegnsett skrudd på, men hvis du sitter på en delt webhost, så kan det jo være at de som drifter serveren har gjort det.

Det man skal se etter er default_charset = "iso-8859-1".

Har du ikke tilgang til php.ini, så kan man også finne denne informasjonen ved hjelp av phpinfo().

Det kan hende at man kan bruke ini_set() til å overstyre verdien, alt ettersom hvordan PHP er konfigurert.

 

 

Webserveren:

 

I apache2 og apache 1.3, kan man også sette standard tegnsett.

Se etter AddDefaultCharset UTF-8 (eller tilsvarende) i /etc/apache2/conf.d/charset og/eller httpd.conf (eller hvor nå enn du har lagt inn konfigurasjonsfilene).

Står det AddDefaultCharset On tilsvarer dette iso-8859-1, alle andre verdier blir tolket som det faktiske tegnsettet du ønsker å bruke.

Man fjerner enkelt standaardtegnsettet ved å slette linja, eller kommentere den ut med et #-tegn.

Apache må så startes på nytt.

Har du ikke tilgang til å konfigurere apache, så kan du bruke .htaccess til det samme.

 

Bruker du IIS, kan du ta en kikk her.

 

 

Annet:

 

Hva er egentlig forskjellen på UTF-8, ISO-8859-x, ASCII og andre tegnsett? Litt teori bak praksisen over:

*kommer snart*

 

Oversikt over de vanligste tegnsettene, og hva de blir kalt i forskjellige sammenhenger:

 

HTML/XHTML/XML :

UTF-8

ISO-8859-1

US-ASCII

WINDOWS-1252

 

PHP:

UTF-8

ISO-8859-1

ASCII

CP1252

 

MySQL:

utf8

latin1

ascii

latin1

 

PostgreSQL

UTF8

LATIN1

SQL_ASCII

WIN1252

 

Hovedpoenget for å finne ut av ÆØÅ-problemer er kort oppsummert:

1. Finn ut hva slags tegnsett dine data har.

2. Konverter dataene eller angi rett tegnsett i det som sendes til nettleseren.

Har du muligheten til å velge, bruk UTF-8!

 

 

Til slutt, lenker og informasjon du burde ta en titt på:

 

Vanlige tegnsett du kommer til å støte på:

ISO-8859-1 http://en.wikipedia.org/wiki/ISO/IEC_8859-1

ISO-8859-15 http://en.wikipedia.org/wiki/ISO/IEC_8859-15

UTF-8 http://en.wikipedia.org/wiki/UTF-8

Windows-1252 (CP1252) http://en.wikipedia.org/wiki/Windows-1252

ANSI http://en.wikipedia.org/wiki/Windows_code_page

ASCII http://en.wikipedia.org/wiki/Ascii

 

Kjekke lenker:

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

Sorting it all out

 

http://no.php.net/mbstring

http://no.php.net/manual/en/function.utf8-encode.php

http://no.php.net/manual/en/function.utf8-decode.php

http://no.php.net/manual/en/function.mb-detect-encoding.php

http://no.php.net/manual/en/function.mb-convert-encoding.php

http://no.php.net/iconv/

 

http://en.wikipedia.org/wiki/Collation

http://en.wikipedia.org/wiki/Character_sets

http://en.wikipedia.org/wiki/Character_encoding

http://en.wikipedia.org/wiki/Multipurpose_...Mail_Extensions

 

http://dev.mysql.com/doc/refman/5.0/en/charset.html

http://dev.mysql.com/doc/refman/5.0/en/charset-syntax.html

http://dev.mysql.com/doc/refman/5.0/en/mysqldump.html

 

http://www.utf-8.com/

http://www.iana.org/assignments/media-types/ (MIME-types)

http://www.unicode.org/

 

Stikkord (for søkefunksjonen):

Collation

Collate

Tegnsett

Character encoding

Character set

Endret av Slettet-rXRozPkg
Lenke til kommentar
Videoannonse
Annonse
Gjest Slettet-rXRozPkg

Oppdateringer:

 

10.02.2009:

- La til et ninjatriks; mysql_query("SET NAMES 'utf8'") siden dette har blitt diskutert en del ganger siden siste oppdatering.

 

07.05.2007:

- La til "Andre grunner til at dine data blir vist med feil tegnsett kan være", men informasjon om php.ini og /etc/apache2/conf.d/charset, sistnevnte etter tips fra marsipankake og -morten.

 

13.03.2007:

- La til mer informasjon om header() og bruk av Live HTTP headers etter tips fra -morten.

- La til kort oversikt over hva noen av de forskjellige tegnsettene blir kalt i HTML, PHP, MySQL og PostgreSQL.

Endret av Slettet-rXRozPkg
Lenke til kommentar

Veldig bra! Tenkte faktisk det samme i går kveld, og vurderte å skrive noe lignende. Men du kom meg i forkjøpet ;)

 

Andre ting du bør ha med:

Litt mer om at HTTP-headeren også sender tegnsett, og at den kan endres både med .htaccess, httpd.conf og header().

Det bør også nevnes at HTTP-headeren og HTML-headeren godt kan si motsatt tegnsett, og da blir det krøll.

For å se på HTTP-headeren kan man bruke denne extensionen til firefox: http://livehttpheaders.mozdev.org/

 

I tillegg kan det jo nevnes at alle nettleserene har et valg for å overstyre hvilket tegnsett siden skal tolkes som (Vis-> Koding i IE). Det kan jo være en kjapp måte å finne ut hva som blir riktig på.

Lenke til kommentar
Gjest Slettet-rXRozPkg

Da har jeg tatt med forslagene til -morten, og gjort noen andre mindre oppdateringer.

 

Jeg fant forøvrig en typisk ÆØÅ-feil på HW.no nå nettopp:

 

typisk_feil_hw_lite.png

Endret av Slettet-rXRozPkg
Lenke til kommentar

Jeg var en av de som spurte om hjelp. Her er hvordan jeg løste problemet.

 

Bruker ubuntu linux. Har installert apache og php5 lokalt.

 

Redigerte /etc/apache2/conf.d/charset

 

Byttet ut UTF-8 med ISO-8859-1

 

Takk!

Endret av marsipankake
Lenke til kommentar
  • 1 måned senere...

jeg må nesten si meg enig med crowly her...

 

æøå er tegns som lager krøll, og om sjansen er til stede for at brukeren ikke alltid har en browser med vår iso så er også sjansen til stede for at det kan bli krøll...

 

Utgangspunk, ikke bruk æøå, men html kodene å ...

 

Merk at du er ikke befridd for problemer like vel!

Hvis brukeren sender iso-x koder i f.eks. et søkefelt så gir dette problemer på utf lagring, så konverter her.

 

Men, utganspunket burde være å hoppe over æøå.

Lenke til kommentar
Gjest Slettet-rXRozPkg

Jeg kan vel legge til en "When all else fails"-seksjon, som beskriver litt bruk av htmlentitites.

Lenke til kommentar

En ting som jeg har hatt litt problemer med, er at enkelte editorer bruker UTF-8 med BOM, ("Byte Order Mark", om jeg ikke tar helt feil.) som gir deg en "Headers already sent"-feil. Før jeg fant ut av dette brukte jeg ISO i stedet, med de problemer det medførte.

Lenke til kommentar
  • 2 uker senere...

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...