Skip to content

Commit e9a4039

Browse files
mpasternakclaude
andcommitted
docs: add CLAUDE.md with i18n isolation rule, release workflow, repo layout
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 65628a4 commit e9a4039

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

CLAUDE.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# django-formdefaults — Claude project notes
2+
3+
Per-user, database-backed default values for Django forms. Published on
4+
PyPI as `django-formdefaults`.
5+
6+
## Repository layout
7+
8+
- `src/formdefaults/` — the published package. Everything inside here
9+
ships in the wheel/sdist.
10+
- `example_project/` — a runnable Django site that demos the package.
11+
**Never shipped on PyPI.** Excluded from sdist/wheel by
12+
`[tool.hatch.build.targets.{sdist,wheel}]` in `pyproject.toml`.
13+
- `tests/` — pytest suite. Uses `pytest-django` + a Postgres
14+
`testcontainer` started in `tests/settings.py`. Run with `pytest`.
15+
- `dist/` — gitignored build artifacts.
16+
17+
The `Makefile` and `example_project/` are deliberately NOT included
18+
in the published distribution.
19+
20+
## i18n — translation catalogs MUST stay isolated
21+
22+
Two separate `django.po` files live in this repo:
23+
24+
| Path | Scope | Shipped? |
25+
|---|---|---|
26+
| `src/formdefaults/locale/<lang>/LC_MESSAGES/django.po` | strings used inside `src/formdefaults/` only | yes — in the wheel |
27+
| `example_project/demo/locale/<lang>/LC_MESSAGES/django.po` | demo-only strings | no |
28+
29+
**Why it matters.** Django merges per-app translations on top of its core
30+
catalog at runtime. If the published package's `.po` accidentally carries
31+
a generic msgid like `"Log in"` translated as `"Zaloguj"`, every Django
32+
site that installs `formdefaults` will lose Django core's `"Zaloguj się"`
33+
on the admin login page. This actually happened pre-0.6.2 (see CHANGELOG).
34+
35+
**The rule.** Never run `django-admin makemessages` from the repo root.
36+
xgettext walks everything under cwd, so a root-level run will harvest demo
37+
strings into the package catalog. Always run from inside the right scope.
38+
39+
### Workflow
40+
41+
Use the `Makefile`:
42+
43+
```bash
44+
make messages # regenerates both .po files in the right cwd each
45+
make messages-pkg # only src/formdefaults/
46+
make messages-example # only example_project/demo/
47+
make compilemessages # both .mo files
48+
49+
make messages LOCALE=de # add a new locale
50+
```
51+
52+
The `LOCALE` variable is named that way on purpose — calling it `LANG`
53+
would silently inherit the shell's `$LANG` env var (e.g.
54+
`pl_PL.UTF-8`), and `makemessages` would create a `pl_PL.UTF-8/`
55+
directory next to `pl/`.
56+
57+
If you must invoke `makemessages` manually:
58+
59+
```bash
60+
cd src/formdefaults && django-admin makemessages -l pl --no-obsolete
61+
cd example_project && python manage.py makemessages -l pl --no-obsolete
62+
```
63+
64+
## Release workflow
65+
66+
1. Bump `version` in `pyproject.toml`.
67+
2. Add a section to `CHANGELOG.md` (Keep-a-Changelog format, semver).
68+
3. `make messages compilemessages` if any translatable strings changed.
69+
4. Commit (typical message: `chore: release X.Y.Z`).
70+
5. `git tag -a vX.Y.Z -m "Release X.Y.Z"`.
71+
6. `git push origin main vX.Y.Z`.
72+
7. `rm dist/django_formdefaults-*` (optional — clean slate).
73+
8. `uv build`.
74+
9. `uv publish` (or `uv publish dist/django_formdefaults-X.Y.Z*` to be
75+
explicit when older artifacts are still in `dist/`).
76+
77+
The `[example]` extra pins `run-site>=0.4` because `run-site` 0.5+ has
78+
been renamed to `django-run-site` and is not yet on PyPI — PyPI rejects
79+
direct git URLs in extras. Don't "fix" this by adding a git URL.
80+
81+
## Testing
82+
83+
```bash
84+
pytest # full suite, uses Postgres testcontainer
85+
pytest tests/test_core.py -k name # single test
86+
```
87+
88+
`tests/settings.py` starts a `postgres:16-alpine` container at import
89+
time and stops it via `atexit`. Docker must be running.
90+
91+
## Permissions / conventions
92+
93+
- Direct pushes to `main` may be blocked by Claude Code's auto-mode
94+
classifier even though the project's history uses them. The user
95+
will approve interactively when needed.
96+
- Don't commit `runsite.toml`, `.dev_helpers_port`, `.dev_helpers_token`
97+
at the repo root — they are per-developer generated files. (They
98+
should arguably be added to `.gitignore`; not done yet.)

0 commit comments

Comments
 (0)