{"id":26249803,"url":"https://github.com/eyalkatz24/localized","last_synced_at":"2026-04-28T14:02:26.824Z","repository":{"id":272212445,"uuid":"915844340","full_name":"EyalKatz24/Localized","owner":"EyalKatz24","description":"Manage your localizable string files easily with a simple Swift macro 😎","archived":false,"fork":false,"pushed_at":"2025-02-15T19:15:48.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-15T19:32:01.298Z","etag":null,"topics":["localizable-strings","swift-localization","swift-macros"],"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/EyalKatz24.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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":"2025-01-13T00:01:03.000Z","updated_at":"2025-02-15T19:15:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"c9aa76e0-6e4c-433d-9c8e-e186f0a6f0e1","html_url":"https://github.com/EyalKatz24/Localized","commit_stats":null,"previous_names":["eyalkatz24/localized"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EyalKatz24%2FLocalized","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EyalKatz24%2FLocalized/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EyalKatz24%2FLocalized/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EyalKatz24%2FLocalized/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EyalKatz24","download_url":"https://codeload.github.com/EyalKatz24/Localized/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243437984,"owners_count":20290863,"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":["localizable-strings","swift-localization","swift-macros"],"created_at":"2025-03-13T15:49:46.448Z","updated_at":"2025-12-28T14:59:10.461Z","avatar_url":"https://github.com/EyalKatz24.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Localized\n\n[![Swift](https://img.shields.io/badge/Swift-5.9+-orange?logo=swift)](https://swift.org)\n[![SPM](https://img.shields.io/badge/SPM-Compatible-brightgreen?logo=hackthebox)](https://swift.org/package-manager)\n[![Platforms](https://img.shields.io/badge/Platforms-iOS%2013+%20|%20macOS%2010.15+%20|%20tvOS%2013+%20|%20watchOS%206+-blue?logo=apple)](https://developer.apple.com)\n[![License](https://img.shields.io/badge/License-MIT-purple?logo=bitwarden)](LICENSE)\n\nA Swift macro that automatically generates localized string properties for enums, making internationalization in Swift projects more type-safe and maintainable.\n\n## Features\n\n- **Type-safe localization**: Convert enum cases to localization keys automatically\n- **Multiple key formats**: Support for upper snake case, lower snake case, camel case, and Pascal case\n- **String formatting**: Automatic handling of associated values for string interpolation\n- **Bundle support**: Custom bundle support for modular apps\n- **Compile-time validation**: Detect key conflicts and invalid usage at compile time\n- **Zero runtime overhead**: All code is generated at compile time\n\n## Installation\n\n### Swift Package Manager\n\nAdd the following dependency to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/EyalKatz24/Localized.git\", from: \"1.0.0\")\n]\n```\n\nOr add it to your Xcode project:\n1. File → Add Package Dependencies\n2. Enter the repository URL\n3. Select the version you want to use\n\n## Usage\n\n### Basic Usage\n\nSimply add the `@Localized` macro to any enum:\n\n```swift\n@Localized\nenum Localization {\n    case ok\n    case cancel\n    case welcome\n    case goodbye\n}\n```\n\nThis generates:\n- A `localized` property that returns the localized string\n- A `localizedKey` property that returns the localization key\n- A private `localized(_:)` function for internal use\n\n### With Associated Values\n\nThe macro automatically handles associated values for string formatting:\n\n```swift\n@Localized\nenum Localization {\n    case welcome(name: String)\n    case totalCost(amount: Double, currency: String)\n    case items(count: Int, itemName: String)\n}\n```\n\n### Key Format Options\n\nYou can customize how enum cases are converted to localization keys:\n\n```swift\n// Upper snake case (default): HELLO_WORLD\n@Localized\nenum Localization {\n    case helloWorld\n}\n\n// Lower snake case: hello_world\n@Localized(keyFormat: .lowerSnakeCase)\nenum Localization {\n    case helloWorld\n}\n\n// Camel case: helloWorld\n@Localized(keyFormat: .camelCase)\nenum Localization {\n    case helloWorld\n}\n\n// Pascal case: HelloWorld\n@Localized(keyFormat: .pascalCase)\nenum Localization {\n    case helloWorld\n}\n```\n\n### Custom Bundle Support\n\nFor modular apps or frameworks, you can specify a custom bundle:\n\n```swift\n@Localized(bundleId: \"com.myapp.core\")\nenum CoreLocalization {\n    case welcome\n    case error\n}\n\n// Or with both key format and bundle\n@Localized(keyFormat: .camelCase, bundleId: \"com.myapp.features\")\nenum FeatureLocalization {\n    case newFeature\n    case settings\n}\n```\n\n### Using with Bundle.module\n\nWhen using in a Swift Package, you can use `Bundle.module`:\n\n```swift\n@Localized(bundleId: \"\\(Bundle.module.bundleIdentifier!)\")\nenum PackageLocalization {\n    case packageSpecific\n}\n```\n\n## Generated Code\n\nThe macro generates the following code for each enum:\n\n```swift\n@Localized\nenum Localization {\n    case welcome(name: String)\n    case goodbye\n    \n    // Generated properties and methods\n    public var localized: String {\n        switch self {\n        case let .welcome(value0):\n            String(format: localized(\"WELCOME\"), value0)\n        case .goodbye:\n            localized(\"GOODBYE\")\n        }\n    }\n    \n    public var localizedKey: String {\n        switch self {\n        case .welcome:\n            \"WELCOME\"\n        case .goodbye:\n            \"GOODBYE\"\n        }\n    }\n    \n    private func localized(_ string: String) -\u003e String {\n        NSLocalizedString(string, comment: \"\")\n    }\n}\n```\n\n## Localization Files\n\nCreate your `.strings` files with the generated keys:\n\n**Localizable.strings (English)**\n```\n\"OK\" = \"OK\";\n\"CANCEL\" = \"Cancel\";\n\"WELCOME\" = \"Welcome, %@!\";\n\"TOTAL_COST\" = \"Total: %@ %@\";\n\"ITEMS\" = \"%d %@\";\n```\n\n**Localizable.strings (Spanish)**\n```\n\"OK\" = \"Aceptar\";\n\"CANCEL\" = \"Cancelar\";\n\"WELCOME\" = \"¡Bienvenido, %@!\";\n\"TOTAL_COST\" = \"Total: %@ %@\";\n\"ITEMS\" = \"%d %@\";\n```\n\n## Best Practices\n\n### 1. Organize by Feature\n\nInstead of one large localization enum, consider organizing by feature:\n\n```swift\n@Localized\nenum AuthLocalization {\n    case login\n    case logout\n    case invalidCredentials\n}\n\n@Localized\nenum ProfileLocalization {\n    case editProfile\n    case saveChanges\n    case profileUpdated\n}\n```\n\n### 2. Use Descriptive Case Names\n\nMake your enum cases descriptive and self-documenting:\n\n```swift\n// Good\ncase welcomeMessage(userName: String)\ncase paymentFailed(reason: String)\n\n// Avoid\ncase wm(name: String)\ncase pf(reason: String)\n```\n\n### 3. Handle Special Characters\n\nThe macro automatically handles special characters and reserved words:\n\n```swift\n@Localized\nenum Localization {\n    case `class` // Becomes \"CLASS\"\n    case `struct` // Becomes \"STRUCT\"\n    case `enum` // Becomes \"ENUM\"\n    case hello_world // Becomes \"HELLO_WORLD\"\n}\n```\n\n## Error Handling\n\nThe macro provides compile-time validation for common issues:\n\n### Key Conflicts\n\n```swift\n@Localized(keyFormat: .pascalCase)\nenum Localization {\n    case duplicate // Error: Key conflict with 'Duplicate'\n    case Duplicate\n}\n```\n\n### Invalid Usage\n\n```swift\n@Localized // Error: Can only be attached to enums\nstruct Localization {\n    // ...\n}\n```\n\n## Requirements\n\n- Swift 5.9+\n- iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ / macCatalyst 13.0+\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyalkatz24%2Flocalized","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feyalkatz24%2Flocalized","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feyalkatz24%2Flocalized/lists"}