Je me débat avec cette question depuis plusieurs mois maintenant, mais je n'ai pas été dans une situation où j'avais besoin d'explorer toutes les options possibles auparavant. En ce moment, j'ai l'impression qu'il est temps de connaître les possibilités et de créer ma propre préférence personnelle à utiliser dans mes projets à venir.
Laissez-moi d'abord esquisser la situation que je recherche
Je suis sur le point de mettre à niveau / redévelopper un système de gestion de contenu que j'utilise depuis un certain temps maintenant. Cependant, je pense que le multilinguisme est une grande amélioration de ce système. Avant, je n'utilisais aucun framework mais je vais utiliser Laraval4 pour le projet à venir. Laravel semble le meilleur choix d'une manière plus propre de coder PHP. Sidenote: Laraval4 should be no factor in your answer
. Je recherche des moyens de traduction généraux indépendants de la plateforme / du framework.
Que faut-il traduire
Comme le système que je recherche doit être aussi convivial que possible, la méthode de gestion de la traduction doit se trouver à l'intérieur du CMS. Il ne devrait pas être nécessaire de démarrer une connexion FTP pour modifier les fichiers de traduction ou tout autre modèle analysé html / php.
De plus, je recherche le moyen le plus simple de traduire plusieurs tables de base de données, peut-être sans avoir besoin de créer des tables supplémentaires.
Qu'est-ce que je suis venu avec moi-même
Comme j'ai déjà cherché, lu et essayé des choses moi-même. J'ai plusieurs options. Mais je n'ai toujours pas l'impression d'avoir atteint une méthode des meilleures pratiques pour ce que je recherche vraiment. Pour le moment, c'est ce que j'ai proposé, mais cette méthode a aussi des effets secondaires.
- Modèles PHP analysés : le système de modèles doit être analysé par PHP. De cette façon, je suis capable d'insérer les paramètres traduits dans le HTML sans avoir à ouvrir les modèles et à les modifier. En plus de cela, les modèles PHP analysés me donnent la possibilité d'avoir 1 modèle pour le site Web complet au lieu d'avoir un sous-dossier pour chaque langue (ce que j'avais auparavant). La méthode pour atteindre cette cible peut être Smarty, TemplatePower, Laravel's Blade ou tout autre analyseur de modèle. Comme je l'ai dit, cela devrait être indépendant de la solution écrite.
- Database Driven : peut-être que je n'ai pas besoin de le mentionner à nouveau. Mais la solution doit être basée sur une base de données. Le CMS est destiné à être orienté objet et MVC, je devrais donc penser à une structure de données logique pour les chaînes. Comme mes modèles seraient structurés: templates / contrôleur / view.php peut - être cette structure serait le plus logique:
Controller.View.parameter
. La table de base de données aurait ces champs un long avec unvalue
champ. Dans les modèles, nous pourrions utiliser une méthode de tri commeecho __('Controller.View.welcome', array('name', 'Joshua'))
et le paramètre contientWelcome, :name
. Ainsi le résultat étantWelcome, Joshua
. Cela semble être un bon moyen de le faire, car les paramètres tels que: nom sont faciles à comprendre par l'éditeur. - Faible charge de la base de données: Bien sûr, le système ci-dessus entraînerait des charges de base de données si ces chaînes sont chargées en déplacement. Par conséquent, j'aurais besoin d'un système de mise en cache qui restitue les fichiers de langue dès qu'ils sont modifiés / enregistrés dans l'environnement d'administration. Étant donné que les fichiers sont générés, une bonne disposition du système de fichiers est également nécessaire. Je suppose que nous pouvons utiliser
languages/en_EN/Controller/View.php
ou .ini, ce qui vous convient le mieux. Peut-être qu'un .ini est même analysé plus rapidement à la fin. Ce fichier doit contenir les données du fichierformat parameter=value;
. Je suppose que c'est la meilleure façon de le faire, car chaque vue rendue peut inclure son propre fichier de langue s'il existe. Les paramètres de langage doivent alors être chargés dans une vue spécifique et non dans une portée globale pour éviter que les paramètres ne s'écrasent les uns les autres. - Traduction de la table de base de données : c'est en fait ce qui m'inquiète le plus. Je cherche un moyen de créer des traductions de News / Pages / etc. aussi vite que possible. Avoir deux tables pour chaque module (par exemple
News
etNews_translations
) est une option, mais cela demande beaucoup de travail pour obtenir un bon système. L'une des choses que j'ai proposées est basée sur undata versioning
système que j'ai écrit: il y a un nom de table de base de donnéesTranslations
, cette table a une combinaison unique delanguage
,tablename
etprimarykey
. Par exemple: en_En / News / 1 (Se référant à la version anglaise de l'actualité avec ID = 1). Mais il y a 2 énormes inconvénients à cette méthode: tout d'abord, cette table a tendance à devenir assez longue avec beaucoup de données dans la base de données et deuxièmement, ce serait un sacré travail d'utiliser cette configuration pour rechercher la table. Par exemple, la recherche du slug SEO de l'élément serait une recherche en texte intégral, ce qui est assez stupide. Mais d'un autre côté: c'est un moyen rapide de créer très rapidement du contenu traduisible dans chaque table, mais je ne pense pas que ce pro surpasse les inconvénients. - Travail frontal: Le front-end nécessiterait également une réflexion. Bien sûr, nous stockerions les langues disponibles dans une base de données et (dés) activerions celles dont nous avons besoin. De cette façon, le script peut générer une liste déroulante pour sélectionner une langue et le back-end peut décider automatiquement quelles traductions peuvent être effectuées à l'aide du CMS. La langue choisie (par exemple en_EN) serait alors utilisée lors de l'obtention du fichier de langue pour une vue ou pour obtenir la bonne traduction pour un élément de contenu sur le site Web.
Alors, les voilà. Mes idées jusqu'à présent. Ils n'incluent même pas encore d'options de localisation pour les dates, etc., mais comme mon serveur prend en charge PHP5.3.2 +, la meilleure option est d'utiliser l'extension intl comme expliqué ici: http://devzone.zend.com/1500/internationalization-in -php-53 / - mais cela serait utile dans tout stade de développement ultérieur. Pour l'instant, le principal problème est de savoir comment disposer des meilleures pratiques de traduction du contenu d'un site Web.
Outre tout ce que j'ai expliqué ici, j'ai encore une autre chose que je n'ai pas encore décidé, cela ressemble à une question simple, mais en fait cela me donne des maux de tête:
Traduction d'URL? Devrions-nous faire cela ou pas? et de quelle manière?
Donc .. si j'ai cette url: http://www.domain.com/about-us
et l'anglais est ma langue par défaut. Cette URL doit-elle être traduite http://www.domain.com/over-ons
lorsque je choisis le néerlandais comme langue? Ou devrions-nous emprunter la voie facile et simplement changer le contenu de la page visible sur /about
. La dernière chose ne semble pas être une option valable car cela générerait plusieurs versions de la même URL, cette indexation du contenu échouera dans le bon sens.
Une autre option consiste à utiliser à la http://www.domain.com/nl/about-us
place. Cela génère au moins une URL unique pour chaque contenu. De plus, il serait plus facile d'aller dans une autre langue, par exemple, http://www.domain.com/en/about-us
et l'URL fournie est plus facile à comprendre pour les visiteurs Google et humains. En utilisant cette option, que faisons-nous avec les langues par défaut? La langue par défaut doit-elle supprimer la langue sélectionnée par défaut? Donc, rediriger http://www.domain.com/en/about-us
vers http://www.domain.com/about-us
... A mes yeux, c'est la meilleure solution, car lorsque le CMS est configuré pour une seule langue, il n'est pas nécessaire d'avoir cette identification de langue dans l'URL.
Et une troisième option est une combinaison des deux options: en utilisant le "language-identification-less" -URL ( http://www.domain.com/about-us
) pour la langue principale. Et utilisez une URL avec un slug SEO traduit pour les sous-langues: http://www.domain.com/nl/over-ons
&http://www.domain.com/de/uber-uns
J'espère que ma question vous fera craquer, ils ont craqué la mienne à coup sûr! Cela m'a aidé déjà à régler les choses comme une question ici. M'a donné la possibilité de revoir les méthodes que j'ai utilisées auparavant et l'idée que j'ai pour mon prochain CMS.
Je voudrais déjà vous remercier d'avoir pris le temps de lire ce tas de texte!
// Edit #1
:
J'ai oublié de mentionner: la fonction __ () est un alias pour traduire une chaîne donnée. Dans cette méthode, il devrait évidemment y avoir une sorte de méthode de secours où le texte par défaut est chargé lorsqu'il n'y a pas encore de traductions disponibles. Si la traduction est manquante, elle doit être insérée ou le fichier de traduction doit être régénéré.
la source
Réponses:
Prémisse du sujet
Il y a trois aspects distincts dans un site multilingue:
Bien qu'ils soient tous interconnectés de différentes manières, du point de vue CMS, ils sont gérés à l'aide de différents éléments d'interface utilisateur et stockés différemment. Vous semblez confiant dans votre mise en œuvre et dans votre compréhension des deux premiers. La question portait sur ce dernier aspect - "Traduction d'URL? Devrions-nous faire cela ou pas? Et de quelle manière?"
De quoi l'URL peut-elle être faite?
Une chose très importante est de ne pas avoir envie d' IDN . Préférez plutôt la translittération (aussi: transcription et romanisation). Bien qu'à première vue, l'IDN semble une option viable pour les URL internationales, il ne fonctionne pas comme annoncé pour deux raisons:
'ч'
ou'ž'
en'%D1%87'
et'%C5%BE'
J'ai en fait essayé d'approcher IDN il y a quelques années dans un projet basé sur Yii (cadre horrible, à mon humble avis). J'ai rencontré les deux problèmes mentionnés ci-dessus avant de gratter cette solution. Aussi, je soupçonne que cela pourrait être un vecteur d'attaque.
Options disponibles ... comme je les vois.
Fondamentalement, vous avez deux choix, qui pourraient être résumés comme suit:
http://site.tld/[:query]
: où[:query]
détermine à la fois le choix de la langue et du contenuhttp://site.tld/[:language]/[:query]
: où une[:language]
partie de l'URL définit le choix de la langue et[:query]
n'est utilisée que pour identifier le contenuLa requête est Α et Ω ..
Disons que vous choisissez
http://site.tld/[:query]
.Dans ce cas, vous avez une source principale de langue: le contenu du
[:query]
segment; et deux sources supplémentaires:$_COOKIE['lang']
pour ce navigateur particulierTout d'abord, vous devez faire correspondre la requête à l'un des modèles de routage définis (si votre choix est Laravel, lisez ici ). En cas de correspondance réussie du modèle, vous devez ensuite trouver la langue.
Vous auriez à parcourir tous les segments du modèle. Trouvez les traductions potentielles pour tous ces segments et déterminez la langue utilisée. Les deux sources supplémentaires (cookie et en-tête) seraient utilisées pour résoudre les conflits de routage, quand (et non "si") ils surviennent.
Prenons par exemple:
http://site.tld/blog/novinka
.C'est la translittération de
"блог, новинка"
, cela en anglais signifie approximativement"blog", "latest"
.Comme vous pouvez déjà le remarquer, en russe "блог" sera translittéré comme "blog". Ce qui signifie que pour la première partie de
[:query]
vous (dans le meilleur des cas ) se retrouvera avec une['en', 'ru']
liste de langues possibles. Ensuite, vous prenez le segment suivant - "novinka". Cela pourrait avoir une seule langue sur la liste des possibilités:['ru']
.Lorsque la liste contient un élément, vous avez trouvé la langue avec succès.
Mais si vous vous retrouvez avec 2 (exemple: russe et ukrainien) ou plus de possibilités .. ou 0 possibilités, selon le cas. Vous devrez utiliser un cookie et / ou un en-tête pour trouver la bonne option.
Et si tout le reste échoue, vous choisissez la langue par défaut du site.
Langue comme paramètre
L'alternative consiste à utiliser une URL, qui peut être définie comme
http://site.tld/[:language]/[:query]
. Dans ce cas, lors de la traduction d'une requête, vous n'avez pas besoin de deviner la langue, car à ce stade, vous savez déjà laquelle utiliser.Il existe également une source secondaire de langage: la valeur du cookie. Mais ici, il ne sert à rien de jouer avec l'en-tête Accept-Language, car vous n'avez pas affaire à une quantité inconnue de langues possibles en cas de "démarrage à froid" (lorsque l'utilisateur ouvre le site pour la première fois avec une requête personnalisée).
Au lieu de cela, vous avez 3 options simples et prioritaires:
[:language]
segment est défini, utilisez-le$_COOKIE['lang']
est défini, utilisez-leLorsque vous avez la langue, vous essayez simplement de traduire la requête, et si la traduction échoue, utilisez la «valeur par défaut» pour ce segment particulier (en fonction des résultats du routage).
N'est-ce pas là une troisième option?
Oui, techniquement , vous pouvez combiner les deux approches, mais cela compliquerait le processus et accueillir que les personnes qui veulent URL changer manuellement de
http://site.tld/en/news
àhttp://site.tld/de/news
et attendre la page de nouvelles du changement vers le Allemand.Mais même ce cas pourrait probablement être atténué en utilisant la valeur du cookie (qui contiendrait des informations sur le choix précédent de la langue), à mettre en œuvre avec moins de magie et d'espoir.
Quelle approche utiliser?
Comme vous l'avez peut-être déjà deviné, je recommanderais
http://site.tld/[:language]/[:query]
l'option la plus judicieuse.Aussi dans une situation de mots réels, vous auriez la 3e partie majeure dans l'URL: "titre". Comme au nom du produit dans la boutique en ligne ou titre d'article dans le site d'actualités.
Exemple:
http://site.tld/en/news/article/121415/EU-as-global-reserve-currency
Dans ce cas, ce
'/news/article/121415'
serait la requête et le'EU-as-global-reserve-currency'
titre. Uniquement à des fins de référencement.Cela peut-il être fait à Laravel?
Kinda, mais pas par défaut.
Je ne suis pas trop familier avec cela, mais d'après ce que j'ai vu, Laravel utilise un mécanisme de routage simple basé sur des modèles. Pour implémenter des URL multilingues, vous devrez probablement étendre la (les) classe (s) principale (s) , car le routage multilingue nécessite l'accès à différentes formes de stockage (base de données, cache et / ou fichiers de configuration).
Il est acheminé. Et maintenant?
En conséquence, vous vous retrouveriez avec deux informations précieuses: la langue actuelle et les segments traduits de la requête. Ces valeurs peuvent ensuite être utilisées pour envoyer à la ou aux classes qui produiront le résultat.
Fondamentalement, l'URL suivante:
http://site.tld/ru/blog/novinka
(ou la version sans'/ru'
) est transformée en quelque chose commeQue vous utilisez uniquement pour l'envoi:
.. ou une variation de celui-ci, en fonction de la mise en œuvre particulière.
la source
Implémentation d'i18n sans impact sur les performances en utilisant un pré-processeur comme suggéré par Thomas Bley
Au travail, nous avons récemment mis en œuvre i18n sur quelques-unes de nos propriétés, et l'une des choses avec lesquelles nous avons continué à lutter était le succès de la gestion de la traduction à la volée, puis j'ai découvert ce super article de blog de Thomas Bley. qui a inspiré la façon dont nous utilisons i18n pour gérer des charges de trafic importantes avec des problèmes de performances minimaux.
Au lieu d'appeler des fonctions pour chaque opération de traduction, ce qui, comme nous le savons en PHP, coûte cher, nous définissons nos fichiers de base avec des espaces réservés, puis utilisons un pré-processeur pour mettre en cache ces fichiers (nous stockons l'heure de modification des fichiers pour nous assurer que nous servons le dernier contenu à tout moment).
Les balises de traduction
Thomas utilise
{tr}
et des{/tr}
balises pour définir le début et la fin des traductions. En raison du fait que nous utilisons TWIG, nous ne voulons pas utiliser{
pour éviter toute confusion, nous utilisons donc[%tr%]
et à la[%/tr%]
place. En gros, cela ressemble à ceci:Notez que Thomas suggère d'utiliser l'anglais de base dans le fichier. Nous ne faisons pas cela parce que nous ne voulons pas avoir à modifier tous les fichiers de traduction si nous changeons la valeur en anglais.
Les fichiers INI
Ensuite, nous créons un fichier INI pour chaque langue, au format
placeholder = translated
:Il serait trivial de permettre à un utilisateur de les modifier à l'intérieur du CMS, il suffit d'obtenir les paires de clés par un
preg_split
on\n
ou=
et de rendre le CMS capable d'écrire dans les fichiers INI.Le composant pré-processeur
Essentiellement, Thomas suggère d'utiliser une fonction de «compilateur» juste à temps (même si, en vérité, c'est un préprocesseur) comme celle-ci pour prendre vos fichiers de traduction et créer des fichiers PHP statiques sur le disque. De cette façon, nous mettons essentiellement en cache nos fichiers traduits au lieu d'appeler une fonction de traduction pour chaque chaîne du fichier:
Remarque: je n'ai pas vérifié que le regex fonctionne, je ne l'ai pas copié à partir de notre serveur d'entreprise, mais vous pouvez voir comment l'opération fonctionne.
Comment l'appeler
Encore une fois, cet exemple est de Thomas Bley, pas de moi:
Nous stockons la langue dans un cookie (ou une variable de session si nous ne pouvons pas obtenir de cookie) puis la récupérons à chaque demande. Vous pouvez combiner cela avec un
$_GET
paramètre facultatif pour remplacer la langue, mais je ne suggère pas de sous-domaine par langue ou page par langue car cela rendra plus difficile de voir quelles pages sont populaires et réduira la valeur de l'entrée liens car vous les aurez à peine diffusés.Pourquoi utiliser cette méthode?
Nous aimons cette méthode de prétraitement pour trois raisons:
Obtenir le contenu de la base de données traduit
Nous ajoutons simplement une colonne pour le contenu de notre base de données appelée
language
, puis nous utilisons une méthode d'accesseur pour laLANG
constante que nous avons définie précédemment, donc nos appels SQL (en utilisant ZF1, malheureusement) ressemblent à ceci:Nos articles ont une clé primaire composée over
id
etlanguage
ainsi l'article54
peut exister dans toutes les langues. Notre valeur parLANG
défaut esten_US
si non spécifié.Traduction de slug d'URL
Je combinerais deux choses ici, l'une est une fonction dans votre bootstrap qui accepte un
$_GET
paramètre de langue et remplace la variable de cookie, et une autre est le routage qui accepte plusieurs slugs. Ensuite, vous pouvez faire quelque chose comme ça dans votre routage:Ceux-ci peuvent être stockés dans un fichier plat qui peut être facilement écrit à partir de votre panneau d'administration. JSON ou XML peuvent fournir une bonne structure pour les prendre en charge.
Remarques concernant quelques autres options
Traduction à la volée basée sur PHP
Je ne vois pas que ceux-ci offrent un avantage par rapport aux traductions prétraitées.
Traductions frontales
J'ai longtemps trouvé cela intéressant, mais il y a quelques mises en garde. Par exemple, vous devez mettre à la disposition de l'utilisateur la liste complète des phrases de votre site Web que vous prévoyez de traduire, cela peut être problématique s'il y a des zones du site que vous gardez cachées ou auxquelles vous ne leur avez pas autorisé l'accès.
Vous devriez également supposer que tous vos utilisateurs sont disposés et capables d'utiliser Javascript sur votre site, mais d'après mes statistiques, environ 2,5% de nos utilisateurs fonctionnent sans lui (ou utilisent Noscript pour empêcher nos sites de l'utiliser) .
Traductions basées sur une base de données
Les vitesses de connectivité de la base de données PHP n'ont rien d'extraordinaire, et cela ajoute à la surcharge déjà élevée de l'appel d'une fonction sur chaque phrase à traduire. Les problèmes de performances et d'évolutivité semblent accablants avec cette approche.
la source
Why?
: simple .. Je ne veux pas être dérangé par de petits changements de texte, les utilisateurs devraient pouvoir le faire eux-mêmes sans utiliser d'éditeur de code et / ou de programme ftp :).INI
fichiers avec une table de base de données 3 colonnes avecplaceholder
,replacement
,language
. Touche composée surplaceholder
etlanguage
. Ensuite, ayez un autre 2-col avectempfile
(chemin vers le modèle) etmodified
(DATETIME).Je vous suggère de ne pas inventer une roue et d'utiliser la liste des abréviations des langues gettext et ISO. Avez-vous vu comment i18n / l10n est implémenté dans des CMS ou des frameworks populaires?
En utilisant gettext, vous aurez un outil puissant où de nombreux cas sont déjà implémentés comme des formes plurielles de nombres. En anglais, vous n'avez que 2 options: singulier et pluriel. Mais en russe par exemple, il existe 3 formes et ce n'est pas aussi simple qu'en anglais.
De plus, de nombreux traducteurs ont déjà une expérience de travail avec gettext.
Jetez un œil à CakePHP ou Drupal . Les deux multilingues sont activés. CakePHP comme exemple de localisation d'interface et Drupal comme exemple de traduction de contenu.
Pour l10n, l'utilisation de la base de données n'est pas du tout le cas. Ce sera des tonnes sur les requêtes. L'approche standard est d'obtenir toutes les données l10n en mémoire à un stade précoce (ou lors du premier appel à la fonction i10n si vous préférez le chargement paresseux). Il peut lire à partir d'un fichier .po ou de la base de données toutes les données à la fois. Et que de simplement lire les chaînes demandées à partir du tableau.
Si vous avez besoin d'implémenter un outil en ligne pour traduire l'interface, vous pouvez avoir toutes ces données dans la base de données, tout en enregistrant toutes les données dans un fichier pour les utiliser. Pour réduire la quantité de données en mémoire, vous pouvez diviser tous vos messages / chaînes traduits en groupes et charger uniquement les groupes dont vous avez besoin si cela est possible.
Donc, vous avez tout à fait raison dans votre # 3. À une exception près: il s'agit généralement d'un gros fichier et non d'un fichier par contrôleur. Parce qu'il est préférable pour les performances d'ouvrir un fichier. Vous savez probablement que certaines applications Web très chargées compilent tout le code PHP dans un seul fichier pour éviter les opérations sur les fichiers lors de l'appel de include / require.
À propos des URL. Google suggère indirectement d'utiliser la traduction:
Je pense également que vous devez rediriger l'utilisateur vers le préfixe de langue par défaut, par exemple http://examlpe.com/about-us redirigera vers http://examlpe.com/en/about-us Mais si votre site n'utilise qu'une seule langue, vous n'ont pas du tout besoin de préfixes.
Consultez: http://www.audiomicro.com/trailer-hit-impact-psychodrama-sound-effects-836925 http://nl.audiomicro.com/aanhangwagen-hit-effect-psychodrama-geluidseffecten-836925 http: / /de.audiomicro.com/anhanger-hit-auswirkungen-psychodrama-sound-effekte-836925
La traduction du contenu est une tâche plus difficile. Je pense qu'il y aura des différences avec différents types de contenu, par exemple des articles, des éléments de menu, etc. Mais au n ° 4, vous êtes dans la bonne voie. Jetez un œil à Drupal pour avoir plus d'idées. Il a un schéma de base de données suffisamment clair et une interface suffisamment bonne pour la traduction. Comme vous créez un article et sélectionnez sa langue. Et que vous pourrez plus tard le traduire dans d'autres langues.
Je pense que ce n'est pas un problème avec les slugs d'URL. Vous pouvez simplement créer une table séparée pour les slugs et ce sera la bonne décision. En utilisant également les bons index, il n'est pas difficile d'interroger la table même avec une énorme quantité de données. Et ce n'était pas une recherche de texte intégral, mais une correspondance de chaîne si utilisera le type de données varchar pour slug et vous pouvez également avoir un index sur ce champ.
PS Désolé, mon anglais est loin d'être parfait.
la source
Cela dépend de la quantité de contenu de votre site Web. Au début, j'ai utilisé une base de données comme toutes les autres personnes ici, mais cela peut prendre du temps pour scénariser tout le fonctionnement d'une base de données. Je ne dis pas que c'est une méthode idéale et surtout si vous avez beaucoup de texte, mais si vous voulez le faire rapidement sans utiliser de base de données, cette méthode pourrait fonctionner, cependant, vous ne pouvez pas permettre aux utilisateurs de saisir des données qui seront utilisés comme fichiers de traduction. Mais si vous ajoutez les traductions vous-même, cela fonctionnera:
Disons que vous avez ce texte:
Vous pouvez saisir ceci dans une base de données avec des traductions, mais vous pouvez également le faire:
Maintenant, si votre site Web utilise un cookie, vous avez ceci par exemple:
Pour vous faciliter la tâche, transformons-le en un code facilement utilisable:
Si votre langue de cookie est le gallois et que vous disposez de ce morceau de code:
Le résultat sera:
Si vous avez besoin d'ajouter beaucoup de traductions pour votre site Web et qu'une base de données est trop consommatrice, l'utilisation d'un tableau peut être une solution idéale.
la source
lang.en.php
qui seront inclus et d'utiliser$lang['welcome']
ce qui est déclaré dans chaque fichier.Je vous suggère de ne pas vraiment dépendre de la base de données pour la traduction, cela pourrait être une tâche vraiment compliquée et pourrait être un problème extrême en cas de codage des données.
J'ai été confronté à un problème similaire il y a quelque temps et j'ai écrit la classe suivante pour résoudre mon problème
Objet: Locale \ Locale
Usage
Comment ça fonctionne
{a:1}
est remplacé par le 1er argument passé à la méthodeLocale::translate('key_name','arg1')
{a:2}
est remplacé par le 2ème argument passé à la méthodeLocale::translate('key_name','arg1','arg2')
Comment fonctionne la détection
geoip
est installé, il retournera le code du pays pargeoip_country_code_by_name
et si geoip n'est pas installé, le retour à l'en-HTTP_ACCEPT_LANGUAGE
têtela source
utf8_general_ci
classement est une manière appropriée de le faire.Juste une réponse secondaire: utilisez absolument des URL traduites avec un identifiant de langue devant elles: http://www.domain.com/nl/over-ons Les
solutions hybrides ont tendance à se compliquer, alors je m'en tiens simplement à cela. Pourquoi? Parce que l'URL est essentielle pour le référencement.
A propos de la traduction de base de données: le nombre de langues est-il plus ou moins fixe? Ou plutôt imprévisible et dynamique? S'il est corrigé, je voudrais simplement ajouter de nouvelles colonnes, sinon aller avec plusieurs tables.
Mais généralement, pourquoi ne pas utiliser Drupal? Je sais que tout le monde veut créer son propre CMS car c'est plus rapide, plus léger, etc. etc. Mais c'est vraiment une mauvaise idée!
la source
Je ne vais pas tenter d’affiner les réponses déjà données. Au lieu de cela, je vais vous parler de la façon dont mon propre framework PHP OOP gère les traductions.
En interne, mon framework utilise des codes comme en, fr, es, cn et ainsi de suite. Un tableau contient les langues prises en charge par le site Web: array ('en', 'fr', 'es', 'cn') Le code de langue est passé via $ _GET (lang = fr) et s'il n'est pas passé ou non valide, il est défini sur la première langue du tableau. Ainsi, à tout moment de l'exécution du programme et dès le début, la langue actuelle est connue.
Il est utile de comprendre le type de contenu qui doit être traduit dans une application typique:
1) messages d'erreur de classes (ou code de procédure) 2) messages non d'erreur de classes (ou code de procédure) 3) contenu de la page (généralement stocké dans une base de données) 4) chaînes à l'échelle du site (comme le nom du site Web) 5) script- chaînes spécifiques
Le premier type est simple à comprendre. Fondamentalement, nous parlons de messages comme "Impossible de se connecter à la base de données ...". Ces messages ne doivent être chargés que lorsqu'une erreur se produit. Ma classe de manager reçoit un appel des autres classes et en utilisant les informations passées en tant que paramètres, va simplement dans le dossier de classe pertinent et récupère le fichier d'erreur.
Le deuxième type de message d'erreur ressemble plus aux messages que vous recevez lorsque la validation d'un formulaire a mal tourné. ("Vous ne pouvez pas laisser ... vide" ou "Veuillez choisir un mot de passe de plus de 5 caractères"). Les chaînes doivent être chargées avant l'exécution de la classe, je sais ce que c'est
Pour le contenu réel de la page, j'utilise une table par langue, chaque table étant préfixée par le code de la langue. Donc en_content est la table avec le contenu en anglais, es_content est pour l'Espagne, cn_content pour la Chine et fr_content est le contenu français.
Le quatrième type de chaîne est pertinent sur l'ensemble de votre site Web. Ceci est chargé via un fichier de configuration nommé en utilisant le code de la langue, c'est-à-dire en_lang.php, es_lang.php et ainsi de suite. Dans le fichier de langue global, vous devrez charger les langues traduites telles que array ('Anglais', 'Chinois', 'Espagnol', 'Français') dans le fichier global anglais et array ('Anglais', 'Chinois', ' Espagnol ',' Francais ') dans le fichier français. Ainsi, lorsque vous remplissez une liste déroulante pour la sélection de la langue, elle est dans la bonne langue;)
Enfin, vous avez les chaînes spécifiques au script. Donc, si vous écrivez une application de cuisson, cela pourrait être "Votre four n'était pas assez chaud".
Dans mon cycle d'application, le fichier de langue global est chargé en premier. Vous y trouverez non seulement des chaînes globales (comme "Jack's Website") mais également des paramètres pour certaines classes. Fondamentalement, tout ce qui dépend de la langue ou de la culture. Certaines de ces chaînes contiennent des masques pour les dates (MMJJAAAA ou JJMMAAAAA) ou des codes de langue ISO. Dans le fichier de langue principal, j'inclus des chaînes pour les classes individuelles car il y en a si peu.
Le deuxième et dernier fichier de langue lu à partir du disque est le fichier de langage de script. lang_en_home_welcome.php est le fichier de langue pour le script home / welcome. Un script est défini par un mode (home) et une action (welcome). Chaque script a son propre dossier avec les fichiers de configuration et de langue.
Le script extrait le contenu de la base de données en nommant la table de contenu comme expliqué ci-dessus.
En cas de problème, le gestionnaire sait où obtenir le fichier d'erreur dépendant de la langue. Ce fichier n'est chargé qu'en cas d'erreur.
La conclusion est donc évidente. Réfléchissez aux problèmes de traduction avant de commencer à développer une application ou un framework. Vous avez également besoin d'un flux de travail de développement qui intègre des traductions. Avec mon framework, je développe l'ensemble du site en anglais puis je traduis tous les fichiers pertinents.
Juste un dernier mot sur la façon dont les chaînes de traduction sont implémentées. Mon framework a un seul global, le $ manager, qui exécute les services disponibles pour tout autre service. Ainsi, par exemple, le service de formulaire s'empare du service html et l'utilise pour écrire le html. L'un des services de mon système est le service de traduction. $ Translator-> set ($ service, $ code, $ string) définit une chaîne pour la langue courante. Le fichier de langue est une liste de telles déclarations. $ Translator-> get ($ service, $ code) récupère une chaîne de traduction. Le $ code peut être numérique comme 1 ou une chaîne comme 'no_connection'. Il ne peut y avoir de conflit entre les services car chacun a son propre espace de noms dans la zone de données du traducteur.
Je poste ceci ici dans l'espoir que cela épargnera à quelqu'un la tâche de réinventer la roue comme je devais le faire il y a quelques années.
la source
J'ai eu le même problème il y a quelque temps, avant de commencer à utiliser le framework Symfony .
Utilisez simplement une fonction __ () qui a des aramètres pageId (ou objectId, objectTable décrit dans # 2), la langue cible et un paramètre facultatif de la langue de secours (par défaut). La langue par défaut pourrait être définie dans une configuration globale afin d'avoir un moyen plus simple de la changer plus tard.
Pour stocker le contenu dans la base de données, j'ai utilisé la structure suivante: (pageId, langue, contenu, variables).
pageId serait un FK de votre page que vous souhaitez traduire. si vous avez d'autres objets, comme des actualités, des galeries ou autre, divisez-les simplement en 2 champs objectId, objectTable.
language - évidemment, il stockerait la chaîne de langue ISO EN_en, LT_lt, EN_us etc.
content - le texte que vous souhaitez traduire avec les caractères génériques pour le remplacement des variables. Exemple "Bonjour monsieur. %% name %%. Le solde de votre compte est de %% balance %%."
variables - les variables codées json. PHP fournit des fonctions pour les analyser rapidement. Exemple "nom: Laurynas, solde: 15,23".
vous avez également mentionné le champ de limaces. vous pouvez l'ajouter librement à ce tableau juste pour avoir un moyen rapide de le rechercher.
Vos appels à la base de données doivent être réduits au minimum avec la mise en cache des traductions. Il doit être stocké dans un tableau PHP, car c'est la structure la plus rapide en langage PHP. La manière dont vous réaliserez cette mise en cache dépend de vous. D'après mon expérience, vous devriez avoir un dossier pour chaque langue prise en charge et un tableau pour chaque pageId. Le cache doit être reconstruit après la mise à jour de la traduction. SEULE la matrice modifiée doit être régénérée.
je pense avoir répondu à cela dans # 2
votre idée est parfaitement logique. celui-ci est assez simple et je pense que cela ne vous posera aucun problème.
Les URL doivent être traduites à l'aide des slugs stockés dans la table de traduction.
Derniers mots
il est toujours bon de rechercher les meilleures pratiques, mais ne réinventez pas la roue. il suffit de prendre et d'utiliser les composants de frameworks bien connus et de les utiliser.
jetez un œil au composant de traduction Symfony . Cela pourrait être une bonne base de code pour vous.
la source
Je me suis posé des questions liées à maintes reprises, puis je me suis perdu dans les langues formelles ... mais juste pour vous aider un peu, j'aimerais partager quelques résultats:
Je recommande de jeter un œil aux CMS avancés
Typo3
pourPHP
(je sais qu'il y a beaucoup de trucs mais c'est celui que je pense être le plus mature)Plone
dansPython
Si vous découvrez que le Web en 2013 devrait fonctionner différemment, partez de zéro. Cela signifierait constituer une équipe de personnes hautement qualifiées / expérimentées pour construire un nouveau CMS. Vous aimeriez peut-être jeter un coup d'œil au polymère à cette fin.
S'il s'agit de codage et de sites Web multilingues / prise en charge de la langue maternelle, je pense que chaque programmeur devrait avoir une idée de l'unicode. Si vous ne connaissez pas l'Unicode, vous gâcherez certainement vos données. N'allez pas avec les milliers de codes ISO. Ils ne vous feront économiser que de la mémoire. Mais vous pouvez tout faire avec UTF-8, même stocker des caractères chinois. Mais pour cela, vous devez stocker des caractères de 2 ou 4 octets, ce qui en fait essentiellement un utf-16 ou un utf-32.
S'il s'agit d'encodage d'URL, là encore, il ne faut pas mélanger les encodages et être conscient qu'au moins pour le nom de domaine, il existe des règles définies par différents lobbies qui fournissent des applications comme un navigateur. par exemple, un domaine pourrait être très similaire comme:
ьankofamerica.com ou bankofamerica.com même nom mais différent;)
Bien sûr, vous avez besoin que le système de fichiers fonctionne avec tous les encodages. Un autre avantage pour unicode utilisant le système de fichiers utf-8.
S'il s'agit de traductions, pensez à la structure des documents. par exemple un livre ou un article. Vous avez les
docbook
spécifications pour comprendre ces structures. Mais en HTML, il ne s'agit que de blocs de contenu. Vous aimeriez donc avoir une traduction à ce niveau, également au niveau de la page Web ou du domaine. Donc, si un bloc n'existe pas, il n'est tout simplement pas là, si une page Web n'existe pas, vous serez redirigé vers le niveau de navigation supérieur. Si un domaine doit être complètement différent dans la structure de navigation, alors .. c'est une structure complètement différente à gérer. Cela peut déjà être fait avec Typo3.S'il s'agit de frameworks, les plus matures que je connaisse, pour faire des trucs généraux comme MVC (mot à la mode, je déteste vraiment ça! Comme "performance" Si vous voulez vendre quelque chose, utilisez le mot performance et featurerich et vous vendez ... quoi l'enfer) est
Zend
. Il s'est avéré être une bonne chose d'apporter des standards aux codeurs php chaos. Mais, typo3 a également un Framework en plus du CMS. Récemment, il a été réaménagé et s'appelle maintenant flow3. Les frameworks couvrent bien sûr l'abstraction de base de données, la création de modèles et les concepts de mise en cache, mais ont des atouts individuels.S'il s'agit de la mise en cache ... cela peut être extrêmement compliqué / multicouche. En PHP, vous penserez à accellerator, opcode, mais aussi html, httpd, mysql, xml, css, js ... toutes sortes de caches. Bien sûr, certaines parties doivent être mises en cache et les parties dynamiques comme les réponses de blog ne le devraient pas. Certains doivent être demandés via AJAX avec des URL générées. JSON, hashbangs etc.
Ensuite, vous aimeriez que n'importe quel petit composant de votre site Web soit accessible ou géré uniquement par certains utilisateurs , donc conceptuellement cela joue un grand rôle.
Vous aimeriez aussi faire des statistiques , peut-être avoir un système distribué / un facebook de facebook, etc. tout logiciel à construire au-dessus de vos cms over the top ... donc vous avez besoin de différents types de bases de données en mémoire, bigdata, xml, que ce soit .
eh bien, je pense que c'est assez pour le moment. Si vous n'avez pas entendu parler de typo3 / plone ou de frameworks mentionnés, vous en avez assez pour étudier. Sur ce chemin, vous trouverez de nombreuses solutions aux questions que vous n'avez pas encore posées.
Si alors vous pensez, faisons un nouveau CMS parce que son 2013 et php sont sur le point de mourir de toute façon, alors vous êtes invités à rejoindre tout autre groupe de développeurs, espérons ne pas vous perdre.
Bonne chance!
Et btw. Et si les gens n'auront plus de sites Web à l'avenir? et nous serons tous sur google +? J'espère que les développeurs deviendront un peu plus créatifs et feront quelque chose d'utile (pour ne pas être assimilé par le borgle)
//// Edit /// Juste une petite pensée pour votre application existante:
Si vous avez un CMS php mysql et que vous vouliez intégrer le support multilang. vous pouvez soit utiliser votre table avec une colonne supplémentaire pour n'importe quelle langue ou insérer la traduction avec un identifiant d'objet et un identifiant de langue dans le même tableau ou créer une table identique pour n'importe quelle langue et y insérer des objets, puis faire une union de sélection si vous le souhaitez pour les afficher tous. Pour la base de données, utilisez utf8 general ci et bien sûr dans le front / backend, utilisez le texte / encodage utf8. J'ai utilisé des segments de chemin d'URL pour les URL de la manière que vous avez déjà expliquée, comme
domain.org/en/about, vous pouvez mapper l'ID de langue à votre table de contenu. de toute façon, vous devez avoir une carte des paramètres pour vos URL afin que vous souhaitiez définir un paramètre à mapper à partir d'un segment de chemin dans votre URL qui serait par exemple
domain.org/en/about/employees/IT/administrators/
configuration de recherche
pageid | URL
1 | /about/employees/../ ..
1 | /../about/employees../../
mapper les paramètres au segment de chemin de l'URL ""
par exemple, cela a déjà été couvert au poste supérieur.
Et pour ne pas oublier, vous devez "réécrire" l'url dans votre fichier php générant qui serait dans la plupart des cas index.php
la source
Travail de base de données:
Créer une table de langues 'languages':
Des champs:
Créez une table dans la base de données 'content':
Des champs:
Travail frontal:
Lorsque l'utilisateur sélectionne une langue dans la liste déroulante ou dans n'importe quelle zone, enregistrez l'identifiant de la langue sélectionnée dans la session comme,
$_SESSION['language']=1;
Récupérez maintenant les données de la table de base de données «contenu» en fonction de l'ID de langue stocké dans la session.
Les détails peuvent être trouvés ici http://skillrow.com/multilingual-website-in-php-2/
la source
En tant que personne vivant au Québec où presque tout le site est français et anglais ... j'ai essayé beaucoup sinon la plupart des plugins multilingues pour WP ... la seule solution utile qui fonctionne avec tout mon site est mQtranslate ... je vis et meurs avec!
https://wordpress.org/plugins/mqtranslate/
la source
Qu'en est-il de WORDPRESS +
MULTI-LANGUAGE SITE BASIS
(plugin)? le site aura une structure:Le plugin fournit une interface pour la traduction de toutes les phrases, avec une logique simple:
alors il peut être sorti:
echo translate('my_title', LNG); // LNG is auto-detected
ps cependant, vérifiez si le plugin est toujours actif.
la source
Une option très simple qui fonctionne avec n'importe quel site Web où vous pouvez télécharger du Javascript est www.multilingualizer.com
Il vous permet de mettre tout le texte de toutes les langues sur une seule page, puis de masquer les langues que l'utilisateur n'a pas besoin de voir. Fonctionne bien.
la source