codex-bot 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. {codex_bot-0.2.1 → codex_bot-0.3.0}/.gitignore +3 -2
  2. {codex_bot-0.2.1 → codex_bot-0.3.0}/CHANGELOG.md +11 -0
  3. {codex_bot-0.2.1 → codex_bot-0.3.0}/PKG-INFO +6 -6
  4. {codex_bot-0.2.1 → codex_bot-0.3.0}/pyproject.toml +3 -3
  5. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/i18n.py +1 -1
  6. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/pyproject.toml.j2 +2 -2
  7. codex_bot-0.3.0/tests/engine/middlewares/test_i18n.py +91 -0
  8. {codex_bot-0.2.1 → codex_bot-0.3.0}/uv.lock +56 -14
  9. {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/ci.yml +0 -0
  10. {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/docs.yml +0 -0
  11. {codex_bot-0.2.1 → codex_bot-0.3.0}/.github/workflows/publish.yml +0 -0
  12. {codex_bot-0.2.1 → codex_bot-0.3.0}/.pre-commit-config.yaml +0 -0
  13. {codex_bot-0.2.1 → codex_bot-0.3.0}/.python-version +0 -0
  14. {codex_bot-0.2.1 → codex_bot-0.3.0}/.secrets.baseline +0 -0
  15. {codex_bot-0.2.1 → codex_bot-0.3.0}/LICENSE +0 -0
  16. {codex_bot-0.2.1 → codex_bot-0.3.0}/NOTICE +0 -0
  17. {codex_bot-0.2.1 → codex_bot-0.3.0}/README.md +0 -0
  18. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/DOCUMENTATION_STANDARD.md +0 -0
  19. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/README.md +0 -0
  20. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/README.md +0 -0
  21. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/animation.md +0 -0
  22. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/base.md +0 -0
  23. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/director.md +0 -0
  24. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/discovery.md +0 -0
  25. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/factory.md +0 -0
  26. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/fsm.md +0 -0
  27. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/helper.md +0 -0
  28. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/http.md +0 -0
  29. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/i18n.md +0 -0
  30. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/middlewares.md +0 -0
  31. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/redis.md +0 -0
  32. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/router_builder.md +0 -0
  33. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/sender.md +0 -0
  34. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/api/url_signer.md +0 -0
  35. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/changelog.md +0 -0
  36. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/README.md +0 -0
  37. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/README.md +0 -0
  38. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/cli/README.md +0 -0
  39. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/README.md +0 -0
  40. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/container.md +0 -0
  41. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/discovery.md +0 -0
  42. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/factory.md +0 -0
  43. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/http_db.md +0 -0
  44. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/i18n.md +0 -0
  45. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/engine/middlewares.md +0 -0
  46. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/animation/README.md +0 -0
  47. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/base/README.md +0 -0
  48. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/director/README.md +0 -0
  49. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/fsm/README.md +0 -0
  50. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/helper/README.md +0 -0
  51. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/helper/url_signer.md +0 -0
  52. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/redis/README.md +0 -0
  53. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/architecture/services/view_sender/README.md +0 -0
  54. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/guide/getting_started.md +0 -0
  55. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/roadmap.md +0 -0
  56. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/001_high_integrated_debug_system.md +0 -0
  57. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/002_med_docker_infrastructure.md +0 -0
  58. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/003_high_in_bot_guide_system.md +0 -0
  59. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/004_high_redis_fsm_integration.md +0 -0
  60. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/005_med_header_driven_navigation.md +0 -0
  61. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/006_med_redis_stream_contract.md +0 -0
  62. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
  63. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/008_high_multi_broker_support.md +0 -0
  64. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/009_high_webhook_server.md +0 -0
  65. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/ARCHIVE.md +0 -0
  66. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/en_EN/tasks/backlog.md +0 -0
  67. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/README.md +0 -0
  68. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/README.md +0 -0
  69. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/cli/README.md +0 -0
  70. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/README.md +0 -0
  71. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/container.md +0 -0
  72. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/discovery.md +0 -0
  73. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/factory.md +0 -0
  74. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/http_db.md +0 -0
  75. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/i18n.md +0 -0
  76. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/engine/middlewares.md +0 -0
  77. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/README.md +0 -0
  78. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/animation/README.md +0 -0
  79. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/base/README.md +0 -0
  80. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/director/README.md +0 -0
  81. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/fsm/README.md +0 -0
  82. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/helper/README.md +0 -0
  83. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/helper/url_signer.md +0 -0
  84. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/redis/README.md +0 -0
  85. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/architecture/services/view_sender/README.md +0 -0
  86. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/guide/getting_started.md +0 -0
  87. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/roadmap.md +0 -0
  88. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/001_high_integrated_debug_system.md +0 -0
  89. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/002_med_docker_infrastructure.md +0 -0
  90. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/003_high_in_bot_guide_system.md +0 -0
  91. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/004_high_redis_fsm_integration.md +0 -0
  92. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/005_med_header_driven_navigation.md +0 -0
  93. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/006_med_redis_stream_contract.md +0 -0
  94. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/007_med_sqlalchemy_sender_storage.md +0 -0
  95. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/008_high_multi_broker_support.md +0 -0
  96. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/009_high_webhook_server.md +0 -0
  97. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/ARCHIVE.md +0 -0
  98. {codex_bot-0.2.1 → codex_bot-0.3.0}/docs/ru_RU/tasks/backlog.md +0 -0
  99. {codex_bot-0.2.1 → codex_bot-0.3.0}/mkdocs.yml +0 -0
  100. {codex_bot-0.2.1 → codex_bot-0.3.0}/project_structure.txt +0 -0
  101. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/__init__.py +0 -0
  102. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/animation/__init__.py +0 -0
  103. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/animation/animation_service.py +0 -0
  104. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/__init__.py +0 -0
  105. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/base_orchestrator.py +0 -0
  106. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/context_dto.py +0 -0
  107. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/base/view_dto.py +0 -0
  108. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/__init__.py +0 -0
  109. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/create_feature.py +0 -0
  110. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/migrations.py +0 -0
  111. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/startproject.py +0 -0
  112. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/commands/utils.py +0 -0
  113. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/main.py +0 -0
  114. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/management.py +0 -0
  115. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/cli/templating.py +0 -0
  116. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/__init__.py +0 -0
  117. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/director.py +0 -0
  118. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/director/protocols.py +0 -0
  119. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/__init__.py +0 -0
  120. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/container.py +0 -0
  121. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/__init__.py +0 -0
  122. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/engine.py +0 -0
  123. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/models.py +0 -0
  124. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/database/repository.py +0 -0
  125. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/discovery/__init__.py +0 -0
  126. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/discovery/service.py +0 -0
  127. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/factory/__init__.py +0 -0
  128. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/factory/bot_builder.py +0 -0
  129. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/http/__init__.py +0 -0
  130. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/http/api_client.py +0 -0
  131. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/i18n/__init__.py +0 -0
  132. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/i18n/locales_compiler.py +0 -0
  133. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/__init__.py +0 -0
  134. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/container.py +0 -0
  135. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/database.py +0 -0
  136. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/director_middleware.py +0 -0
  137. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/throttling.py +0 -0
  138. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/middlewares/user_validation.py +0 -0
  139. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/protocols.py +0 -0
  140. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/router_builder/__init__.py +0 -0
  141. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/router_builder/router_builder.py +0 -0
  142. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/engine/runner.py +0 -0
  143. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/__init__.py +0 -0
  144. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/__init__.py +0 -0
  145. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/default_errors.py +0 -0
  146. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/handlers.py +0 -0
  147. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/orchestrator.py +0 -0
  148. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/features/errors/ui.py +0 -0
  149. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/__init__.py +0 -0
  150. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/common_fsm_handlers.py +0 -0
  151. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/garbage_collector.py +0 -0
  152. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/state_helper.py +0 -0
  153. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/fsm/state_manager.py +0 -0
  154. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/__init__.py +0 -0
  155. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/context_helper.py +0 -0
  156. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/helper/id_inspector.py +0 -0
  157. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/py.typed +0 -0
  158. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/__init__.py +0 -0
  159. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/dispatcher.py +0 -0
  160. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/router.py +0 -0
  161. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/redis/stream_processor.py +0 -0
  162. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/__init__.py +0 -0
  163. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/memory_storage.py +0 -0
  164. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/protocols.py +0 -0
  165. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/redis_storage.py +0 -0
  166. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/sender_keys.py +0 -0
  167. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/sender_manager.py +0 -0
  168. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/sender/view_sender.py +0 -0
  169. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/__init__.py +0 -0
  170. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/dispatcher.py +0 -0
  171. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/stream/router.py +0 -0
  172. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/__init__.py +0 -0
  173. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/feature_setting.py.j2 +0 -0
  174. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/handlers/__init__.py.j2 +0 -0
  175. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/handlers/handlers.py.j2 +0 -0
  176. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/logic/__init__.py +0 -0
  177. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/logic/orchestrator.py.j2 +0 -0
  178. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/__init__.py.j2 +0 -0
  179. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/callbacks.py.j2 +0 -0
  180. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/dto.py.j2 +0 -0
  181. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/keyboards.py.j2 +0 -0
  182. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/redis/resources/texts.py.j2 +0 -0
  183. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/__init__.py +0 -0
  184. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/contracts/contract.py.j2 +0 -0
  185. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/feature_setting.py.j2 +0 -0
  186. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/handlers/__init__.py.j2 +0 -0
  187. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/handlers/handlers.py.j2 +0 -0
  188. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/logic/orchestrator.py.j2 +0 -0
  189. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/logic/state_manager.py.j2 +0 -0
  190. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/callbacks.py.j2 +0 -0
  191. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/dto.py.j2 +0 -0
  192. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/formatters.py.j2 +0 -0
  193. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/keyboards.py.j2 +0 -0
  194. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/resources/texts.py.j2 +0 -0
  195. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/feature/telegram/ui/ui.py.j2 +0 -0
  196. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.env.example.j2 +0 -0
  197. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.env.j2 +0 -0
  198. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.gitignore.j2 +0 -0
  199. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/.python-version.j2 +0 -0
  200. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/README.md.j2 +0 -0
  201. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/docs/architecture_cheat_sheet.md.j2 +0 -0
  202. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/docs/message_flow.md.j2 +0 -0
  203. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/root/manage.py.j2 +0 -0
  204. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/alembic.ini.j2 +0 -0
  205. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/config.py.j2 +0 -0
  206. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/container.py.j2 +0 -0
  207. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/errors.py.j2 +0 -0
  208. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/factory.py.j2 +0 -0
  209. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/logging.py.j2 +0 -0
  210. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/core/settings.py.j2 +0 -0
  211. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/__init__.py.j2 +0 -0
  212. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/__init__.py.j2 +0 -0
  213. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/contracts/menu_contract.py.j2 +0 -0
  214. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/feature_setting.py.j2 +0 -0
  215. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/__init__.py.j2 +0 -0
  216. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/handlers/handlers.py.j2 +0 -0
  217. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/__init__.py.j2 +0 -0
  218. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/logic/orchestrator.py.j2 +0 -0
  219. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/orchestrator.py.j2 +0 -0
  220. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/__init__.py.j2 +0 -0
  221. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/callbacks.py.j2 +0 -0
  222. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/dto.py.j2 +0 -0
  223. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/keyboards.py.j2 +0 -0
  224. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/resources/texts.py.j2 +0 -0
  225. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/__init__.py.j2 +0 -0
  226. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/menu_ui.py.j2 +0 -0
  227. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/bot_menu/ui/ui.py.j2 +0 -0
  228. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/__init__.py.j2 +0 -0
  229. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/__init__.py.j2 +0 -0
  230. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/auth_contract.py.j2 +0 -0
  231. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/contracts/contract.py.j2 +0 -0
  232. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/feature_setting.py.j2 +0 -0
  233. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/__init__.py.j2 +0 -0
  234. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/handlers/handlers.py.j2 +0 -0
  235. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/__init__.py.j2 +0 -0
  236. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/logic/orchestrator.py.j2 +0 -0
  237. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/__init__.py.j2 +0 -0
  238. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/callbacks.py.j2 +0 -0
  239. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/formatters.py.j2 +0 -0
  240. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/keyboards.py.j2 +0 -0
  241. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/resources/texts.py.j2 +0 -0
  242. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/__init__.py.j2 +0 -0
  243. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/features/telegram/commands/ui/commands_ui.py.j2 +0 -0
  244. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/__init__.py.j2 +0 -0
  245. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/env.py.j2 +0 -0
  246. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/database/migrations/script.py.mako.j2 +0 -0
  247. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/migrations/env.py.j2 +0 -0
  248. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/models/base.py.j2 +0 -0
  249. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/redis/container.py.j2 +0 -0
  250. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/infrastructure/repositories/base.py.j2 +0 -0
  251. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/launcher.py.j2 +0 -0
  252. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/resources/locales/en/messages.ftl.j2 +0 -0
  253. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/resources/locales/ru/messages.ftl.j2 +0 -0
  254. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/templates/project/src/shared/schemas/user.py.j2 +0 -0
  255. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/url_signer/__init__.py +0 -0
  256. {codex_bot-0.2.1 → codex_bot-0.3.0}/src/codex_bot/url_signer/service.py +0 -0
  257. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/animation/test_animation_service.py +0 -0
  258. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/base/test_base_orchestrator.py +0 -0
  259. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/base/test_view_dto.py +0 -0
  260. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/conftest.py +0 -0
  261. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/director/test_director.py +0 -0
  262. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/factory/test_bot_builder.py +0 -0
  263. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/http/test_api_client.py +0 -0
  264. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/engine/middlewares/test_throttling.py +0 -0
  265. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/fsm/test_garbage_collector.py +0 -0
  266. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/fsm/test_state_manager.py +0 -0
  267. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/helper/test_context_helper.py +0 -0
  268. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/integration/test_templates_e2e.py +0 -0
  269. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/__init__.py +0 -0
  270. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/test_dispatcher.py +0 -0
  271. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/redis/test_router.py +0 -0
  272. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/sender/test_sender_keys.py +0 -0
  273. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/test_template_consistency.py +0 -0
  274. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/test_templates.py +0 -0
  275. {codex_bot-0.2.1 → codex_bot-0.3.0}/tests/url_signer/test_url_signer.py +0 -0
  276. {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/__init__.py +0 -0
  277. {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/__init__.py +0 -0
  278. {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/check.py +0 -0
  279. {codex_bot-0.2.1 → codex_bot-0.3.0}/tools/dev/generate_project_tree.py +0 -0
@@ -69,5 +69,6 @@ dmypy.json
69
69
  .claude/
70
70
  # Sandbox for template E2E testing
71
71
  sandbox/
72
- # Temporary files from LocalesCompiler (if they leak into root)
73
- bot_locales_*
72
+ # Agent instructions (local-only, points to local knowledge graph)
73
+ AGENTS.md
74
+ CLAUDE.md
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.3.0] - 2026-04-23
9
+
10
+ ### Changed
11
+
12
+ - **Aiogram Stack**: Raised the core `aiogram` dependency contract to `>=3.27.0,<4.0` and the optional i18n extra to `aiogram-i18n[runtime]>=1.5,<2.0`.
13
+ - **Project Templates**: Updated generated project dependencies to use the same modern aiogram and aiogram-i18n ranges.
14
+
15
+ ### Fixed
16
+
17
+ - **I18n Manager Initialization**: Updated `FSMContextI18nManager` to initialize `aiogram-i18n`'s `BaseManager`, restoring `locale_getter` and `locale_setter` for `I18nMiddleware`.
18
+
8
19
  ## [0.2.1] - 2026-04-18
9
20
 
10
21
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-bot
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Feature-based Aiogram framework library — reusable infrastructure for Telegram bots
5
5
  Project-URL: Homepage, https://github.com/codexdlc/codex-bot
6
6
  Project-URL: Documentation, https://codexdlc.github.io/codex-bot/
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Topic :: Communications :: Chat
22
22
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
23
23
  Requires-Python: >=3.12
24
- Requires-Dist: aiogram<4.0,>=3.13.0
24
+ Requires-Dist: aiogram<4.0,>=3.27.0
25
25
  Requires-Dist: aiohttp>=3.13.4
26
26
  Requires-Dist: jinja2>=3.1.0
27
27
  Requires-Dist: pydantic-settings>=2.0
@@ -29,7 +29,7 @@ Requires-Dist: pydantic<3.0,>=2.0
29
29
  Requires-Dist: python-dotenv>=1.0.0
30
30
  Requires-Dist: questionary>=2.0.0
31
31
  Provides-Extra: all
32
- Requires-Dist: aiogram-i18n>=1.4; extra == 'all'
32
+ Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'all'
33
33
  Requires-Dist: aiosqlite>=0.19.0; extra == 'all'
34
34
  Requires-Dist: alembic>=1.13.0; extra == 'all'
35
35
  Requires-Dist: arq>=0.25; extra == 'all'
@@ -49,7 +49,7 @@ Requires-Dist: alembic>=1.13.0; extra == 'db'
49
49
  Requires-Dist: asyncpg>=0.29.0; extra == 'db'
50
50
  Requires-Dist: sqlalchemy>=2.0; extra == 'db'
51
51
  Provides-Extra: dev
52
- Requires-Dist: aiogram-i18n>=1.4; extra == 'dev'
52
+ Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'dev'
53
53
  Requires-Dist: aiosqlite>=0.19.0; extra == 'dev'
54
54
  Requires-Dist: alembic>=1.13.0; extra == 'dev'
55
55
  Requires-Dist: arq>=0.25; extra == 'dev'
@@ -62,7 +62,7 @@ Requires-Dist: loguru>=0.7.0; extra == 'dev'
62
62
  Requires-Dist: mypy>=1.10; extra == 'dev'
63
63
  Requires-Dist: pip-audit>=2.7; extra == 'dev'
64
64
  Requires-Dist: pre-commit>=3.0; extra == 'dev'
65
- Requires-Dist: pygments>=2.20.0; extra == 'dev'
65
+ Requires-Dist: pygments==2.19.1; extra == 'dev'
66
66
  Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
67
67
  Requires-Dist: pytest-cov; extra == 'dev'
68
68
  Requires-Dist: pytest>=9.0.3; extra == 'dev'
@@ -78,7 +78,7 @@ Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
78
78
  Provides-Extra: http
79
79
  Requires-Dist: httpx<1.0,>=0.27; extra == 'http'
80
80
  Provides-Extra: i18n
81
- Requires-Dist: aiogram-i18n>=1.4; extra == 'i18n'
81
+ Requires-Dist: aiogram-i18n[runtime]<2.0,>=1.5; extra == 'i18n'
82
82
  Provides-Extra: postgres
83
83
  Requires-Dist: asyncpg>=0.29.0; extra == 'postgres'
84
84
  Provides-Extra: redis
@@ -22,7 +22,7 @@ classifiers = [
22
22
  "Topic :: Software Development :: Libraries :: Application Frameworks",
23
23
  ]
24
24
  dependencies = [
25
- "aiogram>=3.13.0,<4.0",
25
+ "aiogram>=3.27.0,<4.0",
26
26
  "aiohttp>=3.13.4",
27
27
  "pydantic>=2.0,<3.0",
28
28
  "pydantic-settings>=2.0",
@@ -47,7 +47,7 @@ redis = [
47
47
  "codex-platform",
48
48
  ]
49
49
  arq = ["arq>=0.25"]
50
- i18n = ["aiogram-i18n>=1.4"]
50
+ i18n = ["aiogram-i18n[runtime]>=1.5,<2.0"]
51
51
  http = ["httpx>=0.27,<1.0"]
52
52
  sqlite = ["aiosqlite>=0.19.0"]
53
53
  postgres = ["asyncpg>=0.29.0"]
@@ -58,7 +58,7 @@ all = [
58
58
  dev = [
59
59
  "codex-bot[all]",
60
60
  "pytest>=9.0.3",
61
- "pygments>=2.20.0",
61
+ "pygments==2.19.1",
62
62
  "pytest-asyncio>=0.23",
63
63
  "pytest-cov",
64
64
  "ruff>=0.4",
@@ -51,8 +51,8 @@ class FSMContextI18nManager(BaseManager):
51
51
  allowed_locales: list[str] | None = None,
52
52
  default_locale: str = "en",
53
53
  ) -> None:
54
+ super().__init__(default_locale=default_locale)
54
55
  self.allowed_locales: list[str] = allowed_locales or []
55
- self.default_locale: str = default_locale
56
56
 
57
57
  async def get_locale(self, event_from_user: User | None = None, **kwargs: Any) -> str:
58
58
  """
@@ -9,14 +9,14 @@ description = "Telegram Bot generated via codex-bot"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
11
11
  dependencies = [
12
- "aiogram>=3.4",
12
+ "aiogram>=3.27.0,<4.0",
13
13
  "pydantic-settings>=2.0",
14
14
  "codex-bot",
15
15
  {% if use_loguru %}
16
16
  "loguru>=0.7.0",
17
17
  {% endif %}
18
18
  {% if use_i18n %}
19
- "aiogram-i18n>=1.4",
19
+ "aiogram-i18n[runtime]>=1.5,<2.0",
20
20
  {% endif %}
21
21
  {% if use_redis %}
22
22
  "redis[asyncio]>=5.0",
@@ -0,0 +1,91 @@
1
+ from pathlib import Path
2
+ from unittest.mock import AsyncMock
3
+
4
+ import pytest
5
+ from aiogram.types import TelegramObject, User
6
+
7
+ from codex_bot.engine.middlewares.i18n import FSMContextI18nManager
8
+
9
+
10
+ @pytest.fixture
11
+ def state():
12
+ fsm_state = AsyncMock()
13
+ fsm_state.get_data = AsyncMock(return_value={})
14
+ fsm_state.set_data = AsyncMock()
15
+ return fsm_state
16
+
17
+
18
+ def test_manager_initialization():
19
+ manager = FSMContextI18nManager(default_locale="de")
20
+
21
+ assert hasattr(manager, "locale_getter") is True
22
+ assert hasattr(manager, "locale_setter") is True
23
+ assert manager.default_locale == "de"
24
+
25
+
26
+ async def test_get_locale_prefers_fsm_locale(state):
27
+ state.get_data.return_value = {"locale": "ru"}
28
+ manager = FSMContextI18nManager(allowed_locales=["de"], default_locale="de")
29
+
30
+ locale = await manager.get_locale(state=state)
31
+
32
+ assert locale == "ru"
33
+
34
+
35
+ async def test_get_locale_uses_allowed_telegram_language(state):
36
+ user = User(id=1, is_bot=False, first_name="Test", language_code="ru")
37
+ manager = FSMContextI18nManager(allowed_locales=["ru", "de"], default_locale="de")
38
+
39
+ locale = await manager.get_locale(event_from_user=user, state=state)
40
+
41
+ assert locale == "ru"
42
+
43
+
44
+ async def test_get_locale_falls_back_for_disallowed_language(state):
45
+ user = User(id=1, is_bot=False, first_name="Test", language_code="en")
46
+ manager = FSMContextI18nManager(allowed_locales=["ru", "de"], default_locale="de")
47
+
48
+ locale = await manager.get_locale(event_from_user=user, state=state)
49
+
50
+ assert locale == "de"
51
+
52
+
53
+ async def test_get_locale_uses_default_without_state_or_user():
54
+ manager = FSMContextI18nManager(default_locale="de")
55
+
56
+ locale = await manager.get_locale()
57
+
58
+ assert locale == "de"
59
+
60
+
61
+ async def test_set_locale_writes_to_fsm_storage(state):
62
+ state.get_data.return_value = {}
63
+ manager = FSMContextI18nManager(default_locale="de")
64
+
65
+ await manager.set_locale("ru", state=state)
66
+
67
+ state.set_data.assert_called_once_with({"locale": "ru"})
68
+
69
+
70
+ async def test_aiogram_i18n_middleware_uses_manager_locale_getter(tmp_path: Path, state):
71
+ from aiogram_i18n import I18nMiddleware
72
+ from aiogram_i18n.cores import FluentRuntimeCore
73
+
74
+ locale_dir = tmp_path / "de"
75
+ locale_dir.mkdir()
76
+ (locale_dir / "messages.ftl").write_text("hello = Hallo\n", encoding="utf-8")
77
+
78
+ manager = FSMContextI18nManager(default_locale="de")
79
+ middleware = I18nMiddleware(
80
+ core=FluentRuntimeCore(path=tmp_path / "{locale}"),
81
+ manager=manager,
82
+ default_locale="de",
83
+ )
84
+
85
+ event = TelegramObject()
86
+ handler = AsyncMock(return_value="ok")
87
+
88
+ result = await middleware(handler, event, {"state": state})
89
+
90
+ assert result == "ok"
91
+ handler.assert_awaited_once()
@@ -13,7 +13,7 @@ wheels = [
13
13
 
14
14
  [[package]]
15
15
  name = "aiogram"
16
- version = "3.26.0"
16
+ version = "3.27.0"
17
17
  source = { registry = "https://pypi.org/simple" }
18
18
  dependencies = [
19
19
  { name = "aiofiles" },
@@ -23,9 +23,9 @@ dependencies = [
23
23
  { name = "pydantic" },
24
24
  { name = "typing-extensions" },
25
25
  ]
26
- sdist = { url = "https://files.pythonhosted.org/packages/dd/2b/11709d58a7c47a773cd47239c7b5db258f02f31d784265bddeb562f3e9f9/aiogram-3.26.0.tar.gz", hash = "sha256:12fa1bce9c8cee0f1214f5e3f91bb631586c4503854d6138dacbdd7e7dc1020c", size = 1729985, upload-time = "2026-03-02T23:29:20.843Z" }
26
+ sdist = { url = "https://files.pythonhosted.org/packages/b5/09/4bfeb0314b4d78739fc7c3cdcaa77eacaeb089312d9c16f3eb538d0f0f97/aiogram-3.27.0.tar.gz", hash = "sha256:ed5fd6b40d80a6cdb215ab162c9bd9d9b7892fb2710b45e3b762a98c21119297", size = 1753647, upload-time = "2026-04-03T22:57:00.39Z" }
27
27
  wheels = [
28
- { url = "https://files.pythonhosted.org/packages/da/48/8504168e7a3ede9577a2d8aa0ed3f13471ef2db6431f506105b94f284d05/aiogram-3.26.0-py3-none-any.whl", hash = "sha256:dd8ea7feb2409953ad1424564355926207af90bb2204e37be7373fe6de201016", size = 716388, upload-time = "2026-03-02T23:29:19.076Z" },
28
+ { url = "https://files.pythonhosted.org/packages/aa/1f/64c4a9428d15ccea5aa7b204fd53061b94407640d6b075cd61c38899dd53/aiogram-3.27.0-py3-none-any.whl", hash = "sha256:26a091b6266d87db514e02703072035e7c17feebef480f927083bcfb22f634a3", size = 727326, upload-time = "2026-04-03T22:56:58.427Z" },
29
29
  ]
30
30
 
31
31
  [[package]]
@@ -41,6 +41,11 @@ wheels = [
41
41
  { url = "https://files.pythonhosted.org/packages/d4/09/a5ffedd5fca4e623a3e59ca39e88efe3671415eaaf9189b932d7b43b92d4/aiogram_i18n-1.5-py3-none-any.whl", hash = "sha256:6ce55978d32c8d1008d59f029c300506c6de48a18c8c346de3f666bd78013779", size = 33851, upload-time = "2026-03-07T23:36:16.374Z" },
42
42
  ]
43
43
 
44
+ [package.optional-dependencies]
45
+ runtime = [
46
+ { name = "fluent-runtime" },
47
+ ]
48
+
44
49
  [[package]]
45
50
  name = "aiohappyeyeballs"
46
51
  version = "2.6.1"
@@ -447,7 +452,7 @@ dependencies = [
447
452
 
448
453
  [package.optional-dependencies]
449
454
  all = [
450
- { name = "aiogram-i18n" },
455
+ { name = "aiogram-i18n", extra = ["runtime"] },
451
456
  { name = "aiosqlite" },
452
457
  { name = "alembic" },
453
458
  { name = "arq" },
@@ -471,7 +476,7 @@ db = [
471
476
  { name = "sqlalchemy" },
472
477
  ]
473
478
  dev = [
474
- { name = "aiogram-i18n" },
479
+ { name = "aiogram-i18n", extra = ["runtime"] },
475
480
  { name = "aiosqlite" },
476
481
  { name = "alembic" },
477
482
  { name = "arq" },
@@ -503,7 +508,7 @@ http = [
503
508
  { name = "httpx" },
504
509
  ]
505
510
  i18n = [
506
- { name = "aiogram-i18n" },
511
+ { name = "aiogram-i18n", extra = ["runtime"] },
507
512
  ]
508
513
  postgres = [
509
514
  { name = "asyncpg" },
@@ -518,10 +523,10 @@ sqlite = [
518
523
 
519
524
  [package.metadata]
520
525
  requires-dist = [
521
- { name = "aiogram", specifier = ">=3.13.0,<4.0" },
522
- { name = "aiogram-i18n", marker = "extra == 'all'", specifier = ">=1.4" },
523
- { name = "aiogram-i18n", marker = "extra == 'dev'", specifier = ">=1.4" },
524
- { name = "aiogram-i18n", marker = "extra == 'i18n'", specifier = ">=1.4" },
526
+ { name = "aiogram", specifier = ">=3.27.0,<4.0" },
527
+ { name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'all'", specifier = ">=1.5,<2.0" },
528
+ { name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'dev'", specifier = ">=1.5,<2.0" },
529
+ { name = "aiogram-i18n", extras = ["runtime"], marker = "extra == 'i18n'", specifier = ">=1.5,<2.0" },
525
530
  { name = "aiohttp", specifier = ">=3.13.4" },
526
531
  { name = "aiosqlite", marker = "extra == 'all'", specifier = ">=0.19.0" },
527
532
  { name = "aiosqlite", marker = "extra == 'db'", specifier = ">=0.19.0" },
@@ -559,7 +564,7 @@ requires-dist = [
559
564
  { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.0" },
560
565
  { name = "pydantic", specifier = ">=2.0,<3.0" },
561
566
  { name = "pydantic-settings", specifier = ">=2.0" },
562
- { name = "pygments", marker = "extra == 'dev'", specifier = ">=2.20.0" },
567
+ { name = "pygments", marker = "extra == 'dev'", specifier = "==2.19.1" },
563
568
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3" },
564
569
  { name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.23" },
565
570
  { name = "pytest-cov", marker = "extra == 'dev'" },
@@ -750,6 +755,34 @@ wheels = [
750
755
  { url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" },
751
756
  ]
752
757
 
758
+ [[package]]
759
+ name = "fluent-runtime"
760
+ version = "0.4.0"
761
+ source = { registry = "https://pypi.org/simple" }
762
+ dependencies = [
763
+ { name = "attrs" },
764
+ { name = "babel" },
765
+ { name = "fluent-syntax" },
766
+ { name = "pytz" },
767
+ { name = "typing-extensions" },
768
+ ]
769
+ sdist = { url = "https://files.pythonhosted.org/packages/dc/54/94bbd857443565a5776027165fe1e2634d836681d7d9c8992a2fd0ce8302/fluent.runtime-0.4.0.tar.gz", hash = "sha256:cb5ef96a58a3f67acaaca046d1201d202a1ebf2823e5e664370f359bae20574d", size = 17591, upload-time = "2023-03-16T11:10:35.165Z" }
770
+ wheels = [
771
+ { url = "https://files.pythonhosted.org/packages/e5/89/a19b0bdfc74977b44aca2ad2e0600fd89c778184fcbb7fc44ba1002cc7b5/fluent.runtime-0.4.0-py2.py3-none-any.whl", hash = "sha256:51fd02582c2363e1106d7051642967a1b7f406dd9c317bd4600a73ede40c5146", size = 15627, upload-time = "2023-03-16T11:10:33.43Z" },
772
+ ]
773
+
774
+ [[package]]
775
+ name = "fluent-syntax"
776
+ version = "0.19.0"
777
+ source = { registry = "https://pypi.org/simple" }
778
+ dependencies = [
779
+ { name = "typing-extensions" },
780
+ ]
781
+ sdist = { url = "https://files.pythonhosted.org/packages/51/52/de75f2faf499ed5a089acff2ab8bda5fc3b8db8a3f1615428ef9ccbf1917/fluent.syntax-0.19.0.tar.gz", hash = "sha256:920326d7f46864b9758f0044e9968e3112198bc826acee16ddd8f11d359004fd", size = 15039, upload-time = "2023-03-16T11:03:24.023Z" }
782
+ wheels = [
783
+ { url = "https://files.pythonhosted.org/packages/54/28/475734afb670bf7932caa1828183a4687cac51111950b9fb633c4f976afc/fluent.syntax-0.19.0-py2.py3-none-any.whl", hash = "sha256:b352b3475fac6c6ed5f06527921f432aac073d764445508ee5218aeccc7cc5c4", size = 16432, upload-time = "2023-03-16T11:03:21.934Z" },
784
+ ]
785
+
753
786
  [[package]]
754
787
  name = "frozenlist"
755
788
  version = "1.8.0"
@@ -1921,11 +1954,11 @@ wheels = [
1921
1954
 
1922
1955
  [[package]]
1923
1956
  name = "pygments"
1924
- version = "2.20.0"
1957
+ version = "2.19.1"
1925
1958
  source = { registry = "https://pypi.org/simple" }
1926
- sdist = { url = "https://files.pythonhosted.org/packages/c3/b2/bc9c9196916376152d655522fdcebac55e66de6603a76a02bca1b6414f6c/pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", size = 4955991, upload-time = "2026-03-29T13:29:33.898Z" }
1959
+ sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
1927
1960
  wheels = [
1928
- { url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
1961
+ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
1929
1962
  ]
1930
1963
 
1931
1964
  [[package]]
@@ -2036,6 +2069,15 @@ wheels = [
2036
2069
  { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
2037
2070
  ]
2038
2071
 
2072
+ [[package]]
2073
+ name = "pytz"
2074
+ version = "2026.1.post1"
2075
+ source = { registry = "https://pypi.org/simple" }
2076
+ sdist = { url = "https://files.pythonhosted.org/packages/56/db/b8721d71d945e6a8ac63c0fc900b2067181dbb50805958d4d4661cf7d277/pytz-2026.1.post1.tar.gz", hash = "sha256:3378dde6a0c3d26719182142c56e60c7f9af7e968076f31aae569d72a0358ee1", size = 321088, upload-time = "2026-03-03T07:47:50.683Z" }
2077
+ wheels = [
2078
+ { url = "https://files.pythonhosted.org/packages/10/99/781fe0c827be2742bcc775efefccb3b048a3a9c6ce9aec0cbf4a101677e5/pytz-2026.1.post1-py2.py3-none-any.whl", hash = "sha256:f2fd16142fda348286a75e1a524be810bb05d444e5a081f37f7affc635035f7a", size = 510489, upload-time = "2026-03-03T07:47:49.167Z" },
2079
+ ]
2080
+
2039
2081
  [[package]]
2040
2082
  name = "pyyaml"
2041
2083
  version = "6.0.3"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes