Django
Localhero.ai översätter Djangos gettext-filer i .po-format vid varje pull request. Nya och ändrade strängar översätts och committas till samma PR. Då får du översättningar som följer ditt varumärke, redo att driftsättas tillsammans med resten av ändringarna.
Förutsättningar
- Ett Django-projekt med meddelandekataloger för gettext i
locale/eller en motsvarande mapp - Node 18 eller senare för att köra CLI:t via
npx - En API-nyckel för Localhero.ai
Hämta en API-nyckel från ditt konto.
Konfiguration
1. Sätt upp projektet
Kör CLI:t i projektmappen. Du behöver inte installera något. CLI:t känner igen Django utifrån din manage.py:
npx @localheroai/cli init
När CLI:t känner igen ett Django-projekt kommer det föreslå mönstret **/*.po. Det kommer också leta efter mappen med meddelandekatalogerna bland translations/, locale/ och locales/ och välja den första som finns. En struktur där varje app har en egen <app>/locale/-mapp upptäcks inte automatiskt. Ange därför sökvägarna via --path när du kör init, eller redigera translationFiles.paths i efterhand.
2. Kontrollera den genererade konfigurationen
init kommer skriva en localhero.json i projektmappen. För ett Django-projekt med meddelandekataloger i locale/ kommer konfigurationen se ut så här:
localhero.json
{
"schemaVersion": "1.0",
"projectId": "your-project-id",
"sourceLocale": "en",
"outputLocales": ["sv", "de", "es"],
"translationFiles": {
"paths": ["locale/"],
"pattern": "**/*.po",
"workflow": "django"
}
}
Committa den här filen. Fälten är dokumenterade i Projektkonfiguration.
3. Lägg till ett GitHub Actions-workflow
init kommer fråga om det ska skapa GitHub action workflowet åt dig. Workflowet kör localheroai/localhero-action. Lägg till API-nyckeln på GitHub som en repository secret med namnet LOCALHERO_API_KEY.
Det genererade workflowet innehåller ett makemessages-steg före Localhero.ai-steget. Utan det körs jobbet utan fel men översätter ingenting, eftersom bara strängar som redan finns i dina meddelandekataloger är synliga. Det ser ut så här:
Justera filtret paths: om dina .po-filer ligger någon annanstans än i konfigurationen ovan:
.github/workflows/localhero-translate.yml
name: Localhero.ai - Automatic I18n translation
on:
pull_request:
paths:
- "locale/**"
- "**/*.py"
- "**/*.html"
- "**/*.txt"
- "localhero.json"
repository_dispatch:
types: [localhero-sync]
workflow_dispatch:
concurrency:
group: translate-${{ github.event.client_payload.branch || github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
translate:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
ref: ${{ github.event.client_payload.branch || github.head_ref || github.ref_name }}
fetch-depth: 0
- uses: actions/setup-python@v5
if: github.event_name == 'pull_request'
with:
python-version: "3.12"
- name: Extract messages
if: github.event_name == 'pull_request'
run: |
sudo apt-get install -y -qq gettext
pip install -r requirements.txt
python manage.py makemessages -l sv -l de -l es
- name: Translate
uses: localheroai/localhero-action@v1
with:
api-key: ${{ secrets.LOCALHERO_API_KEY }}
fetch-depth: 0 behövs eftersom actionen diffar mot bas-branchen. Vid en shallow checkout finns ingen historik att jämföra med. Alla inputs beskrivs i guiden för GitHub Actions.
Extraheringssteget gör att nya strängar översätts även när en PR bara ändrar templates eller Python-kod. Dina målspråk anges explicit i stället för --all, som bara plockar upp språk som redan har en katalog och alltså skulle skriva tomt i ett nystartat projekt.
Två saker att kontrollera: steget installerar beroenden med pip install -r requirements.txt och Python 3.12, så justera båda om du använder något annat. init läser din lockfil, så ett projekt med uv.lock, poetry.lock eller Pipfile.lock får det verktyget uppsatt och använt i stället. Extraheringen hoppas över vid synkkörningar, när Localhero.ai skriver tillbaka granskade översättningar. Vill du hellre extrahera lokalt före varje PR? Ta då bort steget och de poster under paths: som gäller källfiler.
Så fungerar det
- Du öppnar en pull request som innehåller ändringar i dina templates, din Python-kod eller dina meddelandekataloger.
- Workflowet kör
makemessagesoch extraherar nya strängar till meddelandekatalogerna. Därefter jämför GitHub-actionen branchen med bas-branchen och översätter bara meddelanden som har ändrats eller fortfarande saknar översättning. Uppdaterade och borttagna meddelanden synkas till Localhero backend. - Actionen committar de uppdaterade
.po-filerna till samma PR. Diffen du granskar innehåller då både kod och översättningar. - Du granskar och redigerar översättningarna i dashboarden, och ändringarna synkas tillbaka till branchen.
- De översatta
.po-filerna måste fortfarande kompileras medpython manage.py compilemessagestill.mo-filer som Django läser in. De flesta projekt kör redan kommandot när appen byggs eller driftsätts. Om ditt projekt inte gör det, lägg till kommandot i driftsättningssteget eller efter översättningssteget i det här workflowet.
Appen behöver inte känna till Localhero.ai. Integrationen sker helt via .po-filerna, så dina gettext-anrop och template-taggar kan vara oförändrade.
Vill du inte översätta automatiskt i pull requests? Kör makemessages och sedan npx @localheroai/cli translate lokalt för att fylla i alla meddelanden som saknar översättning. Committa sedan resultatet själv. Se CLI-referensen.
En längre genomgång med en riktig kodbas: att lokalisera en Django-app. För en fristående genomgång av CI-delen, se att översätta .po-filer i CI.
Specifikt för Django och .po
Mappstruktur för språkfiler
Djangos vanliga mappstruktur för gettext, <locale>/LC_MESSAGES/<domain>.po, fungerar utan extra konfiguration. .po-filens namn anger domänen, inte språket. Mappen ovanför LC_MESSAGES tolkas därför som språkkod.
CLI:t godtar även språkkoder som inte följer standardformatet: sv_FI_custom/LC_MESSAGES/django.po tolkas som sv_FI_custom, utan att du behöver ange localeRegex.
Utesluta meddelanden
Uteslutningar görs per fil, inte per meddelande. Använd translationFiles.ignore med ett glob-mönster för att lämna en hel .po-fil orörd.
Om du vill utesluta en viss uppsättning meddelanden lägger du dem i en egen domän eller mapp och utesluter den sökvägen.
Byta namn på och ta bort meddelanden
I flödet för pull requests sköts det automatiskt: meddelanden som tas bort i diffen rapporteras till Localhero backend tillsammans med övriga ändringar. Det manuella kommandot push är försiktigare och tar aldrig bort något. Om du har ändrat ordalydelsen i eller tagit bort meddelanden utanför en pull request kör du push --prune --force, så att Localhero backend stämmer överens med dina filer.
Det här är vanligare i Django än i format med separata nycklar, eftersom msgid är själva källsträngen. När du redigerar den engelska texten skapas därför ett nytt meddelande i stället för att det befintliga uppdateras.
Pluralformer
Varje målspråks egen Plural-Forms-header avgör hur många msgstr[N]-platser det behöver, inte en kopia av källspråkets antal. Polska får tre platser (msgstr[0]-msgstr[2]) även om ditt engelska källspråk bara skiljer på singular och plural.
Vanliga frågor
Kan jag översätta vissa språk själv?
Ja. Stäng av automatisk översättning för de språk du vill hantera själv. Då skriver Localhero.ai inga översättningar för dem. CLI:t visar vilka språk som har hoppats över, och du hanterar dem i ditt eget flöde medan övriga språk översätts automatiskt.
Översätts hela meddelandekatalogen vid varje pull request?
Nej, bara meddelanden som har ändrats eller saknar översättning. För pull requests jämförs diffen med bas-branchen. Lokalt jämför --changed-only med main, om du inte har angett en annan branch i translationFiles.baseBranch.
Hur hindrar jag actionen från att köras för en viss PR?
Lägg till labeln skip-translation. Actionen hoppar också över draft-PR:er och commits som den själv har skapat. Läs mer i guiden för GitHub Actions.
Last updated
Redo att testa?
Kom igång på några minuter. Inget kreditkort behövs.