web-dev-qa-db-fra.com

Comment rendre les chaînes des modèles traduisibles sur toutes les pages où elles apparaissent?

J'ai quelques appels à t() dans les fichiers * .tpl.php. Par exemple, disons que je parle de produits et de fichier product.tpl.php.

Les chaînes dans les modèles ne sont reconnues que lors de leur première utilisation. Il y avait un fil sur Drupal.org à ce sujet et je l'ai trouvé exact. Malheureusement, si je vais à, disons, http://example.com/pl/product/2 , cette chaîne sera enregistrée dans {locales_source} table avec location champ défini sur /pl/product/200.

J'ai besoin que mes utilisateurs puissent traduire à l'aide de l'outil de traduction sur site du module Client de localisation , afin qu'ils puissent réellement voir ce qu'ils traduisent, en le plaçant dans le contexte approprié. Avec l'emplacement source défini sur /pl/product/200, le produit avec l'ID 200 est le seul sur lequel la chaîne est traduite. Et bien pire, si je peux forcer les utilisateurs à traduire sur ce produit particulier, j'en ai également besoin pour traduire en russe, et il n'y a pas de produit dont l'emplacement est défini sur /ru/product/PID.

Existe-t-il un moyen de reformater la chaîne de localisation dans la base de données, pour rendre toutes les chaînes visibles sur tous les produits, toutes les langues dans l'outil l10n_client?

J'ai essayé de le régler sur:

  • ; sites/default/themes/mytheme/product.tpl.php,
  • sites/default/themes/mytheme/product.tpl.php,
  • sites/default/modules/mymodule/mymodule.module (module qui génère des données thématiques)

Mais cela ne faisait que les rendre invisibles pour l'outil de traduction.

Je suis sûr que ce n'est pas un bug dans Client de localisation , il montre la chaîne où il est dit que cette chaîne s'est produite. Et il semble que ce soit "juste comme ça fonctionne" pour Drupal 7 aussi) a déjà été discuté et signalé, et rien n'a changé. Donc ce n'est pas un rapport de bogue, je demande juste comment travailler avec ce avec quoi nous devons travailler.


Je parle de textes qui n'ont rien à voir avec le module de données fonctionne. Je ne veux pas traduire de produits, juste des chaînes de modèles qui n'ont rien à voir avec le produit lui-même, comme Précédent - Suivant sur le modèle de galerie d'images de produits.

Par exemple, le module renvoie 15 miniatures, et c'est le travail d'un thème d'en afficher 5 à la fois. Et les liens précédents/suivants ont besoin des attributs alt et title. Traduit. Mais mon module ne le sait pas. Et ne devrait jamais en avoir besoin.

14
Mołot

Votre exigence:
Pour que mon site fonctionne en plusieurs langues
en tant qu'utilisateur authentifié
Je dois être capable de traduire à la fois tous les appels de traduction trouvés dans la base de code de mon site qui ont été effectués avec la fonction t().

Cette description des exigences est-elle encore proche de ce que vous demandez?


Explorateurs

Comme quelqu'un l'a dit - un robot pourrait en théorie parcourir tout le site pour forcer l'enregistrement de tous les appels t(). Mais 1) le robot ne sait pas les pages à explorer; 2) nous ne cherchons donc pas à maintenir une liste de pages à explorer; 3) nous ne voulons pas utiliser de robot, point final. Eww. Juste, eww. Droite?


Le problème

  1. Nous n'avons pas de liste de toutes les chaînes de traduction.
  2. Drupal/PHP est un langage dynamique contrairement à C qui est compilé. Nous ne pouvons donc pas dire par exemple: compilez toute cette base de code, puis trouvez-moi toutes les instances de cette fonction t(), puis enregistrez ces instances dans la base de données, puis traduisez toutes ces instances enregistrées de t() en une fois. Je ne pense pas que ce soit une option que nous ayons sur notre table.
  3. Un outil d'analyse de code statique serait impuissant pour la même raison qu'un robot serait impuissant. J'ai trouvé cette t() dans ce fichier. Génial! Dans quelle URL est-il utilisé? Quel est le contexte?

Attaquer le problème avec les outils actuels (Drupal, et certains modules contrib), et avec les contraintes actuelles (en s'appuyant sur des appels à thème en temps réel -> fichiers modèles -> t() appels), ressemble à un non- sortir ruelle ici. Nous devrons peut-être réfléchir un peu hors de la boîte.


Ce dont nous avons besoin

  1. Nous avons besoin d'une source de données, d'un modèle, qui me dit quelles chaînes de traduction actuelles nous avons et quel est leur contexte -
  2. Modèle de données proactif. Le modèle de données actuel est réactif (le modèle est mis à jour chaque fois qu'un appel à t() se produit). Nous avons besoin d'un modèle de données proactif - dans lequel l'application se charge de rechercher les instances de t() avant qu'elles ne soient réellement exécutées par le client.
  3. Nous avons besoin de contexte. t() seul ne suffit pas - car - nous ne savons pas que nous traduisons 'foo', mais la langue cible vers laquelle nous traduisons dépend de l'URL d'où se trouve la t() . Même si nous pouvions coder en dur la langue cible dans l'appel t(), par exemple, en utilisant un appel wrapper, cela ne fonctionnerait pas pour vous.

J'ai identifié certains des outils qui - si nous les avions - aideraient notre problème. Avec ces outils, nous pourrions entrer dans le modèle de données et dire: donnez-moi toutes les chaînes enveloppées dans t() qui n'ont pas encore été remplies. Insérez maintenant ces traductions. Merci.

Et la prochaine fois que le client vient, les traductions sont là.

Comment pourrions-nous ... construire ces outils?


Contraintes

  1. La langue cible ne peut pas être sur le modèle, ce qui est décidé par l'URL. En supposant que la chaîne doit prendre en charge n'importe quelle langue.
  2. La chaîne traduite ne peut pas se trouver sur le modèle. La traduction résidera dans une base de données.

Maintenant que j'ai réfléchi au problème et identifié certains défis et contraintes, je peux penser à examiner toutes les solutions disponibles sur le marché ou à créer des solutions personnalisées.

Solution brainstorming

J'ai besoin de quelque chose qui relie "tout" ensemble. Et ... une entité?

  • Une entité peut contenir le produit à traduire.
  • Les entités peuvent fournir la relation - la colle - entre le produit à traduire et son contexte.
  • L'entité peut spécifier disons, dans un champ, l'emplacement URL par défaut du produit.
  • Les jetons peuvent être utilisés pour spécifier d'autres emplacements (langues?) Sur lesquels le produit apparaîtra.
  • Les entités nous fournissent le modèle de données proactif dont nous avons besoin et son contexte. Ce qui à son tour nous permet de faire des choses telles que: aller dans la base de données, récupérer toutes les entités du produit, et si elles n'ont pas de chaîne de traduction pour les champs X, Y et Z, créer ces chaînes de traduction.

Lorsque le client saisit alors /pl/product/200, vous vous rendez dans la base de données, recherchez le produit 200 et récupérez la traduction pl déjà existante. Vous avez également un champ de titre et de légende pour ce produit? Les traductions devraient également être là.

Notez que je suis très vague et générique ici en termes de module de traduction que vous utilisez. Vous pourriez très bien finir par utiliser votre propre module de traduction - c'est probablement le cas. Tous les modèles de traduction que j'ai vus dans Drupal jusqu'à présent (depuis D7, n'ont pas encore regardé D8)) sont réactifs, pas proactifs.

En bref

En théorie, les outils pour construire ce dont vous avez besoin sont là, les entités étant le composant clé qui relierait tout: - les données (chaîne de traduction), - les langues cibles. Il n'est pas nécessaire d'être sur l'entité elle-même, de préférence un vocabulaire de taxonomie, par exemple pour les langages de produit. ou peut-être aussi une taxonomie générique pour d'autres entités. - Le contexte. URL sur laquelle l'entité apparaît. L'URL contiendrait un jeton, et le jeton à son tour ferait référence à la taxonomie de la langue cible.

Avec ces trois ingrédients, vous pouvez dire: Saisissez toutes les entités product, accédez à URL alias champ, obtenez le jeton de taxonomie, parcourez toutes les combinaisons de termes possibles, présentez toutes les combinaisons à l'utilisateur actuel en utilisant soit un très grand formulaire laid - soit, AJAX - et des formulaires en plusieurs étapes ( quelque chose comme ça), et comme l'utilisateur actuellement connecté traduit les différentes langues du produit 200, enregistrez-les quelque part dans la base de données

Quelque part dans la base de données pourrait être un champ API de champ dans l'entité, le champ de paramètres appartenant à chaque entité (pas exactement l'API de champ, mais il peut toujours contenir des données), ou une table distincte que vous utilisez pour cela. Je pense que l'enregistrement des données dans l'entité garderait le code et les données plus propres et plus faciles.


Building It: Solutions possibles

  • D8MI (Initiative multilingue Drupal 8)
  • Code personnalisé: traductions "index" rendues disponibles dans les modèles par t() en interrogeant et en rendant par programme les bundles disponibles et leurs implémentations de hook de thème associées.

Pseudocode

Entité Foreach (de type x),
Trouver toutes les langues (taxonomie ou langage principal associé au produit),
Rendre l'entité,
- afin de détecter ses chaînes de traduction t()
- rend le thème des appels (), qui gère la couche de présentation multilingue du produit, pas le modèle de données produit lui-même.

Résultat:
Le premier appel pour rendre le modèle d'entité dans chaque langue renvoie l'implémentation de langue par défaut pour chaque appel.
- Les paramètres t() du modèle sont maintenant mis en cache dans Drupal et prêts pour la traduction (pour chaque instance de langue, pas pour chaque produit) exemple).
- L'utilisateur avec le rôle de "traducteur" peut maintenant aller à l'interface de traduction et traduire tous les paramètres t() disponibles, pour chaque langue.
- Le propriétaire du site n'a pas besoin d'attendre que les clients visitent chaque page de produit ou de visiter chaque page de produit manuellement, car cela a été fait par programme pour lui.

Questions ouvertes:
Quel est le contexte? Si j'effectue un appel programmatique au thème () pour chaque ensemble d'entités "produit", enregistre-t-il l'emplacement à partir duquel l'appel a été effectué? Enregistre-t-il l'URL du nœud? Le "contexte" peut-il être modifié? Où le contexte est-il enregistré? Que se passe-t-il lorsque vous avez des modèles "dynamiques" - c'est-à-dire lorsque vous avez plus d'un modèle par produit et comment procédez-vous pour détecter ces variations?

Comme toujours, la théorisation et le pseudocode ne sont bons que pour le brainstorming. Mais en développement, nous ne saurons pas à quoi nous nous heurterons vraiment avant de commencer le prototypage. Donc, après avoir élaboré quelques contraintes, des solutions possibles et des problèmes ou questions possibles - je peux maintenant procéder à la mise en œuvre d'une preuve de concept ou d'un prototype fonctionnel. Certaines des questions ouvertes ci-dessus ne peuvent être résolues que de cette façon, et le plus tôt nous prototypons (indépendamment du succès ou de l'échec), nous pouvons commencer à répondre à certaines de ces questions - ou changer complètement l'approche. Restez à l'écoute ~

5
amateur barista

Ok, j'ai passé plus de temps avec le module de traduction de client et d'entité de localisation pour reproduire le même scénario. Étant donné que cette réponse est totalement différente de la précédente, en ajoutant un commentaire séparé:

  1. La traduction ajoutée pour une langue dans un/premier nœud est disponible pour tous les nœuds.

    Voici un exemple:

    • Si j'ajoute un nouveau produit du même type que le nid 200 et que je visite la traduction pl du nouveau nœud (disons pl/product/204), je verrais la même chaîne de traduction dans pl/product/200.

    • La seule différence est qu'il n'apparaît pas dans le client de localisation. Nous pouvons demander cette fonctionnalité dans la file d'attente des problèmes du module, mais cela introduirait plus de confusion car la traduction n'est pas spécifique à la page actuelle et affecterait toutes les pages (c'est-à-dire à la fois pl/product/200 et pl/product/204).

    • Si les deux nœuds créés par deux personnes différentes, et le dernier veut changer la traduction, alors ils doivent utiliser la traduction de l'interface.

  2. La chaîne est disponible dans le client de localisation pour la première langue que vous visitez pour le même nœud

    Voici un exemple:

    • Si j'ajoute un nouveau produit nid 199 et crée une traduction pour la langue 'pl' (nid 200) et une traduction pour la langue 'rs' (nid 201), vous pouvez voir la chaîne uniquement sur la page 'pl', pas sur la page 'rs'. Encore une fois, cela ressemble à une restriction dans le module client de localisation.
2
vijaycs85

AFAIK avec Extracteur de modèle de traduction vous pouvez extraire la chaîne dans tous vos appels à la fonction t().

L'extracteur de modèle de traduction fournit une interface d'extraction de modèle de traduction Gettext basée sur le Web et en ligne de commande pour Drupal ainsi qu'une API réutilisable pour rechercher les chaînes traduisibles et les erreurs de traductibilité. Cet outil est utilisé sous le capot à http://localize.drupal.org/ ainsi que pour servir de machine d'analyse pour les versions du projet Drupal.org.

Lisez ceci Comment traduire un module?

1
Adrian Cid Almaguer

Votre approche pour ajouter la chaîne de traduction au niveau du modèle ou du fichier de module peut fonctionner pour l'interface utilisateur de traduction d'interface, mais pas pour le client de localisation.

Évidemment, lorsque vous avez la version russe du produit 200, ce sera un nouveau nœud, par exemple/ru/product/201, où vous pourrez traduire à l'aide du client de localisation.

Juste une pensée: recherchez une chaîne qui peut être traduite dans toutes les langues dans l'interface utilisateur de traduction de l'interface et demandez au client de traduire le niveau du produit lorsque cela est vraiment nécessaire. Voici un exemple:

"C'est le produit foo de la catégorie bar"

et si nous sommes sûrs que d'autres que "foo" et "bar" peuvent être communs, nous pouvons ajouter

$vars['product_title'] = t('This is product @product of category @category')

en pré-traitement.

et le fichier .tpl.php sera

<?php t($product_title, array('@product' => t('foo'),  '@category' => t('bar')); ?>
1
vijaycs85