BartyCrouch

repository·main·Indexed 23 days ago

https://github.com/flinedev/bartycrouch

A CLI tool for incrementally updating iOS/macOS Strings files from source code and Interface Builder files. It supports extracting NSLocalizedString entries, updating Storyboards and XIBs, and machine translation via Microsoft Translator and DeepL. Features include a 'transform' workflow for Swift projects to replace custom translation calls with standard localization, a 'lint' command for CI and Xcode integration, and a 'normalize' task to clean up .strings files.

Tokens
4.8K
Snippets
10
Records
28
Agent score
79%

What's inside BartyCrouch

  1. Use the BartyCrouch CLI subcommands

    main

    BartyCrouch is a CLI tool for managing iOS/macOS localizations. It primarily supports two subcommands:

    • update: Synchronizes your .strings files with your code and interfaces based on your configuration.
    • lint: Analyzes your .strings files for common issues like duplicateKeys or emptyValues.

    Important: Always commit your code before running BartyCrouch to avoid losing changes during automated updates.

  2. How the `transform` workflow works

    main

    The transform task allows a highly efficient localization workflow in Swift. Instead of manually managing .strings files, you can write localized code directly in your Swift files.

    1. Write code using BartyCrouch.translate:
      self.title = BartyCrouch.translate(key: "onboarding.first-page.header-title",  translations: [.english: "Welcome!"])
    2. Build the app: BartyCrouch automatically adds the key and the provided translation to your Localizable.strings files.
    3. Automatic Transformation: BartyCrouch replaces the BartyCrouch.translate call with the standard localization call based on your transformer setting.

    Transformer Outputs:

    • If transformer = "foundation": self.title = NSLocalizedString("onboarding.first-page.header-title", comment: "")
    • If transformer = "swiftgenStructured": self.title = L10n.Onboarding.FirstPage.headerTitle

    Note: This only supports Swift. Xcode may show temporary errors on the transformed lines until the next build completes.

    self.title = BartyCrouch.translate(key: "onboarding.first-page.header-title",  translations: [.english: "Welcome!"])
  3. Upgrade from 0.x to 1.x

    main

    When upgrading to BartyCrouch 1.x, note these flag renames and syntax changes:

    • Input Flag: --input-storyboard and -in are now --input and -i.
    • Output Flag: --output-strings-files and -out are now --output and -o.
    • Output Path Separator: Multiple paths passed to -o must now be separated by whitespace instead of commas.
      • Old: -out "path/one,path/two"
      • New: -o "path/one" "path/two"
    • Auto Flag: --output-all-languages and -all are now --auto and -a.
  4. Configure the `update.transform` task for Swift projects

    main

    If you use the transform update task, you must provide a helper implementation in your Swift code to allow BartyCrouch to perform transformations.

    1. Create a file (e.g., SupportingFiles/BartyCrouch.swift) in your project.
    2. Copy the required BartyCrouch enum and translate method into that file.

    This implementation is required for the transform task of the translation helper tool to function correctly.

    //  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!"
        }
    }
  5. Requirements for running BartyCrouch

    main

    To use BartyCrouch, ensure your environment meets the following requirements:

    • Xcode: 14+
    • Swift: 5.7+
    • Xcode Command Line Tools: Must be installed.
    • Xcode 15+ Users: You must set User Script Sandboxing to NO in your target's "Build Settings" tab to allow the tool to run within build scripts.
  6. Setup secrets for translation tests

    main

    To run the translation tests, you must provide an API key by copying the secrets sample file to the expected location:

    cp Tests/BartyCrouchTranslatorTests/Secrets/secrets.json.sample Tests/BartyCrouchTranslatorTests/Secrets/secrets.json
  7. Exclude specific strings from localization

    main

    If you need to prevent BartyCrouch from localizing specific views or code entries, use the following markers:

    In Storyboards/XIBs:

    • Add #bartycrouch-ignore! or #bc-ignore! to the value of the view.
    • Alternatively, add #bc-ignore! to the "Comment For Localizer" field in the utilities pane.

    In Swift Code:

    • Add #bc-ignore! to the comment parameter of an NSLocalizedString macro. This is useful for strings that should be handled by a .stringsdict file instead of .strings.
    func updateTimeLabel(minutes: Int) {
      String.localizedStringWithFormat(NSLocalizedString("%d minute(s) ago", comment: "pluralized and localized minutes #bc-ignore!"), minutes)
    }
  8. Upgrade from 3.x to 4.x

    main

    When upgrading to BartyCrouch 4.x, note the following breaking changes:

    • Subcommand Consolidation: Most subcommands have been bundled into the update subcommand. The lint subcommand remains separate.
    • Configuration Shift: Instead of passing specific subcommands and options via the CLI, you should now use the .bartycrouch.toml configuration file.
    • Build Scripts: Update your build scripts to the new simplified version. Ensure the BartyCrouch step is executed early in your build process.
    • Default Options: The --override-comments (-c) and --extract-loc-strings (-e) options for the code subcommand are now enabled by default and no longer need to be configured.
    • Localization Workflow: Consider adopting the new transform task for your localization workflow, either as a replacement for or an addition to the code task.
  9. Set up BartyCrouch as an Xcode Build Phase

    main

    To automate localization updates and linting, add BartyCrouch as a Run Script Phase in your Xcode target:

    1. Select your target in Xcode.
    2. Go to the Build Phases tab.
    3. Click the + button and select New Run Script Phase.
    4. Set the shell to /bin/sh and paste the following:
    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
    1. Crucial: Drag the script phase so it runs before Compiling Sources (and SwiftGen if used). For example, place it right after Target Dependencies.
  10. Upgrade from 1.x to 2.x

    main

    When upgrading to BartyCrouch 2.x, follow these instructions:

    • Command Structure: Change bartycrouch "$BASE_PATH" -a to bartycrouch -s "$BASE_PATH".
    • Remove Comment Option: Remove the -c option; BartyCrouch 2.x now creates missing keys by default.
    • Simplify Strings Handling: Instead of manually adding every .strings file, use the -t, -s, and -l options to target a project directory and language.

    Example Transformation:

    Old way (manual file addition):

    bartycrouch -t $CREDS -i "$EN_PATH/Localizable.strings" -a -c
    bartycrouch -t $CREDS -i "$EN_PATH/Main.strings" -a
    bartycrouch -t $CREDS -i "$EN_PATH/LaunchScreen.strings" -a
    bartycrouch -t $CREDS -i "$EN_PATH/CustomView.strings" -a

    New way (simplified):

    bartycrouch -t "$CREDS" -s "$PROJECT_DIR" -l en
  11. Install BartyCrouch via Homebrew or Mint

    main

    You can install BartyCrouch using Homebrew or Mint.

    Via Homebrew: To install for the first time:

    brew install bartycrouch

    To update an existing installation:

    brew upgrade bartycrouch

    Via Mint: To install or update to the latest version:

    mint install FlineDev/BartyCrouch
  12. Localizing `LocalizedStringResource` in AppIntents

    main

    Since the introduction of the AppIntents framework, strings can be typed as LocalizedStringResource. To ensure BartyCrouch can extract these, you must use the explicit LocalizedStringResource(_:comment:) initializer rather than the implicit string literal.

    Incorrect (cannot be easily extracted):

    static var title: LocalizedStringResource = "Export all transactions"

    Correct (compatible with BartyCrouch):

    static var title = LocalizedStringResource("Export all transactions", comment: "")

    To support this, ensure your code task configuration includes customFunction="LocalizedStringResource".

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