简化Rails应用程序中的翻译

168 阅读4分钟

简化Rails应用程序中的翻译

国际化(i18n)或翻译是任何面向全球用户的应用程序的一个组成部分。Rails开箱即支持这一点。

要在你的Rails应用程序中添加一组翻译,是相当容易的。默认情况下,rails会在config/locales 文件夹中提供一个en.yml

en:
  hello: "Hello world"

这提供的是,locale:en 中的键hello 将有值Hello world

在这篇文章中,我们将专注于如何在应用程序变大时增加翻译文件,并尽可能避免杂乱和重复。

考虑一个有命名空间的应用程序,以及它下面的一组不同的上下文。在翻译文件中,最终出现下面这样的结构是很常见的:

en:
  admin:
    attendance 
      policies:
        index:
          blank:
            title: Some title

我们有一些命名空间要跨越,直到我们到达我们所需要的键,这就是title

考虑到目录app/views/admin/attendance/policies ,用于管理下的所有考勤命名空间的视图。它包含几个文件index.html.slim,_table.html.slimblank.html.slim

现在,如果对文件blank.html.slim 使用这个标题,我们就会把它当作t('admin.attendance.policies.index.blank.title') 。这不是好事,如果我们的关键词越来越大,或者我们有更多的命名空间,这只会变得更糟。

使用rails的懒人查询

Rails为我们提供了一个懒人查找功能,在这个功能中,如果翻译的路径与视图的路径直接同步,我们就不必提供整个路径。

让我重构一下上面的内容,给你看看。

我更新了视图文件app/views/admin/attendance/policies/_blank.html.slim ,使其翻译为。t(.title)

现在我更新了翻译文件,如下所示(请注意层次结构)

en:
  admin:
   attendance: 
      policies:
        blank:
          title: Some title

这里我去掉了索引,让blank 的键直接在policies 的键下。这就像我们的应用程序中的目录结构一样(检查上面的路径共享)。

如果这个结构匹配,rails会自动拾取t('.title')

长链路径是不需要的。

这将需要我们重新安排一下翻译文件,但额外的努力是值得的。

对常用术语进行分组

我们有很多表格和组件使用了与SubmitCancel 等相同的词,这些词在很多地方都被使用。我们应该在最小的层次下对它们进行分组,即没有一个长的链条。例如,与形式有关的东西可以被归类为:

en:
  form:
    submit: Submit
    cancel: Cancel

然后作为t('form.submit')t(:submit, scope: :form) 参考:你也可以像这样连锁作用域 t(:key, scopes: [:scope_one, :scope_two]),让我们尽可能地坚持最小化。

它可能不是表单,但可以是你可能遇到的应用程序的任何其他实体,最终目的是为了防止这种t('admin.some_module.some_resource.some_action.some_form') == "Submit" ,并且t('admin.another_module.another_resource.another_action.another_form') == "Submit"

注意:我已经看到了human_attribute_name 的用法,它在抽象出复杂性方面也很好--这里没有提到,因为这篇文章的意图主要是关注视图和参数,它们可能不会一直与模型对象打交道,即使有模型对象的也不一定会显示准确的名称。

分割文件

由于我们有很多模块,我们可以去把翻译文件也拆开。考虑到上述情况,任何特定模块的翻译都可以放在以下位置locales/admin/<module_name>/*.yml

目前我们看到的例子中,所有的翻译都在这个位置:config/locales/en.yml

按照分割的方法,我们最终会得到这样的路径config/locales/admin/attendance/en.yml

即使以这种方式,Rails也会懒得去查找翻译。

尽管拆分无助于减少冗余,但它有助于更好地安排。

方法

结合这三种方法将是一个理想的方法。首先让懒人查询发挥作用,然后重新安排常用的文件,最后将文件拆分。这没有硬性规定,因为它应该以同样的顺序进行,但最终我们应该能够做到所有这些。

决定一个词是在全局范围内还是在一个命名空间下移动是一个偏好,例如,如果像 "步骤1 "这样的东西在所有模块中都使用,那么它很可能被移出模块。只有步骤的定义可以改变。如果一个词只在两个模块中使用,那么把它放在模块中也是可以的,但翻译的理想用途是不重复任何一个词,也就是说,如果我们需要改变一些东西,我们只能在一个地方改变它。

提示:在做重构的时候,可以看看这个宝石i18n-tasks。它可以帮助你找到并管理丢失和未使用的翻译。