Recently I've been working a lot with GPT-3 (late to the party I know), and my first aha moment was that it's very good at translating without losing context - something that most automated translation services are pretty bad at.

As an indie team, hiring native speakers to translate our websites has always been a bit of a luxury we couldn't afford, so being able to throw GPT-3 at the problem would be very helpful. Even if the results aren't perfect, for most cases "good enough" would be fine.

So this is what I set out to do with one of our new websites tryellie.com. Ellie is an AI bot who writes replies to emails for you, and has been going a bit viral recently on an international scale. Since the product already works well in different languages, I'm hoping that by internationalizing the website we'll get a boost in traffic.

The hero of ellieai.com in 🇺🇸 English

Preparing the translation files

The website is using Astro, a modern static-site generator that comes with a recommended i18n library, i18next.

With i18next you provide your translations in JSON files and replace everywhere on the page where there's text with a call to t(). For example the hero component translation becomes this:

{
  "hero": {
    "title": "Meet Ellie, your AI email assistant",
    "description": "Ellie learns from your writing style and crafts replies as if they were written by you"
  }
}

And to insert the h1 title of the page I call t('hero.title') - quite straightforward.

Astro uses a simple templating language similar to jsx, so the component looks something like this:

<h1 class="hero-title">
  {t("hero.title")}
</h1>

So this is our only bit of manual work, pulling out all of the text on the page into JSON files - something I'm sure people will tell me I should have been doing from the start 😅, I will next time I promise (narrator: no he wont).

You can see the files here if you like reading JSON.

Writing the GPT-3 prompt

OpenAI has a model that's specifically for writing code, but that didn't work for me at all for this. I assume because what I'm asking the AI to do is mainly natural language it means the regular text model works much better.

A GPT-3 prompt is basically us attempting to twist the AI into writing what we want by inventing something that is likely to precede it.

So if you wanted the AI to write the word "dog" you might prompt it with "An animal that hates cats is called a...":

Super simple OpenAI prompt. The green text is the response from the AI.

I usually start my prompts off by telling the AI what it is and what it does. In this case:

You are a translator that creates JSON config files for the
internationalisation of websites.   

I then provide an example of what we're expecting it to do.

In this case I want to give it a JSON file, and have it output the same JSON file, but with the values translated into different languages:

Here is an example of a JSON configuration file for a website called ellieai.com, 
and the intended output when translated into French:

###
Input JSON config in English:
{
  "meta": {
     "description": "Sign up for Ellie - Your AI Email Assistant"
  },
  "hero": {
     "title": "Meet Ellie, your AI email assistant"
  }
}

Output JSON config in French: 
{
  "meta": {
     "description": "Inscrivez-vous à Ellie - Votre assistant de messagerie IA"
  },
  "hero": {
     "title": "Rencontrez Ellie, votre assistante de messagerie IA"
  }
}
###

I then give the final instruction, including the file to be translated. As an example here I'm using the feature blocks from the Ellie website:

Given the following language config:

{
  "context": {
    "title": "Ellie understands context",
    "content": "<0>Ellie takes context from the email thread to <1>craft intelligent replies</1>.</0><2>We promise you'll be blown away by Ellie's responses!</2>"
  },
  "tailor": {
    "title": "Tailor Ellie's reply",
    "content": "You can provide <0>extra context</0> to Ellie for the perfect reply for every email."
  },
  "multilingual": {
    "title": "Ellie is multilingual",
    "content": "Ellie will reply in <0>any language</0> to match the email being replied to."
  },
  "iterate": {
    "title": "Iterate on Ellie's replies",
    "content": "You can <0>revise Ellie's response</0> to something, to tweak exactly what you want Ellie to say."
  }
}


Write a JSON config in Spanish. It doesn't have to be a direct
translation, you should paraphrase if it would make more sense:

I added the last part because it has a tendency to do direct translations, which usually sound a bit weird. I'm sure there are a lot of small improvements that can be made like this.

You can test out the prompt on the OpenAI playground here, with the options I worked with.

Now we wait a few moments and the AI spits out the following...

{
  "context": {
    "title": "Ellie entiende el contexto",
    "content": "<0>Ellie toma el contexto del hilo de correo electrónico para <1>crear respuestas inteligentes</1>.</0><2>¡Te prometemos que quedarás impresionado por las respuestas de Ellie!</2>"
  },
  "tailor": {
    "title": "Ajusta la respuesta de Ellie",
    "content": "Puedes proporcionar <0>más contexto</0> a Ellie para la respuesta perfecta para cada correo electrónico. "
  },
  "multilingual": {
    "title": "Ellie es multilingüe",
    "content": "Ellie responderá en <0>cualquier idioma</0> para coincidir con el correo electrónico al que se responde. "
  },
  "iterate": {
    "title": "Itera en las respuestas de Ellie",
    "content": "Puedes <0>revisar la respuesta de Ellie</0> a algo, para ajustar exactamente lo que quieres que diga Ellie. "
  }
}

I can't vouch for the quality, as I don't speak Spanish very well. But my friends tell me it looks quite good! 😅 We were going for "good enough", so I'm pleased if we get anything that will help international customers find us, and we can iterate to improve later.

The full 🇪🇦 Spanish translation is here: https://ellieai.com/es/

Time to automate

This is clearly very simple to turn into a script as it's only 3 steps (now that I've done the hard work of pulling the English text into a JSON file).

  1. Read file, replace some variables
  2. Query OpenAI API
  3. Write file

So I wrote a small node script that does just that. You can find it here.

I call the script with the language I want to translate into as the argument, it reads all my English JSON files, sends them to OpenAI, and writes the outputs to the relevant language JSON files. It's quite specific to the folder structure of Astro, but should be easy to adapt if you want to try it out.

$ node create-i18n.js Russian ru
Generating locale files for Russian (ru)...
common.json...
downloads.json...
faq.json...
features.json...
pricing.json...
testimonials.json...
Done!
You can see the Russian output here: https://ellieai.com/ru/

Now I can create an entire translation of my website with a single command and a 5 minute wait. And it only costs a few cents.

Improvements & problems

Too direct

The translations obviously aren't as perfect as if you had a human translator do it. Usually I'm hearing that the language is either too formal, or sounds too much like a direct translation of English. Maybe there's a way to prompt that effect away with a better input. If you manage it then let me know in the HN thread!

Domain knowledge

The translations seem to do badly at website specific terms, for example using the Russian word “Дом” for the link to "Home", when in Russian that more specifically means "House". Probaby a better prompt would fix these.

Non-latin characters, accents, and genders

GPT-3 seems to forget to add accents to letters sometimes, or occassionally just skips a non-latin char and instead uses the English equivilent. I don't know why this happens! Could be related to the next problem - Token blowout.

Also it has a habit of misgendering words. For example I'm told that "email", a masculine word in French, is constantly misgendered by the AI.

Token blowout

I think some languages use more tokens in GPT-3 than others. For example when translating into Russian the AI would freak out that it was running out of tokens and start writing gibberish. Russian specifically seems to use a LOT of tokens.

Cutting the files up into smaller chunks and pushing them through one at a time seems to mostly solve this.

Nonsense Russian

SEO?

Another thought - maybe bad translations are penalized by search algorithms... I have no idea but it sounds like something that makes sense to happen.

Conclusion

As a shortcut for indie developers, or small companies who want to test the water trying to reach international customers, I think this makes sense as a first step.

Is it better to use Deepl? I've no idea, probably if you have the cash and time. Their translations are apparently better, but the service is more expensive. Converting into 6 different languages plus testing and retries cost me about $3 with OpenAI, so it's a cheap alternative to Deepl at the very least.

For some markets the formal translations could be a bit alienating, but it will work for us for the time being. Going forward if we reach these markets then we will hire translators - but at the very least we now have a bunch of JSON files for them to get started on.

Either way I hope this post gives you some ideas on how you can use GPT-3 for translations! If you enjoyed it then add a comment in the HN thread!

P.S. If you want to fix any of the translations then please raise a PR. I'll gift any merged with 1 month free Ellie subscription ❤️


Resources:

Special thanks to people who helped me with translations on this tweet plus help from my friends with Chinese & Russian (@comrade_pogaca), Spanish (@PolinaKocheva), French (@pierregillesl), and Dutch (@Erwin_AI, @mick_ver).