A quel niveau ? (traduction générale du site par outil genre Google Traduction donc automatique ou alors faites par toi même ?)
Au niveau site j'ai un dossier i18n reprenant les fichiers de langue (fr.php, en.php etc) reprenant un tableau, ou des define ou ce que tu as envie du moment qu'ils aient tous les même noms de variable. La seule chose qui change c'est évidemment leur contenu.
Il ne reste plus qu'a inclure le fichier en fonction de la langue (de base tu en imposes une si il n'existe pas de variable lang dans l'URL, ou si celle ci ne correspond pas aux langues prévues).
Donc si l'URL est ?lang=fr -> c'est le fichier fr.php qui sera inclus
?lang=en -> c'est le fichier en.php
?lang=un_nom_qui_ne_veut_rien_dire -> fr.php (car valeur inattendue donc méfiance)
Au niveau de la base de données tu as 2 solutions: un champ par langue:
ID
CreationDate
Title_fr
Title_en
Title_es
Text_fr
Text_en
Text_es
...
Dans ce cas là tu vas récuperer donc le champ Text_<?php echo htmlspecialchars($_GET['lang']); ?>
Le seul soucis, si tu as 15 langues en plus il va te falloir toucher à la structure de ta base de données et rajouter donc les 15 champs par type de données (ici par exemple 15 Text_ et 15 Title_).
Et avouons le c'est assez chiant.
L'autre solution c'est de fonctionner en 2 tables:
news
news_i18n
La table news contiendra toute les données relative à la news et qui n'ont pas besoin d'être traduite (ici par exemple l'ID et la date), la table news_i18n contiendra les "versions" de cette news et elle contiendra toutes les données relative à la news et qui donc doivent être traduites (Title et Text dans ce cas ci), en plus de ça il y a 2 champs supplémentaires: TargetID qui est en fait l'ID de la table news (ba oui il faut bien lié la traduction à la news -> une news possède plusieurs traductions mais une traduction appartient à une seule news, relation 1 à n entre 2 tables donc) et puis un autre qui est donc LanguageID et qui détermine donc la langue.
En bref:
news
ID: 345
CreationDate: 2012-09-07
news_i18n
ID: 777
Title: Ma première news
Text: Texte de ma première news
TargetID: 345
LanguageID: fr
ID: 778
Title: My first news
Text: Text of my first news
TargetID: 345
LanguageID: en
Le gros avantage de cette technique: on peut rajouter 2000 langues si on veut sans avoir besoin de toucher à quoi que se soit au niveau de la base de données, seulement il y aura pour la plupart des tables donc 2 au lieu de 1, mais un seul champ même si il y a 10000 langues (alors que dans l'autre il faudrait 10000 x le nombre de champs à traduire). C'est la solution que j'utilise (et que deepblue utilise aussi je crois).