{"id":24268280,"url":"https://github.com/curiosum-dev/kanta","last_synced_at":"2025-05-15T20:05:47.807Z","repository":{"id":152737340,"uuid":"542493175","full_name":"curiosum-dev/kanta","owner":"curiosum-dev","description":"User-friendly translations manager for Elixir/Phoenix projects.","archived":false,"fork":false,"pushed_at":"2025-05-05T20:04:05.000Z","size":2546,"stargazers_count":192,"open_issues_count":8,"forks_count":17,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-05T21:23:43.707Z","etag":null,"topics":["elixir","elixir-lang","localization","phoenix-framework"],"latest_commit_sha":null,"homepage":"https://kanta.curiosum.com/kanta/dashboard","language":"Elixir","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/curiosum-dev.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}},"created_at":"2022-09-28T08:48:29.000Z","updated_at":"2025-04-26T09:08:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"ae7fb765-ba05-4aba-b628-f3399e0d5434","html_url":"https://github.com/curiosum-dev/kanta","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curiosum-dev%2Fkanta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curiosum-dev%2Fkanta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curiosum-dev%2Fkanta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/curiosum-dev%2Fkanta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/curiosum-dev","download_url":"https://codeload.github.com/curiosum-dev/kanta/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"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":["elixir","elixir-lang","localization","phoenix-framework"],"created_at":"2025-01-15T13:35:09.115Z","updated_at":"2025-05-15T20:05:42.649Z","avatar_url":"https://github.com/curiosum-dev.png","language":"Elixir","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/f0352656-397d-4d90-999a-d3adbae1095f\"\u003e\n\n  \u003ch1\u003eKanta\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eUser-friendly translations manager for Elixir/Phoenix projects\u003c/strong\u003e\u003c/p\u003e\n\n  [![Contact Us](https://img.shields.io/badge/Contact%20Us-%23F36D2E?style=for-the-badge\u0026logo=maildotru\u0026logoColor=white\u0026labelColor=F36D2E)](https://curiosum.com/contact)\n  [![Visit Curiosum](https://img.shields.io/badge/Visit%20Curiosum-%236819E6?style=for-the-badge\u0026logo=elixir\u0026logoColor=white\u0026labelColor=6819E6)](https://curiosum.com/services/elixir-software-development)\n  [![License: MIT](https://img.shields.io/badge/License-MIT-1D0642?style=for-the-badge\u0026logo=open-source-initiative\u0026logoColor=white\u0026labelColor=1D0642)](https://github.com/curiosum-dev/kanta/blob/main/LICENSE.md)\n\u003c/div\u003e\n\n\u003cbr /\u003e\n\n# About The Project\n\n\n\u003cdiv align=\"left\"\u003e\n  \u003ca href=\"https://github.com/curiosum-dev/kanta\"\u003e\n    \u003cimg src=\"./logo.png\" alt=\"Logo\" height=\"80\"\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  \u003cbr /\u003e\n  \u003cp style=\"margin-top: 3rem; font-size: 14pt;\" align=\"left\"\u003e\n    \u003ca href=\"https://kanta.curiosum.com\"\u003eView Demo\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/curiosum-dev/kanta/issues\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/curiosum-dev/kanta/issues\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nIf you're working on an Elixir/Phoenix project and need to manage translations, you know how time-consuming and error-prone it can be. That's where Kanta comes in. Our tool simplifies the process of managing translations by providing an intuitive interface for adding, editing, and deleting translations. Our tool also makes it easy to keep translations up-to-date as your project evolves. With Kanta, you can streamline your workflow and focus on building great software, not managing translations.\n\n\u003cdiv\u003e\n  \u003ca href=\"https://github.com/curiosum-dev/kanta/actions/workflows/development.yml\"\u003e\n    \u003cimg alt=\"CI Status\" src=\"https://github.com/curiosum-dev/kanta/actions/workflows/development.yml/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hex.pm/packages/kanta\"\u003e\n    \u003cimg alt=\"Hex Version\" src=\"https://img.shields.io/hexpm/v/kanta.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hexdocs.pm/kanta\"\u003e\n    \u003cimg alt=\"Hex Docs\" src=\"http://img.shields.io/badge/hex.pm-docs-green.svg?style=flat\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr/\u003e\n\n# Table of contents\n\n\u003cul style=\"margin-top: 3rem; margin-bottom: 3rem;\"\u003e\n  \u003cli\u003e\n    \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#prerequisites\"\u003ePrerequisites\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#database-migrations\"\u003eDatabase Migrations\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#gettext-module\"\u003eGettext Module\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#kanta-supervisor\"\u003eKanta Supervisor\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#kanta-ui\"\u003eKanta UI\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#extracting-from-po-files\"\u003eExtracting from PO files\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#storing-messages-in-the-database\"\u003eStoring messages in the database\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#translation-progress\"\u003eTranslation progress\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003ca href=\"#plugins\"\u003ePlugins\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli\u003e\u003ca href=\"#po-writer\"\u003ePO Writer\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#deepl\"\u003eDeepL\u003c/a\u003e\u003c/li\u003e\n      \u003cli\u003e\u003ca href=\"#kantasync\"\u003eTranslation synchronization\u003c/a\u003e\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#contact\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n  \u003cli\u003e\u003ca href=\"#acknowledgments\"\u003eAcknowledgments\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n---\n\n_Note: Official documentation for Kanta library is [available on hexdocs][hexdoc]._\n\n[hexdoc]: https://hexdocs.pm/kanta\n\n---\n\n\u003cbr /\u003e\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n# Getting Started\n\n## Prerequisites\n\n- Elixir (tested on 1.14.0)\n- Phoenix (tested on 1.7.0)\n- Ecto SQL (tested on 3.6)\n\n## Installation\n\nThe package can be installed\nby adding `kanta` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:kanta, \"~\u003e 0.4.1\"},\n    {:gettext, git: \"git@github.com:ravensiris/gettext.git\", branch: \"runtime-gettext\"}\n  ]\nend\n```\n\nThe dependency on this specific `gettext` version is because this library depends on an in-progress feature, to be included in a future release of `gettext` (see discussion in elixir-gettext/gettext#280 and pull request elixir-gettext/gettext#305). As of March 2023, this has been approved by an Elixir core team member, so we are eagerly awaiting for it being merged upstream.\n\n## Configuration\n\nAdd to `config/config.exs` file:\n\n```elixir\n# config/config.exs\nconfig :my_app, Kanta,\n  endpoint: MyAppWeb.Endpoint, # Your app Endpoint module\n  repo: MyApp.Repo, # Your app Repo module\n  otp_name: :my_app, # Name of your OTP app\n  plugins: []\n```\n\nEcto repo module is used mostly for translations persistency. We also need endpoint to use VerifiedRoutes and project_root to locate the project's .po files.\n\n## Database migrations\n\nMigrations is heavily inspired by the Oban approach. To add to the project tables necessary for the operation of Kanta and responsible for storing translations create migration with:\n\n```bash\nmix ecto.gen.migration add_kanta_translations_table\n```\n\nOpen the generated migration file and set up `up` and `down` functions:\n\n```elixir\ndefmodule MyApp.Repo.Migrations.AddKantaTranslationsTable do\n  use Ecto.Migration\n\n  def up do\n    Kanta.Migration.up(version: 2, prefix: prefix()) # Prefix is needed if you are using multitenancy with i.e. triplex\n  end\n\n  def down do\n    Kanta.Migration.down(version: 2, prefix: prefix()) # Prefix is needed if you are using multitenancy with i.e. triplex\n  end\nend\n```\n\nafter that run\n\n```bash\nmix ecto.migrate\n```\n\n## Gettext module\n\nWe now need to pass information to our project's `Gettext` module that we want Kanta to manage translations. To do this add `Kanta.Gettext.Repo` as a default translation repository inside your `Gettext` module.\n\n```elixir\nuse Gettext, ..., repo: Kanta.Gettext.Repo\n```\n\n## Kanta Supervisor\n\nIn the `application.ex` file of our project, we add Kanta and its configuration to the list of processes.\n\n```elixir\n  def start(_type, _args) do\n    children = [\n      ...\n      {Kanta, Application.fetch_env!(:my_app, Kanta)}\n      ...\n    ]\n    ...\n  end\n```\n\n## Kanta UI\n\nInside your `router.ex` file we need to connect the Kanta panel using the kanta_dashboard macro. \n\n```elixir \nimport KantaWeb.Router\n\nscope \"/\" do\n  pipe_through :browser\n\n  kanta_dashboard(\"/kanta\")\nend\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n# Features\n\n## Extracting from PO files\n\n\u003cimg style=\"margin-top: 1rem; margin-bottom: 1rem;\" src=\"./messages.png\" alt=\"messages\"\u003e\n\nKanta is based on the Phoenix Framework's default localization tool, GNU gettext. The process, which runs at application startup, analyzes .po files with messages and converts them to a format for convenient use with Ecto and Kanta itself.\n\n## Storing messages in the database\n\n\u003cimg style=\"margin-top: 1rem; margin-bottom: 1rem;\" src=\"./singular.png\" alt=\"singular\"\u003e\n\nMessages and translations from .po files are stored in tables created by the Kanta.Migration module. This allows easy viewing and modification of messages from the Kanta UI or directly from database tools. The caching mechanism prevents constant requests to the database when downloading translations, so you don't have to worry about a delay in application performance.\n\n## Translation progress\n\n\u003cimg style=\"margin-top: 1rem; margin-bottom: 1rem;\" src=\"./dashboard.png\" alt=\"dashboard\"\u003e\n\nKanta tracks the progress of your application's translation into other languages and reports it in the user's dashboard. In the dashboard you can filter your messages by domain or context, or use a search engine. It is also possible to display only the messages that need translation to better see how much work remains to be done.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n# Plugins\n\n## DeepL\n\nNot all of us are polyglots, and sometimes we need the help of machine translation tools. For this reason, we have provided plug-ins for communication with external services that will allow you to translate texts into another language without knowing it. As a first step, we introduced integration with DeepL API offering 500,000 characters/month for free and more in paid plans. To use DeepL API add `{:kanta_deep_l_plugin, \"~\u003e 0.1.1\"}` to your `deps` and append `Kanta.DeepL.Plugin` to the list of plugins along with the API key from your account at DeepL. New features will then be added to the Kanta UI that will allow you to translate using this tool.\n\n\u003cimg style=\"margin-top: 1rem; margin-bottom: 1rem;\" src=\"./plural.png\" alt=\"plural\"\u003e\n\n```elixir\n# mix.exs\ndefp deps do \n  ...\n  {:kanta_deep_l_plugin, \"~\u003e 0.1.1\"}\nend\n```\n\n```elixir\n# config/config.exs\nconfig :kanta,\n  ...\n  plugins: [\n    {Kanta.DeepL.Plugin, api_key: \"YOUR_DEEPL_API_KEY\"}\n  ]\n```\n\n## KantaSync \n\nThe [KantaSync plugin](https://github.com/curiosum-dev/kanta_sync_plugin) allows you to synchronize translations between your production and staging/dev environments. It ensures that any changes made to translations in one are reflected in the others, helping you maintain consistency across different stages of development.\n\n```elixir \n# mix.exs \ndefp deps do \n  ...\n  {:kanta_sync_plugin, \"~\u003e 0.1.0\"}\nend\n```\n\nYou need to have Kanta API configured by using kanta_api macro. \n\n```elixir\n# router.ex \nimport KantaWeb.Router\n\nscope \"/\" do \n  kanta_api(\"/kanta-api\")\nend \n```\n\n### Authorization\n\nSet `KANTA_SECRET_TOKEN` environment variable for restricting API access. It should be generated with `mix phx.gen.secret 256` and both environments must have the same `KANTA_SECRET_TOKEN` environment variables.\n\nYou can also disable default authorization mechanism and use your own, by passing `disable_api_authorization: true` option into Kanta's config.\n\n## PO Writer\n\nKanta was created to allow easy management of static text translations in the application, however, for various reasons like wanting a backup or parallel use of other tools like TMS etc. you may want to overwrite .po files with translations entered in Kanta. To install it append `{:kanta_po_writer_plugin, git: \"https://github.com/curiosum-dev/kanta_po_writer_plugin\"}` to your `deps` list. Currently, it's not on Hex because it's in a pre-release version. Then add `Kanta.Plugins.POWriter` to the list of plugins, and new functions will appear in the Kanta UI to allow writing to .po files.\n\n```elixir\n# mix.exs\ndefp deps\n  ...\n  {:kanta_po_writer_plugin, git: \"https://github.com/curiosum-dev/kanta_po_writer_plugin\"},\nend\n```\n\n```elixir\n# config/config.exs\nconfig :kanta,\n  ...\n  plugins: [\n    Kanta.POWriter.Plugin\n  ]\n```\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n## Roadmap\n\n- [ ] Typespecs, tests, better docs\n- [ ] CI/CD\n- [ ] Gettext extract/merge automation\n- [ ] Google Translate, Yandex Translate, LibreTranslate Plugins\n- [ ] File import/export\n- [ ] Bumblebee AI translations\n- [ ] REST API\n\nSee the [open issues](https://github.com/curiosum-dev/kanta/issues) for a full list of proposed features (and known issues).\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\u003c!-- CONTRIBUTING --\u003e\n\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. We prefer gitflow and Conventional commits style but we don't require that. You can also simply open an issue with the tag \"enhancement\".\nDon't forget to give the project a star! Thanks again!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'feat: Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\u003c!-- LICENSE --\u003e\n\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\u003c!-- CONTACT --\u003e\n\n## Contact\n\n[Curiosum](https://curiosum.com)\n\nMichał Buszkiewicz - michal@curiosum.com\n\nKrzysztof Janiec - krzysztof.janiec@curiosum.com\n\nArtur Ziętkiewicz - artur.zietkiewicz@curiosum.com\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuriosum-dev%2Fkanta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcuriosum-dev%2Fkanta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuriosum-dev%2Fkanta/lists"}