{"id":27443388,"url":"https://github.com/Flinesoft/BartyCrouch","last_synced_at":"2025-04-15T02:00:59.256Z","repository":{"id":37831303,"uuid":"51701588","full_name":"FlineDev/BartyCrouch","owner":"FlineDev","description":"Localization/I18n: Incrementally update/translate your Strings files from .swift, .h, .m(m), .storyboard or .xib files.","archived":false,"fork":false,"pushed_at":"2024-04-05T11:31:19.000Z","size":2584,"stargazers_count":1392,"open_issues_count":42,"forks_count":121,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-04-14T13:58:27.664Z","etag":null,"topics":["code","incremental","language","localization","machine-translation","storyboard","swift","translation","xcode","xib"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FlineDev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-14T16:08:40.000Z","updated_at":"2025-04-13T16:40:20.000Z","dependencies_parsed_at":"2024-04-05T12:33:59.379Z","dependency_job_id":null,"html_url":"https://github.com/FlineDev/BartyCrouch","commit_stats":{"total_commits":599,"total_committers":47,"mean_commits":12.74468085106383,"dds":0.6310517529215358,"last_synced_commit":"da21794e7b23370e058264a487404c946675abcc"},"previous_names":["flinesoft/bartycrouch"],"tags_count":92,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlineDev%2FBartyCrouch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlineDev%2FBartyCrouch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlineDev%2FBartyCrouch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FlineDev%2FBartyCrouch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FlineDev","download_url":"https://codeload.github.com/FlineDev/BartyCrouch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248991546,"owners_count":21194894,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code","incremental","language","localization","machine-translation","storyboard","swift","translation","xcode","xib"],"created_at":"2025-04-15T02:00:46.007Z","updated_at":"2025-04-15T02:00:59.216Z","avatar_url":"https://github.com/FlineDev.png","language":"Swift","readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/FlineDev/BartyCrouch/main/Logo.png\" width=600\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/FlineDev/BartyCrouch/actions?query=workflow%3ACI+branch%3Amain\"\u003e\n    \u003cimg src=\"https://github.com/FlineDev/BartyCrouch/workflows/CI/badge.svg?branch=main\"\n         alt=\"CI Status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.codacy.com/gh/FlineDev/BartyCrouch\"\u003e\n    \u003cimg src=\"https://api.codacy.com/project/badge/Grade/7b34ad9193c2438aa32aa29a0490451f\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.codacy.com/gh/FlineDev/BartyCrouch\"\u003e\n    \u003cimg src=\"https://api.codacy.com/project/badge/Coverage/7b34ad9193c2438aa32aa29a0490451f\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/FlineDev/BartyCrouch/releases\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Version-4.14.0-blue.svg\"\n         alt=\"Version: 4.14.0\"\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Swift-5.7-FFAC45.svg\"\n     alt=\"Swift: 5.7\"\u003e\n  \u003ca href=\"https://github.com/FlineDev/BartyCrouch/blob/main/LICENSE.md\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-lightgrey.svg\"\n         alt=\"License: MIT\"\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  \u003ca href=\"https://paypal.me/Dschee/5EUR\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/PayPal-Donate-orange.svg\"\n         alt=\"PayPal: Donate\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/sponsors/Jeehut\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/GitHub-Become a sponsor-orange.svg\"\n         alt=\"GitHub: Become a sponsor\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://patreon.com/Jeehut\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Patreon-Become a patron-orange.svg\"\n         alt=\"Patreon: Become a patron\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\n  • \u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e\n  • \u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\n  • \u003ca href=\"#build-script\"\u003eBuild Script\u003c/a\u003e\n  • \u003ca href=\"#donation\"\u003eDonation\u003c/a\u003e\n  • \u003ca href=\"#migration-guides\"\u003eMigration Guides\u003c/a\u003e\n  • \u003ca href=\"https://github.com/FlineDev/BartyCrouch/issues\"\u003eIssues\u003c/a\u003e\n  • \u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\n  • \u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\n\u003c/p\u003e\n\n\u003e :sparkles: **Important Notice** :sparkles:\n\u003e\n\u003e 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 a [detailed FAQ](https://www.fline.dev/the-missing-string-catalogs-faq-for-xcode-15/) about String Catalogs if you want to learn more. It's really awesome, everybody should migrate to it!\n\u003e\n\u003e 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. Use [TranslateKit](https://apps.apple.com/app/apple-store/id6476773066?pt=549314\u0026ct=github.com\u0026mt=8) in the future by simply drag \u0026 dropping the String Catalog file and letting it handle the translation, it's really easy.\n\u003e\n\u003e Note that TranslateKit is being **actively worked on**. In comparison, BartyCrouch is kept up-to-date only by volunteers in the community.\n\n# BartyCrouch\n\nBartyCrouch **incrementally updates** your Strings files from your Code *and* from Interface Builder files. \"Incrementally\" means that BartyCrouch will by default **keep** both your already **translated values** and even your altered comments. Additionally you can also use BartyCrouch for **machine translating** from one language to 60+ other languages. Using BartyCrouch is as easy as **running a few simple commands** from the command line what can even be **automated using a [build script](#build-script)** within your project.\n\nCheckout [this blog post](https://jeehut.medium.com/localization-in-swift-like-a-pro-48164203afe2?sk=da26d918390db21261b7ead4837286fc) to learn how you can effectively use BartyCrouch in your projects.\n\n## Requirements\n\n- Xcode 14+ \u0026 Swift 5.7+\n- Xcode Command Line Tools (see [here](http://stackoverflow.com/a/9329325/3451975) for installation instructions)\n- In Xcode 15 or later: Set \"User Script Sandboxing\" to NO in your target's \"Build Settings\" tab\n\n## Getting Started\n\n### Installation\n\n\u003cdetails\u003e\n\u003csummary\u003eVia \u003ca href=\"https://brew.sh/\"\u003eHomebrew\u003c/a\u003e\u003c/summary\u003e\n\nTo install Bartycrouch the first time, simply run the command:\n\n```bash\nbrew install bartycrouch\n```\n\nTo **update** to the newest version of BartyCrouch when you have an old version already installed run:\n\n```bash\nbrew upgrade bartycrouch\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eVia \u003ca href=\"https://github.com/yonaskolb/Mint\"\u003eMint\u003c/a\u003e\u003c/summary\u003e\n\nTo **install** or update to the latest version of BartyCrouch simply run this command:\n\n```bash\nmint install FlineDev/BartyCrouch\n```\n\u003c/details\u003e\n\n### Configuration\n\nTo configure BartyCrouch for your project, first create a configuration file within your projects root directory. BartyCrouch can do this for you:\n\n```\nbartycrouch init\n```\n\nNow you should have a file named `.bartycrouch.toml` with the following contents:\n\n```toml\n[update]\ntasks = [\"interfaces\", \"code\", \"transform\", \"normalize\"]\n\n[update.interfaces]\npaths = [\".\"]\nsubpathsToIgnore = [\".git\", \"carthage\", \"pods\", \"build\", \".build\", \"docs\"]\ndefaultToBase = false\nignoreEmptyStrings = false\nunstripped = false\nignoreKeys = [\"#bartycrouch-ignore!\", \"#bc-ignore!\", \"#i!\"]\n\n[update.code]\ncodePaths = [\".\"]\nsubpathsToIgnore = [\".git\", \"carthage\", \"pods\", \"build\", \".build\", \"docs\"]\nlocalizablePaths = [\".\"]\ndefaultToKeys = false\nadditive = true\nunstripped = false\nignoreKeys = [\"#bartycrouch-ignore!\", \"#bc-ignore!\", \"#i!\"]\n\n[update.transform]\ncodePaths = [\".\"]\nsubpathsToIgnore = [\".git\", \"carthage\", \"pods\", \"build\", \".build\", \"docs\"]\nlocalizablePaths = [\".\"]\ntransformer = \"foundation\"\nsupportedLanguageEnumPath = \".\"\ntypeName = \"BartyCrouch\"\ntranslateMethodName = \"translate\"\n\n[update.normalize]\npaths = [\".\"]\nsubpathsToIgnore = [\".git\", \"carthage\", \"pods\", \"build\", \".build\", \"docs\"]\nsourceLocale = \"en\"\nharmonizeWithSource = true\nsortByKeys = true\n\n[lint]\npaths = [\".\"]\nsubpathsToIgnore = [\".git\", \"carthage\", \"pods\", \"build\", \".build\", \"docs\"]\nduplicateKeys = true\nemptyValues = true\n```\n\nThis 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:\n\n1. To speed it up significantly, provide more specific paths for any key containing `path` if possible (especially in the `update.transform` section, e.g. `[\"App/Sources\"]` for `codePaths` or `[\"App/Supporting Files\"]` for `supportedLanguageEnumPaths`).\n2. Remove the `code` task if your project is Swift-only and you use the new [`transform` update task](#localization-workflow-via-transform).\n3. If you are using [SwiftGen](https://github.com/SwiftGen/SwiftGen#strings) with the `structured-swift4` template, you will probably want to use the `transform` task and change its `transformer` option to `swiftgenStructured`.\n4. If you decided to use the `transform` task, create a new file in your project (e.g. under `SupportingFiles`) named `BartyCrouch.swift` and copy the following code:\n\n```swift\n//  This file is required in order for the `transform` task of the translation helper tool BartyCrouch to work.\n//  See here for more details: https://github.com/FlineDev/BartyCrouch\n\nimport Foundation\n\nenum BartyCrouch {\n    enum SupportedLanguage: String {\n        // TODO: remove unsupported languages from the following cases list \u0026 add any missing languages\n        case arabic = \"ar\"\n        case chineseSimplified = \"zh-Hans\"\n        case chineseTraditional = \"zh-Hant\"\n        case english = \"en\"\n        case french = \"fr\"\n        case german = \"de\"\n        case hindi = \"hi\"\n        case italian = \"it\"\n        case japanese = \"ja\"\n        case korean = \"ko\"\n        case malay = \"ms\"\n        case portuguese = \"pt-BR\"\n        case russian = \"ru\"\n        case spanish = \"es\"\n        case turkish = \"tr\"\n    }\n\n    static func translate(key: String, translations: [SupportedLanguage: String], comment: String? = nil) -\u003e String {\n        let typeName = String(describing: BartyCrouch.self)\n        let methodName = #function\n\n        print(\n            \"Warning: [BartyCrouch]\",\n            \"Untransformed \\(typeName).\\(methodName) method call found with key '\\(key)' and base translations '\\(translations)'.\",\n            \"Please ensure that BartyCrouch is installed and configured correctly.\"\n        )\n\n        // fall back in case something goes wrong with BartyCrouch transformation\n        return \"BC: TRANSFORMATION FAILED!\"\n    }\n}\n```\n\n5. If you don't develop in English as the first localized language, you should update the `sourceLocale` of the `normalize` task.\n6. If you want to use the machine translation feature of BartyCrouch, add `translate` to the tasks list at the top and copy the following section into the configuration file with `secret` replaced by your [Microsoft Translator Text API Subscription Key](https://docs.microsoft.com/en-us/azure/cognitive-services/translator/translator-text-how-to-signup#authentication-key):\n\n```toml\n[update.translate]\npaths = \".\"\ntranslator = \"microsoftTranslator\"\nsecret = \"\u003c#Subscription Key#\u003e\"\nsourceLocale = \"en\"\n```\n\n## Usage\n\nBefore using BartyCrouch please **make sure you have committed your code**. Also, we highly recommend using the **build script method** described [below](#build-script).\n\n---\n\n`bartycrouch` accepts one of the following sub commands:\n\n- **`update`:** Updates your `.strings` file contents according to your configuration.\n- **`lint`:** Checks your `.strings` file contents for empty values \u0026 duplicate keys.\n\nAlso the following command line options can be provided:\n\n- **`-v`, `--verbose`**: Prints more detailed information about the executed command.\n- **`-x`, `--xcode-output`**: Prints warnings \u0026 errors in Xcode compatible format.\n- **`-w`, `--fail-on-warnings`**: Returns a failed status code if any warning is encountered.\n- **`-p`, `--path`**: Specifies a different path than current to run BartyCrouch from there.\n\n### `update` subcommand\n\nThe update subcommand can be run with one or multiple of the following tasks:\n\n- `interfaces`: Updates `.strings` files of Storyboards \u0026 XIBs.\n- `code`: Updates `Localizable.strings` file from `NSLocalizedString` entries in code.\n- `transform`: A mode where BartyCrouch replaces a specific method call to provide translations in multiple languages in a single line. Only supports Swift files.\n- `translate`: Updates missing translations in other languages than the source language.\n- `normalize`: Sorts \u0026 cleans up `.strings` files.\n\nIn order to configure which tasks are executed, edit this section in the config file:\n\n```toml\n[update]\ntasks = [\"interfaces\", \"code\", \"transform\", \"normalize\"]\n```\n\n\u003cdetails\u003e\u003csummary\u003eOptions for \u003ccode\u003einterfaces\u003c/code\u003e\u003c/summary\u003e\n\n- `paths`: The directory / directories to search for Storyboards \u0026 XIB files.\n- `subpathsToIgnore`: The subpaths to be ignored inside the directories found via the `paths` option.\n- `defaultToBase`: Add Base translation as value to new keys.\n- `ignoreEmptyStrings`: Doesn't add views with empty values.\n- `unstripped`: Keeps whitespaces at beginning \u0026 end of Strings files.\n- `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.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eOptions for \u003ccode\u003ecode\u003c/code\u003e\u003c/summary\u003e\n\n- `codePaths`: The directory / directories to search for Swift code files.\n- `subpathsToIgnore`: The subpaths to be ignored inside the directories found via the `paths` option.\n- `localizablePaths`: The enclosing path(s) containing the localized `Localizable.strings` files.\n- `defaultToKeys`: Add new keys both as key and value.\n- `additive`: Prevents cleaning up keys not found in code.\n- `customFunction`: Use alternative name to search for strings to localize, in addition to `NSLocalizedString`, and `CFCopyLocalizedString`. Defaults to `LocalizedStringResource`.\n- `customLocalizableName`: Use alternative name for `Localizable.strings`.\n- `unstripped`: Keeps whitespaces at beginning \u0026 end of Strings files.\n- `plistArguments`: Use a plist file to store all the code files for the ExtractLocStrings tool. (Recommended for large projects.)\n- `ignoreKeys`: Keys (e.g. in the comment) indicating that specific translation entries should be ignored when generating String files.\n- `overrideComments`: Always overrides the comment with the keys new translation, useful for IB files.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eOptions for \u003ccode\u003etransform\u003c/code\u003e\u003c/summary\u003e\n\n- `codePaths`: The directory / directories to search for Swift code files.\n- `subpathsToIgnore`: The subpaths to be ignored inside the directories found via the `paths` option.\n- `localizablePaths`:  The enclosing path(s) containing the localized `Localizable.strings` files.\n- `transformer`: Specifies the replacement code. Use `foundation` for `NSLocalizedString` or `swiftgenStructured` for `L10n` entries.\n- `supportedLanguageEnumPath`: The enclosing path containing the `SupportedLanguage` enum.\n- `typeName`: The name of the type enclosing the `SupportedLanguage` enum and translate method.\n- `translateMethodName`: The name of the translate method to be replaced.\n- `customLocalizableName`: Use alternative name for `Localizable.strings`.\n- `separateWithEmptyLine`: Set to `false` if you don't want to have empty lines between Strings entries. Defaults to `true.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eOptions for \u003ccode\u003etranslate\u003c/code\u003e\u003c/summary\u003e\n\n- `paths`: The directory / directories to search for Strings files.\n- `subpathsToIgnore`: The subpaths to be ignored inside the directories found via the `paths` option.\n- `translator`: Specifies the translation API. Use `microsoftTranslator` or `deepL`.\n- `secret`: Your [Microsoft Translator Text API Subscription Key](https://docs.microsoft.com/en-us/azure/cognitive-services/translator/translator-text-how-to-signup#authentication-key) or [Authentication Key for DeepL API](https://www.deepl.com/pro-account/plan).\n- `sourceLocale`: The source language to translate from.\n- `separateWithEmptyLine`: Set to `false` if you don't want to have empty lines between Strings entries. Defaults to `true.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eOptions for \u003ccode\u003enormalize\u003c/code\u003e\u003c/summary\u003e\n\n- `paths`: The directory / directories to search for Strings files.\n- `subpathsToIgnore`: The subpaths to be ignored inside the directories found via the `paths` option.\n- `sourceLocale`: The source language to harmonize keys of other languages with.\n- `harmonizeWithSource`: Synchronizes keys with source language.\n- `sortByKeys`: Alphabetically sorts translations by their keys.\n- `separateWithEmptyLine`: Set to `false` if you don't want to have empty lines between Strings entries. Defaults to `true.\n\n\u003c/details\u003e\n\n### `lint` subcommand\n\nThe lint subcommand was designed to analyze a project for typical translation issues. The current checks include:\n\n- `duplicateKeys`: Finds duplicate keys within the same file.\n- `emptyValues`: Finds empty values for any language.\n\nNote that the `lint` command can be used both on CI and within Xcode via the build script method:\n\n- In Xcode the `-x` or `--xcode-output` command line argument should be used to get warnings which point you directly to the found issue.\n- 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.\n\n\n### Localization Workflow via `transform`\n\nWhen the `transform` update task is configured (see recommended step 4 in the [Configuration](#configuration) section above) and you are using the [build script method](#build-script), you can use the following simplified process for writing localized code during development:\n\n1. Instead of `NSLocalizedString` calls you can use `BartyCrouch.translate` and specify a key, translations (if any) and optionally a comment. For example:\n\n```swift\nself.title = BartyCrouch.translate(key: \"onboarding.first-page.header-title\",  translations: [.english: \"Welcome!\"])\n```\n\n2. Once you build your app, BartyCrouch will automatically add the new translation key to all your `Localizable.strings` files and add the provided translations as values for the provided languages.\n3. Additionally, during the same build BartyCrouch will automatically replace the above call to `BartyCrouch.translate` with the proper translation call, depending on your `transformer` option setting.\n\nThe resulting code depends on your `transformer` option setting:\n\nWhen set to `foundation`, the above code will transform to:\n\n```swift\nself.title = NSLocalizedString(\"onboarding.first-page.header-title\", comment: \"\")\n```\n\nWhen set to `swiftgenStructured` it will transform to:\n\n```swift\nself.title = L10n.Onboarding.FirstPage.headerTitle\n```\n\n**Advantages of `transform` over the `code` task:**\n* You can provide translations for keys without switching to the Strings files.\n* In case you use SwiftGen, you don't need to replace calls to `NSLocalizedString` with `L10n` calls manually after running BartyCrouch.\n* 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 \u0026 without ever leaving the code.\n\n**Disadvantages of `transform` over the `code` task:**\n* Only works for Swift Code. No support for Objective-C. (You can use both methods simultaneously though.)\n* Xcode will mark the freshly transformed code as errors (but build will succeed anyways) until next build.\n* Not as fast as `code` since [SwiftSyntax](https://github.com/apple/swift-syntax) currently isn't [particularly fast](https://www.jpsim.com/evaluating-swiftsyntax-for-use-in-swiftlint/). (But this should improve over time!)\n\nNOTE: As of version 4.x of BartyCrouch *formatted* localized Strings are not supported by this automatic feature.\n\n### Localizing strings of `LocalizableStringResource` type (AppIntents, ...)\n\nHistorically, Apple platforms used `CFCopyLocalizedString`, and `NSLocalizedString` macros and their variants, to mark strings used in code to be localized, and to load their localized versions during runtime from `Localizable.strings` file.\n\nSince introduction of the AppIntents framework, the localized strings in code can also be typed as `LocalizedStringResource`, and are no longer marked explicitly.\n\nLet's examine this snippet of AppIntents code:\n\n```\nstruct ExportAllTransactionsIntent: AppIntent {\n    static var title: LocalizedStringResource = \"Export all transactions\"\n\n    static var description =\n        IntentDescription(\"Exports your transaction history as CSV data.\")\n}\n```\n\nIn the example above, both the `\"Export all transactions\"`, and `\"Exports your transaction history as CSV data.\"` are actually `StaticString` instances that will be converted during compilation into `LocalizedStringResource` instances, and will lookup their respective localizations during runtime from `Localized.strings` file the same way as when using `NSLocalizedString` 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 using `Product -\u003e Export Localizations...` option.\n\nIn order to continue translating these strings with `bartycrouch` it is required to mark them explicitely with `LocalizedStringResource(_: String, comment: String)` call, and specify `customFunction=\"LocalizedStringResource\"` in `code` task options.\n\nThe example AppIntents code that can be localized with `bartycrouch` will look like this:\n\n```\nstruct ExportAllTransactionsIntent: AppIntent {\n    static var title = LocalizedStringResource(\"Export all transactions\", comment: \"\")\n\n    static var description =\n        IntentDescription(LocalizedStringResource(\"Exports your transaction history as CSV data.\", comment: \"\"))\n}\n```\n\nNote that you must use the full form of `LocalizedStringResource(_: StaticString, comment: StaticString)` for the `bartycrouch`, or more specifically for the `extractLocStrings` (see `xcrun extractLocStrings`) to properly parse the strings.\n\n### Build Script\n\nIn order to truly profit from BartyCrouch's ability to update \u0026 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 the `Build Phases` tab and click the + button on the top left corner of that pane. Select `New Run Script Phase` and copy the following into the text box below the `Shell: /bin/sh` of your new run script phase:\n\n```shell\nexport PATH=\"$PATH:/opt/homebrew/bin\"\n\nif which bartycrouch \u003e /dev/null; then\n    bartycrouch update -x\n    bartycrouch lint -x\nelse\n    echo \"warning: BartyCrouch not installed, download it from https://github.com/FlineDev/BartyCrouch\"\nfi\n```\n\n\u003cimg src=\"Images/Build-Script-Example.png\"\u003e\n\nNext, make sure the BartyCrouch script runs before the steps `Compiling Sources` (and `SwiftGen` if used) by moving it per drag \u0026 drop, for example right after `Target Dependencies`.\n\nNow 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.\n\n*Note: Please make sure you commit your code using source control regularly when using the build script method.*\n\n---\n\n### Exclude specific Views / NSLocalizedStrings from Localization\n\nSometimes you may want to **ignore some specific views** containing localizable texts e.g. because **their values are going to be set programmatically**.\n\nFor 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.\n\nThis will tell BartyCrouch to ignore this specific view when updating your `.strings` files.\n\nHere's an example of how a base localized view in a XIB file with partly ignored strings might look like:\n\n\u003cimg src=\"Images/Exclusion-Example.png\"\u003e\n\nHere's an example with the alternative comment variant:\n\n\u003cdiv style=\"float:left;\"\u003e\n\t\u003cimg src=\"Images/IB-Comment-Exclusion-Example1.png\" width=\"255px\" height=\"437px\"\u003e\n\t\u003cimg src=\"Images/IB-Comment-Exclusion-Example2.png\" width=\"254px\" height=\"140px\"\u003e\n\u003c/div\u003e\n\nYou can also use `#bc-ignore!` in your `NSLocalizedString` macros comment part to ignore them so they are not added to your `Localizable.strings`. This might be helpful when you are using a `.stringsdict` file to handle pluralization (see [docs](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html)).\n\nFor example you can do something like this:\n\n```swift\nfunc updateTimeLabel(minutes: Int) {\n  String.localizedStringWithFormat(NSLocalizedString(\"%d minute(s) ago\", comment: \"pluralized and localized minutes #bc-ignore!\"), minutes)\n}\n```\n\nThe `%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.\n\n\n## Donation\n\nBartyCrouch was brought to you by [Cihat Gündüz](https://github.com/Jeehut) in his free time. If you want to thank me and support the development of this project, please **make a small donation on [PayPal](https://paypal.me/Dschee/5EUR)**. In case you also like my other [open source contributions](https://github.com/FlineDev) and [articles](https://medium.com/@Jeehut), please consider motivating me by **becoming a sponsor on [GitHub](https://github.com/sponsors/Jeehut)** or a **patron on [Patreon](https://www.patreon.com/Jeehut)**.\n\nThank you very much for any donation, it really helps out a lot! 💯\n\n## Migration Guides\n\nSee the file [MIGRATION_GUIDES.md](https://github.com/FlineDev/BartyCrouch/blob/main/MIGRATION_GUIDES.md).\n\n## Contributing\n\nContributions 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 your **commit messages** (see rationale [here](http://chris.beams.io/posts/git-commit/)). Also, please make sure to add an entry to the `CHANGELOG.md` file which explains your change.\n\nIn 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:\n```shell\ncp Tests/BartyCrouchTranslatorTests/Secrets/secrets.json.sample Tests/BartyCrouchTranslatorTests/Secrets/secrets.json\n```  \n\nAfter Release Checklist:\n\n1. Run `make portable_zip` to generate `.build/release/portable_bartycrouch.zip`\n2. Create new release with text from new `CHANGELOG.md` section \u0026 attach `portable_bartycrouch.zip` as binary\n3. Run `pod trunk push` to make a new release known to CocoaPods\n4. Update `tag` and `revision` in `Formula/bartycrouch.rb`, commit \u0026 push change\n5. Run `brew bump-formula-pr bartycrouch --tag=\u003ctag\u003e --revision=\u003crevision\u003e`\n\n## License\nThis library is released under the [MIT License](http://opensource.org/licenses/MIT). See LICENSE for details.\n","funding_links":["https://paypal.me/Dschee/5EUR","https://github.com/sponsors/Jeehut","https://patreon.com/Jeehut","https://paypal.me/Dschee/5EUR)*","https://www.patreon.com/Jeehut)*"],"categories":["Localization [🔝](#readme)","Libs","Localization","多语言"],"sub_categories":["Localization","Other Hardware"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlinesoft%2FBartyCrouch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFlinesoft%2FBartyCrouch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFlinesoft%2FBartyCrouch/lists"}