安装 • 配置 • 使用 • 构建脚本 • 捐赠 • 迁移指南 • 问题 • 贡献 • 许可证
✨ 重要通知 ✨
苹果在 Xcode 15 中引入了 String Catalogs,它实现了 BartyCrouch 的许多功能,例如增量自动提取或警告空翻译。它也完全向后兼容所有 iOS 版本。迁移非常简单,只需右键单击
.strings
文件并选择“迁移到 String Catalog...”。我写了一篇关于 String Catalogs 的 详细常见问题解答,如果您想了解更多信息。它真的很棒,每个人都应该迁移到它!它唯一缺少的功能是机器翻译,但我编写了一个应用程序来填补这一空白,它甚至支持比 BartyCrouch 更多的翻译服务。将来使用 TranslateKit,只需拖放 String Catalog 文件,让它处理翻译,真的很容易。
请注意,TranslateKit 正在积极开发中。相比之下,BartyCrouch 仅由社区志愿者维护更新。
BartyCrouch 从您的代码和 Interface Builder 文件中增量更新您的 Strings 文件。“增量”意味着 BartyCrouch 默认情况下会保留您已经翻译的值,甚至您修改过的注释。此外,您还可以使用 BartyCrouch 从一种语言机器翻译到 60 多种其他语言。使用 BartyCrouch 非常简单,只需从命令行运行一些简单的命令,甚至可以使用项目中的构建脚本来自动化。
查看 这篇博客文章,了解如何在您的项目中有效地使用 BartyCrouch。
要首次安装 Bartycrouch,只需运行命令
brew install bartycrouch
要更新到最新版本的 BartyCrouch(如果您已安装旧版本),请运行
brew upgrade bartycrouch
要安装或更新到最新版本的 BartyCrouch,只需运行此命令
mint install FlineDev/BartyCrouch
要为您的项目配置 BartyCrouch,首先在您的项目根目录中创建一个配置文件。BartyCrouch 可以为您完成此操作
bartycrouch init
现在您应该有一个名为 .bartycrouch.toml
的文件,其中包含以下内容
[update]
tasks = ["interfaces", "code", "transform", "normalize"]
[update.interfaces]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
defaultToBase = false
ignoreEmptyStrings = false
unstripped = false
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]
[update.code]
codePaths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
localizablePaths = ["."]
defaultToKeys = false
additive = true
unstripped = false
ignoreKeys = ["#bartycrouch-ignore!", "#bc-ignore!", "#i!"]
[update.transform]
codePaths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
localizablePaths = ["."]
transformer = "foundation"
supportedLanguageEnumPath = "."
typeName = "BartyCrouch"
translateMethodName = "translate"
[update.normalize]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
sourceLocale = "en"
harmonizeWithSource = true
sortByKeys = true
[lint]
paths = ["."]
subpathsToIgnore = [".git", "carthage", "pods", "build", ".build", "docs"]
duplicateKeys = true
emptyValues = true
这是 BartyCrouch 的默认配置,应该适用于大多数项目。为了最大限度地使用 BartyCrouch,建议考虑进行以下更改
path
的键提供更具体的路径(如果可能,尤其是在 update.transform
部分,例如 ["App/Sources"]
用于 codePaths
或 ["App/Supporting Files"]
用于 supportedLanguageEnumPaths
)。transform
更新任务,请删除 code
任务。structured-swift4
模板,您可能需要使用 transform
任务,并将其 transformer
选项更改为 swiftgenStructured
。transform
任务,请在您的项目中创建一个新文件(例如在 SupportingFiles
下),命名为 BartyCrouch.swift
并复制以下代码// This file is required in order for the `transform` task of the translation helper tool BartyCrouch to work.
// See here for more details: https://github.com/FlineDev/BartyCrouch
import Foundation
enum BartyCrouch {
enum SupportedLanguage: String {
// TODO: remove unsupported languages from the following cases list & add any missing languages
case arabic = "ar"
case chineseSimplified = "zh-Hans"
case chineseTraditional = "zh-Hant"
case english = "en"
case french = "fr"
case german = "de"
case hindi = "hi"
case italian = "it"
case japanese = "ja"
case korean = "ko"
case malay = "ms"
case portuguese = "pt-BR"
case russian = "ru"
case spanish = "es"
case turkish = "tr"
}
static func translate(key: String, translations: [SupportedLanguage: String], comment: String? = nil) -> String {
let typeName = String(describing: BartyCrouch.self)
let methodName = #function
print(
"Warning: [BartyCrouch]",
"Untransformed \(typeName).\(methodName) method call found with key '\(key)' and base translations '\(translations)'.",
"Please ensure that BartyCrouch is installed and configured correctly."
)
// fall back in case something goes wrong with BartyCrouch transformation
return "BC: TRANSFORMATION FAILED!"
}
}
normalize
任务的 sourceLocale
。translate
添加到顶部的任务列表中,并将以下部分复制到配置文件中,并将 secret
替换为您的 Microsoft Translator Text API 订阅密钥[update.translate]
paths = "."
translator = "microsoftTranslator"
secret = "<#Subscription Key#>"
sourceLocale = "en"
在使用 BartyCrouch 之前,请确保您已提交代码。此外,我们强烈建议使用下面描述的构建脚本方法。
bartycrouch
接受以下子命令之一
update
: 根据您的配置更新您的 .strings
文件内容。lint
: 检查您的 .strings
文件内容是否存在空值和重复键。还可以提供以下命令行选项
-v
, --verbose
: 打印有关执行命令的更详细信息。-x
, --xcode-output
: 以 Xcode 兼容格式打印警告和错误。-w
, --fail-on-warnings
: 如果遇到任何警告,则返回失败状态代码。-p
, --path
: 指定与当前路径不同的路径,从该路径运行 BartyCrouch。update
子命令可以与以下一个或多个任务一起运行
interfaces
: 更新 Storyboards 和 XIB 的 .strings
文件。code
: 从代码中的 NSLocalizedString
条目更新 Localizable.strings
文件。transform
: 一种模式,其中 BartyCrouch 替换特定的方法调用,以在单行中提供多种语言的翻译。仅支持 Swift 文件。translate
: 更新源语言以外的其他语言中缺少的翻译。normalize
: 排序和清理 .strings
文件。为了配置要执行的任务,请编辑配置文件中的此部分
[update]
tasks = ["interfaces", "code", "transform", "normalize"]
interfaces
的选项paths
: 要搜索 Storyboards 和 XIB 文件的目录。subpathsToIgnore
: 在通过 paths
选项找到的目录中要忽略的子路径。defaultToBase
: 将 Base 翻译作为值添加到新键。ignoreEmptyStrings
: 不添加具有空值的视图。unstripped
: 保留 Strings 文件开头和结尾的空格。ignoreKeys
: 键(例如在注释中)指示在生成 String 文件时应忽略特定的翻译条目。用于忽略将在代码中翻译的字符串。code
的选项codePaths
: 要搜索 Swift 代码文件的目录。subpathsToIgnore
: 在通过 paths
选项找到的目录中要忽略的子路径。localizablePaths
: 包含本地化的 Localizable.strings
文件的封闭路径。defaultToKeys
: 将新键同时添加为键和值。additive
: 阻止清理在代码中未找到的键。customFunction
: 使用替代名称来搜索要本地化的字符串,除了 NSLocalizedString
和 CFCopyLocalizedString
之外。默认为 LocalizedStringResource
。customLocalizableName
: 使用 Localizable.strings
的替代名称。unstripped
: 保留 Strings 文件开头和结尾的空格。plistArguments
: 使用 plist 文件来存储 ExtractLocStrings 工具的所有代码文件。(建议用于大型项目。)ignoreKeys
: 键(例如在注释中)指示在生成 String 文件时应忽略特定的翻译条目。overrideComments
: 始终使用键的新翻译覆盖注释,对 IB 文件很有用。transform
的选项codePaths
: 要搜索 Swift 代码文件的目录。subpathsToIgnore
: 在通过 paths
选项找到的目录中要忽略的子路径。localizablePaths
: 包含本地化的 Localizable.strings
文件的封闭路径。transformer
: 指定替换代码。对于 NSLocalizedString
使用 foundation
,对于 L10n
条目使用 swiftgenStructured
。supportedLanguageEnumPath
: 包含 SupportedLanguage
枚举的封闭路径。typeName
: 包含 SupportedLanguage
枚举和 translate 方法的类型的名称。translateMethodName
: 要替换的 translate 方法的名称。customLocalizableName
: 使用 Localizable.strings
的替代名称。separateWithEmptyLine
: 如果您不希望在 Strings 条目之间有空行,请设置为 false
。默认为 `true。translate
的选项paths
: 要搜索 Strings 文件的目录。subpathsToIgnore
: 在通过 paths
选项找到的目录中要忽略的子路径。translator
: 指定翻译 API。使用 microsoftTranslator
或 deepL
。secret
: 您的 Microsoft Translator Text API 订阅密钥 或 DeepL API 的身份验证密钥。sourceLocale
: 要从中翻译的源语言。separateWithEmptyLine
: 如果您不希望在 Strings 条目之间有空行,请设置为 false
。默认为 `true。normalize
的选项paths
: 要搜索 Strings 文件的目录。subpathsToIgnore
: 在通过 paths
选项找到的目录中要忽略的子路径。sourceLocale
: 用于协调其他语言键的源语言。harmonizeWithSource
: 将键与源语言同步。sortByKeys
: 按键的字母顺序对翻译进行排序。separateWithEmptyLine
: 如果您不希望在 Strings 条目之间有空行,请设置为 false
。默认为 `true。lint
子命令旨在分析项目中的典型翻译问题。当前的检查包括
duplicateKeys
: 在同一文件中查找重复键。emptyValues
: 查找任何语言的空值。请注意,lint
命令可以同时在 CI 和 Xcode 中通过构建脚本方法使用
-x
或 --xcode-output
命令行参数来获取警告,这些警告会直接指向找到的问题。-w
或 --fail-on-warnings
参数,以确保在遇到任何警告时 BartyCrouch 失败。当配置了 transform
更新任务时(请参阅上面配置部分中的建议步骤 4)并且您正在使用 构建脚本方法,您可以使用以下简化的流程在开发期间编写本地化代码
BartyCrouch.translate
并指定键、翻译(如果有)以及可选的注释,而不是 NSLocalizedString
调用。例如self.title = BartyCrouch.translate(key: "onboarding.first-page.header-title", translations: [.english: "Welcome!"])
Localizable.strings
文件,并将提供的翻译添加为所提供语言的值。transformer
选项设置,自动将上述对 BartyCrouch.translate
的调用替换为正确的翻译调用。结果代码取决于您的 transformer
选项设置
当设置为 foundation
时,上面的代码将转换为
self.title = NSLocalizedString("onboarding.first-page.header-title", comment: "")
当设置为 swiftgenStructured
时,它将转换为
self.title = L10n.Onboarding.FirstPage.headerTitle
transform
相对于 code
任务的优势
NSLocalizedString
的调用替换为 L10n
调用。transform
相对于 code
任务的劣势
code
快,因为 SwiftSyntax 目前 不是特别快。(但这应该会随着时间的推移而改善!)注意:截至 BartyCrouch 4.x 版本,此自动功能不支持格式化的本地化 Strings。
从历史上看,Apple 平台使用 CFCopyLocalizedString
和 NSLocalizedString
宏及其变体来标记代码中使用的字符串以进行本地化,并在运行时从 Localizable.strings
文件加载其本地化版本。
自从引入 AppIntents 框架以来,代码中的本地化字符串也可以键入为 LocalizedStringResource
,并且不再显式标记。
让我们检查一下这个 AppIntents 代码片段
struct ExportAllTransactionsIntent: AppIntent {
static var title: LocalizedStringResource = "Export all transactions"
static var description =
IntentDescription("Exports your transaction history as CSV data.")
}
在上面的示例中,"Export all transactions"
和 "Exports your transaction history as CSV data."
实际上都是 StaticString
实例,它们将在编译期间转换为 LocalizedStringResource
实例,并在运行时从 Localized.strings
文件中查找其各自的本地化,方式与过去使用 NSLocalizedString
时相同。唯一的例外是这些字符串没有被显式标记,并且需要 swift 编译器来解析和提取这些字符串以进行本地化。这就是 Xcode 从版本 13 开始使用 Product -> Export Localizations...
选项时所做的事情。
为了继续使用 bartycrouch
翻译这些字符串,需要使用 LocalizedStringResource(_: String, comment: String)
调用显式标记它们,并在 code
任务选项中指定 customFunction="LocalizedStringResource"
。
可以使用 bartycrouch
本地化的示例 AppIntents 代码如下所示
struct ExportAllTransactionsIntent: AppIntent {
static var title = LocalizedStringResource("Export all transactions", comment: "")
static var description =
IntentDescription(LocalizedStringResource("Exports your transaction history as CSV data.", comment: ""))
}
请注意,您必须使用 LocalizedStringResource(_: StaticString, comment: StaticString)
的完整形式才能用于 bartycrouch
,或者更具体地说是用于 extractLocStrings
(请参阅 xcrun extractLocStrings
)以正确解析字符串。
为了真正从 BartyCrouch 更新和 lint 您的 .strings
文件的能力中获益,您可以使其成为 Xcode 中开发工作流程的自然组成部分。为此,请选择您的目标,选择“构建阶段”选项卡,然后单击该窗格左上角的 + 按钮。选择“新建运行脚本阶段”,并将以下内容复制到新运行脚本阶段的“Shell: /bin/sh”下方的文本框中
export PATH="$PATH:/opt/homebrew/bin"
if which bartycrouch > /dev/null; then
bartycrouch update -x
bartycrouch lint -x
else
echo "warning: BartyCrouch not installed, download it from https://github.com/FlineDev/BartyCrouch"
fi
接下来,通过拖放移动 BartyCrouch 脚本,确保它在步骤“编译源文件”(和“SwiftGen”,如果使用)之前运行,例如紧跟在“目标依赖项”之后。
现在,BartyCrouch 将在每次构建时运行,您将无需(再次)手动调用它。此外,所有未安装 BartyCrouch 的同事都会看到警告,其中包含有关如何安装它的提示。
注意:使用构建脚本方法时,请确保定期使用源代码控制提交您的代码。
有时您可能想要忽略某些特定的视图,其中包含可本地化的文本,例如因为它们的值将以编程方式设置。
对于这些情况,您只需在基本本地化的 Storyboard/XIB 文件中的值中包含 #bartycrouch-ignore!
或简写 #bc-ignore!
。或者,您可以在实用工具窗格的“本地化器注释”框中添加 #bc-ignore!
。
这将告诉 BartyCrouch 在更新您的 .strings
文件时忽略此特定视图。
这是一个 XIB 文件中具有部分忽略字符串的基本本地化视图的外观示例
这是一个带有替代注释变体的示例
您还可以在 NSLocalizedString
宏注释部分中使用 #bc-ignore!
来忽略它们,以便它们不会添加到您的 Localizable.strings
中。当您使用 .stringsdict
文件来处理复数形式时,这可能会有所帮助(请参阅 文档)。
例如,您可以这样做
func updateTimeLabel(minutes: Int) {
String.localizedStringWithFormat(NSLocalizedString("%d minute(s) ago", comment: "pluralized and localized minutes #bc-ignore!"), minutes)
}
%d minute(s) ago
键将从 Localizable.stringsdict 文件中获取,而不是从 Localizable.strings 中获取,这就是为什么它应该被 BartyCrouch 忽略。
BartyCrouch 是由 Cihat Gündüz 在他的空闲时间为您带来的。如果您想感谢我并支持这个项目的开发,请在 PayPal 上进行小额捐赠。如果您也喜欢我的其他 开源贡献 和 文章,请考虑通过在 GitHub 上成为赞助者或在 Patreon 上成为赞助人来激励我。
非常感谢您的任何捐赠,它真的很有帮助!💯
请参阅文件 MIGRATION_GUIDES.md。
欢迎贡献。欢迎在 GitHub 上提出您想法的问题,或者自己实现一个想法并发布拉取请求。如果您想贡献代码,请尝试在您的提交消息中遵循相同的语法和语义(请参阅 此处 的理由)。此外,请确保在 CHANGELOG.md
文件中添加一个条目,解释您的更改。
为了使测试能够运行构建问题,您需要运行 – 并在新文件中添加 API 密钥以运行翻译测试。
cp Tests/BartyCrouchTranslatorTests/Secrets/secrets.json.sample Tests/BartyCrouchTranslatorTests/Secrets/secrets.json
发布后检查清单
make portable_zip
以生成 .build/release/portable_bartycrouch.zip
CHANGELOG.md
部分中的文本创建新版本,并将 portable_bartycrouch.zip
作为二进制文件附加pod trunk push
以使 CocoaPods 知道新版本Formula/bartycrouch.rb
中的 tag
和 revision
,提交并推送更改brew bump-formula-pr bartycrouch --tag=<tag> --revision=<revision>
此库在 MIT 许可证下发布。有关详细信息,请参阅 LICENSE。