Easier internationalization (Part 1 of 3)

2024-07-06

A really important part of making a site or app accessible is to support more languages. There are many tools to handle internationalization (or i18n - that means: an "i" followed by 18 letters followed by an "n"): Rails has the I18n class, Phoenix uses gettext, for Heroic we use the i18next package and the Intl module, and other frameworks have other solutions.

This article is not going to focus on those tools though... All of them provide methods and functions for translation and localization, but there's a lot more than translating words when dealing with multiple languages.

During this series, I'll use examples of Heroic's code but most of these ideas can be applied anywhere.

Text direction

Not all languages are written from left to right (like this blog), there are languages like Hebrew, Arabic, or Persian, that are written in the opposite direction. There's also languages like Traditional Chinese, Traditional Japanese, or Korena that are written vertically!

But wait! there's more! There are some ancient scripts that used the Boustrophedon writing style: it switched back and forth with one line written from left to right, the next from right to left (with mirrored characters), then again from left to right, and so on.

But don't worry! Don't freak out! The chances of an Etruscan using your app is probably zero.

CSS's direction Property

The initial value of this property is ltr so we usually don't think about it when building a site in English, but it also supports the rtl value that impacts how some elements are rendered by the browser.

by Ariel Juod (@arieljuod) on CodePen.

See the Pen LTR vs RTL direction

The list could go on and on, but what's important to know is that most HTML elements already know how to render the content with the correct direction so we should always set this (we could do that in the body element for example, and the children will inherit it).

What I like to do is:

  1. If the rendered language is a RTL language, add an isRTL class to the body element (or any wrapper element like #root in a React app)
  2. Add a this CSS:
    body.isRTL {
      direction: rtl;
    }

And that's it! a lot of your content will be way more user-friendly (though still far from perfect).

This also gives you a simple selector to tweak the CSS when the direction or position is not handled automatically.

Check these examples in Heroic's source code:

HTML's dir Attribute

The dir property is similar to the direction CSS property with using the ltr or rtl value (it's not the same though, there are more details in the MDN docs for both properties).

But there's a third possible value: auto. It tells the browser to infer the direction based on the content of the element! So, if the content has (for example) one Arabic character, the browser will consider that the element should be rendered from right to left.

What About "Top to Bottom"?

I don't have experience handling this, but guess what? CSS can do that too! There's another property called writing-mode that can handle different combinations.

When dealing with these languages, the layout of the pages tend to change A LOT compared to horizontal ones. In these cases you'll probably need to do more changes than just CSS properties.

If you really need to support this, I recommend this article that explains most of the challenges.

What's next?

For RTL languages, the expectation is not only for the text to start from the right, the layout has to be mirrored too! For example: Heroic has a sidebar menu on the left side of the app, but, when a RTL language is selected, we render it on the right side of the screen instead.

In the text article I'll talk about how to manage the layout changes and about using logical CSS properties.