django-admin-inline-controls 0.1.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 (99) hide show
  1. django_admin_inline_controls-0.1.0/.github/workflows/compat-matrix.yml +27 -0
  2. django_admin_inline_controls-0.1.0/.github/workflows/js-tests.yml +24 -0
  3. django_admin_inline_controls-0.1.0/.github/workflows/pre-commit.yml +26 -0
  4. django_admin_inline_controls-0.1.0/.github/workflows/pytest.yml +31 -0
  5. django_admin_inline_controls-0.1.0/.github/workflows/release.yml +55 -0
  6. django_admin_inline_controls-0.1.0/.gitignore +42 -0
  7. django_admin_inline_controls-0.1.0/.pre-commit-config.yaml +68 -0
  8. django_admin_inline_controls-0.1.0/CHANGELOG.md +52 -0
  9. django_admin_inline_controls-0.1.0/CONTRIBUTING.md +113 -0
  10. django_admin_inline_controls-0.1.0/LICENSE +21 -0
  11. django_admin_inline_controls-0.1.0/PKG-INFO +823 -0
  12. django_admin_inline_controls-0.1.0/README.md +770 -0
  13. django_admin_inline_controls-0.1.0/biome.json +19 -0
  14. django_admin_inline_controls-0.1.0/docs/screenshots/.gitkeep +0 -0
  15. django_admin_inline_controls-0.1.0/docs/screenshots/actions.png +0 -0
  16. django_admin_inline_controls-0.1.0/docs/screenshots/footer-rows.png +0 -0
  17. django_admin_inline_controls-0.1.0/docs/screenshots/hero.png +0 -0
  18. django_admin_inline_controls-0.1.0/docs/screenshots/row-actions.png +0 -0
  19. django_admin_inline_controls-0.1.0/docs/screenshots/save-inline.png +0 -0
  20. django_admin_inline_controls-0.1.0/docs/themes/unfold/stacked.png +0 -0
  21. django_admin_inline_controls-0.1.0/docs/themes/unfold/tab-dark.png +0 -0
  22. django_admin_inline_controls-0.1.0/docs/themes/unfold/tabular.png +0 -0
  23. django_admin_inline_controls-0.1.0/docs/themes/unfold.md +63 -0
  24. django_admin_inline_controls-0.1.0/example/demo/__init__.py +0 -0
  25. django_admin_inline_controls-0.1.0/example/demo/admin.py +104 -0
  26. django_admin_inline_controls-0.1.0/example/demo/admin_unfold.py +39 -0
  27. django_admin_inline_controls-0.1.0/example/demo/management/__init__.py +0 -0
  28. django_admin_inline_controls-0.1.0/example/demo/management/commands/__init__.py +0 -0
  29. django_admin_inline_controls-0.1.0/example/demo/management/commands/seed_demo.py +46 -0
  30. django_admin_inline_controls-0.1.0/example/demo/migrations/0001_initial.py +43 -0
  31. django_admin_inline_controls-0.1.0/example/demo/migrations/__init__.py +0 -0
  32. django_admin_inline_controls-0.1.0/example/demo/models.py +38 -0
  33. django_admin_inline_controls-0.1.0/example/example/__init__.py +0 -0
  34. django_admin_inline_controls-0.1.0/example/example/settings.py +66 -0
  35. django_admin_inline_controls-0.1.0/example/example/settings_unfold.py +8 -0
  36. django_admin_inline_controls-0.1.0/example/example/urls.py +6 -0
  37. django_admin_inline_controls-0.1.0/example/example/urls_unfold.py +6 -0
  38. django_admin_inline_controls-0.1.0/example/example/wsgi.py +7 -0
  39. django_admin_inline_controls-0.1.0/example/manage.py +20 -0
  40. django_admin_inline_controls-0.1.0/package-lock.json +2963 -0
  41. django_admin_inline_controls-0.1.0/package.json +16 -0
  42. django_admin_inline_controls-0.1.0/pyproject.toml +145 -0
  43. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/__init__.py +1 -0
  44. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/actions.py +176 -0
  45. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/apps.py +7 -0
  46. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/checks.py +212 -0
  47. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/contrib/__init__.py +4 -0
  48. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/contrib/filters.py +69 -0
  49. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/contrib/nested.py +77 -0
  50. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/contrib/unfold.py +85 -0
  51. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/controls.py +684 -0
  52. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/locale/es/LC_MESSAGES/django.mo +0 -0
  53. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/locale/es/LC_MESSAGES/django.po +232 -0
  54. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/mixins.py +932 -0
  55. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/py.typed +0 -0
  56. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/row_actions.py +173 -0
  57. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/css/contrib/unfold.css +111 -0
  58. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/css/core.css +294 -0
  59. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/js/actions.js +330 -0
  60. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/js/contrib/unfold.js +21 -0
  61. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/js/core.js +570 -0
  62. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/static/django_admin_inline_controls/js/save.js +109 -0
  63. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/footer.html +99 -0
  64. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/inline.html +34 -0
  65. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/inline_response.html +14 -0
  66. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/row_actions.html +19 -0
  67. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/tfoot.html +36 -0
  68. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templates/django_admin_inline_controls/toolbar.html +93 -0
  69. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templatetags/__init__.py +0 -0
  70. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/templatetags/inline_controls.py +72 -0
  71. django_admin_inline_controls-0.1.0/src/django_admin_inline_controls/types.py +40 -0
  72. django_admin_inline_controls-0.1.0/tests/__init__.py +0 -0
  73. django_admin_inline_controls-0.1.0/tests/admin.py +108 -0
  74. django_admin_inline_controls-0.1.0/tests/conftest.py +54 -0
  75. django_admin_inline_controls-0.1.0/tests/e2e/__init__.py +0 -0
  76. django_admin_inline_controls-0.1.0/tests/e2e/test_e2e.py +507 -0
  77. django_admin_inline_controls-0.1.0/tests/js/inline_controls.test.js +755 -0
  78. django_admin_inline_controls-0.1.0/tests/settings.py +61 -0
  79. django_admin_inline_controls-0.1.0/tests/templates/custom/footer.html +5 -0
  80. django_admin_inline_controls-0.1.0/tests/templates/custom/inline.html +5 -0
  81. django_admin_inline_controls-0.1.0/tests/templates/custom/tfoot.html +3 -0
  82. django_admin_inline_controls-0.1.0/tests/templates/custom/themed_tabular.html +33 -0
  83. django_admin_inline_controls-0.1.0/tests/templates/custom/toolbar.html +7 -0
  84. django_admin_inline_controls-0.1.0/tests/test_actions.py +363 -0
  85. django_admin_inline_controls-0.1.0/tests/test_checks.py +45 -0
  86. django_admin_inline_controls-0.1.0/tests/test_contrib.py +194 -0
  87. django_admin_inline_controls-0.1.0/tests/test_edge_cases.py +140 -0
  88. django_admin_inline_controls-0.1.0/tests/test_footer_rows.py +479 -0
  89. django_admin_inline_controls-0.1.0/tests/test_helpers.py +132 -0
  90. django_admin_inline_controls-0.1.0/tests/test_i18n.py +144 -0
  91. django_admin_inline_controls-0.1.0/tests/test_inline_controls.py +312 -0
  92. django_admin_inline_controls-0.1.0/tests/test_media.py +73 -0
  93. django_admin_inline_controls-0.1.0/tests/test_row_actions.py +400 -0
  94. django_admin_inline_controls-0.1.0/tests/test_save_inline.py +217 -0
  95. django_admin_inline_controls-0.1.0/tests/test_selectors.py +78 -0
  96. django_admin_inline_controls-0.1.0/tests/test_templates.py +111 -0
  97. django_admin_inline_controls-0.1.0/tests/urls.py +12 -0
  98. django_admin_inline_controls-0.1.0/uv.lock +1546 -0
  99. django_admin_inline_controls-0.1.0/vitest.config.js +15 -0
@@ -0,0 +1,27 @@
1
+ name: Compatibility Matrix
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+
9
+ jobs:
10
+ tox:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ with:
18
+ enable-cache: true
19
+
20
+ - name: Install Python versions
21
+ run: uv python install 3.10 3.12 3.13 3.14
22
+
23
+ - name: Install dependencies
24
+ run: uv sync
25
+
26
+ - name: Run compatibility matrix (tox)
27
+ run: uv run tox run
@@ -0,0 +1,24 @@
1
+ name: JavaScript Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Setup Node.js
15
+ uses: actions/setup-node@v4
16
+ with:
17
+ node-version: "20"
18
+ cache: "npm"
19
+
20
+ - name: Install dependencies
21
+ run: npm ci
22
+
23
+ - name: Run Tests & Coverage
24
+ run: npm run coverage
@@ -0,0 +1,26 @@
1
+ name: Pre-commit
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+
8
+ jobs:
9
+ pre-commit:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Install uv
15
+ uses: astral-sh/setup-uv@v5
16
+ with:
17
+ enable-cache: true
18
+
19
+ - name: Set up Python
20
+ run: uv python install
21
+
22
+ - name: Install dependencies
23
+ run: uv sync
24
+
25
+ - name: Run pre-commit
26
+ run: uv run pre-commit run --all-files
@@ -0,0 +1,31 @@
1
+ name: Python and Playwright Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+
9
+ jobs:
10
+ test-python:
11
+ name: Python Tests
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v5
18
+ with:
19
+ enable-cache: true
20
+
21
+ - name: Set up Python
22
+ run: uv python install
23
+
24
+ - name: Install dependencies
25
+ run: uv sync
26
+
27
+ - name: Install Playwright browsers
28
+ run: uv run playwright install --with-deps chromium
29
+
30
+ - name: Run Pytest
31
+ run: uv run pytest
@@ -0,0 +1,55 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types:
6
+ - published
7
+
8
+ jobs:
9
+ release-build:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v5
17
+ with:
18
+ enable-cache: true
19
+
20
+ - name: Show project version
21
+ run: |
22
+ grep "version" pyproject.toml
23
+
24
+ - name: Build release distributions
25
+ run: uv build
26
+
27
+ - name: Upload distributions
28
+ uses: actions/upload-artifact@v4
29
+ with:
30
+ name: release-dists
31
+ path: dist/
32
+
33
+ pypi-publish:
34
+ runs-on: ubuntu-latest
35
+ needs:
36
+ - release-build
37
+ permissions:
38
+ id-token: write
39
+ contents: read
40
+
41
+ environment:
42
+ name: pypi
43
+ url: https://pypi.org/project/django-admin-inline-controls/
44
+
45
+ steps:
46
+ - name: Retrieve release distributions
47
+ uses: actions/download-artifact@v4
48
+ with:
49
+ name: release-dists
50
+ path: dist/
51
+
52
+ - name: Publish release distributions to PyPI
53
+ uses: pypa/gh-action-pypi-publish@release/v1
54
+ with:
55
+ packages-dir: dist/
@@ -0,0 +1,42 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .installed.cfg
9
+ *.egg
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # Testing / coverage
17
+ .pytest_cache/
18
+ .coverage
19
+ .coverage.*
20
+ coverage/
21
+ htmlcov/
22
+ .mypy_cache/
23
+ .ruff_cache/
24
+ .tox/
25
+
26
+ # Django
27
+ *.log
28
+ local_settings.py
29
+ db.sqlite3
30
+ db.sqlite3-journal
31
+ media/
32
+
33
+ # Node / JS
34
+ node_modules/
35
+
36
+ # Editors / OS
37
+ .vscode/
38
+ .idea/
39
+ .DS_Store
40
+
41
+ # Docs
42
+ docs/_build/
@@ -0,0 +1,68 @@
1
+ default_language_version:
2
+ python: &python-version python3.14
3
+
4
+ repos:
5
+ - repo: https://github.com/pre-commit/pre-commit-hooks
6
+ rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0
7
+ hooks:
8
+ - id: check-added-large-files
9
+ - id: check-case-conflict
10
+ - id: check-json
11
+ - id: check-merge-conflict
12
+ - id: check-symlinks
13
+ - id: check-toml
14
+ - id: debug-statements
15
+ - id: end-of-file-fixer
16
+ - id: trailing-whitespace
17
+
18
+ - repo: https://github.com/biomejs/pre-commit
19
+ rev: d1ce4972fb5ad09afd33b432bca71e8c5dfbb2b5 # frozen: v2.5.6
20
+ hooks:
21
+ - id: biome-check
22
+ additional_dependencies:
23
+ - '@biomejs/biome@2.3.8'
24
+ language_version: default
25
+
26
+ - repo: https://github.com/adamchainz/django-upgrade
27
+ rev: bdcc9646c249f00ec9781751791e7b75b48b3722 # frozen: 1.31.1
28
+ hooks:
29
+ - id: django-upgrade
30
+ args: [--target-version, "4.2"]
31
+
32
+ - repo: https://github.com/astral-sh/ruff-pre-commit
33
+ rev: 39d9ac5938dadb73df0564a45f163e25ff9fa6e2 # frozen: v0.16.1
34
+ hooks:
35
+ - id: ruff-check
36
+ args: [--fix]
37
+ - id: ruff-format
38
+
39
+ - repo: local
40
+ hooks:
41
+ - id: mypy
42
+ name: mypy
43
+ entry: mypy
44
+ language: python
45
+ additional_dependencies:
46
+ - mypy>=1.10
47
+ - django-stubs[compatible-mypy]>=5
48
+ - django>=4.2
49
+ - django-filter>=23.2
50
+ - django-nested-admin>=4.1
51
+ - pytest-django>=4.8
52
+ types: [python]
53
+ files: ^(src|example)/
54
+ pass_filenames: false
55
+ args: [src/django_admin_inline_controls, example]
56
+
57
+ # Only needed if the library ships Django templates (src/<pkg>/templates/).
58
+ # Remove this hook if it doesn't.
59
+ - repo: https://github.com/adamchainz/djade-pre-commit
60
+ rev: 52a7ce253113456c2a1113186a4a19b15c8b68af # frozen: 1.9.0
61
+ hooks:
62
+ - id: djade
63
+ files: '(/|^)templates/'
64
+
65
+ - repo: https://github.com/tox-dev/pyproject-fmt
66
+ rev: d600c142bb19f521ae6a6a345f94a2efd7937759 # frozen: v2.26.0
67
+ hooks:
68
+ - id: pyproject-fmt
@@ -0,0 +1,52 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-10-05
9
+
10
+ First release.
11
+
12
+ ### Added
13
+
14
+ - **`InlineControlsMixin`** for `TabularInline` and `StackedInline`:
15
+ - pagination, with page links or infinite scroll, and saving rows loaded
16
+ across several pages;
17
+ - filters, generated from lookups or from a form of yours
18
+ (`contrib.filters` for a django-filter `FilterSet`);
19
+ - multi-column sorting from the column headers;
20
+ - state namespaced per inline in the URL, and in-place refresh of a
21
+ single inline (re-initializing the admin's inline and widget JS) with
22
+ an unsaved-changes prompt.
23
+ - **Saving one inline** (`inline_save_button`, with
24
+ `InlineControlsAdminMixin` on the parent): without submitting or
25
+ reloading the rest of the page, recorded in the parent's history.
26
+ - **Bulk actions** (`inline_bulk_actions`): like the changelist's, on the
27
+ selected rows, with "select all" across pages, the `@inline_action`
28
+ decorator (permissions, confirmation prompts) and a built-in
29
+ `delete_selected`.
30
+ - **Row actions** (`inline_actions`): buttons on each saved row, with
31
+ django-inline-actions' API — the `(request, obj, parent_obj)` signature,
32
+ `get_inline_actions()`, per-row `get_<action>_label/css/attr()` hooks and
33
+ the `ViewAction`, `DeleteAction` and `DefaultActionsMixin` mixins — run
34
+ without submitting the change form, with the permissions checked by the
35
+ server.
36
+ - **Footer rows** (`inline_footer_rows`, `inline_footer_scope`): totals,
37
+ averages… aggregated in one query over the filtered rows or the page,
38
+ rendered by the server as the table's `<tfoot>` (also in the add view,
39
+ empty) or as a summary line; raw values in `data-*` attributes for the
40
+ page's JS; format (`format_inline_footer_value()`) and markup
41
+ (`tfoot.html`) customizable.
42
+ - **Customizable markup:** template blocks throughout, per-inline
43
+ templates, and `inline_controls_selectors` (`DEFAULT_SELECTORS`) for
44
+ themes and custom inline templates, plus the `inline-controls:place` and
45
+ `inline-controls:updated` events.
46
+ - **django-unfold** support (`contrib.unfold`, `unfold` extra): the
47
+ controls in Unfold's inlines with its colors, light and dark.
48
+ - **django-nested-admin** support (`contrib.nested`, `nested` extra).
49
+ - Only the scripts an inline uses are loaded (`core.js`, `save.js`,
50
+ `actions.js`).
51
+ - Spanish translation, and system checks for every option.
52
+ - Django 4.2 – 6.1, Python 3.10+.
@@ -0,0 +1,113 @@
1
+ # Contributing
2
+
3
+ ## Development setup
4
+
5
+ With [uv](https://docs.astral.sh/uv/) (recommended):
6
+
7
+ ```bash
8
+ uv sync
9
+ uv run playwright install --with-deps chromium
10
+ npm install
11
+ uv run pre-commit install
12
+ ```
13
+
14
+ Without uv:
15
+
16
+ ```bash
17
+ pip install -e ".[dev]"
18
+ playwright install --with-deps chromium
19
+ npm install
20
+ pre-commit install
21
+ ```
22
+
23
+ ## Running the example project
24
+
25
+ ```bash
26
+ cd example
27
+ python manage.py migrate
28
+ python manage.py createsuperuser
29
+ python manage.py runserver
30
+ ```
31
+
32
+ ## Tests
33
+
34
+ Python (pytest + pytest-django, coverage always on via `addopts`):
35
+
36
+ ```bash
37
+ uv run pytest
38
+ ```
39
+
40
+ `tests/e2e/` (real-browser tests via pytest-playwright, driving a real
41
+ Chromium against `live_server`) runs as part of that same `uv run pytest`
42
+ — no separate command. They need `uv run playwright install chromium`
43
+ once (see Setup above) and are slower than the rest of the suite;
44
+ everything else under `tests/` is unit/integration-level and doesn't
45
+ touch a browser.
46
+
47
+ JavaScript (vitest + jsdom):
48
+
49
+ ```bash
50
+ npm test
51
+ npm run coverage
52
+ ```
53
+
54
+ ## Compatibility matrix (tox)
55
+
56
+ `uv run pytest` above only runs against whatever Django version `uv.lock`
57
+ resolved (the newest one satisfying `dependencies`). To check the full
58
+ supported range — every Django series in `classifiers`, against the
59
+ oldest and newest Python it supports (within this package's own
60
+ `requires-python` floor) — run the tox matrix instead:
61
+
62
+ ```bash
63
+ uv run tox run-parallel # every env, in parallel
64
+ uv run tox -e py314-dj52 # a single env, e.g. to debug one failure
65
+ ```
66
+
67
+ `[tool.tox]` in `pyproject.toml` lists the exact envs. Each one gets its own ephemeral venv (via
68
+ [tox-uv](https://github.com/tox-dev/tox-uv), using uv's own Python
69
+ builds — `uv python install <version>` once for any you don't have yet)
70
+ with only `pytest`/`pytest-django`/`pytest-cov` and that env's pinned
71
+ Django, not the full `dev` group, and skips `tests/e2e/` (no Playwright
72
+ in those envs). This only tests boundaries (oldest + newest Python per
73
+ Django series), not every valid combination — that catches most real
74
+ breakage while staying fast. Runs in CI as a separate
75
+ `compat-matrix.yml` workflow, alongside the regular `pytest.yml`. Update
76
+ the `env_list` here whenever `classifiers` gains or drops a Django
77
+ series.
78
+
79
+ ## Lint / format / type-check
80
+
81
+ ```bash
82
+ uv run ruff check .
83
+ uv run ruff format --check .
84
+ uv run mypy src example
85
+ # or, everything at once:
86
+ uv run pre-commit run --all-files
87
+ ```
88
+
89
+ The mypy pre-commit hook runs against the project venv (it needs
90
+ django-stubs to resolve model types), not an isolated pre-commit env.
91
+
92
+ ## Before opening a PR
93
+
94
+ - [ ] `uv run pytest`
95
+ - [ ] `npm test`
96
+ - [ ] `uv run pre-commit run --all-files`
97
+
98
+ ## Translations
99
+
100
+ Catalogs live in `src/django_admin_inline_controls/locale/`. After changing
101
+ translatable text, from that package directory:
102
+
103
+ ```bash
104
+ cd src/django_admin_inline_controls
105
+ DJANGO_SETTINGS_MODULE=tests.settings PYTHONPATH=../..:../../example \
106
+ uv run django-admin makemessages -l es --no-obsolete --add-location file
107
+ # translate the new/changed entries in locale/es/LC_MESSAGES/django.po, then:
108
+ DJANGO_SETTINGS_MODULE=tests.settings PYTHONPATH=../..:../../example \
109
+ uv run django-admin compilemessages
110
+ ```
111
+
112
+ Commit both the `.po` and the compiled `.mo`. `tests/test_i18n.py` fails if
113
+ an entry is untranslated or fuzzy, or if a `.mo` is older than its `.po`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rodolfo Becerra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.