Refactoring Ruby on Rails i18n YAML files using dictionaries

后端 未结 4 1503
长发绾君心
长发绾君心 2020-12-08 14:55

This StackOverflow question gave me food for thought on what is a good structure for Rails i18n files, so I thought I\'d share another structure for refactoring Rails i18n y

相关标签:
4条回答
  • 2020-12-08 15:18

    Improving of refactiring YAML files, especially for those who have many models:

    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: "Электропочта"
    

    Userful link

    0 讨论(0)
  • 2020-12-08 15:25

    TLDNR; Don't hack your file format, improve the rails helpers and help to establish a standardized key structure!

    TLDR;

    Don't want to rain on your parade, but I have a few issues with this technique. The dilemma of where to use the dot shortcut and how the rails helpers' key structure differs can be a bit puzzling.

    As I understand it, the question is basically about DRYing up your locale files and using a feature of the YAML language to achieve this.

    Firstly, anchors are only really guaranteed to work for YAML so this solution can't be applied generically to I18n. This technique is probably not feasible if you use a different backend. Be it SQL, Redis or Json, I'm not aware of any of them having any kind symlinking functionality. And that's without going too much into the fact that under the hood, the translations are in fact duplicated.

    The second and bigger problem that I have is about linguistics. Your example makes the case that all of these terms are exactly equal in context and in meaning. Unfortunately this is only ever the case in extremely simple examples.

    Undoubtedly, as your app grows or as you add additional languages, you'll find that a Person's "name" attribute has to be distinct from say a Book's "name" attribute which in English we'll call a "title" - OK, this example is really convoluted ;) but as you mix in more and more languages this situation does occur frequently and ideally, we want a generic way of dealing with it.

    I think in large part, the complexity comes from the rails helpers that have evolved with different defaults without there being a convention for key structures.

    Going back to your example you mention 2 things that I think are really distinct : activerecord attribute translations which use the rails helpers and view translations which use the dot shortcut.

    Let me give you an example of a workflow that is super frequent :

    1. You create a form with the User's "name" field in this situation, you want to use the generic "name" attribute translations (label_tag should use something like :'attributes.name'). This is the simplest, DRYest case to get you up and running quickly, bulk translating simple attributes.
    2. A while later you decide that User's "name" needs to be translated as "full name" for this model only so you create a new translation that has a higher priority in label_tag's lookup call (say :'activerecord.attributes.users.name'))
    3. Later still, the marketing guy has the brilliant idea of displaying this field's label as "enter your funky fresh name" on this page (and only on this page). We're not describing the name attribute anymore, we're describing a particular view of this form; this is where the dot shortcut comes in converting :'.form.name' to something like ':users.new.form.name'.

    There is no way we could handle this situation with a shared "dictionary". Sure our locale file would be DRY, but our linguistic/translation concerns are vastly different from our developer concerns here (sadly).

    On the plus side, we can get clearer about what kind of content we're describing and reflect that in our key structures and in our tools - that for me is the way forward! :)

    0 讨论(0)
  • 2020-12-08 15:34

    I just release a gem called i18n-recursive-lookup that allows a definition to contain embedded references to other definitions by introducing the special embedded marker ${}

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

    Using it you could refactor your example to:

    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}
    

    The nice thing is that once compiled the translations are written back to the translation store so that all interpolation/recursive lookup happens once.

    I know this might not answer the more philosophical questions about what the 'right' way to DRY up translations is, but I thought it's a better alternative to using the & label reference YML hack.

    0 讨论(0)
  • 2020-12-08 15:36

    I just released a gem called dry_i18n: https://rubygems.org/gems/dry_i18n

    I created this gem in order to solve the issue you ask for. With this gem you'll be able to even reuse keys with interpolations and nest them.

    I hope it is useful.

    0 讨论(0)
提交回复
热议问题