Placeholder avatar betomorrow
Developer Front-end
Jan 22, 2024·3 min
MobileWeb

BBCode-like styling in React and React Native

Cover of "Stylize text easily" article

Emphasizing parts of your text with a different style like bold or italic might be basic, but it is always cool to play with.

It brings fast understanding and ability to scan words that carry the most weight in your content. Pretty common, right?

React-Native default implementation

React-Native Text component uses the web paradigm to provide different styles. To render partially styled text, you have to nest Text components and define style for each parts. This way, the child component inherits his parent styles.

Let us see how it is done in React Native with the following example: “It is a tasty apple

Gestion du style react native
import React from "react";
import { Text, View } from "react-native";

const TextWithStyle = () => (
  <View>
    <Text>
      It is a <Text style={{ fontWeight: "bold" }}>tasty </Text>
      apple
    </Text>
  </View>
);

Pretty straightforward, right? If this solution suit you, you should keep it. The simpler, the better.

The Challenge of Internationalization

Surely life cannot be that simple, and your needs never fit perfectly with what you have. One of our problem with the first approach is internationalization (i18n). The emphasize parts placement depends on the user language, and it is nearly impossible to maintain each cases.

Going back to our previous example, in English, French and Japanese:

  • en-US: “It is a tasty apple”

  • fr-FR: “C’est une pomme délicieuse

  • ja-JP: “おいしいリンゴです”

For each emphasized words, we have to split the sentences in 3 parts, depending on its position: at start, at end, or in the middle.

You might come up with the following translation files :

Fichier de traduction
// en-US
{
  "apple": {
    "part1": "It is a ",
    "part2_Emphasize": "tasty ",
    "part3": "apple",
  },
}
// fr-FR
{ 
  "apple": {
    "part1": "C'est une pomme ",
    "part2_Emphasize": "délicieuse",
    "part3": "",
  },
}
// ja-JP
{
  "apple": {
    "part1": "",
    "part2_Emphasize": "おいしい",
    "part3": "リンゴです",
  },
}

And the component :

Composant texte stylisé I18n
import React from "react";
import { Text, View } from "react-native";

const TextWithStyle = () => (
  <View>
    <Text>
      <Text>{I18n.t("part1")}</Text>
      <Text style={{ fontWeight: "bold" }}>{I18n.t("part2_Emphasize")}</Text>
      <Text>{I18n.t("part3")}</Text>
    </Text>
  </View>
);

Some limits there :

  • With split sentences, wording keys lost their meaning

  • Having your translation file bigger for implementation details seems wrong

  • You might encounter language that need more complex sentences to express the emphasize part

  • You always put wrong spaces between parts

BBCode to the rescue

Remember the time of bulletin boards, when you wrote formatted content with BBCode markup language, ignoring everything about html/css?

Boards admin define specific square bracket tags that users can use, permitting to safely translate their content into beautiful formatted html.

I wanted to bring back this simplicity, provide a [b] tag that emphasize the enclosed words. This way, content writer could safely and easily format wordings without implementation knowledge.

So, I came up with these translation files, adding the emphasized part into enclosed tags :

Fichier de traduction avec BBCode
// en-US
{
  "apple": "It is a [b]tasty[/b] apple"
}
// fr-FR
{ 
  "apple": "C'est une pomme [b]délicieuse[/b]"
}
// ja-JP
{
  "apple": "[b]おいしい[/b]リンゴです"
}

And I wrote a package, called styled-tagged-text, that provide a StyledTaggedText components, which, given a StyleSheet, render as many nested Text components as needed to apply your styles. The key of the StyleSheet is used as the tag name, so you can wrap this component into a global RichText component with a commun style for all your application.

Composant texte stylisé I18n et BBCode
import { StyledTaggedText } from "@betomorrow/styled-tagged-text/native";
import React from "react";
import { StyleSheet, View } from "react-native";

const tagStyles = StyleSheet.create({
  b: {
    fontWeight: "bold",
  },
});

const TextWithStyles = () => {
  <View>
    <StyledTaggedText tagsStyle={tagStyles}>{I18n.t("apple")}</StyledTaggedText>
  </View>;
};

Styled-tagged-text

Installation guide, native and web example are available in the GitHub repository, alongside a CodeSandbox.

It is designed to be minimal, works on native and web projects, supports nested tags.

Conclusion

There are many ways to apply custom styles in your text but mixing it with internationalization bring difficulties in the implementation and complicate the translation file as well. Using styled-tagged-text, you provide an easy way to apply different styles inside your text, while keeping your translations clean.

  • No more split sentences, so you can distinguish emphasize part, directly in translation files.

  • Everyone can edit your wording and apply style while ignoring implementation details

  • It is available on React-Native and React as well, so we can share the same translation formats between platform.

Thank you for reading this article.