# General Translation Knowledge Base: General Translation 与 Mobility：该选哪一个？
URL: https://generaltranslation.com/zh/kb/general-translation-vs-mobility.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Mobility 将翻译后的模型属性存储在您的数据库中。General Translation 则通过其 API，结合您的词汇表和自定义提示词生成这些译文。两者搭配使用，即可在保留现有 Rails 模型的同时，翻译商品列表、文章及其他数据库内容。
Category: 国际化
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

Mobility 是一个用于翻译数据库中数据的 Ruby gem：只需在模型上声明 `translates :title`，`post.title` 就会从您选择的存储后端读取并返回当前区域设置下的标题。它只负责存储和读取译文，译文本身则需要由您的编辑、译者或某种服务来提供。General Translation 正是通过其 HTTP API 来提供这些译文。Mobility 将翻译后的属性保存在您现有的数据库中，您可以继续沿用现有的查询和模型方法来访问它们。

## Mobility 的优势

* **多种存储方式可选。** 默认的 `key_value` 后端[将所有翻译保存在两张共享表中](https://github.com/shioyama/mobility/wiki/KeyValue-Backend) (一张存字符串，一张存文本) 。`table` 后端为每个模型使用一张翻译表 (即 Globalize 的做法) ；`column` 使用带后缀的列，例如 `title_en` 和 `title_es`；`serialized` 将翻译保存在单个文本列中；在 PostgreSQL 上，`json`、`jsonb`、`hstore` 和 `container` (每个模型一个 jsonb 列) 则以原生方式存储翻译。你也可以自行编写后端。
* **跨后端统一的 API。** 读写操作均遵循 `I18n.locale`，各类插件 (后备内容、`post.title_es` 这类区域设置访问器、脏值跟踪、缓存以及存在性检查) [无论选用哪种后端，行为都完全一致](https://github.com/shioyama/mobility#backends)。
* **查询。** [`Post.i18n.where(title: "...")`](https://github.com/shioyama/mobility#querying) 会针对当前区域设置自动构建连接，因此无需了解翻译属性的存储方式即可直接搜索。
* **ORM 支持。** 它[支持 Active Record 7.0 及以上版本和 Sequel](https://github.com/shioyama/mobility#installation)，其 wiki 中还提供了从 Globalize 迁移的指南。
* **免费。** 采用 MIT 许可证；[当前发布版本为 1.3.2](https://rubygems.org/gems/mobility)。

## Mobility 留给你处理的部分

下面是一篇包含英文标题和正文的文章，它在 SQLite 上使用 `key_value` 后端，并且仅为标题配置了从西班牙语到英语的后备内容：

```ruby title="app/models/post.rb"
class Post < ApplicationRecord
  extend Mobility
  translates :title, type: :string, fallbacks: { es: :en }
  translates :body,  type: :text
end
```

```ruby
post = Post.create!(title: "Spring sale", body: "Everything is 20% off this week.")

I18n.with_locale(:es) { post.title } # => "Spring sale"（英文，来自后备语言）
I18n.with_locale(:es) { post.body }  # => nil
I18n.with_locale(:ja) { post.title } # => nil
```

对存储层来说，这正是应有的行为：Mobility 保存了英文值，而在有人写入内容之前，其他区域设置都是空的。如果配置了后备内容，西班牙语读者会看到英文；如果没有，他们就什么也看不到。对于商品列表、文章或帮助页面这类每天都在变化的内容，必须有人把每条新增或修改过的记录翻译成各种语言，并保存到对应的区域设置下。

## 使用 General Translation 填充 Mobility 属性

General Translation 的运行时翻译端点 `POST https://api.gtx.dev/v2/translate` 可按需翻译字符串。调用时，需将具有 **运行时翻译** 权限的项目 API 密钥作为 bearer token 传入，并在请求体中提供：一个以你自定义的 ID 为键的 `requests` 对象 (每项包含一个 `source` 字符串，以及可选的 `metadata`，例如 `context` 备注) ，外加 `sourceLocale`、`targetLocale` 和一个顶层 `metadata` 对象 (可以为空) 。响应同样以这些 ID 为键。只需一个简短的 Ruby 方法即可完成：

```ruby title="app/services/gt_translate.rb"
require "net/http"
require "json"

# 使用 General Translation 的运行时 API 翻译 { field => text } 形式的哈希。
# 返回所有请求的翻译结果；若有失败，则在写入数据库之前抛出异常。
def gt_translate(fields, from:, to:, context: nil)
  uri = URI("https://api.gtx.dev/v2/translate")
  requests = fields.to_h do |field, text|
    [field.to_s, { source: text, metadata: { dataFormat: "STRING", context: context }.compact }]
  end

  request = Net::HTTP::Post.new(uri)
  request["Authorization"] = "Bearer #{ENV.fetch("GT_API_KEY")}" # 具有“运行时翻译”权限的项目密钥
  request["Content-Type"] = "application/json"
  request["gt-api-version"] = "2026-03-06.v1"
  request.body = { requests:, sourceLocale: from.to_s, targetLocale: to.to_s, metadata: {} }.to_json

  response = Net::HTTP.start(uri.host, uri.port, use_ssl: true,
                            open_timeout: 5, read_timeout: 30) { |http| http.request(request) }
  raise "Translation request failed (#{response.code})" unless response.is_a?(Net::HTTPSuccess)

  results = JSON.parse(response.body)
  requests.keys.to_h do |field|
    result = results.fetch(field)
    unless result["success"] == true && result["translation"].is_a?(String)
      raise "Translation incomplete for #{field}"
    end
    [field, result.fetch("translation")]
  end
end
```

如需对上面的文章进行一次性翻译，请读取其英文属性，并保存完整的西班牙语翻译结果：

```ruby
source = Mobility.with_locale(:en) do
  { title: post.title(fallback: false), body: post.body(fallback: false) }
end
translated = gt_translate(source,
                          from: :en, to: :es, context: "Blog post for an online shoe store")
Mobility.with_locale(:es) { post.update!(translated) }
```

该辅助函数会在更新文章之前，检查每个请求的字段是否都已有译文。模型原有的校验规则依然有效。 (有关请求和响应字段，请参阅[端点参考](/docs/platform/openapi/reference/translation/translate-content)。)

General Translation 不只是一次简单的机器翻译调用：该端点会结合项目的[词汇表和自定义提示词](/docs/platform/dashboard/guides/defining-context-for-translations)进行翻译，确保产品名称和语气与产品其他部分保持一致。上下文备注会告诉它这些文本用于一家鞋店；共享术语则让这些产品描述与你的应用和营销网站保持统一。请务必将 API 密钥保存在服务器端。如需持续自动化，请将翻译接入现有的内容发布工作流，并遵守 API 的[速率限制](/docs/platform/openapi/overview#api-basics)。

本示例直接将结果保存到模型中。如果内容需要编辑在发布前审核，请通过与源文章相同的草稿和发布流程来保存结果。

## Mobility 与 General Translation 对比一览

| 功能           | Mobility             | General Translation                             |
| ------------ | -------------------- | ----------------------------------------------- |
| 定位           | 用于存储模型属性译文的 Ruby gem | 翻译平台，提供 HTTP API、CLI、JavaScript 和 Python 库以及仪表板 |
| 将译文存储在您的数据库中 | 是，支持八种存储后端           | 为同样这些模型属性提供译文                                   |
| 生成译文         | 否                    | 是，通过 `POST /v2/translate`                       |
| Ruby 集成      | 模型属性和区域设置访问器         | 在 Ruby 中调用 HTTP API                             |
| 术语和语气一致性     | 取决于您的译者              | 每个请求都会应用词汇表和自定义提示词                              |
| 费用           | 免费，MIT 许可            | [按用量计费](https://generaltranslation.com/pricing) |

## 何时只用 Mobility 就够了

如果你的译文本来就由人工完成，例如编辑在管理后台表单中逐一录入各语言内容、交给翻译公司处理，或者是法律文本这类必须人工翻译的内容，那么单独使用 Mobility 就够了。如果你只支持两三种语言，且记录很少变动，只用 Mobility 也足以应对。当内容增长的速度超过人工翻译的速度时，例如用户发布的商品信息、帮助中心文章，或包含数千种商品的商品目录，而你又希望每条新记录一经保存就能立即提供所有语言版本，就可以引入 General Translation。

## 要点总结

* Mobility 支持在八种后端中存储和读取已翻译的模型属性，并提供后备内容和查询功能，但它本身不负责生成译文。
* Rails 应用调用 General Translation 的 `POST /v2/translate` 端点，再通过 Mobility 保存翻译后的属性。
* General Translation 会应用你的词汇表、自定义提示词以及针对具体内容的上下文，而你现有的模型和发布工作流均无需改动。

## Related questions

- [General Translation 与 Rails I18n：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-rails-i18n.mdx): Rails I18n 负责查找消息并格式化日期和数字。General Translation 负责生成译文，在英文内容变更时让译文保持同步，并为团队提供用于审校的仪表板。两者搭配使用，即可在每次发布时交付已翻译的 Rails 目录。
- [General Translation 与 i18n-tasks：应该选择哪一个？](https://generaltranslation.com/zh/kb/general-translation-vs-i18n-tasks.mdx): i18n-tasks 是一个 Ruby gem，用于查找缺失和未使用的 Rails I18n 键、整理区域设置文件，还能借助 Google Translate、DeepL、OpenAI、Yandex 或 watsonx 补全缺失的键。General Translation 则结合你的词汇表、自定义提示词和仪表板审校，翻译完整的区域设置文件。两者分工不同，许多团队完全可以搭配使用。
- [Google Translate 替代方案：General Translation 与 Google Translate 对比](https://generaltranslation.com/zh/kb/general-translation-vs-google-translate.mdx): Google Translate 适合快速翻译一次性文本，但要以另一种语言发布产品，还需要结合上下文翻译每个字符串、保持术语一致、正确处理变量和复数形式、进行审校，并建立发布流程。General Translation 能理解代码中每个字符串的上下文，将从代码、审校到每一次发布的整个本地化工作流全面自动化。
- [General Translation 与 i18next、react-intl 和 next-intl 对比：应该选择哪个国际化库？](https://generaltranslation.com/zh/kb/general-translation-vs-i18n-libraries.mdx): i18next、react-intl 和 next-intl 等开源库本身并不翻译任何内容。它们只负责显示你在各语言目录文件中提供的译文，这些译文由你、你的译者或其他服务编写。General Translation 的库同样开源，承担同样的工作，此外 General Translation 还会以你的代码为上下文完成翻译。
- [为什么选择 General Translation 而不是 TMS（Smartling、Lokalise、Phrase、Crowdin 或 Transifex）？](https://generaltranslation.com/zh/kb/general-translation-vs-tms.mdx): Smartling、Lokalise、Phrase、Crowdin 或 Transifex 等翻译管理系统（TMS）负责协调译员，但工程师仍需提取字符串、发送出去、等待译文，再把译文接回产品中。General Translation 结合上下文直接翻译代码中的内容，每次发布都同步交付所有语言，并基于开源库运行，不存在供应商锁定。

## Previous and next questions

- Previous question: [General Translation 与 Locize 对比：该选哪个？](https://generaltranslation.com/zh/kb/general-translation-vs-locize.mdx)
- Next question: [General Translation 与 nestjs-i18n：该选哪一个？](https://generaltranslation.com/zh/kb/general-translation-vs-nestjs-i18n.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/zh/kb/sitemap.md) for every article.
