2009-09-01 11 views
8

Dans une application multilingue avec tables de recherche, quelle est la meilleure façon de gérer les traductions? Par exemple, pour une table de recherche de pays, un utilisateur américain devrait voir les noms de pays anglais, comme un allemand devrait voir les noms allemands. Mais toujours leurs identifiants devraient être les mêmes.Quelle est la meilleure façon de gérer I18N dans les tables de recherche?

Je peux penser à ce qui suit:

  • Ajouter une table de recherche différent pour chaque langue
  • Utilisez une table de consultation unique avec plusieurs entrées pour le même pays en fonction de son battant le pavillon langue.
  • Débarrassez-vous de toutes les tables de consultation et faire toutes les recherches par code de programme
  • [Toute autre idée que je ne pensais pas?]

Répondre

8

La grande question est ici - peut traductions peut être modifiée en fin utilisateurs?

Si la réponse est "NON", les regroupements de ressources sont plus faciles et plus rapides à utiliser que les tables. Au lieu du texte réel, vos tables contiendront la clé de ressource (ou vous pouvez utiliser la clé primaire à cette fin si elle est textuelle plutôt que numérique) et le regroupement de ressources approprié contiendra la traduction.

Si la réponse est "OUI", vous devez stocker les traductions dans la base de données. J'ai trouvé, cependant, que l'approche la plus simple dans ce scénario consiste à imiter la fonctionnalité de regroupement de ressources ci-dessus dans la base de données - par ex. avoir une seule table avec des colonnes "locale", "resource key", "resource value" que toutes les autres tables utiliseront pour rechercher du texte localisé.

3

Présentation disjointe de la programmation. En interne, utilisez des ID pour tout; lors de la présentation aux utilisateurs, présentez des données localisées.

1

J'ai fait une application multilingue une fois. Tout devait être multilingue, y compris les utilisateurs de contenu entrés, et il devait également être facile de faire une traduction sur ce contenu.

Maintenant, si c'est juste pour le texte statique, recommande le plus les fichiers XML de ressources pour ce faire. Je crois que cela est très bien supporté par le framework .NET.

Si elle doit être dynamique, je ne une structure de table de

Tableau ResourceStrings resourceId Guid PK cultureCode Chaîne texte PK Chaîne

Cela m'a alors permis todo cascade lire sur le code de la culture ainsi que. Donc, si quelqu'un avait un code de culture en-nous, je pourrais faire une requête où je l'ai fait

SELECT FROM ResourceStrings 
WHERE resourceId = <AND ID> AND cultureCode IS IN ('en','en-us') 
ORDER BY cultureCode DESC 

De cette façon, le plus long du code de culture reviendrait d'abord et être le plus spécifique. Maintenant, je recommande ce uniquement si vous autorisez les utilisateurs à entrer du texte et à le traduire. J'en avais besoin car le contenu devait être multilingue ainsi que l'application elle-même.

0

Découvrez quelque chose comme les structures de données et les algorithmes Adobe Source Libraries 'xstring. La localisation est gérée avec un identifiant pour la chaîne ainsi qu'un contexte détaillant la localisation. Les tables de localisation peuvent être stockées en XML et les chaînes sont localisées au moment de l'exécution en fonction du contexte d'exécution (langue, pays, plateforme, etc.Bien que le code fonctionne, je ne considérerais pas la qualité de la production. Néanmoins, les concepts sont solides.

1

Dans mon projet actuel (un CMS personnalisé écrit en django), notre solution pour les modèles I18N est basée sur cet exemple: http://www.djangosnippets.org/snippets/855/, que j'ai étendu pour être plus utilisable dans les templates et intégré dans l'interface d'administration. Fondamentalement, chaque contenu aimable a deux tables: une avec les champs communs (comme la catégorie des articles) et une avec le contenu traduisible (titre, corps, slug - étiquette unique utilisée dans l'URL - etc.). De toute évidence, il existe une relation ony-to-many entre le modèle commun et le modèle de traduction. Voici l'exemple l'auteur donne:

class Article(models.Model): 
    author = models.CharField(max_length = 40) 

class ArticleI18N(I18NModel): 
    title = models.CharField(max_length = 120) 
    body = models.TextField() 

Je pense que cette façon, la mise en page de base de données est très proche du concept d'avoir contenu avec des attributs communs et des champs traduisibles. Mais alors, la partie la plus délicate est de rester SEC dans votre code, ou vous vous retrouverez avec un tas de messages à chaque fois que vous aurez besoin de gérer du contenu traduisible. Heureusement, la flexibilité de Python a été d'une grande aide.

Si votre langage de programmation et votre environnement ne permettent pas de trucs similaires (comme la création dynamique de sous-classes, une sorte de hook d'héritage, etc.), je suppose que ce type de base de données va être plus qu'une malédiction. une bénédiction.

Gardez donc le principe YAGNI à l'esprit. Si vous avez besoin de traductions à l'intérieur de vos modèles avec moins de complications, je l'ai vu d'autres moyens efficaces, qui sont bien aussi longtemps que vous pouvez vous permettre la flexibilité limitée et le manque d'intégrité conceptuelle de ces alternatives:

  • 1) utilisent colonnes supplémentaires pour chaque colonne traduisible et chaque langue: title_en, title_fr, title_de, content_en, content_fr, content_de, ...
  • 2) sérialiser plusieurs langues dans une colonne.
    Par exemple: title = "| FR | Bienvenue | FR | Bienvenue | DE | Willkommen"
    Je n'aime pas particulièrement celui-ci, mais ce qui compte vraiment ici, c'est de savoir s'il s'intègre bien dans un environnement existant, ce qui était le cas.
  • 3) Parfois, le lien entre le même contenu dans différentes langues n'a pas besoin d'être strict. Je pense que c'est le cas des articles en wikipedia - les traductions sont juste des hyperliens définis manuellement par les auteurs. En conséquence, ces liens sont moins exploitables par le logiciel, mais ce qui compte ici, c'est d'être consultable par un utilisateur.
1

Voici un moyen de le faire au niveau de la base de données.

Quand j'ai eu besoin de faire cela, j'ai cassé chaque table de code en deux tables. L'une contenait des données invariantes par culture: l'ID interne du code, le code lui-même si le code était invariable par culture, et éventuellement d'autres colonnes (comme les catégories de tri/groupement). L'autre contenait des données spécifiques à la culture: descriptions, codes spécifiques à la culture, le cas échéant, etc.

(Les codes spécifiques à la culture sont un nid de frelon, ne pas le lancer si vous n'avez pas à le faire.Il peut être un peu difficile de comprendre que US et EU sont le même code dans différents mais il y a des pays où il peut être politiquement désagréable que les utilisateurs francophones utilisent US comme abréviation de États-Unis.Avoir une table de code invariant de culture vous permet d'établir des contraintes de clé étrangère entre elle et les tables principales qui l'utilisent. La construction de requêtes spécifiques à la culture est assez simple:

SELECT m.*, c.Code, ISNULL(s.Description, lf.Message) 
FROM MainTable m 
JOIN FooCodeData c ON m.CodeID = c.ID 
LEFT JOIN CultureSpecificFooCodeData s ON s.CodeID = c.ID AND s.Culture = @Culture 
JOIN LookupFailure lf ON lf.Culture = @Culture 

Notez que si vos codes sont spécifiques à la culture, vous ne même pas besoin de se joindre FooCodeData dans cette requête, la sélection s.Code à la place. Notez également une faiblesse inhérente de cette approche, comme indiqué par les LEFT JOIN et ISNULL dans cette requête: vous ne pouvez pas créer de contrainte pour garantir l'existence d'une ligne spécifique à la culture pour chaque combinaison code/culture. C'est ce que LookupFailure est pour: il reçoit le message spécifique à la culture qui indique que l'enregistrement de code spécifique à la culture n'a pas été entré pour un code donné.

Questions connexes