{"id":49764276,"url":"https://github.com/bodrovis/ex_lokalise_transfer","last_synced_at":"2026-05-11T10:16:39.158Z","repository":{"id":341439190,"uuid":"1169457252","full_name":"bodrovis/ex_lokalise_transfer","owner":"bodrovis","description":"ExLokaliseTransfer is a wrapper around Lokalise API download and upload endpoints for Elixir projects.","archived":false,"fork":false,"pushed_at":"2026-05-07T15:36:59.000Z","size":153,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-07T17:34:14.781Z","etag":null,"topics":["api","client","elixir","http","i18n","l10n","localization","lokalise","lokalise-api","translation","translation-files","wrapper"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bodrovis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-28T18:04:52.000Z","updated_at":"2026-05-07T15:49:35.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bodrovis/ex_lokalise_transfer","commit_stats":null,"previous_names":["bodrovis/ex_lokalise_transfer"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/bodrovis/ex_lokalise_transfer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodrovis%2Fex_lokalise_transfer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodrovis%2Fex_lokalise_transfer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodrovis%2Fex_lokalise_transfer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodrovis%2Fex_lokalise_transfer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bodrovis","download_url":"https://codeload.github.com/bodrovis/ex_lokalise_transfer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bodrovis%2Fex_lokalise_transfer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32890220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"online","status_checked_at":"2026-05-11T02:00:05.975Z","response_time":120,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["api","client","elixir","http","i18n","l10n","localization","lokalise","lokalise-api","translation","translation-files","wrapper"],"created_at":"2026-05-11T10:16:38.361Z","updated_at":"2026-05-11T10:16:39.153Z","avatar_url":"https://github.com/bodrovis.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ExLokaliseTransfer\n\n![CI](https://github.com/bodrovis/ex_lokalise_transfer/actions/workflows/ci.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/bodrovis/ex_lokalise_transfer/badge.svg?branch=master)](https://coveralls.io/github/lokalise/ex_lokalise_transfer?branch=master)\n[![Module Version](https://img.shields.io/hexpm/v/ex_lokalise_transfer.svg)](https://hex.pm/packages/ex_lokalise_transfer)\n[![Total Download](https://img.shields.io/hexpm/dt/ex_lokalise_transfer.svg)](https://hex.pm/packages/ex_lokalise_transfer)\n\n`ExLokaliseTransfer` is a wrapper around Lokalise API download and upload endpoints for Elixir projects.\n\nIt provides:\n\n- sync and async download of translation bundles\n- async upload of locale files\n- retry/backoff handling\n- polling for async processes\n- local extraction utilities\n\n\u003e Sample app can be found in the [bodrovis/ex_lokalise_transfer_demo](https://github.com/bodrovis/ex_lokalise_transfer_demo) repo.\n\n## Getting started\n\n### Requirements\n\n- Lokalise project\n- Lokalise API token with read/write access  \n  (read-only tokens work for downloads only)\n\n### Installation\n\n```elixir\ndef deps do\n  [\n    {:ex_lokalise_transfer, \"~\u003e 0.1.0\"}\n  ]\nend\n```\n\n## Required application config\n\nThe following config is required globally.\n\nConfigure the Lokalise API token:\n\n```elixir\nconfig :elixir_lokalise_api,\n  api_token: {:system, \"LOKALISE_API_TOKEN\"}\n```\n\nConfigure the Lokalise project id:\n\n```elixir\nconfig :ex_lokalise_transfer,\n  project_id: {:system, \"LOKALISE_PROJECT_ID\"}\n```\n\n## Downloading translation files\n\n### Sync download\n\nDownloads a bundle directly and extracts it locally.\n\n```elixir\n# You can also use ExLokaliseTransfer.download_sync()\nExLokaliseTransfer.download(\n  body: [\n    format: \"json\",\n    original_filenames: false\n  ],\n  extra: [\n    extract_to: \"./priv/locales\"\n  ]\n)\n```\n\nReturns: `:ok | {:error, reason}`.\n\n### Async download\n\nEnqueues a bundle build in Lokalise, waits for completion, then downloads and extracts it.\n\n```elixir\nExLokaliseTransfer.download_async(\n  body: [\n    format: \"json\"\n  ],\n  poll: [\n    max_attempts: 15,\n    min_sleep_ms: 3_000,\n    max_sleep_ms: 60_000,\n    jitter: :centered\n  ],\n  extra: [\n    extract_to: \"./priv/locales\"\n  ]\n)\n```\n\n## Uploading translations\n\n### Async upload\n\nUploads multiple locale files and processes them asynchronously.\n\n```elixir\n{:ok, summary} =\n  ExLokaliseTransfer.upload(\n    body: [\n      format: \"json\"\n    ],\n    extra: [\n      locales_path: \"./priv/locales\",\n      include_patterns: [\"*.json\"],\n      exclude_patterns: [],\n      lang_resolver: :basename\n    ],\n    poll: [\n      max_attempts: 10,\n      min_sleep_ms: 3_000,\n      max_sleep_ms: 60_000,\n      jitter: :centered\n    ]\n  )\n```\n\nReturns: `{:ok, summary} | {:error, summary}`\n\n#### Summary structure\n\n```elixir\n%{\n  discovered_entries: [Entry.t()],\n  enqueue_successes: [\n    %{entry: Entry.t(), process_id: String.t()}\n  ],\n  enqueue_errors: [\n    %{entry: Entry.t(), error: term()}\n  ],\n  process_results: [\n    %{\n      entry: Entry.t(),\n      process_id: String.t(),\n      result: {:ok, map()} | {:error, term()}\n    }\n  ],\n  errors: [term()]\n}\n```\n\n## Options\n\nAll flows share a common structure of options:\n\n```elixir\n[\n  body: [...],\n  retry: [...],\n  poll: [...],\n  extra: [...]\n]\n```\n\n### body — Lokalise API options\n\nPassed directly to Lokalise bundle/upload requests.\n\nExample:\n\n```elixir\nbody: [\n  format: \"json\",\n  original_filenames: true,\n  directory_prefix: \"\",\n  indentation: \"2sp\"\n]\n```\n\n- `format` (required for download)\n- any other fields supported by Lokalise API\n\n### retry — retry/backoff configuration\n\nUsed for API calls and downloads.\n\n```elixir\nretry: [\n  max_attempts: 3,\n  min_sleep_ms: 1_000,\n  max_sleep_ms: 60_000,\n  jitter: :centered\n]\n```\n\n- `max_attempts` — total attempts (including first)\n- `min_sleep_ms` — minimum delay\n- `max_sleep_ms` — maximum delay\n- `jitter` — `:centered` or `:full`\n\n### poll — async polling configuration\n\nUsed only in async flows.\n\n```elixir\npoll: [\n  max_attempts: 10,\n  min_sleep_ms: 3_000,\n  max_sleep_ms: 60_000,\n  jitter: :centered\n]\n```\n\nControls how long the system waits for Lokalise async processes.\n\n### extra — local behaviour options\n\n#### Download\n\n```elixir\nextra: [\n  extract_to: \"./priv/locales\"\n]\n```\n\n- `extract_to` — target directory for extracted files (automatically expanded to absolute path)\n\n## Testing\n\nRun:\n\n```\nmix test\n```\n\nTo see coverage:\n\n```\nmix coveralls.html\n```\n\n### Integration testing\n\nTo run integration tests:\n\n```\nmix test --include integration\n```\n\nNote that in this case you'll need to set `LOKALISE_API_TOKEN` and `LOKALISE_PROJECT_ID` environment variables.\n\n## License\n\nBSD-3-Clause (c) [Elijah S. Krukowski](https://bodrovis.tech)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbodrovis%2Fex_lokalise_transfer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbodrovis%2Fex_lokalise_transfer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbodrovis%2Fex_lokalise_transfer/lists"}