Reconfiguration des fichiers Ruby on Rails I18N YAML à l'aide de dictionnaires

cette question de StackOverflow m'a donné matière à réflexion sur ce qui est une bonne structure pour les Rails i18n fichiers, donc j'ai pensé que je partagerais une autre structure pour le remaniement des Rails i18n fichiers yml pour votre considération/critique.

étant donné que je voudrais

  1. garder la structure par défaut de l'application afin que je puisse utiliser la sténographie "lazy" comme t('.some_translation') dans mes vues, ainsi que d'avoir une idée où les traductions sont utilisées dans l'application,
  2. éviter autant de répétition de chaîne que possible, en particulier avec des mots qui ne sont pas identiques, mais qui ont aussi des contextes/significations identiques,
  3. il suffit de changer une clé une seule fois pour qu'elle se reflète partout où elle est référencée,

pour un config/locales/fr.YML fichier qui ressemble à quelque chose comme ceci:

activerecord:
  attributes:
    user:
      email: Email
      name: Name
      password: Password
      password_confirmation: Confirmation
  models:
    user: User
users:
  fields:
    email: Email
    name: Name
    password: Password
    confirmation: Confirmation
sessions:
  new:
    email: Email
    password: Password

je peux voyez qu'il y a une répétition significative, et que le contexte de mots comme "Email" et "mot de passe" sont sans ambiguïté et ont le même sens dans leurs vues respectives. Il serait un peu ennuyeux d'avoir à aller changer tous si je décide de changer de "Courriel" pour "e-mail", donc j'aimerais refactoriser les cordes pour faire référence à un dictionnaire de la sorte. Alors, que diriez-vous d'ajouter un hachage de dictionnaire en haut du fichier avec quelques ancres & comme ceci:

dictionary:
  email: &email Email
  name: &name Name
  password: &password Password
  confirmation: &confirmation Confirmation

activerecord:
  attributes:
    user:
      email: *email
      name: *name
      password: *password
      password_confirmation: *confirmation
  models:
    user: User
users:
  fields:  
    email: *email
    name: *name
    password: *password
    confirmation: *confirmation
sessions:
  new:
    email: *email
    password: *password

vous pouvez toujours continuer à utiliser des chaînes statiques (par exemple" Utilisateur " ci-dessus), mais chaque fois que vous obtenez plus d'une instance de exactement le même mot/phrase dans vos vues, vous pouvez le remanier vers le dictionnaire. Si la traduction du dictionnaire d'une clé dans la langue de base n'a pas de sens pour une langue cible, alors il suffit de changer la valeur référencée dans la langue cible en une chaîne statique ou de l'ajouter comme entrée supplémentaire au dictionnaire de la langue cible. Je suis sûr que chaque langue le dictionnaire peut être refactorisé dans un autre fichier s'il devient trop gros et lourd (Tant qu'il est réimporté en haut du fichier de traduction pour que les références fonctionnent).

cette façon de structurer les fichiers i18n yaml semble bien fonctionner avec certaines applications de test locales sur lesquelles je l'ai essayé. J'espère que le merveilleux Localeapp fournira un soutien pour ce genre d'ancrage / référencement à l'avenir. Mais de toute façon, tous ces dictionnaires ne peuvent pas peut-être une idée originale, alors y a-t-il d'autres problèmes avec le référencement d'ancre dans YAML, ou peut-être juste avec l'ensemble du "dictionnaire" concept en général? Ou est-ce qu'il est juste préférable de simplement enlever le backend par défaut et le remplacer par Redis ou quelque chose si vous avez des besoins au-delà des conventions i18n de Rails par défaut?

Modifier :

je voulais essayer d'adresser l'exemple de flux de travail de tigrish mentionné dans un commentaire ci-dessous, jusqu'ici, plutôt que comme un autre commentaire ci-dessous sa réponse. S'il vous plaît excusez-moi si Je ne semble pas obtenir les points étant fait ou si je suis juste naïf:

Point 1 : vous avez un attribut "name" général pour les modèles ActiveRecord, et ils tous pointent juste au dictionnaire générique pour le nom:

dictionary:
  name: &name Name

activerecord:
  attributes:
    name: *name
    user:
      name: *name
    product:
      name: *name

Point 2 : le nom du modèle Utilisateur doit être changé. D'autres noms rester le même.

Option 1 : conserver les noms des champs model identiques sur le verso et juste changer la traduction de l'avant vers laquelle il pointe.

dictionary:
  name: &name Name
  full_name: &full_name Full Name

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
    product:
      name: *name

Option 2 : changez également le nom du champ User model. Il faudrait pour cela modifier toute référence à cette clé dans le code, ainsi qu'une migration change_table / rename_column .

dictionary:
  name: &name Name
  full_name: &full_name Full Name

activerecord:
  attributes:
    name: *name
    user:
      full_name: *full_name
    product:
      name: *name

Option 3 : si vous voulez être très complet, modifiez l'information contenue dans un" nom " pour séparer les champs de base de données/Activemodel, qui auraient besoin de nouvelles entrées de dictionnaire et une migration. Vous pouvez décider sur vos vues comment vous voudriez qu'un" nom complet "s'affiche:

dictionary:
  name: &name Name
  name_prefix: &name_prefix Prefix
  first_name: &first_name First
  middle_name: &middle_name Middle
  last_name: &last_name Last
  name_suffix: &name_suffix Suffix

activerecord:
  attributes:
    name: *name
    user:
      name_prefix: *name_prefix
      first_name: *first_name
      middle_name: *middle_name
      last_name: *last_name
      name_suffix: *name_suffix
    product:
      name: *name

Point 3 : toute personne pour une raison quelconque a besoin d'un changement de traduction, Marketing dans ce cas. Je vais suivre de Point 2 L'exemple de L'Option 1

Option 1 : les noms des champs du modèle sont les mêmes, il suffit de changer la traduction de l'extrémité avant.

dictionary:
  name: &name Name
  full_name: &full_name Full Name
  funky_name: &funky_name Ur Phunky Phresh Naym

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
    product:
      name: *name
sessions: # Sign up page keys
  new:
    name: *funky_name

Option 2 : "Funky name" a désespérément besoin d'être sauvegardé dans la base de données, aussi, pour une raison quelconque. Appelons-le un username si personne ne s'y oppose (ou funky_name si pour une raison quelconque le Marketing insiste).

dictionary:
  name: &name Name
  full_name: &full_name Full Name
  funky_name: &funky_name Ur Phunky Phresh Naym

activerecord:
  attributes:
    name: *name
    user:
      name: *full_name
      username: *funky_name
    product:
      name: *name
sessions: # Sign up page keys
  new:
    name: *name
    funky_name: *funky_name

D'accord, donc j'admets que j'ai peu d'idée de ce que je fais, cependant, Je suis prêt à être abattu publiquement afin de comprendre pourquoi cette façon de travailler avec i18n dans Haml est une mauvaise idée dans une application Rails. Difficile à lire? Entretien cauchemar? Est-ce vraiment considéré comme 'hacking the file format' si j'utilise (ce que je pense être) une caractéristique de la langue?

merci encore à tigrish de m'avoir amené à sortir tout ça.

22
demandé sur Community 2012-06-19 12:50:49

4 réponses

TLDNR; ne pas hacker votre format de fichier, améliorer les aides rails et aider à établir une structure de clé standardisée!

TLDR;

Je ne veux pas qu'il pleuve sur votre défilé, mais j'ai quelques problèmes avec cette technique. Le dilemme de savoir où utiliser le raccourci de points et comment la structure de la clé des assistants de rails diffère peut être un peu déroutant.

d'après ce que j'ai compris, la question est essentiellement de sécher vos fichiers locaux et utiliser une caractéristique du langage YAML pour y parvenir.

tout d'abord, les ancres ne sont vraiment garanties de fonctionner que pour YAML, donc cette solution ne peut pas être appliquée de manière générique à I18n. Cette technique n'est probablement pas réalisable si vous utilisez un support différent. Que ce soit SQL, Redis ou Json, Je ne suis pas au courant de l'un d'eux ayant une fonctionnalité de symlinking. Et cela sans entrer trop dans le fait que sous le capot, les traductions sont en fait dupliquées.

le deuxième et le plus gros problème que j'ai, c'est la linguistique. Votre exemple montre que tous ces termes sont exactement égaux dans leur contexte et dans leur signification. Malheureusement, ce n'est le cas que dans des exemples extrêmement simples.

sans aucun doute, au fur et à mesure que votre application se développe ou que vous ajoutez d'autres langues, vous constaterez que l'attribut" name " d'une personne doit être distinct de l'attribut "name" d'un livre que nous appellerons en anglais "title" - OK, cet exemple est mais comme vous mélangez dans de plus en plus de langues cette situation se produit fréquemment et idéalement, nous voulons une façon générique de traiter avec elle.

je pense qu'en grande partie, la complexité vient des helpers rails qui ont évolué avec différents défauts sans qu'il y ait une convention pour les structures clés.

pour revenir à votre exemple, vous mentionnez deux choses que je pense sont vraiment distincts : activerecord attribut traductions qui utilisez les helpers de rails et visualisez les traductions qui utilisent le raccourci à points.

Permettez-moi de vous donner un exemple d'un flux de travail qui est très fréquent:

  1. vous créez un formulaire avec le champ "Nom" de l'utilisateur dans cette situation, vous voulez utiliser les traductions génériques d'attribut " nom " (label_tag doit utiliser quelque chose comme :'attributs.nom"). C'est le cas le plus simple, le plus sec pour vous mettre en route rapidement, traduire en masse des attributs simples.
  2. un peu plus tard, vous décidez que le" nom "de L'utilisateur doit être traduit par" nom complet " pour ce modèle seulement afin de créer une nouvelle traduction qui a une priorité plus élevée dans l'appel de recherche de label_tag (par exemple :'activerecord.attributs.utilisateurs.nom'))
  3. plus tard encore, le gars du marketing a la brillante idée d'afficher l'étiquette de ce domaine comme "entrez votre nom frais funky" sur cette page (et seulement sur cette page). Nous ne décrivons plus l'attribut du nom., nous décrivons une vue particulière de cette forme; c'est là que le raccourci de points vient en conversion :'.form.Nom' to something like': users.new.form.nom".

il n'y a aucun moyen que nous puissions gérer cette situation avec un"dictionnaire" partagé. Bien sûr notre fichier local serait sec, mais nos préoccupations linguistiques/de traduction sont très différentes de nos préoccupations de développeur ici (malheureusement).

du côté positif, nous pouvons obtenir plus clair sur ce genre de contenu nous décrivons et reflétons cela dans nos structures clés et dans nos outils - c'est pour moi la voie à suivre! :)

10
répondu tigrish 2017-08-01 14:48:44

je viens de publier une gemme appelée i18n-recursive-lookup qui permet à une définition de contenir des références intégrées à d'autres définitions en introduisant le marqueur spécial intégré $ {}

https://github.com/annkissam/i18n-recursive-lookup

en l'utilisant, vous pourriez reformuler votre exemple en:

dictionary:
  email: Email
  name: Name
  password: Password
  confirmation: Confirmation

activerecord:
  attributes:
    user:
      email: ${dictionary.email}
      name: ${dictionary.name}
      password: ${dictionary.password}
      password_confirmation: ${dictionary.confirmation}
  models:
    user: User
users:
  fields:  
    email: ${dictionary.email}
    name: ${dictionary.name}
    password: ${dictionary.password}
    confirmation: ${dictionary.confirmation}
sessions:
  new:
    email: ${dictionary.email}
    password: ${dictionary.password}

la bonne chose est qu'une fois compilées les traductions sont écrites de nouveau à la traduction stocker de façon à ce que toute interpolation/recherche récursive n'arrive qu'une fois.

je sais que cela pourrait ne pas répondre aux questions plus philosophiques sur ce que la "bonne" façon de sécher les traductions est, mais j'ai pensé que c'est une meilleure alternative à l'utilisation du hack YML de référence & label.

4
répondu Northern Bite 2013-04-19 18:38:10

amélioration des fichiers YAML refactiring, en particulier pour ceux qui ont plusieurs modèles:

ru:
  dictionary:
    name: &name "Имя"
    title_ru: &title_ru "Заголовок (ru)"
    title_en: &title_en "Заголовок (en)"
    content_ru: &content_ru "Содержание (ru)"
    content_en: &content_en "Содержание (en)"
    role: &role "Роль"
    created_at: &created_at "Создано в"
    updated_at: &updated_at "Обновлено в"
    published: &published "Опубликовано"

    nomination: &nomination
      name: *name
      title_ru: *title_ru
      title_en: *title_en

    post: &post
      content_ru: *content_ru
      content_en: *content_en
      published: *published

    dates: &dates
      created_at: *created_at
      updated_at: *updated_at

  activerecord:
    attributes:
      article:
        <<: *nomination
        <<: *post
        <<: *dates

      user:
        <<: *dates
        role: *role
        email: "Электропочта"

Divers lien

0
répondu Artur Loginov 2017-05-23 12:09:24

je viens de sortir une gemme appelée dry_i18n: https://rubygems.org/gems/dry_i18n

j'ai créé ce bijou afin de résoudre le problème que vous demandez. Avec ce bijou, vous pourrez même réutiliser des clés avec des interpolations et les emboîter.

j'espère que c'est utile.

0
répondu Ignacio Palacios 2016-06-12 16:04:08