🌏 Pluto in different languages!

We want to make Julia and Pluto more accessible to a wider audience! Since 0.20.14 (August 2025), Pluto has a localization system, which means that the Pluto UI interface can be used in a different language, not just in English!


A screenshot of Pluto in Greek! Also notice that one piece of text in the middle (Enter cel code...) has not been localized yet, so it uses English as a fallback.

A new dropdown menu in the bottom-left (or bottom-right in Arabic, one day!) lets you pick the language. In a future release, we will also auto-detect the system language and use that as the default.

What this does not change

This does not change anything in Julia. For example, sqrt(-1) will still say “Domain Error”, regardless of the selected language. And you can still write code and Markdown in any language! This is only about the Pluto UI.

Example of error in Dutch


:glowing_star: Calling for contributions!

We need you! Do you speak a language other than English, and would you like to help make Pluto available to more people? Consider making a contribution by localizing Pluto to your language!

It’s a fun task, and your work will be appreciated by many users in years to come! Read the language contributors documentation here

17 Likes

Hi there,

A few weeks ago, I wrote an I18nPlugin for Genie. It’s designed to be more generic and flexible, and in the future, it might not be limited to Genie at all. One of its features is the ability to automatically translate TOML files (which I find better than JSON) using AI. The translation quality is quite good and it saves a lot of time.

Feel free to take a look at the code if you’re interested! It’s not published yet, but I’d be happy to share it with you. Maybe you might only be interested in the auto-translations and adopt the code for your usecase.

(locales/en/main.toml)

[main]
welcome = "Hello, {{name}}!"

Lookup in Julia:

julia> @t("main!welcome"; name="Pete")
"Welcome, Pete!"

Manually passing a dict:

julia> t("main!welcome"; 
         locale="en", translations=I18N.dict, name="Alice")
"Hello, Alice!"

But maybe this part of code can help you more if you adapt it to the localization tool you use.

using I18nPlugin.AutoTranslations

translate_locales!("locales"; 
    src="en", 
    targets=["es","de","fr"], 
    model="gpt-4.1-nano")

I will:

  1. Parse locales/en/*.toml (the “NEW” JSON)
  2. Parse existing locales/<lang>/*.toml (the “OLD” JSON)
  3. Send both to GPT with instructions like:

    “Keep every OLD value if the English text didn’t change. Otherwise translate the NEW JSON. Return only the merged JSON object.”

  4. Write back well-formed nested TOML for each target

This saves you super much time and if you have people working on it, they just have to review the toml files.

Here you will find another toml example. I choose toml because it allows you to write comments in it and is more readable and human editable.

[authentication.login]
title       = "Login"
prompt      = "Please authenticate in order to access the information."
username    = "Username"
password    = "Password"
button      = "Login"
# if you enable registration:
register_link = "Not registered yet? Register"
forgot_password = "Forgot password"
forgot_password_link = "Reset password"

[authentication.register]
title       = "Register"
prompt      = "Please fill in the form to create an account."
username    = "Username"
password    = "Password"
email       = "Email"
button      = "Register"
terms_heading = "Terms"
accept_terms = "Accept Terms"
sucess	    = "Registration successful"

[authentication.confirm]
heading        = "Confirmation Link Expired"
description    = "Your confirmation link is no longer valid. Enter your email to get a new one."
email_label    = "Email address"
resend_button  = "Resend Confirmation Email"

[authentication.success]
title       = "Success!"
message     = "You are now logged in!"
go_home     = "Go home"

[authentication.flash]
failed      = "Authentication failed!"
goodbye     = "Good bye!"

[authentication.forgot]
heading       = "Forgot your password?"
email_label   = "Enter your email address"
submit        = "Send me a reset link"
sent           = "If that account exists you’ll receive an email shortly."
not_found      = "No account found with that email."

[authentication.reset]
heading         = "Choose a new password"
invalid_token   = "Invalid or expired token"
password_label  = "New password"
submit          = "Update password"
success         = "Your password has been updated. Please log in."
expired_heading = "Reset Link Expired"
expired_description ="Sorry, your password reset link has expired. You can request a new one below."
resend_button = "Send New Reset Link"

[authentication.github_auth]
button  = "Sign in with GitHub"

[authentication.github_auth.callback]
error_invalid_state = "Invalid GitHub login response."

[authentication.github_auth.login]
logged_in       = "Logged in with GitHub"
account_linked  = "Your GitHub account has been linked."
account_created = "New account created via GitHub"

in the end maybe you can profit from auto-translations in some way…