Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Localization/I18n: Incrementally update/translate your Strings files from .swift, .h, .m(m), .storyboard or .xib files.

License

NotificationsYou must be signed in to change notification settings

FlineDev/BartyCrouch

Repository files navigation

CI StatusVersion: 4.14.0Swift: 5.7License: MIT
PayPal: DonateGitHub: Become a sponsorPatreon: Become a patron

InstallationConfigurationUsageBuild ScriptDonationMigration GuidesIssuesContributingLicense

Important Notice

Apple introduced String Catalogs in Xcode 15 which implements many aspects of BartyCrouch like the incremental auto-extraction, or warning against empty translations. It's also fully backward-compatible with all iOS versions. Migrating is as simple as right-clicking a.strings file and choosing "Migrate to String Catalog...". I wrote adetailed FAQ about String Catalogs if you want to learn more. It's really awesome, everybody should migrate to it!

The only feature it's missing is machine translation, but I wrote an app to fill the gap and it supports even more translation services than BartyCrouch. UseTranslateKit in the future by simply drag & dropping the String Catalog file and letting it handle the translation, it's really easy.

Note that TranslateKit is beingactively worked on. In comparison, BartyCrouch is kept up-to-date only by volunteers in the community.

BartyCrouch

BartyCrouchincrementally updates your Strings files from your Codeand from Interface Builder files. "Incrementally" means that BartyCrouch will by defaultkeep both your alreadytranslated values and even your altered comments. Additionally you can also use BartyCrouch formachine translating from one language to 60+ other languages. Using BartyCrouch is as easy asrunning a few simple commands from the command line what can even beautomated using abuild script within your project.

Checkoutthis blog post to learn how you can effectively use BartyCrouch in your projects.

Requirements

  • Xcode 14+ & Swift 5.7+
  • Xcode Command Line Tools (seehere for installation instructions)
  • In Xcode 15 or later: Set "User Script Sandboxing" to NO in your target's "Build Settings" tab

Getting Started

Installation

ViaHomebrew

To install Bartycrouch the first time, simply run the command:

brew install bartycrouch

Toupdate to the newest version of BartyCrouch when you have an old version already installed run:

brew upgrade bartycrouch
ViaMint

Toinstall or update to the latest version of BartyCrouch simply run this command:

mint install FlineDev/BartyCrouch

Configuration

To configure BartyCrouch for your project, first create a configuration file within your projects root directory. BartyCrouch can do this for you:

bartycrouch init

Now you should have a file named.bartycrouch.toml with the following contents:

[update]tasks = ["interfaces","code","transform","normalize"][update.interfaces]paths = ["."]subpathsToIgnore = [".git","carthage","pods","build",".build","docs"]defaultToBase =falseignoreEmptyStrings =falseunstripped =falseignoreKeys = ["#bartycrouch-ignore!","#bc-ignore!","#i!"][update.code]codePaths = ["."]subpathsToIgnore = [".git","carthage","pods","build",".build","docs"]localizablePaths = ["."]defaultToKeys =falseadditive =trueunstripped =falseignoreKeys = ["#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 =truesortByKeys =true[lint]paths = ["."]subpathsToIgnore = [".git","carthage","pods","build",".build","docs"]duplicateKeys =trueemptyValues =true

This is the default configuration of BartyCrouch and should work for most projects as is. In order to use BartyCrouch to its extent, it is recommended though to consider making the following changes:

  1. To speed it up significantly, provide more specific paths for any key containingpath if possible (especially in theupdate.transform section, e.g.["App/Sources"] forcodePaths or["App/Supporting Files"] forsupportedLanguageEnumPaths).
  2. Remove thecode task if your project is Swift-only and you use the newtransform update task.
  3. If you are usingSwiftGen with thestructured-swift4 template, you will probably want to use thetransform task and change itstransformer option toswiftgenStructured.
  4. If you decided to use thetransform task, create a new file in your project (e.g. underSupportingFiles) namedBartyCrouch.swift and copy the following code:
//  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/BartyCrouchimport FoundationenumBartyCrouch{enumSupportedLanguage:String{        // TODO: remove unsupported languages from the following cases list & add any missing languagescase 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"}staticfunc translate(key:String, translations:[SupportedLanguage:String], comment:String?=nil)->String{lettypeName=String(describing:BartyCrouch.self)letmethodName= #functionprint("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 transformationreturn"BC: TRANSFORMATION FAILED!"}}
  1. If you don't develop in English as the first localized language, you should update thesourceLocale of thenormalize task.
  2. If you want to use the machine translation feature of BartyCrouch, addtranslate to the tasks list at the top and copy the following section into the configuration file withsecret replaced by yourMicrosoft Translator Text API Subscription Key:
[update.translate]paths ="."translator ="microsoftTranslator"secret ="<#Subscription Key#>"sourceLocale ="en"

Usage

Before using BartyCrouch pleasemake sure you have committed your code. Also, we highly recommend using thebuild script method describedbelow.


bartycrouch accepts one of the following sub commands:

  • update: Updates your.strings file contents according to your configuration.
  • lint: Checks your.strings file contents for empty values & duplicate keys.

Also the following command line options can be provided:

  • -v,--verbose: Prints more detailed information about the executed command.
  • -x,--xcode-output: Prints warnings & errors in Xcode compatible format.
  • -w,--fail-on-warnings: Returns a failed status code if any warning is encountered.
  • -p,--path: Specifies a different path than current to run BartyCrouch from there.

update subcommand

The update subcommand can be run with one or multiple of the following tasks:

  • interfaces: Updates.strings files of Storyboards & XIBs.
  • code: UpdatesLocalizable.strings file fromNSLocalizedString entries in code.
  • transform: A mode where BartyCrouch replaces a specific method call to provide translations in multiple languages in a single line. Only supports Swift files.
  • translate: Updates missing translations in other languages than the source language.
  • normalize: Sorts & cleans up.strings files.

In order to configure which tasks are executed, edit this section in the config file:

[update]tasks = ["interfaces","code","transform","normalize"]
Options forinterfaces
  • paths: The directory / directories to search for Storyboards & XIB files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via thepaths option.
  • defaultToBase: Add Base translation as value to new keys.
  • ignoreEmptyStrings: Doesn't add views with empty values.
  • unstripped: Keeps whitespaces at beginning & end of Strings files.
  • ignoreKeys: Keys (e.g. in the comment) indicating that specific translation entries should be ignored when generating String files. Useful to ignore strings that are gonna be translated in code.
Options forcode
  • codePaths: The directory / directories to search for Swift code files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via thepaths option.
  • localizablePaths: The enclosing path(s) containing the localizedLocalizable.strings files.
  • defaultToKeys: Add new keys both as key and value.
  • additive: Prevents cleaning up keys not found in code.
  • customFunction: Use alternative name to search for strings to localize, in addition toNSLocalizedString, andCFCopyLocalizedString. Defaults toLocalizedStringResource.
  • customLocalizableName: Use alternative name forLocalizable.strings.
  • unstripped: Keeps whitespaces at beginning & end of Strings files.
  • plistArguments: Use a plist file to store all the code files for the ExtractLocStrings tool. (Recommended for large projects.)
  • ignoreKeys: Keys (e.g. in the comment) indicating that specific translation entries should be ignored when generating String files.
  • overrideComments: Always overrides the comment with the keys new translation, useful for IB files.
Options fortransform
  • codePaths: The directory / directories to search for Swift code files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via thepaths option.
  • localizablePaths: The enclosing path(s) containing the localizedLocalizable.strings files.
  • transformer: Specifies the replacement code. Usefoundation forNSLocalizedString orswiftgenStructured forL10n entries.
  • supportedLanguageEnumPath: The enclosing path containing theSupportedLanguage enum.
  • typeName: The name of the type enclosing theSupportedLanguage enum and translate method.
  • translateMethodName: The name of the translate method to be replaced.
  • customLocalizableName: Use alternative name forLocalizable.strings.
  • separateWithEmptyLine: Set tofalse if you don't want to have empty lines between Strings entries. Defaults to `true.
Options fortranslate
  • paths: The directory / directories to search for Strings files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via thepaths option.
  • translator: Specifies the translation API. UsemicrosoftTranslator ordeepL.
  • secret: YourMicrosoft Translator Text API Subscription Key orAuthentication Key for DeepL API.
  • sourceLocale: The source language to translate from.
  • separateWithEmptyLine: Set tofalse if you don't want to have empty lines between Strings entries. Defaults to `true.
Options fornormalize
  • paths: The directory / directories to search for Strings files.
  • subpathsToIgnore: The subpaths to be ignored inside the directories found via thepaths option.
  • sourceLocale: The source language to harmonize keys of other languages with.
  • harmonizeWithSource: Synchronizes keys with source language.
  • sortByKeys: Alphabetically sorts translations by their keys.
  • separateWithEmptyLine: Set tofalse if you don't want to have empty lines between Strings entries. Defaults to `true.

lint subcommand

The lint subcommand was designed to analyze a project for typical translation issues. The current checks include:

  • duplicateKeys: Finds duplicate keys within the same file.
  • emptyValues: Finds empty values for any language.

Note that thelint command can be used both on CI and within Xcode via the build script method:

  • In Xcode the-x or--xcode-output command line argument should be used to get warnings which point you directly to the found issue.
  • When running on the CI you should specify the-w or--fail-on-warnings argument to make sure BartyCrouch fails if any warnings are encountered.

Localization Workflow viatransform

When thetransform update task is configured (see recommended step 4 in theConfiguration section above) and you are using thebuild script method, you can use the following simplified process for writing localized code during development:

  1. Instead ofNSLocalizedString calls you can useBartyCrouch.translate and specify a key, translations (if any) and optionally a comment. For example:
self.title=BartyCrouch.translate(key:"onboarding.first-page.header-title",  translations:[.english:"Welcome!"])
  1. Once you build your app, BartyCrouch will automatically add the new translation key to all yourLocalizable.strings files and add the provided translations as values for the provided languages.
  2. Additionally, during the same build BartyCrouch will automatically replace the above call toBartyCrouch.translate with the proper translation call, depending on yourtransformer option setting.

The resulting code depends on yourtransformer option setting:

When set tofoundation, the above code will transform to:

self.title=NSLocalizedString("onboarding.first-page.header-title", comment:"")

When set toswiftgenStructured it will transform to:

self.title=L10n.Onboarding.FirstPage.headerTitle

Advantages oftransform over thecode task:

  • You can provide translations for keys without switching to the Strings files.
  • In case you use SwiftGen, you don't need to replace calls toNSLocalizedString withL10n calls manually after running BartyCrouch.
  • Can be combined with the machine translation feature to provide a source language translation in code and let BartyCrouch translate it to all supported languages in a single line & without ever leaving the code.

Disadvantages oftransform over thecode task:

  • Only works for Swift Code. No support for Objective-C. (You can use both methods simultaneously though.)
  • Xcode will mark the freshly transformed code as errors (but build will succeed anyways) until next build.
  • Not as fast ascode sinceSwiftSyntax currently isn'tparticularly fast. (But this should improve over time!)

NOTE: As of version 4.x of BartyCrouchformatted localized Strings are not supported by this automatic feature.

Localizing strings ofLocalizableStringResource type (AppIntents, ...)

Historically, Apple platforms usedCFCopyLocalizedString, andNSLocalizedString macros and their variants, to mark strings used in code to be localized, and to load their localized versions during runtime fromLocalizable.strings file.

Since introduction of the AppIntents framework, the localized strings in code can also be typed asLocalizedStringResource, and are no longer marked explicitly.

Let's examine this snippet of AppIntents code:

struct ExportAllTransactionsIntent: AppIntent {    static var title: LocalizedStringResource = "Export all transactions"    static var description =        IntentDescription("Exports your transaction history as CSV data.")}

In the example above, both the"Export all transactions", and"Exports your transaction history as CSV data." are actuallyStaticString instances that will be converted during compilation intoLocalizedStringResource instances, and will lookup their respective localizations during runtime fromLocalized.strings file the same way as when usingNSLocalizedString in the past. The only exception being that such strings are not marked explicitly, and require swift compiler to parse and extract such strings for localization. This is what Xcode does from version 13 when usingProduct -> Export Localizations... option.

In order to continue translating these strings withbartycrouch it is required to mark them explicitely withLocalizedStringResource(_: String, comment: String) call, and specifycustomFunction="LocalizedStringResource" incode task options.

The example AppIntents code that can be localized withbartycrouch will look like this:

struct ExportAllTransactionsIntent: AppIntent {    static var title = LocalizedStringResource("Export all transactions", comment: "")    static var description =        IntentDescription(LocalizedStringResource("Exports your transaction history as CSV data.", comment: ""))}

Note that you must use the full form ofLocalizedStringResource(_: StaticString, comment: StaticString) for thebartycrouch, or more specifically for theextractLocStrings (seexcrun extractLocStrings) to properly parse the strings.

Build Script

In order to truly profit from BartyCrouch's ability to update & lint your.strings files you can make it a natural part of your development workflow within Xcode. In order to do this select your target, choose theBuild Phases tab and click the + button on the top left corner of that pane. SelectNew Run Script Phase and copy the following into the text box below theShell: /bin/sh of your new run script phase:

export PATH="$PATH:/opt/homebrew/bin"if which bartycrouch> /dev/null;then    bartycrouch update -x    bartycrouch lint -xelseecho"warning: BartyCrouch not installed, download it from https://github.com/FlineDev/BartyCrouch"fi

Next, make sure the BartyCrouch script runs before the stepsCompiling Sources (andSwiftGen if used) by moving it per drag & drop, for example right afterTarget Dependencies.

Now BartyCrouch will be run on each build and you won't need to call it manually ever (again). Additionally, all your co-workers who don't have BartyCrouch installed will see a warning with a hint on how to install it.

Note: Please make sure you commit your code using source control regularly when using the build script method.


Exclude specific Views / NSLocalizedStrings from Localization

Sometimes you may want toignore some specific views containing localizable texts e.g. becausetheir values are going to be set programmatically.

For these cases you can simply include#bartycrouch-ignore! or the shorthand#bc-ignore! into your value within your base localized Storyboard/XIB file. Alternatively you can add#bc-ignore! into the field "Comment For Localizer" box in the utilities pane.

This will tell BartyCrouch to ignore this specific view when updating your.strings files.

Here's an example of how a base localized view in a XIB file with partly ignored strings might look like:

Here's an example with the alternative comment variant:

You can also use#bc-ignore! in yourNSLocalizedString macros comment part to ignore them so they are not added to yourLocalizable.strings. This might be helpful when you are using a.stringsdict file to handle pluralization (seedocs).

For example you can do something like this:

func updateTimeLabel(minutes:Int){String.localizedStringWithFormat(NSLocalizedString("%d minute(s) ago", comment:"pluralized and localized minutes #bc-ignore!"), minutes)}

The%d minute(s) ago key will be taken from Localizable.stringsdict file, not from Localizable.strings, that's why it should be ignored by BartyCrouch.

Donation

BartyCrouch was brought to you byCihat Gündüz in his free time. If you want to thank me and support the development of this project, pleasemake a small donation onPayPal. In case you also like my otheropen source contributions andarticles, please consider motivating me bybecoming a sponsor onGitHub or apatron onPatreon.

Thank you very much for any donation, it really helps out a lot! 💯

Migration Guides

See the fileMIGRATION_GUIDES.md.

Contributing

Contributions are welcome. Feel free to open an issue on GitHub with your ideas or implement an idea yourself and post a pull request. If you want to contribute code, please try to follow the same syntax and semantic in yourcommit messages (see rationalehere). Also, please make sure to add an entry to theCHANGELOG.md file which explains your change.

In order for the tests to run build issues, you need to run – also add an API key in the new file to run the translations tests, too:

cp Tests/BartyCrouchTranslatorTests/Secrets/secrets.json.sample Tests/BartyCrouchTranslatorTests/Secrets/secrets.json

After Release Checklist:

  1. Runmake portable_zip to generate.build/release/portable_bartycrouch.zip
  2. Create new release with text from newCHANGELOG.md section & attachportable_bartycrouch.zip as binary
  3. Runpod trunk push to make a new release known to CocoaPods
  4. Updatetag andrevision inFormula/bartycrouch.rb, commit & push change
  5. Runbrew bump-formula-pr bartycrouch --tag=<tag> --revision=<revision>

License

This library is released under theMIT License. See LICENSE for details.


[8]ページ先頭

©2009-2025 Movatter.jp