Δυστυχώς, η λύση του προβλήματος είναι σύνθετη καθώς το web είναι αποτέλεσμα μίξης προτύπων και διαδικασιών, κάθε μία εκ των οποίων απαιτεί διαφορετικές ρυθμίσεις. Για παράδειγμα, μπορεί η σελίδα μας να εμφανίζεται σωστά αλλά να στέλνει email σε άπταιστα ...Κινέζικα!
Αυτός ο οδηγός φιλοδοξεί να γίνει η απόλυτη αναφορά σχετικά με την ορθή χρήση και απεικόνιση των Ελληνικών στο web, καθώς συγκεντρώνει όλες τις επιμέρους διαδικασίες που συνεργούν σε μια ολοκληρωμένη εφαρμογή. Αν και το κείμενο υποθέτει τη χρήση της πλέον δημοφιλούς πλατφόρμας ανάπτυξης - της PHP - αυτό δεν θα πρέπει να αποθαρρύνει τους δημιουργούς στατικών σελίδων ή χρήστες άλλων τεχνολογιών, καθώς οι πληροφορίες που παρέχονται είναι πλήρους φάσματος!
Ελληνικά filenames
Ξεκινώ από αυτό, γιατί είναι το θέμα που θα μας απασχολήσει λιγότερο:
*** ΜΗ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ ΕΛΛΗΝΙΚΑ FILENAMES ***
Απλούστατο και κατανοητό!
Εν αρχή ήτο το character set
Η γλώσσα μας πέρασε από 40 κύματα μέχρι να βρει τη θέση της στο παγκόσμιο στερέωμα των προτύπων που αφορούν την κωδικοποίηση των συμβόλων γραφής. Πριν την έλευση και τη μαζική υιοθέτηση του UTF-8, η συνήθης (και ορθή) επιλογή ήταν το ISO-8859-7. Λέω "συνήθης" γιατί έχω δει sites κωδικοποιημένα σε Windows-1253 καθώς και σε ISO-8859-1 (!), όπου φυσικά τα πάντα μετατρέπονταν σε html entities!
Η απάντηση στο ερώτημα "ποιο από τα δύο sets να χρησιμοποιήσω;" είναι απλή: αν επιθυμείτε η εφαρμογή σας να δέχεται και να απεικονίζει περιεχόμενο σε οποιαδήποτε γλώσσα (πέραν της Ελληνικής και των Αγγλικών) ή/και να δέχεται και να απεικονίζει περιεχόμενο από άλλα sites/υπηρεσίες, τότε είναι προτιμότερο το UTF-8। Αν σκοπεύετε να λειτουργείτε αυστηρά κεκλεισμένων των θυρών και δεν σας ενδιαφέρει τίποτε άλλο από το να δείξετε συγκεκριμένα πράγματα με συγκεκριμένο τρόπο, τότε μπορείτε να το κάνετε και με ISO-8859-7.
Ας δούμε, όμως, πως οι κωδικοποιήσεις αυτές διαφοροποιούνται στην πράξη:
•Η θεμελιώδης διαφορά μεταξύ των δύο κωδικοποιήσεων είναι το μέγεθος (σε bytes) των χαρακτήρων. Η ISO-8859-7 είναι single-byte, συνεπώς αντιστοιχεί 1 byte σε κάθε χαρακτήρα. Η UTF-8 είναι multi-byte, αντιστοιχούν από 1 έως 6* bytes σε κάθε χαρακτήρα, ανάλογα το set. Στο ελληνικό αλφάβητο (ευτυχώς) αντιστοιχούν 2 bytes ανά χαρακτήρα.
*Θεωρητικό μέγιστο. Στην πράξη ισχύει το 4.
•Ως εκ τούτου, τα UTF-8 ελληνικά κείμενα χρειάζονται περίπου διπλάσιο χώρο αποθήκευσης. Λέω "περίπου" καθώς το ASCII set (λατινικοί χαρακτήρες, ψηφία, σημεία στίξης, κοινά σύμβολα) εξακολουθεί να καταλαμβάνει 1 byte. Αυτός άλλωστε ήταν και ο λόγος της ευρείας αποδοχής του UTF-8: η πλήρης συμβατότητα με τα υπάρχοντα αναρίθμητα ASCII κείμενα και source codes.
•Η PHP, και συγκεκριμένα οι συναρτήσεις που έχουν να κάνουν με το χειρισμό των strings, είναι single-byte. Για την ακρίβεια, είναι binary με την έννοια ότι δεν ασχολούνται καν με χαρακτήρες. Αυτό αναμένεται να αλλάξει στην επερχόμενη έκδοση 6, η οποία θα υποστηρίζει το UTF-8 εγγενώς. Μέχρι τότε, συναρτήσεις όπως η strlen(), substr(), parse_str(), κλπ, θέλουν προσοχή ή/και αντικατάσταση με τις αντίστοιχες multi-byte.
•Αν η σελίδα σας είναι σε ISO-8859-7 και επιθυμείτε να την ενημερώσετε με κείμενα που γράφετε στο PC σας, θυμηθείτε πως τα Windows χρησιμοποιούν παρόμοια κωδικοποίηση (1253), και όχι ακριβώς την ίδια. Η πιο χαρακτηριστική διαφορά είναι η διαφορετική θέση του Ά (άλφα κεφαλαίο τονούμενο). Ανάλογα με τον τρόπο που τα μεταφέρετε, μπορεί να έχετε πρόβλημα. Φυσικά, αυτό μπορεί να συμβεί και στην περίπτωση του UTF-8, εκεί όμως οποιοδήποτε σφάλμα είναι άμεσα εμφανές.
•Σήμερα, είναι πιο εύκολο να βρείτε Unicode Ελληνική γραμματοσειρά παρά ANSI. Αυτές, άρχισαν να εξαφανίζονται με την έλευση των XP.
•Ο κόσμος του web δικτυώνεται ολοένα και περισσότερο, μέσω διαδικασιών syndication (RSS), δημοσίων APIs, restfull υπηρεσιών και mashup. Η κοινή "γλώσσα" όλων αυτών, η esperanto του web τρόπος ειπείν, είναι η UTF-8. Η κωδικοποίηση αυτή σας παρέχει τη δυνατότητα ανταλλαγής δεδομένων με οποιοδήποτε άλλο site ή υπηρεσία, σε οποιαδήποτε γλώσσα, χωρίς την ανάγκη περίπλοκων - και ενίοτε αδύνατων - μετατροπών.
Για μένα, δεν τίθεται θέμα επιλογής. Υποστηρίζω ένθερμα το UTF-8, γιατί θέλω οι εφαρμογές μου να είναι "international". Να παίζουν οπουδήποτε, να δέχονται κείμενα από παντού. Να κάνω τα mashup μου χωρίς να με απασχολεί αν ο τίτλος του youtube clip - για παράδειγμα - είναι στα Γαλλικά, ή μιας ταινίας από το IMDB στα Ισπανικά. Να ανταλλάσσω feeds και πάσης φύσεως xml χωρίς μετατροπές. Προφανώς, αυτή είναι η κωδικοποίηση που θα υιοθετήσω και στη συνέχεια του οδηγού. Φυσικά, είστε ελεύθεροι να διαφωνήσετε. Στις περισσότερες περιπτώσεις, το μόνο που χρειάζεται είναι μια απλή αντικατάσταση. Αν χρειάζεται διαφορετική αντιμετώπιση, να είστε σίγουροι πως θα την αναφέρω. Συνεπώς, αν δεν λέω τίποτα, όπου βλέπετε UTF-8 εσείς θα βάζετε ISO-8859-7. Διαφορετικά, δώστε προσοχή στο κείμενο!
Τα εργαλεία κάνουν το μάστορα
Είναι αυτονόητο πως το πρώτο την τάξη εργαλείο σας, είναι ο editor. Συνηθίζουμε να τον λέμε ascii, text ή code editor. Υπάρχουν πολλοί, για κάθε γούστο: σκέτοι ή με καλούδια, δωρεάν ή επί πληρωμή. Το ελάχιστο ζητούμενο είναι, φυσικά, η υποστήριξη UTF-8 προκειμένου να σώζουμε σωστά τα αρχεία που περιέχουν Ελληνικές συμβολοσειρές.
Ένας τέτοιος editor, με την υποστήριξη που ζητάμε, έρχεται προεγκατεστημένος με τα Windows. Αναφέρομαι στο περίφημο ανά τους αιώνες Notepad, δεινόσαυρο που ζει μέχρι τις μέρες μας. Με σπαρτιάτικο εξοπλισμό, το Notepad φαντάζει και είναι η φυσική επιλογή των νεοφώτιστων. Ένα πράγμα έχω να σας πω γι αυτό:
*** ΜΗ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ ΤΟ NOTEPAD ΤΩΝ WINDOWS ***
Δεν μπορείτε να φανταστείτε πόσα topics έχουν ανοίξει, πόσα μηνύματα έχουν γραφτεί και πόσες ώρες έχουν χαθεί εξαιτίας του... Αν πω χιλιάδες, θα είμαι συντηρητικός στις εκτιμήσεις μου! Ο λόγος της οικολογικής αυτής καταστροφής ακούει στο όνομα BOM και είναι 3 αόρατα bytes που εισάγονται - με το έτσι θέλω - στην αρχή κάθε αρχείου που σώζεται από το Notepad ως UTF-8. Τα bytes αυτά, αν και αόρατα στον άνθρωπο, είναι καθόλα ορατά στα προγράμματα Η/Υ και συγκεκριμένα την PHP και τους browsers. Και η μεν και οι δε, τους δέχονται - με δυσάρεστες όμως συνέπειες:
•Η μεν PHP τους θεωρεί ως έξοδο (συνήθως πρόωρη) με αποτέλεσμα πολύ συχνά να διαμαρτύρεται φωνάζοντας το περιβόητο και συχνά ακατανόητο "headers already sent", κάθε φορά που χρησιμοποιούμε έμμεσα ή άμεσα την εντολή header(). Η πιο διαδεδομένη έμμεση χρήση, είναι η session_start().
•Οι δε browsers (αν και όχι όλοι, ονόματα δεν λέμε) αγνοούν το
Στα πλαίσια αυτού του οδηγού δεν έχει νόημα να επεκταθώ περισσότερο, σχετικά με την επίδραση του BOM στην ψυχική σας υγεία. Προς το παρόν, αρκεί να ξέρετε πως είναι ένα κακό και ανεπιθύμητο πράγμα, γι αυτό:
*** ΜΗ ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ BOM ***
Και αφού το Notepad δεν δίνει την επιλογή, δεν έχετε άλλη λύση από το να μην το χρησιμοποιείτε। Μπορείτε, κάλλιστα, να το αντικαταστήσετε με πληθώρα εναλλακτικών editors, ένας εκ των οποίων είναι και το (δωρεάν) Notepad++. Όχι μόνο θα λύσετε το πρόβλημα του BOM, αλλά θα αυξήσετε την παραγωγικότητά σας κατακόρυφα μιας και το Notepad++ έρχεται εξοπλισμένο σαν αστακός!
Ξεκινήστε σε σωστή βάση
Τα θεμέλια μιας δυναμικής εφαρμογής είναι η βάση δεδομένων της. Εκεί σώζονται τα κείμενά μας και από εκεί ανασύρονται. Ο server που τη διαχειρίζεται (DBMS), αγνοεί τις προθέσεις μας. Υπακούει μόνο σε εντολές και ρυθμίσεις! Αν θέλουμε, λοιπόν, να μην έχουμε πρόβλημα μαζί του θα πρέπει να δηλώσουμε ευθύς εξαρχής το επιθυμητό character set. Η διαδικασία ποικίλει ανάλογα τη βάση. Θα περιγράψω τις ρυθμίσεις της MySQL, μιας και αυτή είναι η πλέον δημοφιλής επιλογή.
Η MySQL είναι τρομακτικά ευέλικτη όσον αφορά το θέμα των character sets και collations που χρησιμοποιεί. Η ευελιξία της αυτή, στην πράξη, δημιουργεί προβλήματα αφού - κατά κανόνα - όλοι οι "πρωτοετείς" την πατάνε! Να θυμίσω πως το character set χρησιμοποιείται στις μετατροπές ιδίων χαρακτήρων σε διαφορετικά sets (πχ ISO-8859-1 σε UTF-8) ενώ το collation χρησιμοποιείται στις μετατροπές (συγκρίσεις/ταξινομήσεις) διαφορετικών χαρακτήρων του ιδίου set (πχ UPPER, 'ABΓ'='αβγ', ORDER BY, κλπ). Όπως αντιλαμβάνεστε, σε ένα character set αντιστοιχούν περισσότερα του ενός collations, ενώ το αντίθετο δεν ισχύει: σε κάθε collation αντιστοιχεί ένα character set. Για το λόγο αυτό, το collation χρησιμοποιείται ως συντόμευση/αναφορά και των δύο.
Για την απροβλημάτιστη συνεργασία σας με τη MySQL χρειάζονται δύο απλοί κανόνες:
- Σωστό collation στη δημιουργία της βάσης και των πινάκων της (λογικό και ευνόητο)
- Σωστό collation στην επικοινωνία σας μαζί της (Ουπς! εδώ γίνεται το μπέρδεμα)
Το πρώτο πράγμα που κάνει κανείς είναι η δημιουργία database. Αυτό, παραδοσιακά, γίνεται μέσω του phpMyAdmin, de facto περιβάλλον διαχείρισης της MySQL. Στην αρχική του σελίδα υπάρχει ένα input με τον τίτλο "Create new database". Δίπλα του, ένα select επιλογής collation και στη συνέχεια το submit "Create". Από κάτω, ένα select για την επιλογή του "connection collation".
*** ΕΠΙΛΕΞΤΕ utf8_general_ci ΚΑΙ ΣΤΑ ΔΥΟ SELECTS ***
Το αντίστοιχο του ISO-8859-7, είναι το greek_general_ci.
Αυτό το στάδιο είναι τόσο σημαντικό όσο δεν φαντάζεστε. Η default επιλογή της MySQL είναι το latin1_swedish_ci, παντελώς ακατάλληλη για μας. Εάν η database υπάρχει ήδη, βεβαιωθείτε πως έχει το σωστό collation. Το βλέπετε στην καρτέλα "Structure" (δεξιά), όταν κλικάρετε στο όνομα της database (αριστερά). Αναγράφεται στην τελευταία γραμμή του πίνακα. Αν στη στήλη "Collation" δείτε οτιδήποτε άλλο από utf8_general_ci, θα παιδευτείτε αδίκως. Η δημιουργήστε την εξ' αρχής, ή πηγαίνετε στην καρτέλα "Operations" και αλλάξτε της collation.
Αφού σετάρουμε τη βάση με το σωστό collation, προχωράμε στο προγραμματιστικό της μέρος, ξεκινώντας με τη σύνδεση:
if (mysql_connect($server, $username, $password))
{
if
(mysql_select_db($database))
{
mysql_query("SET NAMES 'utf8'"); // use
'greek' for ISO-8859-7
}
else
{
; // handle selection error
}
}
else
{
; // handle connection error
}
Στο παραπάνω snipet κρύβεται το μυστικό... To "SET NAMES 'utf8'" είναι το πρώτο και απολύτως απαραίτητο query που πρέπει να εκτελούμε αμέσως μετά τη σύνδεση. Βλέπετε, το collation της βάσης και των πινάκων δεν είναι αρκετό. Πρέπει να ταιριάξουμε και τα collation της επικοινωνίας, των εντολών μας και των δεδομένων αποστολής και λήψης. Όλα αυτά σετάρει μονομιάς η "SET NAMES...".
Αν δημιουργούμε τους πίνακες προγραμματιστικά (το πιο λογικό και σύνηθες), φροντίζουμε να επαναλάβουμε για μια ακόμη φορά τι θέλουμε:
κώδικας:
CREATE TABLE MyTable (...) ENGINE=MyISAM CHARSET=DEFAULT;
Με το option "CHARSET=DEFAULT" δηλώνουμε πως επιθυμούμε τη χρήση του default set της βάσης, και όχι του default set της MySQL (latin1_swedish_ci).
Θα ήθελα να κλείσω αυτήν την ενότητα με 2 σημαντικές επισημάνσεις:
1. Προσοχή στη χρήση του CHAR ως column type. Το CHAR αντιστοιχεί σε byte, κάτι που όπως έγραψα στην αρχή δεν συνάδει με την ταυτότητα του UTF-8. Αν αυτό που εννοείτε είναι "χαρακτήρες" και όχι "bytes", τότε θα πρέπει να χρησιμοποιήσετε VARCHAR. Για να γίνω πιο σαφής, ας υποθέσουμε πως έχετε ένα πεδίο ονόματι "name" όπου καταχωρείτε το όνομα του χρήστη. Ας υποθέσουμε, επίσης, πως επιτρέπετε ονόματα σε οποιαδήποτε γλώσσα αρκεί να μην ξεπερνούν τους 8 χαρακτήρες. Αν το δηλώσετε ως CHAR(8), τότε το όνομα "Vaggelis" θα περάσει, ενώ το "Βαγγέλης" θα κοπεί! Γιατί; Γιατί χρειάζεται 16 bytes και όχι 8. Αν το δηλώσετε ως VARCHAR(8), δεν θα έχετε πρόβλημα.
2. Το επίθεμα _ci σημαίνει "case insensitive", δηλαδή χωρίς διάκριση πεζών-κεφαλαίων. Αν η εφαρμογή σας απαιτεί διαφορετική μεταχείριση, τότε θα χρειαστείτε διαφορετικό collation.
Αλτ! Τις ει;
Σε αυτό το σημείο έχουμε το script μας σωσμένο σωστά, τη βάση μας σεταρισμένη όπως πρέπει, η σύνδεσή μας άψογη, και είμαστε έτοιμοι να στείλουμε σελιδούλα στον browser. Ε, δεν θα πρέπει να πούμε και σε αυτόν τον ταλαίπωρο ποια γλώσσα μιλάμε; Τι είναι αυτό που του στέλνουμε;
Αυτό (πρέπει να) το κάνουμε σε δύο μέρη:
- στα response headers του server, και
- στην html
Για το πρώτο, χρησιμοποιούμε την εντολή header():
κώδικας:
header('Content-type: text/html; charset=UTF-8');
...πριν από οποιαδήποτε έξοδο.
Για το δεύτερο, φροντίζουμε ώστε η σελίδα μας να έχει την ακόλουθη γραμμή:
κώδικας:
...αμέσως μετά το !
Δράττομαι της ευκαιρίας να επισημάνω μία - σοβαρή κατ' εμέ - παρανόηση η οποία βρίσκεται διάχυτη στο διαδίκτυο. Παντού θα βρείτε τη 2η γραμμή (meta), μα πουθενά την 1η (server responce). Αν και στην πράξη λειτουργεί (όπως λειτουργούν και άλλα πράγματα που δεν θα έπρεπε), ουσιαστικά είναι ημιτελής αντιμετώπιση καθώς οι δύο παραπάνω γραμμές εξυπηρετούν διαφορετικά ...συμφέροντα.
Η πρώτη γραμμή αφορά ένα υποχρεωτικό από το πρωτόκολο πεδίο: το Content-type. Αν δεν το βάλετε εσείς στον κώδικά σας, θα το βάλει μόνη της η PHP. Με τη μόνη διαφορά ότι η PHP - μιας και δεν ξέρει τι στέλνετε - θα το βάλει μισό:
κώδικας:
header('Content-type: text/html');
...δηλαδή, θα λείπει το character set! Αυτό σημαίνει, πως στέλνετε ότι νά'ναι... το default του πρωτοκόλου, το οποίο κάνει override το default του browser, το οποίο γίνεται override από το χρήστη μέσω σχετικής ρύθμισης στο μενού, και το οποίο - τελικά - γίνεται override από το meta!
Το "meta http-equiv" σημαίνει "http-equivalent", δηλαδή "http ισοδύναμο"। Παίζει το ρόλο του server response header. Πότε; Μα φυσικά, όταν ΔΕΝ υπάρχει ο server. Όπως, για παράδειγμα, όταν φορτώνουμε τη σελίδα από το σκληρό μας δίσκο!
Δώσμου το mail σου να σου πω ποιος είμαι
Μετά από μια ...επιτυχημένη σελίδα, έρχεται η σειρά του email. Είναι το επόμενο βήμα που παίζει το ρόλο της παγίδας, καθώς τα emails - εξ ορισμού - μεταφέρουν μηνύματα σε US-ASCII και 7bit. Οτιδήποτε άλλο απαιτεί χρήση των λεγόμενων MIME headers.
Για να μη σας σκοτίζω με λεπτομέρειες, παραθέτω συνάρτηση ονόματι mailex(), την οποία μπορείτε να χρησιμοποιείτε στη θέση της mail(). Η μόνη διαφορά βρίσκεται στο πρόσθετο όρισμα $from που είναι το mail του αποστολέα, κι αυτό γιατί είναι απαραίτητο. Τα υπόλοιπα ορίσματα είναι κοινά:
function mailex($from, $to, $subject, $message, $headers='', $args='')
{
$subject = '=?UTF-8?B?'.base64_encode($subject).'?=';
$headers = "From: $from\r\n".
"MIME-Version: 1.0\r\n".
"Content-Type: text/html; charset=\"UTF-8\"\r\n".
"Content-Transfer-Encoding: 8bit\r\n".
trim($headers);
return mail($to, $subject, $message, $headers, $args);
}
Για να την δοκιμάσετε, καλέστε την ως εξής:
κώδικας:
mailex('from@mail.gr', 'to@mail.gr', 'Δοκιμαστικό mail!', 'Για να δούμε τι θα δούμε...');
Προσοχή: Στη θέση των $from/$to ορισμάτων, βάζετε υπαρκτά mail accounts!
Μια εικόνα χίλιες λέξεις;
Η δημιουργία δυναμικών εικόνων με ελληνικό κείμενο είναι το τρίτο κατά σειρά ερώτημα που τίθεται, μετά τις σελίδες και τα emails. Το λάθος που κατά κανόνα γίνεται είναι η χρήση της συνάρτησης imagestring(). Αυτή είναι παντελώς ακατάλληλη για τη δουλειά που τη θέλουμε. Υπάρχει, ευτυχώς, η κατάλληλη και ακούει στο όνομα imagettftext(). Σύμφωνα και με το manual (που θα πρέπει οπωσδήποτε να διαβάσετε), υποστηρίζει Unicode TrueType (*.ttf) fonts.
Παραθέτω ένα code snipet (βιβλιοθήκη GD) για να δείτε στην πράξη πως λειτουργεί:
κώδικας:
$img = imagecreatetruecolor(400, 48);
$fgc = imagecolorallocate($img, 255, 255, 255); // white
$bgc = imagecolorallocate($img, 0, 0, 0); // black
imagefill($img, 0, 0, $bgc);
//imagettftext($img, 32, 0, 8, 40, $fgc, 'DejaVuSans.ttf', iconv('ISO-8859-7', 'UTF-8', 'Δοκιμή Ελληνικών')); // ISO-8859-7
imagettftext($img, 32, 0, 8, 40, $fgc, 'DejaVuSans.ttf', 'Δοκιμή Ελληνικών'); // UTF-8
header('content-type: image/jpeg');
imagejpeg($img);
Κατ' αρχάς χρειαζόμαστε ένα font. Στο παράδειγμα, χρησιμοποιώ το (ελεύθερο δικαιωμάτων) DejaVuSans. Αφού το κάνετε download, το αποσυμπιέζετε στον κατάλογο που βρίσκετε το script σας. Στο σημείο αυτό θα ήθελα να εφιστήσω την προσοχή σας στο όρισμα $fontfile. Η συνάρτηση είναι πολύ περίεργη όσον αφορά το όνομα και δυστυχώς η συμπεριφορά της ποικίλει ανάλογα με την έκδοση της βιβλιοθήκης GD που χρησιμοποιείτε. Στη δική μου περίπτωση (έκδοση 2.0.34), η κατάληξη είναι απαραίτητη. Σε άλλες, δεν πρέπει να υπάρχει!
Το δεύτερο πράγμα που πρέπει να προσέξετε είναι το όρισμα $text. Εάν έχετε επιλέξει UTF-8, δεν χρειάζεται να κάνετε καμιά μετατροπή. Αν όμως έχετε επιλέξει ISO-8859-7, θα πρέπει να το μετατρέψετε σε UTF-8, όπως φαίνεται στο παράδειγμα.
Ανακεφαλαίωση
Για την απροβλημάτιστη χρήση των Ελληνικών, απαιτούνται οι εξής ενέργειες:
•Επιλογή ενός εκ των δύο αποδεκτών κωδικοποιήσεων UTF-8 ή ISO-8859-7, και χρήση αυτού (και μόνον αυτού) με θρησκευτική ευλάβεια οπουδήποτε υπάρχει ελληνικό κείμενο.
•Στην περίπτωση του UTF-8, χρησιμοποιείτε editor με την ανάλογη υποστήριξη (όχι το Notepad!) και σώζετε τα αρχεία σας με την αντίστοιχη επιλογή - χωρίς BOM. Στην περίπτωση του ISO-8859-7, σώζετε ως "plain text", πλην όμως οι χρήστες Windows θα έχουν πρόβλημα με το Ά (άλφα κεφαλαίο τονούμενο). Αν ο editor σας δίνει τη δυνατότητα να εργάζεστε και να σώνετε σε ISO-8859-7 (έναντι των Windows-1253), κάντε το.
•Δημιουργείτε τη βάση και τους πίνακες με το κατάλληλο collation: utf8_general_ci (UTF-8) ή greek_general_ci (ISO-8859-7). Το πρώτο query που εκτελείτε, αμέσως μετά τη σύνδεση - είναι το "SET NAMES 'utf8'" ή "SET NAMES 'greek'" αντιστοίχως.
•Στο markup σας (html) θα πρέπει να υπάρχει το αμέσως μετά το . Για να είστε τύπος και υπογραμμός, θα πρέπει πριν την οποιαδήποτε έξοδο από το script σας (echo, print, κλπ), να προηγηθεί η εντολή header('Content-type: text/html; charset=UTF-8'); (αντικαθιστάτε με ISO-8859-7, και στις δύο περιπτώσεις, εφόσον αυτό επιλέξατε)
•Για να στείλετε email, αντικαθιστάτε τη mail() με τη mailex() (βλέπε ανωτέρω).
•Για κείμενο σε εικόνες (μέσω της βιβλιοθήκης GD) θα χρειαστείτε ένα unicode truetype font και την imagettftext().
Σας εύχομαι happy coding, και μακρυά από τις ...κακοτοπιές!
Με την επιφύλαξη του δικαιώματος αντιγραφής
Νικόλαος Β. Κάσσος (aka "nbc")
Απο: http://www.freestuff.gr/forums/viewtopic.php?t=52609