Multilingual Ghost - automated translation of posts with Make and DeepL

Here’s how to translate your posts to any language instantly for free (well, 500.000 characters / month) with DeepL Translate and Make. Links, images and Ghost Cards are preserved in the translation.

Steps to enable translation

  1. Register a free API account on DeepL Translate
  2. Create a custom Integration in Ghost
  3. Create an internal tag in Ghost, #translated / hash-translated
  4. Create a Scenario in Make with Ghost and DeepL

This is what we’ll have in Make when ready…

First, register a free API-account with DeepL Translate and save the API-key.

Then, set up a Custom integration for Make.com in Ghost

You need three things for Make integration…

  • Admin API key
  • API url
  • Integration ID

Create the internal tag #translated

The Make scenario triggers on Post Published in Ghost. Since the scenario will/can publish a post, we have to cut the loop, else Make will continue to translate already translated posts… until we run out of Make credits.

And, if we leave the translated post as Draft, we don’t want it to translated again when we Publish.

In the next step we will set up a filter with this #translated tag so Make will not execute the translation if the tag is found.

Create the Scenario in Make

OK, here we go, a Blueprint json for this scenario in Make is available on this link, right-click to save.

  1. Add a Ghost Publish Post module, using the data from Ghost Custom integration
  2. Add a DeepL translate module, using the API key - translate the HTML field from Ghost module, and assign source and target language.
  3. Add a second DeepL translate module, translate the Title field from Ghost module, and assign source and target language.
  4. Add a Ghost Create Post module using the output from the two DeepL modules (HTML and Title). Add a hash-translated tag to the new post, and don’t forget the Feature Image. Suggestion: create new posts as Draft until you see everything working.
  5. Add a Filter after the first Ghost module to stop execution if the hash-translated tag is found. Here’s the filter set-up. Only posts which do not contain hash-translated are processed.

make-ghost-translate3-filter

Done

Activate the scenario in Make and publish a post in Ghost. Your post, translated, shows up a few seconds later in Ghost.

5 Likes

Update: The filter will work much better with an array operator, “Does not contain”.

The previous filter works if hash-translated is the first primary tag, this filter checks all tags…

image

2 Likes

Thank you so much for sharing this! Just to clarify, this process produces a translated post within the same Ghost site? In other words, the English and (for example) French content would be in the same site. Or can the post be published in a second French site?

1 Like

You’re welcome @Andy_DeRoin_They-The

If you translate to same site you can use routing on tags “fr” or “en”. Assign language tags to posts and make Collections in Ghost based on the tag.

https://ghost.org/docs/themes/routing/

More SEO friendly is separate sites, you can localize menu & UX, get all metadata translated for en.example.com and fr.example.com etc…

2 Likes

Hey @mheland , thanks so much for posting this! I was able to help a journalist client get this set up yesterday for several languages. She’s super excited about being able to support community members who would otherwise have poor access to local news.

We hit one snag, and I wonder if you have any ideas on it. Although she sees a bunch of language choices in the dropdown for target language, she’s missing several of the ones she needs, even though they’re on this list: Languages supported | DeepL API Documentation

Any ideas, or have you seen something similar? I looked over the blueprint, thinking that maybe it had hard-coded the languages, but it doesn’t, so I’m guessing they must be coming from DeepL, and I’m not sure why she’s getting only a partial list?

Many thanks!

Hi Cathy, Glad I could help, switch it to map and enter any language code
Should/could work ;)

/m

2 Likes

Thanks so much! We’ll give it a try and report back. :)
Update: That did the trick!

Hey @mheland !

I’m continuing to play with this, doing some expansion (doing multiple languages in one scenario eventually), BUT… I’m having problems with the tags filter. I can replicate that if there’s just one tag (actually named hash-translated, not #translated) and i do current.tags.name text does not contain hash-translated, that filters correctly.

However, when I switch to the array syntax you recommend in your January '24 update, the filter lets everything through.

I’ve got some other improvements to share back – appending tags, multiple languages, etc, but I’m hoping you can help me get this one sorted before someone else makes the mistake I did and completely bombs themselves out of free tier. (Yes, I should have been experimenting with “run once”, but I thought it was working! Oops…)

1 Like

Update: I scrapped Make and wrote my own in javascript. Which I should have done several hours earlier. :rofl: Works great. I’m going to tidy up a bit and then will update with it in case anyone wants it. :)

1 Like

I wish this can be ported to N8N (open-source automation engine). I have plans to try something IA crafted for me some days ago.

I will share my experiences and the workflow if it works. Thanks for following this up, multilingual is a must on 2025.

I’m dropping a public repo on github. Feel free to port the logic to N8N if you like.

Update: Repo here: GitHub - cathysarisky/netlify-translate-template: Ghost -> Netlify webhook -> DeepL -> translated posts in Ghost

2 Likes

Thanks Cathy, you’re doing great as always. Just to point out (since I read you like human translations) that DeepL was created by the makers of Linguee, a dictionary that uses real human translations.

That explains why their translations feel more natural and clear than everything else. Perhaps the only service that could match this level is machinetranslation(.)com, which combines DeepL with other providers.

It’s expensive, and I don’t know if they really improved the quality, to be honest.

1 Like

DeepL went shopping…

https://datacentremagazine.com/technology-and-ai/how-deepl-will-expand-ai-in-europe-with-nvidia-dgx-superpod

Because of my webhook running amok? :rofl:

1 Like

Hey Cathy, I found a little issue trying to deploy it on Netlify (it’s my first time here, I’m trying to be friendly with non open-sourced tools):

Deploy site                                                   
────────────────────────────────────────────────────────────────
​
​
Configuration error                                           
────────────────────────────────────────────────────────────────
​
  Error message
  Deploy did not succeed: Build cancelled, found file owned by root
​
  Resolved config
  build:
    command: npm install
    commandOrigin: config
    environment:
      - DEEPL_AUTH_KEY
      - GHOST_ADMIN_API_KEY
      - GHOST_ADMIN_API_URL
      - GHOST_WEBHOOK_SECRET
      - TARGET_LANGUAGES
      - TRANSLATED_LABEL
    publish: /opt/build/repo
    publishOrigin: default
  functions:
    '*':
      node_bundler: esbuild
  functionsDirectory: /opt/build/repo/netlify/functions
Build failed due to a user error: Build script returned non-zero exit code: 2
Failing build: Failed to build site

It seems your repo need to ignore some development folders?

1 Like

Is that from clicking ‘deploy on netlify’ or from forking the repo and running ‘netlify dev’ from the command line?

It definitely builds for me when I deploy from netlify-cli, but this is my first time trying to make a ‘deploy on netlify’ button and perhaps I’ve failed somewhere…

1 Like

Oh well, I think it’s more probable that I’m failing trying to deploy it. I tried using the button on your Github page without forking and forking it, without success.

I can start to play around using netlify-cli, for sure and I will update if I found anything valuable. Just sharing my experience because we all know that a single click should bring more users around and that’s how Ghost is improving those days :)

This. Make is more and more buggy every day. I guess they moved all staff over to the AI team, as they dropped the ball on that one, a lot of strange stuff is happening on the platform. Integrations suddenly just falling apart… troubling. We switched to n8n which is absolutely bussin’.

2 Likes

That’s good to know, we need to use open platforms over hyped centralized ones :slight_smile:

May we know if you published your new workflow as N8N open community templates?