Android XML 资源

使用 Lingo.dev CLI 对 Android XML 资源文件进行 AI 翻译

什么是 Android XML 资源?

Android 使用基于 XML 的资源文件来存储用于本地化的字符串资源。这些文件通常存放在 res/values/ 目录下,并带有特定语言环境的子目录(例如,西班牙语为 res/values-es/)。

例如:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MyApp</string>
    <string name="welcome_message">Hello, world!</string>
    <string-array name="color_names">
        <item>Red</item>
        <item>Green</item>
    </string-array>
    <plurals name="notification_count">
        <item quantity="one">%d new message</item>
        <item quantity="other">%d new messages</item>
    </plurals>
</resources>

注意: 标记为 translatable="false" 的字符串不会被翻译,仅会出现在源语言环境文件中。

什么是 Lingo.dev CLI?

Lingo.dev CLI 是一款免费开源的命令行工具,可通过 AI 翻译应用和内容。它旨在替代传统的翻译管理软件,并可集成到现有的开发流水线中。

如需了解更多,请参见 概述

关于本指南

本指南介绍如何使用 Lingo.dev CLI 翻译 Android XML 资源文件。

你将学习如何:

  • 从零创建项目
  • 配置翻译流水线
  • 使用 AI 生成翻译内容

前置条件

要使用 Lingo.dev CLI,请确保已安装 Node.js v18 及以上版本:

❯ node -v
v22.17.0

步骤 1:创建项目

在你的项目目录下,创建一个 i18n.json 文件:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

该文件定义了翻译流水线的行为,包括需要翻译的语言以及本地化内容在文件系统中的位置。

如需了解可用属性,请参见 i18n.json

步骤 2:配置源语言环境

源语言环境 是指你的内容最初编写时所用的语言和地区。要配置源语言环境,请在 i18n.json 文件中设置 locale.source 属性:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

源语言环境必须以 BCP 47 语言标签 的形式提供。

有关 Lingo.dev CLI 支持的所有语言环境代码的完整列表,请参见 支持的语言环境代码

第 3 步:配置目标语言环境

目标语言环境 是指您希望将内容翻译成的语言和地区。要配置目标语言环境,请在 locale.targets 属性中设置于 i18n.json 文件:

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {}
}

第 4 步:创建源内容

如果尚未创建,请新建一个或多个包含待翻译内容的 Android XML 资源文件。

对于 Android XML 资源文件,需满足以下要求:

  • 文件必须为有效的 XML,并以 <resources> 作为根元素。
  • 字符串资源使用 <string name="key">value</string> 标签定义。
  • 字符串数组使用 <string-array name="key"><item>value</item></string-array> 结构。
  • 复数形式使用 <plurals name="key"><item quantity="one|other">value</item></plurals> 结构。
  • 标记为 translatable="false" 的元素不会被翻译。
  • 支持布尔型(<bool>)和整型(<integer>)资源类型。
  • 保留 CDATA 区段和 HTML 实体。

第 5 步:创建 bucket

  1. i18n.json 文件中,向 buckets 对象添加一个 "android" 对象:

    {
      "$schema": "https://lingo.dev/schema/i18n.json",
      "version": "1.10",
      "locale": {
        "source": "en",
        "targets": ["es"]
      },
      "buckets": {
        "android": {}
      }
    }
    
  2. "android" 对象中,定义一个或多个 include 模式的数组:

    {
      "$schema": "https://lingo.dev/schema/i18n.json",
      "version": "1.10",
      "locale": {
        "source": "en",
        "targets": ["es"]
      },
      "buckets": {
        "android": {
          "include": ["./[locale]/example.xml"]
        }
      }
    }
    

    这些模式定义了需要翻译的文件。

    模式本身:

    • 必须包含 [locale] 作为已配置语言环境的占位符
    • 可以指向文件路径(如 "[locale]/strings.xml"
    • 可以使用星号作为通配符(如 "[locale]/*.xml"

    不支持递归 glob 模式(如 **/*.xml)。

第 6 步:配置 LLM

Lingo.dev CLI 使用大型语言模型(LLM)通过 AI 翻译内容。要使用这些模型,您需要从支持的服务商获取 API 密钥。

为了尽快开始使用,我们推荐使用 Lingo.dev Engine —— 我们自有的托管平台,每月可免费使用 10,000 个 token:

  1. 注册 Lingo.dev 账号

  2. 运行以下命令:

    npx lingo.dev@latest login
    

    这将打开您的默认浏览器,并要求您进行身份验证。

  3. 按照提示操作。

步骤 7. 生成翻译内容

在包含 i18n.json 文件的目录下,运行以下命令:

npx lingo.dev@latest run

该命令将:

  1. 读取 i18n.json 文件。
  2. 查找需要翻译的文件。
  3. 提取文件中的可翻译内容。
  4. 使用已配置的 LLM 翻译提取的内容。
  5. 将翻译后的内容写回文件系统。

首次生成翻译时,会创建一个 i18n.lock 文件。该文件用于记录已翻译的内容,防止后续运行时重复翻译。

示例

en/example.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MyApp</string>
    <string name="welcome_message">Hello, world!</string>
    <string name="button_text">Get Started</string>

    <string name="api_endpoint" translatable="false">https://api.example.com</string>

    <string-array name="color_names">
        <item>Red</item>
        <item>Green</item>
        <item>Blue</item>
    </string-array>

    <plurals name="notification_count">
        <item quantity="one">%d new message</item>
        <item quantity="other">%d new messages</item>
    </plurals>
</resources>

es/example.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MyApp</string>
    <string name="welcome_message">¡Hola, mundo!</string>
    <string name="button_text">Comenzar</string>

    <string name="api_endpoint" translatable="false">https://api.example.com</string>

    <string-array name="color_names">
        <item>Rojo</item>
        <item>Verde</item>
        <item>Azul</item>
    </string-array>

    <plurals name="notification_count">
        <item quantity="one">%d mensaje nuevo</item>
        <item quantity="other">%d mensajes nuevos</item>
    </plurals>
</resources>

i18n.json

{
  "$schema": "https://lingo.dev/schema/i18n.json",
  "version": "1.10",
  "locale": {
    "source": "en",
    "targets": ["es"]
  },
  "buckets": {
    "android": {
      "include": ["./[locale]/example.xml"]
    }
  }
}

i18n.lock

version: 1
checksums:
  ec06a6ebae97ffd5f7afc99d9a8f051b:
    app_name: 7dc70110429d46e3685f385bd2cc941c
    welcome_message: 0468579ef2fbc83c9d520c2f2f1c5059
    button_text: 1d5f030c4ec9c869e647ae060518b948
    html_snippet: f060191b1af70b3848106a4df91f43cd
    apostrophe_example: 997099339b144b06266f8da411de8d93
    cdata_example: ba876d1379f854628eaebf67ea330ccc
    color_names/0: bace0083b78cdb188523bc4abc7b55c6
    color_names/1: 482ff383a4258357ba404f283682471d
    color_names/2: a5cf034b2d370a976119335cd99f4217
    mixed_items/0: 9278f79dfb062c6c04f6395108907816
    mixed_items/1: 9823a57cbe6e6e84c1d025ce24a1eec4
    notification_count/one: fe0aceb70f334c52a87937c36898a1d0
    notification_count/other: 13acfd95b16962ebe1f67dcd343513e1