你如何在 Rails 中构建 i18n yaml 文件?

Posted

技术标签:

【中文标题】你如何在 Rails 中构建 i18n yaml 文件?【英文标题】:How do you structure i18n yaml files in Rails? 【发布时间】:2012-05-04 04:49:39 【问题描述】:

我开始在 Rails 中填充一个 en yaml 文件,我已经知道它很快就会变得混乱和失控。是否有保持此文件井井有条的约定?

到目前为止,我有这个结构:

language:
  resource:
    pages: # index, show, new, edit
      page html elements: # h1, title
  activerecord:
    attributes:
      model:
        property:

现在我想将以下内容融入此结构,但我不确定如何:

    导航 按钮文本(保存更改、创建帐户等) 来自控制器闪存的错误消息 如何添加多字键。我使用空格还是下划线?例如,t(".update button")) 或 t(".update_button")

语言环境文件结构有约定吗?

【问题讨论】:

您现在可以将惰性查找与您自己的自定义语言环境命名空间一起使用:github.com/abitdodgy/i18n_lazy_scope 【参考方案1】:

直接编辑 yaml 文件会导致文件混乱且无法读取。 此外,如果有一天您希望非开发人员添加一种新语言,您将很难提供对翻译人员的访问权限。

我建议使用localeapp,它会生成一个 yaml 文件。 但允许您在网络界面中轻松查看和管理您的翻译。 并为翻译人员创建额外的访问权限。

【讨论】:

谢谢。虽然我很欣赏您的意见,但它并没有回答这个问题。不过,这绝对是一项有趣的服务。我开始使用它。 对于 localeapp,您是否将一种语言的所有翻译键放入 localeapp 生成的单个 yaml 文件中?或者你还在使用 application.*.yml 吗?【参考方案2】:

您的问题不容易回答,关于该主题的可用资料不多。我发现最好的资源是:

Rails Styleguide,国际化部分 I18n wiki 中有很多资源,但我没有找到可以回答您问题的资源。

所以我就直接在这里试一试:

导航

我认为您的意思是导航元素,如面包屑、标签、... 您必须为它们定义视图,然后遵守规则将所有视图元素移动到目录views 中的单独文件中(请参阅规则的样式指南)。

按钮文本(保存更改、创建帐户等)

查看元素,也进入相同的文件。如果您在不同的视图中使用相同的按钮,请定义一个通用文件,然后使用它。

来自控制器闪存的错误消息

我会使用与视图相同的规则。定义一个单独的目录,在其中包含控制器的文件。

如何添加多字键。我使用空格还是下划线?例如,t(".update button")) 或 t(".update_button")

我个人更喜欢使用.update_button,而不是.update button,因为它更明确地表明这是一个键。

【讨论】:

【参考方案3】:

我发现最好的整体策略是在某种程度上重现文件结构,以便在给出任何翻译后,我可以立即找到调用它的位置。这为我提供了一些翻译背景。

大多数应用程序翻译都在视图中找到,所以我最大的***命名空间通常是views

我为控制器名称和正在使用的操作名称或部分创建子名称空间:

views.users.index.title views.articles._sidebar.header

这两个示例都应该清楚地表明我们正在翻译我的应用程序的哪个部分以及要查看哪个文件来找到它。

您提到导航和按钮,如果它们是通用的,那么它们属于 views.application 命名空间,就像它们的视图对应物一样:

views.application._main_nav.links.about_us - 我们应用主导航部分中的链接 views.application.buttons.save views.application.buttons.create - 我有一堆这样的按钮可以在需要时使用

Flash 消息是从控制器生成的,因此它们的***命名空间是...controllers! :)

我们应用与视图相同的逻辑:

controllers.users.create.flash.success|alert|notice

同样,如果您想提供“操作成功”之类的通用 Flash 消息,您可以编写如下内容:

controllers.application.create.flash.notice

最后,key 可以是任何有效的 YAML,但按照惯例,请坚持使用句点 . 作为分隔符并在单词之间使用下划线 _

现在唯一需要解决的事情就是将 rails 的翻译转换到它自己的命名空间中以清理我们的顶层 :)

【讨论】:

太棒了!谢谢你。我已经陷入了这种模式,但不确定我是否以正确的方式进行。 我喜欢这种模式,但遗憾的是,Rails 没有内置任何东西来帮助管理闪存消息,因为它是针对活动记录错误(使用级联)完成的。我们总是必须一遍又一遍地输入相同的范围......根本不是 DRY...... @GauthierDelacroix 我意识到了这一点,所以我构建了一个 gem,让您可以在自己的自定义命名空间中使用惰性查找:github.com/abitdodgy/i18n_lazy_scope【参考方案4】:

我知道答案已经被接受,但是这个问题为我提供了一些思考的食物,我想我会分享 Rails i18n yml 文件的另一种结构供您考虑/批评。

因为我愿意

    保留默认应用结构,以便在我的视图中使用速记“惰性”查找,例如 t('.some_translation'), 尽可能避免重复字符串,尤其是单词不仅相同,而且具有相同的上下文/含义, 只需更改一次密钥,即可在所引用的任何地方反映它,

对于一个看起来像这样的 config/locales/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

我可以看到有很多重复,并且“电子邮件”和“密码”等词的上下文是明确的,并且在各自的视图中具有相同的含义。如果我决定将“电子邮件”更改为“电子邮件”,则必须全部更改它们会有点烦人,所以我想重构字符串以引用某种字典。那么,如何使用一些 & 锚在文件顶部添加字典哈希,如下所示:

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

当您在视图中获得多个完全相同的单词/短语时,您可以将其重构到字典中。如果基本语言中键的字典翻译对目标语言没有意义,则只需将目标语言中的引用值更改为静态字符串或将其作为额外条目添加到目标语言的字典中。我敢肯定,如果每种语言的字典变得太大且笨拙,都可以将它们重构到另一个文件中。

这种构建 i18n yaml 文件的方式似乎适用于我尝试过的一些本地测试应用程序。我希望美妙的Localeapp 将在未来为这种锚定/引用提供支持。但无论如何,所有这些字典讨论都不可能是一个原创的想法,那么 YAML 中的锚引用是否还有其他问题,或者可能只是整个“字典”概念?还是完全删除默认后端并将其替换为Redis 或其他什么更好?

【讨论】:

这是个好问题。也许你可以发布它,看看你得到了什么输入? 感谢您的反馈!我在 SO here 上将此作为自己的问题发布,所以让我们看看会发生什么。 这增加了一个额外的间接层(并增加了知识债务),以获得最小的好处,可以在重复出现的少数情况下使用查找和替换来缓解。此外,您多久更改一次电子邮件、密码、确认等简单术语的措辞。在应用的生命周期内使用一次或两次? 您现在可以对自定义命名空间使用惰性查找。这解决了组织语言环境文件的最大部分:github.com/abitdodgy/i18n_lazy_scope 不同意@Magne。如果您构建了重要的 Rails 应用程序,您会发现自己几乎到处都在重复与业务领域相关的词。对我来说,我必须记住“此文件中的 * 表示它是字典术语”的次数总是少于我为相同单词添加/更改翻译的次数。我认为这是一个优雅的解决方案。【参考方案5】:

我问这个问题已经快两年了,我想分享一些见解。我相信最佳结构是根据它们的 MVC 角色(模型、视图、控制器)进行命名空间转换。这使语言环境文件保持整洁,并防止命名空间冲突(例如,范围 en.users 可以表示视图或控制器)。

en:
  controllers:
    users:
      show:
        welcome_flash: "Welcome back!"
  mailers:
    users_mailer:
      welcome_email:
        subject: "Good of you to join us"
  views:
    users:
      show:
        notice: "Oh no!

但是使用像这样整洁的命名空间会破坏 Rails 中的惰性查找功能。如果您使用惰性查找,Rails 会自动为您插入命名空间,并且它不会包含您创建的***命名空间(viewscontrollers 等...)。

例如,t('.welcome_flash') 的范围解析为 en.users.show。这很臭,因为用户没有明确定义。它是什么?控制器?一个看法?还有什么?

解决这个问题I created the gem I18nLazyLookup。它允许您对自己的自定义命名空间使用惰性查找。

您可以使用t_scoped('welcome_flash'),而不是使用t,这样会自动将范围解析为en.controllers.users.show。它也适用于视图和邮件程序,您可以按照自己喜欢的方式自定义命名空间。

【讨论】:

如何将闪光灯放在显示它们的视图中?所以 welcome_flash 会在 view.users.show.welcome_flash 下。这样你就可以消除控制器/视图命名空间的区别,并且只是隐含地假设 users.show.notice 指的是视图(控制器也会闪烁,ofc)。似乎减少了 YAML 文件的混乱程度。 @Magne 我发现我更喜欢在设置字符串的位置命名字符串。所以我更喜欢在控制器中命名控制器闪存消息。尤其是在大多数情况下,flash 对整个应用程序都是通用的,并且通常存在于布局中,不属于特定的动作。但是两者都有理由。我只是更喜欢更明确。 我还没有找到明显优于其他方案的方法。我最终只是创建了自己的系统,该系统使用我自己的 I18n 后端,我设计该后端允许我从字符串中引用键。这让我可以按照自己喜欢的方式组织文件,但仍然通过指定它们并指向它们在 YAML 文件中的真实键来提供 Rails 正在查看的范围。这对我来说没问题,因为它是一个个人项目,但在这方面缺乏标准化仍然使多人难以做出贡献。【参考方案6】:

战斗结束几年后,但这里有一个(有点完全)不同的答案。

首先,我不喜欢带有基于文件结构的默认命名空间的标准t('.xxx') 样式。我也不太喜欢根据 DOM 结构对翻译进行分类。虽然这对于非常结构化的翻译来说是一种不错的方法,但它通常是重复的,而且不是很直观。

我宁愿将我的翻译重新组合成更有用的类别,以便让我的翻译更容易,因为他们可以处理具体的主题,而不是一些奇怪的风格(有些翻译甚至不知道 MVC 是什么意思)

所以我的翻译文件的结构是这样的

fr:
  theme1:
    theme11:
      translationxxx: blabla
  theme2:
    translationyyy: blabla

根据需要,“主题”可以是模型、更抽象的上下文等,对译者来说是最直观的。

因为每次在我的视图中编写范围都会很麻烦,所以我在帮助程序中添加了一些方便的方法来获得基于堆栈的翻译上下文。

我通过调用t_scope([new_scope]pop_t 在我的视图中将翻译范围推入/弹出堆栈 我重写了 t 帮助程序以使用堆栈的最后一个范围

翻译范围方法的代码在that answer中提供

【讨论】:

以上是关于你如何在 Rails 中构建 i18n yaml 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails 3 中使用 I18n 后备功能

如何使用 i18n 和 rails 配置语言环境别名?

如何在Rails中的I18n zh-CN文件中返回数组转换?

使用rails(I18n)Api翻译错误消息

Rails:如何将I18N放入SVG文件

在 Vue-CLI 3 项目的 i18n 标签中添加 yaml-loader