# General Translation Knowledge Base: 什么是伪本地化？
URL: https://generaltranslation.com/zh/kb/pseudo-localization.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 伪本地化是一种测试方法：将源文本替换为改写后的版本——加上重音符号、长度扩充约 40%，并用方括号包裹——这样在还没有任何翻译之前，硬编码字符串、截断、字体显示异常和句子拼接等问题就会暴露出来。Android 为此内置了 en-XA 和 ar-XB 两个伪区域设置。
Category: 国际化
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

伪本地化 (英文也写作 pseudolocalization) 检验的是代码是否已为翻译做好准备，而非翻译质量的好坏。由于改写后的文本依然可读，团队里的任何人都能在伪区域设置下把应用点一遍，找出出问题的地方。它几秒钟就能跑完，零成本，而且从开发第一天起就能用上。

## 伪翻译与伪区域设置有什么区别？

[Microsoft 的全球化文档](https://learn.microsoft.com/en-us/globalization/methodology/pseudolocalization)将其分为两部分：

* **伪翻译**转换的是字符串本身：&quot;Save changes&quot; 会变成类似 `[Šáṽé çĥáñĝéš~~~~~]` 的形式。
* **伪区域设置**是虚构的区域设置代码，例如 Windows 的 `qps-ploc` 或 Android 的 `en-XA`，可以像真实语言一样选用。有些伪区域设置还会刻意采用不寻常的日期、时间和数字格式，用于测试格式化代码。

Microsoft 建议使用格式规范、但永远不会对应真实区域设置的代码，例如 Windows 的 `qps-` 系列代码，它们位于 BCP 47 保留给私有用途的范围内。这条经验来之不易：Microsoft 最初使用的伪区域设置是 `tk-TM` (土库曼语，土库曼斯坦) ，而该代码后来作为真实的 Windows 区域设置正式发布，结果与构建和测试系统产生了冲突。

## 伪本地化能发现哪些问题？

* **硬编码字符串。** 凡是没有经过 i18n 层处理的文本，都会保持纯英文，而周围的内容都带有重音符号，因此在每个页面上都格外显眼。 (如需在代码中查找这些字符串，请参阅[如何查找未翻译的硬编码字符串？](/kb/find-hardcoded-strings)) 
* **文本膨胀导致的截断和溢出。** 填充后的字符串能暴露出哪些按钮、标签页和表头会被裁切、换行异常，或把控件挤出屏幕。
* **编码和字体问题。** 带重音符号的字符和非拉丁字符能暴露出编码错误、缺少对应字形的字体，以及会截掉变音符号的行高。
* **字符串拼接。** 由片段拼接而成的句子会显示为多个带方括号的片段，如 `[Ýöû ĥáṽé~~~~] 3 [íţéɱš~~]`，而不是一个整体。这说明译者拿到的只是零散片段，而非完整句子。
* **缺少从右到左支持。** 借助 RTL 伪区域设置，可以看出布局是否会镜像翻转、哪些图标需要翻转，以及从左到右的值会在哪些地方出错。 (请参阅[如何在 CSS 中支持 RTL (从右到左) 语言？](/kb/right-to-left-css))

## 伪本地化是如何工作的？

大多数工具会组合使用以下几种手段：

* **重音符号和其他文字体系。** 按照 Microsoft 指南的建议，将 `a` 替换为 `á`、`ä` 或 `å` 等字符，并将数字替换为带圈数字。
* **扩展。** 加长每个字符串。对于英文源文本，Microsoft 建议以约 40% 作为经验值，并指出某些字符串翻译后会变长 200% 甚至 400%，其中只有一两个单词的字符串增幅最大。
* **分隔符。** 用方括号或脱字符等标记包裹每个字符串。如果缺少结束标记，就说明文本被截断了。
* **标识符。** 可选择为每个字符串添加一个简短 ID，方便测试人员追溯其源字符串。
* **从右到左。** 反转文本方向，让 UI 呈现出阿拉伯语或希伯来语环境下的效果，Android 的 `ar-XB` 和 Windows 的镜像 `qps-plocm` 就是这样做的。

译文也可能变短。宽度变化取决于具体字符串以何种字体、字号和字重渲染，而非整个语言统一的固定百分比。填充式伪翻译用于测试扩展情况；较短的标签、间距和对齐，还需要用真实译文来检查。

## 哪些平台内置了伪区域设置？

| 平台                  | 伪区域设置                                                                | 作用                                                          | 启用方式                                                                                      |
| ------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Android             | `en-XA`、`ar-XB`                                                      | `en-XA` 会添加重音符号、拉长文本，并用括号包裹每条消息；`ar-XB` 会将消息切换为从右到左，并反转字符顺序 | 在 debug 构建类型中设置 `pseudoLocalesEnabled`；启用开发者选项并重启设备，然后在设备的语言设置中选择伪区域设置                    |
| Xcode (iOS, macOS)  | Double-Length、Right-to-Left、Accented、Bounded String、Tall 等伪语言        | 将字符串长度加倍、翻转文本方向、添加重音符号、包裹字符串以暴露截断问题、增加垂直高度                  | **Product &gt; Scheme &gt; Edit Scheme &gt; Run &gt; Options**，然后在 **App Language** 菜单中选择 |
| Windows             | `qps-ploc`、`qps-plocm`、`qps-ploca` (Windows 10 起另有 `qps-Latn-x-sh`)  | 基础、镜像 (从右到左) 和东亚伪区域设置，附带日期、字体和字符串长度的测试数据                    | 将伪区域设置名称传入 NLS API (如 `GetLocaleInfoEx`) ；Microsoft 的 Multilingual App Toolkit 可对资源进行伪翻译  |
| Lingui (JavaScript) | 任意自定义名称的区域设置，例如 `pseudo-LOCALE`                                      | 在编译时生成带重音符号的消息，还可选择生成从右到左的变体                                | Lingui 配置中的 `pseudoLocale` 键                                                              |

在 Android 上，可按照[伪区域设置指南](https://developer.android.com/guide/topics/resources/pseudolocales)在模块的 Gradle 文件中启用：

```kotlin title="build.gradle.kts"
android {
    buildTypes.getByName("debug") {
        isPseudoLocalesEnabled = true
    }
}
```

[Gradle 参考文档](https://developer.android.com/reference/tools/gradle-api/8.3/null/com/android/build/api/dsl/BuildType)指出，可以使用 `resourceConfigurations` 过滤器从 APK 中剔除伪区域设置资源。在 Xcode 中，同一个 scheme 设置面板还提供 **Show non-localized strings** 选项，开启后，Xcode 不会导出的字符串将以全大写形式渲染。 (参见 Apple 的 [Preparing your interface for localization](https://developer.apple.com/documentation/xcode/preparing-your-interface-for-localization)。) Windows 在 [Pseudo-Locales](https://learn.microsoft.com/en-us/windows/win32/intl/pseudo-locales) 页面列出了相关代码，并说明这些代码默认不会被枚举为系统区域设置 ([Using pseudo-locales](https://learn.microsoft.com/en-us/windows/win32/intl/using-pseudo-locales-for-localization-testing)) ；Lingui 则在其[伪本地化指南](https://lingui.dev/guides/pseudolocalization)中介绍了具体的初始化设置方法。

## 在 JavaScript 中对字符串进行伪本地化

Web 平台没有内置的伪区域设置，不过自己写一个转换函数也只需几行代码。下面的函数会为 ASCII 字母加上重音符号，将长度扩充约 40%，并用方括号包裹结果，同时保留 `{placeholders}` 和 HTML 标签原样不动，确保插值和标记仍能正常工作：

```js title="pseudo.mjs"
// 与 ASCII 字母形似的带重音字符
const ACCENTS = {
  a: 'á', b: 'ƀ', c: 'ç', d: 'ð', e: 'é', f: 'ƒ', g: 'ĝ', h: 'ĥ', i: 'í',
  j: 'ĵ', k: 'ķ', l: 'ļ', m: 'ɱ', n: 'ñ', o: 'ö', p: 'þ', q: 'ǫ', r: 'ŕ',
  s: 'š', t: 'ţ', u: 'û', v: 'ṽ', w: 'ŵ', x: 'ẋ', y: 'ý', z: 'ž',
  A: 'Á', B: 'Ɓ', C: 'Ç', D: 'Ð', E: 'É', F: 'Ƒ', G: 'Ĝ', H: 'Ĥ', I: 'Í',
  J: 'Ĵ', K: 'Ķ', L: 'Ļ', M: 'Ṁ', N: 'Ñ', O: 'Ö', P: 'Þ', Q: 'Ǫ', R: 'Ŕ',
  S: 'Š', T: 'Ţ', U: 'Û', V: 'Ṽ', W: 'Ŵ', X: 'Ẋ', Y: 'Ý', Z: 'Ž',
};

// {name} 之类的占位符和 <b> 之类的标签必须保持原样
const PROTECTED = /(\{[^}]*\}|<[^>]+>)/;

export function pseudoLocalize(text, { expansion = 0.4 } = {}) {
  const accented = text
    .split(PROTECTED)
    .map((part, i) =>
      i % 2 === 1 ? part : part.replace(/[A-Za-z]/g, (ch) => ACCENTS[ch])
    )
    .join('');
  // 按源文本长度的约 40% 进行填充，以模拟更长的译文
  const padding = '~'.repeat(Math.ceil(text.length * expansion));
  // 方括号标示字符串的起止位置，便于发现截断
  return `[${accented}${padding}]`;
}
```

```js title="demo.mjs"
import { pseudoLocalize } from './pseudo.mjs';

for (const source of ['Save changes', 'Hello, {name}!', 'Read the <a>terms</a>']) {
  console.log(pseudoLocalize(source));
}
```

使用 Node.js 24 运行 `node demo.mjs`：

```text title="Output"
[Šáṽé çĥáñĝéš~~~~~]
[Ĥéļļö, {name}!~~~~~~]
[Ŕéáð ţĥé <a>ţéŕɱš</a>~~~~~~~~~]
```

用法是：在启用调试标志或伪区域设置时，对 i18n 层返回的每条消息都应用该函数。这样一来，拼接而成的句子就会原形毕露：

```js title="concatenation.mjs"
import { pseudoLocalize } from './pseudo.mjs';

// ❌ 拆成三段：译者始终看不到完整的句子
console.log(pseudoLocalize('You have') + ' 3 ' + pseudoLocalize('items'));
// ✅ 合并为一条带占位符的消息
console.log(pseudoLocalize('You have {count} items'));
```

```text title="Output"
[Ýöû ĥáṽé~~~~] 3 [íţéɱš~~]
[Ýöû ĥáṽé {count} íţéɱš~~~~~~~~~]
```

该占位符正则表达式仅能处理简单的 `{name}` 变量。ICU plural 和 select 消息存在嵌套花括号，因此应对格式化后的输出进行伪本地化，而不是直接处理原始消息。 [`pseudo-localization`](https://github.com/tryggvigy/pseudo-localization) npm 软件包同样如此：它的 `pseudoLocalizeString('Hello, {name}!')` 会返回 `Ħḗḗŀŀǿǿ, {ƞȧȧḿḗḗ}!`，连占位符名称也被加上了重音符号。因此，请按照其 README 中的示例，对翻译后的输出运行该函数。 该软件包还提供用于从右到左测试的 `bidi` 策略，以及可对整个页面进行伪本地化的 DOM 模式。如需自行进行 RTL 检查，请在伪区域设置启用时，在 `<html>` 元素上设置 `dir="rtl"`。

要找出硬编码的字符串，应在 i18n 边界处进行转换。对整个页面做 DOM 转换会连硬编码文本一并改变，虽然可用于测试布局，却无法看出哪些字符串没有经过你的翻译调用。对格式化后的输出进行转换，还会改变插值进去的名称及其他数据；请在测试 UI 中保留这类输出。

## 伪本地化无法测试的内容

伪本地化无法反映翻译质量、语序或语气，也无法检验复数规则：英语有 2 种复数形式，阿拉伯语有 6 种，而加了重音符号的英文字符串依然只有英语的 2 种。Microsoft 的指南指出，伪本地化“并不能完全替代”对已翻译应用的验证，因此发布前还应使用真实语言进行测试。具体需要检查哪些内容，请参阅[多语言应用发布检查清单](/kb/multilingual-app-launch-checklist)。

## 将伪本地化与真实译文结合使用

General Translation 支持在开发期间测试真实译文：只要项目 API 密钥具备运行时翻译权限，`gt-next` 就会按需向 GT 的服务请求译文。切换到德语可以检查实际措辞和布局，切换到复数规则不同的语言则可以测试相应的分支。位于 [`<T>`](/docs/react/reference/components/t) 或翻译函数之外的文本会保持源语言不变。 (参见 [Next.js 快速入门](/docs/react/nextjs-quickstart)) 。建议先用伪本地化做早期布局检查，此时测试人员仍能读懂界面内容；然后使用 [CLI](/docs/cli/reference/commands/translate) 生成发布用的译文，并在 GT 的[翻译编辑器](/docs/platform/dashboard/guides/reviewing-translations)和运行中的应用里审阅这些译文。仅靠加长英文文本，既无法判断译文是否准确，也无法确认译文能否放进同样的空间。

## 要点总结

* 伪本地化会将源文本替换为带重音符号、经过填充、用括号包裹或镜像翻转的版本，从而在翻译开始前发现 i18n 缺陷。
* 它可以发现硬编码的字符串、截断、字体和编码问题、拼接而成的句子，以及缺少从右到左支持等问题。
* Android (`en-XA`、`ar-XB`) 、Xcode (scheme 选项中的伪语言) 和 Windows (`qps-ploc`、`qps-plocm`、`qps-ploca`) 均已内置该功能；在 Web 端，只需一个简短的转换函数或 `pseudo-localization` 软件包即可实现。
* 它无法检验翻译质量或复数规则；这些方面需要用真实译文来测试，而 `gt-next` 可以在开发期间按需生成译文。

## Related questions

- [如何找出未翻译的硬编码字符串？](https://generaltranslation.com/zh/kb/find-hardcoded-strings.mdx): 在 CI 中运行 linter，标记面向用户的字符串字面量，例如 JSX 可使用 eslint-plugin-i18next 的 no-literal-string 规则，Android 可使用 Android Lint 的 HardcodedText 检查，Rails 可使用 erb_lint 的 HardCodedString linter。然后切换到伪区域设置，逐一浏览应用，找出静态检查无法追踪到的文本。
- [如何在 CSS 中支持 RTL（从右到左）语言？](https://generaltranslation.com/zh/kb/right-to-left-css.mdx): 在 html 元素上同时设置 dir="rtl" 和 lang，因为仅设置 lang 并不会改变文本方向；然后将 margin-left 等物理 CSS 属性替换为 margin-inline-start 等逻辑属性。Flex 行、Grid 列和默认文本对齐会自动翻转，而 translateX()、left 和 right 不会。
- [多语言应用本地化测试清单](https://generaltranslation.com/zh/kb/multilingual-app-launch-checklist.mdx): 在生产环境构建中，于每个支持的区域设置下测试九项内容：包括错误状态和邮件在内的完整流程、语言切换、复数形式、货币与时区、文本扩展、从右到左布局、无障碍访问、译文交付，以及可抓取的语言 URL。为每项检查设定明确的通过标准。
- [国际化与本地化（i18n 与 l10n）](https://generaltranslation.com/zh/kb/internationalization-vs-localization.mdx): 国际化（i18n）是让一款产品支持多种区域设置的代码与设计工作，例如使用 Intl 格式化日期、支持从右到左的文本等。本地化（l10n）则针对某一区域设置对产品进行适配，除翻译外，还涵盖货币、日期格式、计量单位、语气和法律细节等方面。

## Previous and next questions

- Previous question: [什么是 ICU 消息格式？](https://generaltranslation.com/zh/kb/icu-message-format.mdx)
- Next question: [什么是翻译管理系统（TMS）？](https://generaltranslation.com/zh/kb/what-is-a-translation-management-system.mdx)

## Sitemap

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