ruby-on-rails - 使用字典重构 Ruby on Rails i18n YAML 文件

标签 ruby-on-rails internationalization refactoring structure yaml

This StackOverflow 问题让我深思什么是 Rails i18n 文件的良好结构,所以我想我会分享另一种重构 Rails i18n yml 文件的结构,供您考虑/批评。

鉴于我想

  • 保留默认的应用程序结构,以便我可以使用速记“惰性”查找,例如 t('.some_translation')在我看来,以及有一个想法在应用程序中使用翻译,
  • 尽可能避免重复字符串,尤其是那些不仅相同而且上下文/含义相同的单词,
  • 只需更改一次 key 即可在其引用的任何地方反射(reflect)出来,

  • 对于 配置/语言环境/en.yml 看起来像这样的文件:
    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
    

    我可以看到存在显着的重复,并且“电子邮件”和“密码”等词的上下文是明确的,并且在各自的 View 中具有相同的含义。如果我决定将“电子邮件”更改为“电子邮件”,那么不得不全部更改它们会有点烦人,所以我想重构字符串以引用某种字典。那么,如何用一些 & 在文件顶部添加一个字典哈希值? anchor 是这样的:
    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
    

    您仍然可以继续使用静态字符串(例如上面的“用户”),但是当您在 View 中获得多个完全相同的词/短语实例时,您可以将其重构到字典中。如果基本语言中键的字典翻译对目标语言没有意义,则只需将目标语言中的引用值更改为静态字符串,或将其作为额外条目添加到目标语言字典中。我敢肯定,如果每种语言的词典太大且笨拙,都可以将它们重构为另一个文件(只要它在翻译文件的顶部重新导入,以便引用工作)。

    这种构建 i18n yaml 文件的方式似乎适用于我尝试过的一些本地测试应用程序。我希望精彩Localeapp将来会为这种 anchor 定/引用提供支持。但无论如何,所有这些字典谈话不可能是一个原创的想法,那么 YAML 中的 anchor 引用是否还有其他问题,或者可能只是整个“字典”概念?或者最好完全删除默认后端并将其替换为 Redis或者如果您有超出 Rails 默认 i18n 约定的需求?

    编辑 :

    我想尝试解决这里下面的评论中提到的 tigrish 的工作流程示例,而不是作为他的答案下方的另一条评论。如果我似乎没有得到所提出的观点或者我只是天真,请原谅我:

    第 1 点 :您有一个用于 ActiveRecord 模型的通用“名称”属性,它们都只是指向名称的通用字典:
    dictionary:
      name: &name Name
    
    activerecord:
      attributes:
        name: *name
        user:
          name: *name
        product:
          name: *name
    

    第 2 点 :用户模型的名称只需要更改。其他名称保持不变。

    选项 1:在后端保持模型字段名称相同,只需更改它指向的前端翻译。
    dictionary:
      name: &name Name
      full_name: &full_name Full Name
    
    activerecord:
      attributes:
        name: *name
        user:
          name: *full_name
        product:
          name: *name
    

    选项 2:也更改用户模型字段名称。这将需要更改代码中对此键的任何引用,以及 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
    

    选项 3:如果您想非常彻底,请将包含在“名称”中的信息重构为单独的数据库/Activemodel 字段,这将需要新的字典条目和迁移。您可以决定您希望“全名”如何显示的 View :
    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
    

    第 3 点 :任何人出于任何原因都需要翻译更改,在这种情况下是营销。我将从第 2 点选项 1 的示例继续

    选项1:模型字段名称相同,只需更改前端翻译。
    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
    

    选项 2:出于某种原因,“时髦的名字”也迫切需要保存到数据库中。我们称之为 username如果没有人反对(或 funky_name,如果出于某种原因营销部门坚持)。
    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
    

    是的,所以我承认我不知道我在做什么,但是,为了理解为什么这种在 Haml 中使用 i18n 的方式在 Rails 应用程序中是个坏主意,我愿意被公开驳斥。阅读困难?维修噩梦?如果我使用(我认为是)语言的一个特性,它真的被认为是“破解文件格式”吗?

    再次感谢 tigrish 驱使我解决所有这些问题。

    最佳答案

    TLDNR;不要破解您的文件格式,改进 rails 助手并帮助建立标准化的 key 结构!

    TLDR;

    不想在你的游行中下雨,但我对这项技术有一些问题。在何处使用点快捷方式以及 rails 助手的键结构如何不同的困境可能有点令人费解。

    据我了解,问题基本上是关于干燥您的语言环境文件并使用 YAML 语言的功能来实现这一点。

    首先, anchor 只能真正保证适用于 YAML,因此该解决方案不能普遍应用于 I18n。如果您使用不同的后端,此技术可能不可行。无论是 SQL、Redis 还是 Json,我都不知道它们中的任何一个具有任何类型的符号链接(symbolic link)功能。这并没有过多考虑在引擎盖下,翻译实际上是重复的。

    我遇到的第二个也是更大的问题是关于语言学的。您的示例说明所有这些术语在上下文和含义上完全相同。不幸的是,这只是在极其简单的例子中的情况。

    毫无疑问,随着您的应用程序的增长或添加其他语言,您会发现 Person 的“name”属性必须与 Book 的“name”属性不同,在英语中我们将其称为“title” - 好吧,这个例子真的很复杂 ;) 但是当你混入越来越多的语言时,这种情况确实经常发生,理想情况下,我们想要一种通用的方法来处理它。

    我认为在很大程度上,复杂性来自 Rails 助手,它们随着不同的默认值而演变,而没有关键结构的约定。

    回到你的例子,你提到了我认为非常不同的两件事:使用 rails 助手的 activerecord 属性翻译和使用点快捷方式的查看翻译。

    让我举一个非常频繁的工作流示例:

  • 在这种情况下,您使用用户的“名称”字段创建一个表单,您希望使用通用的“名称”属性翻译(label_tag 应该使用类似 :'attributes.name' 的内容)。这是最简单的 DRYest 案例,可让您快速启动并运行,批量翻译简单属性。
  • 一段时间后,您决定只需要将用户的“姓名”翻译为此模型的“全名”,因此您创建了一个在 label_tag 的查找调用中具有更高优先级的新翻译(例如:'activerecord.attributes.users.name' ))
  • 稍后,营销人员有一个绝妙的主意,即在此页面上(并且仅在此页面上)显示此字段的标签为“输入您时髦的新名称”。我们不再描述 name 属性,而是描述此表单的特定 View ;这就是点快捷方式将 :'.form.name' 转换为类似 ':users.new.form.name' 的地方。

  • 我们无法使用共享的“字典”来处理这种情况。当然,我们的语言环境文件是 DRY 的,但我们的语言/翻译问题与我们的开发人员关注的问题大不相同(遗憾的是)。

    从好的方面来说,我们可以更清楚地了解我们正在描述的内容类型,并在我们的关键结构和工具中反射(reflect)出来——这对我来说是前进的方向! :)

    关于ruby-on-rails - 使用字典重构 Ruby on Rails i18n YAML 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11097572/

    相关文章:

    internationalization - Gradle 为 i18n 和 PrettyFaces 构建配置文件

    mysql - 一列 SQL 表,该列是一个 ID - 这很疯狂吗?

    java - 重构 if-else 控制流程

    ruby-on-rails - 如何从谷歌分析导入报告?

    ruby-on-rails - ruby 检查当前日期是否在日期记录内

    regex - 连字符和撇号字符 - 不同语言的相同 ASCII 代码?

    java - 如何在Java中重构大量的if语句?

    javascript - 在 perl 脚本中包含单独的 javascript 文件

    ruby-on-rails - AWS::S3::错误::访问拒绝。无法使用 Ruby on Rails 保存到 S3

    ruby-on-rails - 一种模型 - Rails 中的许多数据库连接?