{"id":18744515,"url":"https://github.com/freshos/localize","last_synced_at":"2025-04-05T23:09:43.786Z","repository":{"id":66259667,"uuid":"76102683","full_name":"freshOS/Localize","owner":"freshOS","description":"🏁 Automatically clean your Localizable.strings files","archived":false,"fork":false,"pushed_at":"2023-08-31T11:59:16.000Z","size":205,"stargazers_count":358,"open_issues_count":8,"forks_count":30,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-29T22:06:31.318Z","etag":null,"topics":["cleanup","freshos","ios","localisation","script","swift","translation","xcode"],"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/freshOS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"open_collective":"freshos","github":"s4cha"}},"created_at":"2016-12-10T09:19:38.000Z","updated_at":"2025-03-24T02:29:04.000Z","dependencies_parsed_at":"2024-04-15T08:28:48.228Z","dependency_job_id":"ab551dcd-4f1f-48d7-bd17-f1cb5e847c11","html_url":"https://github.com/freshOS/Localize","commit_stats":{"total_commits":58,"total_committers":10,"mean_commits":5.8,"dds":0.3448275862068966,"last_synced_commit":"d16bb0a7eed421b746fc6204639f436e7b299e07"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FLocalize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FLocalize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FLocalize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FLocalize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freshOS","download_url":"https://codeload.github.com/freshOS/Localize/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247411235,"owners_count":20934653,"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":["cleanup","freshos","ios","localisation","script","swift","translation","xcode"],"created_at":"2024-11-07T16:15:04.717Z","updated_at":"2025-04-05T23:09:43.768Z","avatar_url":"https://github.com/freshOS.png","language":"Swift","readme":"![Localize](https://raw.githubusercontent.com/s4cha/Localize/master/banner.png)\n\n# Localize\n[![Language: Swift](https://img.shields.io/badge/language-swift-f48041.svg?style=flat)](https://developer.apple.com/swift)\n![Platform: iOS](https://img.shields.io/badge/platform-iOS-blue.svg?style=flat)\n[![codebeat badge](https://codebeat.co/badges/1eefc440-01e1-4408-bc92-1b8eeab9796c)](https://codebeat.co/projects/github-com-freshos-localize-master)\n[![License: MIT](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](https://github.com/s4cha/Localize/blob/master/LICENSE)\n[![Release version](https://img.shields.io/badge/release-0.1-blue.svg)]()\n\n*Localize* is a tiny run script that keeps your `Localizable.strings` files clean and emits warnings when something is suspicious.\n\n\n![Localize](https://raw.githubusercontent.com/s4cha/Localize/master/xcodeScreenshot.png)\n\n\nBecause **Localization** files tend to **rot over time** and become a hassle to work with. **Stressful** when you have to test your app against many different Localizations.\n\n## Try it!\n\nLocalize is part of [freshOS](https://freshos.github.io/) iOS toolset. Try it out in the included example app!\n\n## How\nBy using a **script** running automatically, you have a **safety net** keeping them **sane**, checking for **translation issues** and preventing then to **rot over time.**\n\n## What\nAutomatically (On build)\n  - [x] **Cleans** you localization files (removes spaces)\n  - [x] **Sorts** keys Alphabetically\n  - [x] Checks for **Unused Keys**\n  - [x] Checks for **Missing Keys**\n  - [x] Checks for **Untranslated** (which you can ignore with a flag)\n  - [x] Checks for **Redundant Keys**\n  - [x] Checks for **Duplicate Keys**\n\n## Installation\n\nAdd the following `Run Script` in your project's `Build Phases` in XCode, this will run the script at every build.\nUse the path of where you copied `Localize.swift` script.\n\n```shell\n${SRCROOT}/{REPLACE ME}} # e.g. ${SRCROOT}/Libs/Localize.swift\n```\nRun and Enjoy \\o/\n\n## Configuration\nConfigure the top section of the `Localize.swift` according to your project.\n\n## More\n\n### Ignore [Potentially Untranslated] warnings\nJust Add `//ignore-same-translation-warning` next to the translation.\nExample :\n```\n\"PhotoKey\" = \"Photo\"; //ignore-same-translation-warning\n```\nThis will take care of ignoring `[Potentially Untranslated] \"XXX\" in FR file doesn't seem to be localized`\n\n### Unused false positive\n\n#### Not found by the script reason 1\nThe script parses your project sources and checks if your keys are called within `NSLocalizedString` calls.\nBut chances are you have a helper for a shorter NSLocalizedString syntax.\nThis is indeed supported but you have to give the script what to look for.\n\nYou can modify the script to include other ways of localizations:\n\n```swift\nlet patterns = [\n    \"NSLocalizedString\\\\(@?\\\"(\\\\w+)\\\"\", // Swift and Objc Native\n    \"Localizations\\\\.((?:[A-Z]{1}[a-z]*[A-z]*)*(?:\\\\.[A-Z]{1}[a-z]*[A-z]*)*)\", // Laurine Calls\n    //Add your own matching regex here\n    \"fsLocalized\\\\(@?\\\"(\\\\w+)\\\"\"\n]\n```\n\n#### Not found by the script reason 2\nAnother common pattern is to have keys being built at runtime.\nOf course those keys are not present at compile time so the script can't know about them and emits false positive errors.\nYou can add those keys at the top of of the script to prevent this from happening:\n\n```swift\nlet ignoredFromUnusedKeys = [\n    \"NotificationNoOne\",\n    \"NotificationCommentPhoto\",\n    \"NotificationCommentHisPhoto\",\n    \"NotificationCommentHerPhoto\"\n]\n```\n\n## Author\n\nSacha Durand Saint Omer, sachadso@gmail.com\n\n## Contributors\n[JuliusBahr](https://github.com/JuliusBahr), [ezisazis](https://github.com/ezisazis/), [michalsrutek](https://github.com/michalsrutek/)\n\n## Contributing\n\nContributions to Localize are very welcomed and encouraged!\n\n## License\n\nLocalize is available under the MIT license. See [LICENSE](https://github.com/s4cha/Localize/blob/master/LICENSE) for more information.\n\n\n# Backers\nLike the project? Offer coffee or support us with a monthly donation and help us continue our activities :)\n\n\u003ca href=\"https://opencollective.com/freshos/backer/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/9/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/10/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/10/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/11/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/11/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/12/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/12/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/13/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/13/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/14/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/14/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/15/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/15/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/16/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/16/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/17/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/17/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/18/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/18/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/19/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/19/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/20/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/20/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/21/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/21/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/22/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/22/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/23/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/23/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/24/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/24/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/25/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/25/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/26/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/26/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/27/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/27/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/28/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/28/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/29/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/29/avatar.svg\"\u003e\u003c/a\u003e\n\n### Sponsors\nBecome a sponsor and get your logo on our README on Github with a link to your site :)\n\n\u003ca href=\"https://opencollective.com/freshos/sponsor/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/9/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/10/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/10/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/11/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/11/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/12/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/12/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/13/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/13/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/14/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/14/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/15/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/15/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/16/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/16/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/17/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/17/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/18/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/18/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/19/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/19/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/20/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/20/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/21/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/21/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/22/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/22/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/23/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/23/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/24/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/24/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/25/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/25/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/26/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/26/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/27/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/27/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/28/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/28/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/29/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/29/avatar.svg\"\u003e\u003c/a\u003e\n","funding_links":["https://opencollective.com/freshos","https://github.com/sponsors/s4cha","https://opencollective.com/freshos/backer/0/website","https://opencollective.com/freshos/backer/1/website","https://opencollective.com/freshos/backer/2/website","https://opencollective.com/freshos/backer/3/website","https://opencollective.com/freshos/backer/4/website","https://opencollective.com/freshos/backer/5/website","https://opencollective.com/freshos/backer/6/website","https://opencollective.com/freshos/backer/7/website","https://opencollective.com/freshos/backer/8/website","https://opencollective.com/freshos/backer/9/website","https://opencollective.com/freshos/backer/10/website","https://opencollective.com/freshos/backer/11/website","https://opencollective.com/freshos/backer/12/website","https://opencollective.com/freshos/backer/13/website","https://opencollective.com/freshos/backer/14/website","https://opencollective.com/freshos/backer/15/website","https://opencollective.com/freshos/backer/16/website","https://opencollective.com/freshos/backer/17/website","https://opencollective.com/freshos/backer/18/website","https://opencollective.com/freshos/backer/19/website","https://opencollective.com/freshos/backer/20/website","https://opencollective.com/freshos/backer/21/website","https://opencollective.com/freshos/backer/22/website","https://opencollective.com/freshos/backer/23/website","https://opencollective.com/freshos/backer/24/website","https://opencollective.com/freshos/backer/25/website","https://opencollective.com/freshos/backer/26/website","https://opencollective.com/freshos/backer/27/website","https://opencollective.com/freshos/backer/28/website","https://opencollective.com/freshos/backer/29/website"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreshos%2Flocalize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffreshos%2Flocalize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffreshos%2Flocalize/lists"}