(Right to Left (The Mirror World


It might seem that there is something wrong with the title up there, right? This is one of the challenges developers are likely to face when adding support for languages like Arabic on websites. In this blog post, we talk about the problems we faced and the solutions we came up with when supporting Arabic on the Spotify desktop client and web player.

Localization at Spotify is a big deal. Our mission is to “unlock the potential of human creativity—by giving a million creative artists the opportunity to live off their art and billions of fans the opportunity to enjoy and be inspired by it.” To achieve this mission, it’s important to be able to effectively communicate across the various languages that reflects the diversity of our users . Recently Spotify launched in the North Africa and West Asia regions. One of the languages spoken in these regions is  Arabic. Unlike English, which is read from left to right, Arabic is read from right to left. This has implications for websites that want to support Arabic.

Post overview

  • Mirroring Layout
  • English Text in RTL Layout
  • Arabic Font
  • Maintaining High Quality
  • Useful Resources

We will use the following acronyms throughout the blog post

LTR: Left To Right — text that reads from left to right, like English or Spanish text.
RTL: Right To Left — text that reads from right to left, like Arabic text.

Mirroring Layout

In Arabic, It’s not only text that flows from right to left, but the entire page layout. For example, images that indicate direction need to be flipped. We encountered a few exceptions which will be covered later in the Icons section.

How the dir attribute works

To tell the browser the direction of text within an element the dir attribute should be used. To set the global direction of the page you set the dir attribute on the  element.

The dir attribute can have the following values:

  • ltr – Used for languages that are written from left to right (e.g. English, Swedish). This is the default value.
  • rtl – Used for languages that are written from right to left (e.g. Arabic, Hebrew, Persian)
  • auto – Used for dynamic content. The browser needs to decide the direction. It uses the Unicode Bidirectional Algorithm to parse the characters of the element and decide the direction. More about it can be found in “English Text in RTL Layout ” section.

CSS

Both CSS Flexbox and CSS Grid layouts look at the dir attribute to determine the direction of element. For example, flex-start will flip to go from the right automatically when the dir attribute is set to ”rtl”.

Having a dir attribute and using flexbox or grid might not be enough to mirror the entire UI for RTL. There are a lot of asymmetrical CSS properties that we need to watch out for when developing a website that supports both LTR and RTL. For example margin-left: 20px and text-align: right will have to flip and become margin-right: 20px and text-align: left in RTL.

There are a lot of tools available to automate that job for you. We decided to use PostCSS-RTL in our build step. PostCSS-RTL generates RTL rules with flipped properties.

.foo {
  margin-left: 15px;
  text-align: right;
  color: rebeccapurple;
}

CSS Input

[dir] .foo {
  color: rebeccapurple;
}

[dir="ltr"] .foo {
  margin-left: 15px;
  text-align: right;
}

[dir="rtl"] .foo {
  margin-right: 15px;
  text-align: left;
}

CSS Output

Icons

Icons and elements that have direction or relate to progress should be mirrored in RTL. For example, back and forward navigation buttons have to be reversed.

Back button in LTR
Back button in RTL (English text used instead of Arabic)

All directional animations need to be flipped as well. For example, carousels needs to slide in the other direction.

 

 

Exceptions

Initially, we assumed that everything needs to be mirrored. But quite quickly we learned that there are some exceptions. For instance, media playback buttons and the media progress bar do not require mirroring as they refer to the direction of tape being played. Arabic speaking users expect playback controls and progress bar to look the same as they would in a left-to-right language.

Now playing bar in LTR

English Text in RTL Layout

It’s not uncommon to have both LTR and RTL text mixed together on a single page. Spotify has over 40 million songs by artists from all over the world and more than 3 billion playlists. The content is comprised from many different languages and can be seen by users all over the world. It’s not uncommon to  encounter a mix of LTR and RTL content in the Spotify clients.

(Hello (World – punctuation and parentheses problem

One of the first problems we encountered looked like this:

Parentheses problem

This happens because the browser sets a base text direction from the value of the dir attribute on our element. Punctuation characters like ( ) . ! and more are non-directional in Unicode. They inherit the base text direction.

The Unicode Bidirectional Algorithm looks at each character in a string from right to left. Let’s take the string “Hello (World)” in a page that has  as an example.

  • The algorithm starts parsing the string from the right. It sees “)” which is a non-directional character so it looks at the base text direction and sees that it is right-to-left. The algorithm decides to put ”)” at the beginning of the string.
        “Hello (World)” -> “(Hello (World”
  • The algorithm sees “d” which is a left-directional character. It doesn’t need to reposition it. Same goes for the other English characters until “(“.
  • The algorithm sees “(“ which is a non-directional character. It remembers that the prevailing base direction (set by the previous character “W”) is left-to-right. The algorithm decides to not reposition “(“. Same goes for the space character, and all characters in “Hello”

Read more about how the Unicode Bidirectional Algorithm works here.

We end up with the string “(Hello (World”. The way we addressed this was to add overrides anywhere we had dynamic content like artist, album and song names. Setting the dir attribute on an element to “auto” isolates the content and sets the base direction according to the first strongly-typed directional character. In this case non-directional characters will always inherit direction from the characters surrounding them instead of the page. This results in the string “Hello (World)”. To make sure that your text is still aligned to the expected side use the attribute only on inline elements. Otherwise, you might need to add text-align CSS property to the element.

…ello World – truncation issues

Having mixed content is also challenging when you want to add truncation to text that does not fit in your element.

LTR UI – Arabic text truncated from the wrong side
RTL UI – English text truncated from the wrong side

Truncation on the wrong side happens because the browser sets text direction from the dir attribute. Setting the dir attribute to “auto” on the element containing the truncated text solves the issue.

LTR UI – Arabic text truncated on the correct side
RTL UI – English text truncated on the correct side

Arabic Font

When designing UI for different languages, it’s important to check if the design choices work for all alphabets. Here is a summary of things to look out for when adding Arabic to your website.

Letter spacing

Arabic is cursive. Most, if not all, of the characters in a word are connected together. For this reason, letter spacing should not be used in Arabic. It rips characters in a word apart, breaking the cursive nature of Arabic words.

Font size

Arabic characters tend to have more complex glyphs than English characters. There are more lines and nuances that have to fit in a similar space. That causes Arabic in the same font size as English to be less legible. The characters are too small. We decided to bump the minimum font-size from 11px to 12px in Arabic. We also made sure to use a font that keeps Arabic glyphs simple. A good choice is Google Noto which is more legible than the browsers’ default fallback font for Arabic, Arial.

Vertical cut-off

Some Arabic characters are taller than English characters. This can cause vertical cut-offs on the characters. Arabic might need increased line-height.

Vertical cut-off

Capitalization

Arabic does not have capital letters. Using capitalization to distinguish content on a page will not have any effect in Arabic.

Arabic commas

Many languages like German, Spanish and English use the comma separator (“,”) to separate items in lists. Arabic has a different comma separator (“،“).

We had a lot of places where we simply did array.join(‘, ‘). That had to change. We added a getSeparator() method to be able to support different separators depending on a user’s locale.

Numbers in Arabic

There are two numeral systems in Arabic

  • Western Arabic numerals: 0 1 2 3 4 5 6 7 8 9
  • Eastern Arabic numerals: ٩ ٨ ٧ ٦ ٥ ٤ ٣ ٢ ١ ٠

Decide to use one system consistently across the whole app. We picked Western Arabic numerals.

Transparency in text color

Glyphs in Arabic can overlap. Using transparency in text color doesn’t work as the overlapped parts don’t get the expected transparency. A solution to this issue is avoiding transparency in text color altogether. Instead, use an opaque color and set the opacity on the text element.

Transparency issue

Maintaining High Quality

These are some of the things we did to ensure quality while introducing Arabic:

  • Test sessions within the team
  • Beta test with native Arabic speaking employees
  • External agencies tested both the UI itself and the translations.

In order to keep the quality of the Arabic user experience high we needed some tools.

We decided to build a GitHub bot that comments inline on pull requests for things that match potential issues. The comment doesn’t enforce anything; it’s a reminder to check how the change looks in Arabic and has a link to instructions for how to test it. The bot comments on changed lines that match things like padding, letter-spacing, transform etc. CSS changes will be converted by PostCSS-RTL, so most often it’s enough to have a look at the change in Arabic and verify that it looks good. CSS properties can be set through JS and PostCSS-RTL does not convert JS. The bot will look at JS files too, so JS changes involving matching properties will get a comment from the bot reminding you to make sure to check Arabic.

tob-bot’s comment

— The Desktop and Web Player Teams.

Useful Resources

  1. Material Design – Bidirectionality: https://material.io/design/usability/bidirectionality.html
  2. Internationalization techniques: Authoring HTML & CSS: https://www.w3.org/International/techniques/authoring-html
  3. Authoring HTML: Handling Right-to-left Scripts: https://www.w3.org/TR/i18n-html-tech-bidi/
  4. Arabic & Persian Gap Analysis: https://w3c.github.io/alreq/gap-analysis/
  5. ECMAScript Internationalization API https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl