Add a language
Translate the interface into another language and contribute it
Rezepte's interface is available in English and German. Adding another language takes no programming and four files: you name the language in one line, translate a copy of the English texts, list the words recipes in your language use so importing a recipe understands them, and register that list in one more line. Two commands generate the rest. Your recipes are not affected — Rezepte never translates recipe content.
What you need
- A clone of the repository.
- mise, which installs every other tool the project uses. Run
mise run setuponce in the clone.
Steps
Name the language
Add its language code to locales in service/internal/i18n/locales.json — for French, fr:
{
"baseLocale": "en",
"locales": ["en", "de", "fr"]
}Leave baseLocale as it is. English is what every text falls back to.
Translate the texts
Copy frontend/messages/en.json to frontend/messages/fr.json (with your language's code) and translate every value on the right-hand side:
"overview_headline": "Que cuisine-t-on aujourd'hui ?",- Keep every key on the left exactly as it is.
- Keep every placeholder in curly braces, such as
{count}or{name}, exactly as it is. You can move it within the sentence. editor_unit_optionsis not a sentence but the units the recipe editor suggests, separated by commas. Do not translate the English list word for word: write the units a cook in your language actually uses, in their usual abbreviations, as many or as few as fit. German, for example, hasTL,EL,BundandZeheand nocup.time_units_seconds,time_units_minutesandtime_units_hoursare not sentences but the words for seconds, minutes and hours, separated by|, andtime_words_rangeandtime_words_andare the words in "10 to 15 minutes" and "1 hour and 20 minutes". The recipe editor uses them to spot the times in a step. Write every spelling and abbreviation a recipe in your language uses, with full words first: German hasMinuten|Minute|Min.|Min.import_exampleis an example recipe, not a sentence. Translate it using the headings (the "Ingredients" and "Method" equivalents) that your language's word list inlang_xx.goknows:mise run checkimports it and fails otherwise.- Translate every entry. The check in the next step fails on any that are missing, so the interface never shows a half-translated screen.
The mails Rezepte sends take their texts from the same file — the keys starting with mail_ — so translating them translates the mails too.
The language picker names the language by itself, in the reader's language and in its own ("French · Français"), so there is nothing to add for that.
List the recipe words
Copy service/internal/recipeimport/lang_en.go to lang_fr.go (with your language's code) and replace the English words with your language's: the units cooks write after an amount ("EL", "Prise"), the headings above ingredients and steps ("Zutaten", "Zubereitung"), words like "to taste" that make an amount vague, and the others the comments in service/internal/recipeimport/lang.go explain. Then add french to the list languages in lang.go. The check in the next step fails while a language has no such list. If writing the tests for it is new to you, say so in the pull request and a maintainer adds them.
Check and look at it
mise run //service:generate
mise run check
mise run //docs/user:openapi
RZP_DEMO_LOCALE=fr mise run demoThe first command copies the mail texts of your file to service/internal/mail/messages/fr.json, where the service reads them; without it mise run check fails, naming your language's embedded copy as stale. mise run check finds missing texts and placeholders. The third command updates the API reference, which lists the languages the API accepts. The fourth starts a demo instance at the address it prints; log in as demo / demo1234 and the interface is in your language. The demo recipes stay English unless your language has sample recipes of its own, which is optional; those get simple placeholder images instead of photos.
Contribute it
Open a pull request with the two new files (fr.json and lang_fr.go), the lines in locales.json and lang.go, the generated service/internal/mail/messages/fr.json and the updated API reference. A translation can be improved later like any other change.
/mcp POST
The endpoint an MCP client such as an AI agent connects to: stateless Streamable HTTP, one JSON-RPC message per request, answered as JSON. The tools describe themselves over tools/list; the token's scopes decide which ones it lists. See https://modelcontextprotocol.io/specification.
Changelog
What changed in each release, and what to do before you upgrade