|
文件扩展名 |
.xcstrings |
|
API 扩展 |
strings_catalog |
|
导入 |
是 |
|
导出 |
是 |
|
支持复数形式 |
是 |
|
支持描述 |
是 |
|
格式选项 这些选项可以在上传和/或下载文件时指定。根据上传/下载方式(API、CLI、仓库同步等),它们可以在查询参数 |
convert_placeholder default_extraction_state locale_code_mapping |
Apple 字符串目录 (.xcstrings) 是 Xcode 15 引入的一种本地化格式。它通过支持用于处理复数形式、特定设备变体等的结构化格式,增强了开发人员管理本地化字符串的方式。这种格式正成为管理 iOS 和 macOS 应用程序本地化的推荐方法。
comment、extractionState 和 shouldTranslate 元数据字段会按所需顺序导入和导出,以确保与 Xcode 的兼容性。
Phrase 也会在导入期间将 Xcode 翻译状态映射到最接近的 Strings 等效项,并在导出时将其转换回 Xcode 兼容的值。如果没有特定的映射适用,则使用 translated 作为默认导出值。如果需要,请使用 选项来跳过状态映射。
代码示例
{
{"sourceLanguage": "en",
"strings": {
"Sync Warning": {
"comment":"同步功能不可用消息",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value":"Cloud Sync must be enabled to use this feature."
}
},
"fr": {
"stringUnit": {
"state": "translated",
"value":"必须启用云同步才能使用此功能。"
}
}
}
},
"Chosen Collections": {
"comment":"查看指示所选照片合集的标题",
"localizations": {
"fr": {
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "translated",
"value": "%ld collection sélectionnée"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "%ld collections sélectionnées"
}
}
}
}
},
"en": {
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "translated",
"value": "%ld Collection Selected"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "%ld Collections Selected"
}
}
}
}
}
}
},
"Settings Hub": {
"localizations": {
"es": {
"stringUnit": {
"state": "translated",
"value":"Centro de configuración"
}
}
}
}
},
"version":"1.0"
}
使用 Phrase CLI 时,文件导出遵循 .phrase.yml 配置文件中定义的结构。为确保在拉取操作期间将多种语言导出到单个 .XCSTRINGS 文件中:
-
在 CLI 配置文件中仅指定一个文件目标。
-
使用
locale_ids参数列出导出中包含的所有语言区域设置。
.phrase.yml 配置示例
拉取:
目标:
- 文件:./i18n-test/Localizable.xcstrings
参数:
区域设置 ID:en # 下载的主要语言
区域设置 ID:# 要包含的其他语言
- de
- es
- fr
文件格式:strings_catalog
设备变体
Apple Strings Catalog 支持设备变体,允许针对同一键根据所使用的 Apple 设备提供不同的翻译内容。
为了在 Phrase Strings 中处理设备变体,系统会使用分隔符 |==| 为每种设备创建单独的键。导入 .XCSTRINGS 文件时,设备类型会使用此分隔符添加到基础键名中。
示例
名为 %lld Product(s) Ordered 且用于 applewatch 设备的键,在导入 Phrase Strings 时会作为名为 %lld Product(s) Ordered|==|device.applewatch 的复数键。
在导出期间,Phrase Strings 会使用该分隔符检测设备变体,并将其恢复为 Apple 本地化格式所需的原始嵌套结构。
{
"sourceLanguage": "en",
"strings": {
"%lld Product(s) Ordered": {
"comment":"Indicates the number of products ordered, with device-specific variations",
"localizations": {
"en": {
"variations": {
"device": {
"applewatch": {
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (Apple Watch)"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (Apple Watch)"
}
}
}
}
},
"ipad": {
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (iPad)"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (iPad)"
}
}
}
}
},
"iphone": {
"variations": {
"plural": {
"one": {
“stringUnit”: {
“state”: “translated”,
"value": "已订购 %lld 件产品 (iPhone)"
}
},
"other": {
“stringUnit”: {
“state”: “translated”,
"value": "已订购 %lld 件产品 (iPhone)"
}
}
}
}
},
"mac": {
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (Mac)"
}
},
"other": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品 (Mac)"
}
}
}
}
}
}
}
},
"fr": {
"variations": {
"plural": {
"few": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品"
}
},
"many": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品"
}
},
"one": {
"stringUnit": {
"state": "translated",
"value": "已订购 %lld 件产品"
}
}
}
}
}
}
}
}
}
字符串替换
Apple 字符串目录支持字符串替换,可为动态内容提供灵活的占位符。
若要处理 Phrase Strings 中的字符串替换,请使用分隔符 |==| 创建单独的键。导入 .XCSTRINGS 文件时,替换项会使用此分隔符添加到基础键名中。
Phrase Strings 也支持直接在项目中创建替换字符串。手动创建替换结构时,必须定义基础键和相应的替换键,以确保在导出时生成正确的嵌套格式。
替换项始终需要特定的键命名格式:keyName|==|substitution.[specifier]。
示例:从现有的 .XCSTRINGS 文件导入替换结构
BIRDS 替换项的名为 birdSightingAlert 的键被导入为 Phrase Strings 中名为 birdSightingAlert|==|substitution.BIRDS 的复数键。
导出期间,Phrase Strings 会使用该分隔符检测替换项,并为其 Apple 本地化格式恢复原始的嵌套结构。
"birdSightingAlert": {
"comment":提示消息,显示发现的鸟类数量。
"localizations": {
"en": {
"stringUnit": {
"state": "new",
"value":"You spotted %#@BIRDS@!"
},
"substitutions": {
"BIRDS": {
"formatSpecifier":"BIRDS",
"variations": {
"plural": {
"one": {
"stringUnit": {
"state": "new",
"value": "a bird"
}
},
"other": {
"stringUnit": {
"state": "new",
"value": "several birds"
}
},
"zero": {
"stringUnit": {
"state": "new",
"value": "no birds"
}
}
}
}
}
}
}
}
示例:从零开始创建替换字符串
-
基础键
名为
keyName的基础键表示包含替换占位符%#@format@的顶级格式字符串。导出时,此键被写入为条目的主要
stringUnit:"keyName": { "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%#@format@" } } } } -
替换键
替换字符串定义为使用替换命名格式的单独键:
keyName|==|substitution.li。此键包含替换文本,通常带有复数变体。在导出期间,Phrase Strings 会使用
|==|substitution.分隔符检测替换,并恢复基础键下的相应嵌套结构:{ "sourceLanguage": "en", "strings": { "keyName": { "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%#@format@" }, "substitutions": { "li": { "formatSpecifier": "li", "variations": { "plural": { "one": { "stringUnit": { "state": "translated", "value": "%@ 天" } }, "other": { "stringUnit": { "state": "translated", "value": "%@ 天" } } } } } } } } } }, "version":"1.0" }
格式选项
|
标识符 |
convert_placeholder |
|
类型 |
布尔值 |
|
上传 |
否 |
|
下载 |
是 |
|
默认 |
假 |
|
描述 |
占位符将被转换以匹配特定格式的要求。示例: |
|
标识符 |
默认提取状态 |
|
类型 |
字符串 |
|
上传 |
否 |
|
下载 |
是 |
|
默认 |
null |
|
描述 |
定义当键上尚未定义提取状态时,写入导出文件中键的 支持:
|
|
标识符 |
locale_code_mapping |
|
类型 |
对象 |
|
上传 |
是 |
|
下载 |
是 |
|
默认 |
{} |
|
描述 |
将 Phrase 区域设置代码映射到写入 .XCSTRINGS 文件的区域设置代码。每个键都是 Phrase 区域设置代码;每个值都是写入文件的代码,例如: {
"en": "en-GB",
"fr": "fr-FR"
}
下载时,Phrase 会重写 上传时,Phrase 会反向应用相同的映射,并将文件语言环境代码转换回相应的 Phrase 语言环境代码,包括 此选项仅影响从 .XCSTRINGS 文件本身读取和写入的语言环境代码。基于文件名的语言环境映射(例如用于 Git 集成文件命名模式)是一种单独的设置,它映射的是文件路径,而不是 .XCSTRINGS 内部的代码。 |
从 iOS Strings (.strings) 迁移到 Strings Catalog (.xcstrings)
传统的 iOS Strings 格式 (.strings) 将翻译内容中的字面量反斜杠-n 序列 (\\n) 视为等同于实际的换行符。因此,在使用 .strings 格式时创建或编辑的翻译可能包含字面量文本 \n,而不是实际的换行符。
Strings Catalog (.xcstrings) 是一种基于 JSON 的格式。当包含字面量 \n 序列的内容导出到 .xcstrings 时,JSON 编码会将该字面量文本在文件中转义为 \\n。此行为并非双重转义错误。它反映了翻译内容中已存在的字面量 \n 文本,并使用正确的 JSON 转义进行了导出。
若要在从 .strings 迁移到 .xcstrings 后解决此问题,请将受影响内容中的字面量 \n 序列替换为实际的换行符:
-
照常导出内容。
-
在文本编辑器中打开导出的文件。
-
将所有字面量
\n序列实例替换为实际的换行符。 -
重新导入文件。
应用内搜索和替换不支持插入实际的换行符,因此必须在重新导入文件之前在外部文本编辑器中执行此替换。