{"id":19442618,"url":"https://github.com/ackeecz/acklocalization","last_synced_at":"2025-04-25T00:31:57.495Z","repository":{"id":40245015,"uuid":"114271112","full_name":"AckeeCZ/ACKLocalization","owner":"AckeeCZ","description":"Localize your Cocoa apps from Google Spreadsheet","archived":false,"fork":false,"pushed_at":"2024-11-17T00:54:30.000Z","size":272,"stargazers_count":27,"open_issues_count":2,"forks_count":3,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-03T13:21:23.638Z","etag":null,"topics":["cocoa","ios","localization","macos"],"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/AckeeCZ.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2017-12-14T16:10:43.000Z","updated_at":"2024-11-18T08:13:07.000Z","dependencies_parsed_at":"2024-11-10T15:45:06.624Z","dependency_job_id":"defb75f1-fe7f-4825-bc07-b2ac86442922","html_url":"https://github.com/AckeeCZ/ACKLocalization","commit_stats":{"total_commits":185,"total_committers":9,"mean_commits":"20.555555555555557","dds":0.3027027027027027,"last_synced_commit":"a73d0cb741eb1c019630c9440749ca5852a8cbd1"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AckeeCZ%2FACKLocalization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AckeeCZ%2FACKLocalization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AckeeCZ%2FACKLocalization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AckeeCZ%2FACKLocalization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AckeeCZ","download_url":"https://codeload.github.com/AckeeCZ/ACKLocalization/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250733209,"owners_count":21478313,"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":["cocoa","ios","localization","macos"],"created_at":"2024-11-10T15:40:16.287Z","updated_at":"2025-04-25T00:31:57.472Z","avatar_url":"https://github.com/AckeeCZ.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Tests](https://github.com/AckeeCZ/ACKLocalization/workflows/Tests/badge.svg)\n\n# ACKLocalization\n\nSimply localize your app with translations stored in Google Spreadsheet.\n\n## Installation\n\nPreferred installation method is using [Mint](https://github.com/yonaskolb/Mint), just add it to your Mintfile\n\n```\nAckeeCZ/ACKLocalization\n```\n\n## Usage\n\nYou can use ACKLocalization in three ways:\n1. [application default credentials](#application-default-credentials)\n2. safer and recommended [use with Service Account](#use-with-service-account)\n3. [use with API key](#use-with-api-key)\n\n### Application default credentials (ADC)\n\nFor authorization to Google Spreadsheet we recommend using [Application default credentials](https://cloud.google.com/docs/authentication/application-default-credentials). This way you can safely authorize locally using your personal Google account and use a service account in CI environment.\n\nTo setup application default credentials you need to install gcloud CLI utility and run\n\n```\ngcloud auth application-default login --billing-project \u003cproject_id\u003e --scopes https://www.googleapis.com/auth/spreadsheets.readonly,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/sqlservice.login,https://www.googleapis.com/auth/userinfo.email,openid\n```\n\nYou need to add additional scope `https://www.googleapis.com/auth/spreadsheets.readonly` that will allow your ADC to read spreadsheet API on your behalf.\n\nAs Spreadsheet API is [Client-based](https://cloud.google.com/docs/quotas/quota-project#project-client-based) you need to provide a quota project. Spreadsheet API is free so you do not need to worry about that. The project just needs to have Spreadsheet API enabled.\n\n### Use with Service Account\n\nThis method is safe in the way that you can fully control who has access to your spreadsheet. You create a service account, invite it as viewer to your spreadsheet and you're ready to go.\n\n#### Create a Service Account\n\nYou need to have a Google project in [Google Dev console](https://console.developers.google.com), there you go to Credentials ➡️ create credentials ➡️ service account key. Then you need to enable Google Sheets API in the console.\n\n#### Invite Service Account to your spreadsheet\n\nThe Service Account has associated email address, you need to invited that address to your spreadsheet, so it is available to read the document.\n\nNow you can skip to [getting your spreadsheet identifier](#get-your-google-spreadsheet-identifier)\n\n### Use with API key\n\nYou need to have a Google project in [Google Dev console](https://console.developers.google.com), there you go to Credentials ➡️ create credentials ➡️ API Key. This will create unrestricted API key, we recommend to restrict it as much as possible - application restrictions are unluckily not possible to use - maybe if you intend to run the script on CI, then you can restrict it to certain IPs. What you can do is to restrict the API key to Google Sheets API (you might need to enable this API first in the console).\n\n### Get your Google Spreadsheet identifier\n\nYou get the spreadsheet identifier from its URL:\n```\nhttps://docs.google.com/spreadsheets/d/\u003cYOUR_SPREADSHEET_ID\u003e/edit#gid=0\n```\n\n### Now you can build your configuration file\n\nThe file is named `localization.json`. This is how example file looks like, you can find the Swift representation [here](Sources/ACKLocalizationCore/Model/Configuration.swift):\n\n```json\n{\n    \"defaultFileName\": \"Localizable\",\n    \"destinations\": {\n        \"Localizable\": \"Framework/Resources\",\n        \"InfoPlist\": \"App/Resources\"\n    },\n    \"keyColumnName\": \"iOS\",\n    \"languageMapping\": {\n        \"CZ\": \"cs\"\n    },\n    \"serviceAccount\": \"Resources/ServiceAccount.json\",\n    \"spreadsheetID\": \"\u003cGOOGLE_SPREADSHEET_ID\u003e\",\n}\n```\n\nAttributes documentation:\n\n| Name | Required | Note |\n| ---- | -------- | ---- |\n| `defaultFileName` | ✅ | Name of default strings(dict) file |\n| `destinations` | ✅ | Dictionary of destinations for all generated files (at least entry with  `defaultFileName` is required), if you use `plist.\u003cfilename\u003e.` prefix in your sheet, you might wanna add those entries as well, otherwise they will be generated alongside the default file |\n| `keyColumnName` | ✅ | Name of column that contains keys to be localized |\n| `languageMapping` | ✅ | Mapping of language column names to app languages, you specify how columns in spreasheet should be mapped to app languages |\n| `apiKey` | ❌ | API key that will be used to communicate with Google Sheets API, `apiKey` or `serviceAccount` has to be provided |\n| `serviceAccount` | ❌ | Path to service account file that will be used to access spreadsheet, `apiKey` or `serviceAccount` has to be provided |\n| `spreadsheetID` | ✅ | Identifier of spreadsheet that should be downloaded |\n| `spreadsheetTabName` | ❌ | Name of spreadsheet tab to be fetched, if nothing is specified, we will use the first tab in spreadsheet |\n\nThe file has to be in the same directory where you call ACKLocalization.\n\nTo be able to communicate with Google Sheets API, you need to provide either `apiKey` or `serviceAccount` parameter or [use environment variable](#environment-variables). If both are provided, then `serviceAccount` will be used.\n\n### Environment variables\n\nDo you want to share secrets across multiple projects, or do you not want to keep secrets in the project repository? We have the solution for you. Just set one of the environment variables below.\n\n`ACKLOCALIZATION_SERVICE_ACCOUNT_PATH` - Path to service account file that will be used to access spreadsheet\n`ACKLOCALIZATION_API_KEY` - API key that will be used to communicate with Google Sheets API\n\n`apiKey` or `serviceAccount` defined in `localization.json` have higher priority than environment values.\nIf both are provided then `ACKLOCALIZATION_SERVICE_ACCOUNT_PATH` will be used. \n\n### Calling ACKLocalization\n\nJust call the binary, remember that the configuration file has to be in the same directory where you call ACKLocalization.\n\n### Example\n\nWe love to call **ACKLocalization** from Xcode (we have a separate aggregate target which calls the script) so I'll stick with that with this example.\n\n#### Project structure\n\nThis is example folder structure of the project\n```\n|-localization.json\n|-Project.xcodeproj\n|-ServiceAccount.json\n|-App\n|---Resources\n|------en.lproj\n|----------InfoPlist.strings\n|------cs.lproj\n|----------InfoPlist.strings\n|-Framework\n|---Resources\n|------en.lproj\n|----------Localizable.strings\n|----------Localizable.stringsDict\n|------cs.lproj\n|----------Localizable.strings\n|----------Localizable.stringsDict\n```\n\n#### Spreadsheet structure\n\nThis is example structure of the spreadsheet with translations\n\n| key_ios | EN    | CS   |\n|---------|-------|------|\n| hello   | Hello | Ahoj |\n| plist.InfoPlist.NSCameraUsageDescription | Cammera usage description | Popis využití kamery |\n\n#### Example config file for this case would be\n\nThis is the example config file:\n```json\n{\n    \"defaultFileName\": \"Localizable\",\n    \"destinations\": {\n        \"Localizable\": \"Framework/Resources\",\n        \"InfoPlist\": \"App/Resources\"\n    },\n    \"keyColumnName\": \"key_ios\",\n    \"languageMapping\": {\n        \"CS\": \"cs\",\n        \"EN\": \"en\"\n    },\n    \"serviceAccount\": \"Resources/ServiceAccount.json\",\n    \"spreadsheetID\": \"\u003cGOOGLE_SPREADSHEET_ID\u003e\",\n    \"spreadsheetTabName\": \"Localizations\"\n}\n```\n\n### Plist keys\n\nACKLocalization supports localizing plist files. Simply prefix the key with `plist.InfoPlist`, where `InfoPlist` is the name of plist you need to localize and ACKLocalization will automatically generate respective `InfoPlist.strings` files. Please note that `InfoPlist` name is case-sensitive.\n\nExample keys:\n\n```\nplist.InfoPlist.NSPhotoLibraryAddUsageDescription\nplist.InfoPlist.NSUserTrackingUsageDescription\n```\n\n`InfoPlist.strings` result:\n\n```\n\"NSPhotoLibraryAddUsageDescription\" = \"Your photo library usage message.\";\n\"NSUserTrackingUsageDescription\" = \"Your tracking permission message.\";\n```\n\n### Plural keys\n\nTo add plurals to the spreadsheet, you need to specify the translation key and the plural type using the following [native convention](https://developer.apple.com/documentation/xcode/localizing-strings-that-contain-plurals):\n\n```\ntranslation.key##{zero}\ntranslation.key##{one}\ntranslation.key##{two}\ntranslation.key##{few}\ntranslation.key##{many}\ntranslation.key##{other}\n```\n\nThis will be automatically generated into `Localizable.stringsDict` and the key won't be presented in `Localizable.strings`.\n\nExample:\n\n![ackee|ACKLocalization](Resources/plurals-example.png)\n\n## Author\n\n[Ackee](https://ackee.cz) team\n\n## License\n\nACKLocalization is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fackeecz%2Facklocalization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fackeecz%2Facklocalization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fackeecz%2Facklocalization/lists"}