Django
Localhero.ai oversetter Djangos gettext-filer i .po-format ved hver pull request. Nye og endrede strenger oversettes og committes til samme PR. Dermed får du oversettelser som er i tråd med merkevaren din og klare til å driftsettes sammen med resten av endringene.
Forutsetninger
- Et Django-prosjekt med meldingskataloger for gettext i
locale/eller en tilsvarende mappe - Node 18 eller nyere for å kjøre CLI-et via
npx - En API-nøkkel for Localhero.ai
Hent en API-nøkkel fra kontoen din.
Oppsett
1. Sett opp prosjektet
Kjør CLI-et i prosjektmappen. Du trenger ikke å installere noe. CLI-et kjenner igjen Django ut fra manage.py:
npx @localheroai/cli init
Når CLI-et kjenner igjen et Django-prosjekt, foreslår det mønsteret **/*.po. Det leter også etter mappen med meldingskatalogene blant translations/, locale/ og locales/, og velger den første som finnes. En struktur der hver app har sin egen <app>/locale/-mappe oppdages ikke automatisk. Angi derfor stiene via --path når du kjører init, eller rediger translationFiles.paths i etterkant.
2. Sjekk den genererte konfigurasjonen
init oppretter localhero.json i prosjektmappen. For et Django-prosjekt med meldingskataloger i locale/ ser konfigurasjonen slik ut:
localhero.json
{
"schemaVersion": "1.0",
"projectId": "your-project-id",
"sourceLocale": "en",
"outputLocales": ["sv", "de", "es"],
"translationFiles": {
"paths": ["locale/"],
"pattern": "**/*.po",
"workflow": "django"
}
}
Committ denne filen. Feltene er dokumentert i Prosjektoppsett.
3. Legg til en GitHub Actions-arbeidsflyt
init spør om den skal opprette GitHub Actions-arbeidsflyten for deg. Arbeidsflyten bruker localheroai/localhero-action. Legg til API-nøkkelen på GitHub som en repository secret med navnet LOCALHERO_API_KEY.
Den genererte arbeidsflyten inneholder et makemessages-steg før Localhero.ai-steget. Uten det kjører jobben uten feil, men oversetter ingenting, fordi bare strenger som allerede finnes i meldingskatalogene dine er synlige. Den ser slik ut:
Juster filteret paths: hvis .po-filene dine ligger et annet sted enn i konfigurasjonen over:
.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 trengs fordi actionen sammenligner mot bas-branchen. En shallow checkout har ingen historikk å sammenligne med. Du finner alle parametrene i guiden for GitHub Actions.
Ekstraheringssteget gjør at nye strenger oversettes selv når en PR bare endrer templates eller Python-kode. Målspråkene dine oppgis eksplisitt i stedet for --all, som bare plukker opp språk som allerede har en katalog og dermed ville skrevet tomt i et nystartet prosjekt.
To ting å kontrollere: steget installerer avhengigheter med pip install -r requirements.txt og Python 3.12, så juster begge hvis du bruker noe annet. init leser lockfilen din, så et prosjekt med uv.lock, poetry.lock eller Pipfile.lock får det verktøyet satt opp og brukt i stedet. Ekstraheringen hoppes over ved synkjøringer, når Localhero.ai skriver tilbake gjennomgåtte oversettelser. Vil du heller trekke ut strengene lokalt før hver PR? Fjern da steget og oppføringene under paths: som gjelder kildefiler.
Slik fungerer det
- Du åpner en pull request som inneholder endringer i templates, Python-koden eller meldingskatalogene dine.
- Arbeidsflyten kjører
makemessagesog trekker ut nye strenger til meldingskatalogene. Deretter sammenligner GitHub-actionen den aktuelle branchen med bas-branchen og oversetter bare meldinger som er endret eller fortsatt mangler oversettelse. Oppdaterte og fjernede meldinger synkroniseres til Localhero backend. - Actionen committer de oppdaterte
.po-filene til samme PR. Diffen du går gjennom, inneholder da både kode og oversettelser. - Du går gjennom og redigerer oversettelsene i dashbordet, og endringene synkroniseres tilbake til branchen.
- De oversatte
.po-filene må fortsatt kompileres til.mo-filer medpython manage.py compilemessagesfør Django kan lese dem inn. De fleste prosjekter kjører allerede denne kommandoen når appen bygges eller driftsettes. Hvis prosjektet ditt ikke gjør det, legger du kommandoen til i driftsettingssteget eller etter oversettelsessteget i denne arbeidsflyten.
Appen din trenger ikke å vite at Localhero.ai finnes. Integrasjonen skjer helt via .po-filene, så gettext-kallene og template-taggene dine kan være uendret.
Vil du ikke oversette automatisk i pull requests? Kjør makemessages og deretter npx @localheroai/cli translate lokalt for å fylle inn alle meldinger som mangler oversettelse. Committ deretter resultatet selv. Se CLI-referansen.
En lengre gjennomgang med en reell kodebase: slik lokaliserer du en Django-app. For en frittstående gjennomgang av CI-delen, se å oversette .po-filer i CI.
Spesifikt for Django og .po
Mappestruktur for språkfiler
Djangos vanlige mappestruktur for gettext, <locale>/LC_MESSAGES/<domain>.po, fungerer uten ekstra konfigurasjon. .po-filnavnet angir domenet, ikke språket. Mappen over LC_MESSAGES tolkes derfor som språkkoden.
CLI-et godtar også språkkoder som ikke følger standardformatet: sv_FI_custom/LC_MESSAGES/django.po tolkes som sv_FI_custom, uten at du trenger å angi localeRegex.
Ekskludere meldinger
Ekskludering skjer per fil, ikke per melding. Bruk translationFiles.ignore med et glob-mønster for å la en hel .po-fil være urørt.
Vil du ekskludere et bestemt utvalg meldinger, legger du dem i et eget domene eller en egen mappe og ekskluderer den stien.
Gi nytt navn til og fjerne meldinger
I pull request-flyten skjer dette automatisk: Meldinger som fjernes i diffen, rapporteres til Localhero backend sammen med resten av endringene. Den manuelle push-kommandoen er mer forsiktig og fjerner aldri noe. Har du endret ordlyden i eller fjernet meldinger utenfor en pull request, kjører du push --prune --force for å synkronisere Localhero backend med filene dine.
Dette skjer oftere i Django enn i nøkkelbaserte formater, fordi msgid er selve kildestrengen. Å redigere den engelske teksten skaper derfor en ny melding i stedet for å oppdatere en eksisterende.
Pluralformer
I .po-filer er pluralformene indekserte, ikke navngitte. Plural-Forms-headeren for hvert målspråk avgjør hvor mange msgstr[N]-plasser språket trenger. Antallet kopieres ikke fra kildespråket. Polsk får tre plasser (msgstr[0]-msgstr[2]) selv om det engelske kildespråket bare skiller mellom entall og flertall.
Vanlige spørsmål
Kan jeg oversette enkelte språk selv?
Ja. Slå av automatisk oversettelse for språkene du vil håndtere selv. Da skriver Localhero.ai ingen oversettelser for dem. CLI-et viser hvilke språk som hoppes over, og du håndterer dem i din egen arbeidsflyt mens resten oversettes automatisk.
Blir hele meldingskatalogen oversatt ved hver pull request?
Nei, bare meldinger som er endret eller mangler oversettelse. I en pull request sammenligner actionen den aktuelle branchen med bas-branchen. Lokalt sammenligner --changed-only med main, med mindre du har angitt en annen branch i translationFiles.baseBranch.
Hvordan hindrer jeg actionen i å kjøre for en bestemt PR?
Legg til labelen skip-translation. Actionen hopper også over draft-PR-er og sine egne commits. Detaljene finner du i guiden for GitHub Actions.
Last updated
Klar til å prøve?
Kom i gang på noen minutter. Du trenger ikke kredittkort.