Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ venv
node_modules
dist/
*.sqlite3
*.mo
44 changes: 44 additions & 0 deletions docs/development/translation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
title: Translations
order: 3
description: Learn how to contribute translations for django-unfold using Django's built-in internationalization framework.
---

# Translations

Add new language support to `django-unfold` using Django's internationalization framework.

## Prerequisites

- Django installed
- `gettext` available

## Workflow

1. **Navigate to source directory:**

```bash
cd src/unfold
```

2. Create message files for your language:

```bash
django-admin makemessages -l <language_code>
```

3. Prune Django default translations

```bash
../../scripts/prune_locale.py <language_code>
```

4. Edit translations:
* Open `locale/<language_code>/LC_MESSAGES/django.po`
* Add or update translations

5. Compile messages:

```bash
django-admin compilemessages
```
26 changes: 19 additions & 7 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ django-money = "^3.5"

[tool.poetry.group.dev.dependencies]
python-semantic-release = "^9.21"
polib = "^1.2"
click = "<8.2.1" # 8.2.1+ requires Python 3.10+

[tool.ruff]
fix = true
Expand Down
59 changes: 59 additions & 0 deletions scripts/prune_locale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env python3

# This file includes code adapted from django-jazzmin (https://github.com/farridav/django-jazzmin)
# Copyright (c) David Farrington
# Licensed under the MIT License

import pathlib
from itertools import chain

import click
import django
import polib

THIS_DIR = pathlib.Path(__file__)
LOCALE_DIR = THIS_DIR.parent.parent / "src" / "unfold" / "locale"
LOCALES = [p.name for p in LOCALE_DIR.iterdir()]
DJANGO_PATH = pathlib.Path(django.__path__[0])


@click.command()
@click.argument("prune", type=click.Choice(LOCALES))
def main(prune: str):
"""
Remove the django provided strings

e.g - ./prune_locale.py de
"""
our_po = polib.pofile(LOCALE_DIR / prune / "LC_MESSAGES" / "django.po")
admin_po = polib.pofile(
DJANGO_PATH
/ "contrib"
/ "admin"
/ "locale"
/ "en"
/ "LC_MESSAGES"
/ "django.po"
)
admindocs_po = polib.pofile(
DJANGO_PATH
/ "contrib"
/ "admindocs"
/ "locale"
/ "en"
/ "LC_MESSAGES"
/ "django.po"
)

existing_strings = {x.msgid for x in chain(admin_po, admindocs_po)}
new_po = polib.POFile()
new_po.metadata = our_po.metadata
for po in our_po:
if po.msgid not in existing_strings:
new_po.append(po)

new_po.save(LOCALE_DIR / prune / "LC_MESSAGES" / "django.po")


if __name__ == "__main__":
main()
Loading