npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-from-text

v2.0.0

Published

Create React elements from a string containing markup and/or placeholders. Useful for creating nicely-structured translation strings.

Downloads

8

Readme

react-from-text

Create React elements from a string containing markup. Useful for creating nicely-structured translation strings containing HTML-like tags.

Background

You want to build a React app that is translated into multiple languages. To make the translations sound natural, you need to give the translators the flexibility to re-order placeholder items within the translated strings.

For example, suppose you want to include a variable, a link, and some bold text in a sentence to be translated. Ignoring translation requirements, it would be something like this:

function SomeComponent({ prize }) {
  return (
    <div>You will <b>win a {prize}</b> if you <a href="https://example.com/">Click Here</a>!</div>
  );
}

One way to handle this would be to break the text into several chunks and submit them separately to translators. In this case the chunks would be:

"You will"

"win a"

"if you"

"Click Here"

Breaking up the string forces translators to figure out a way to translate the chunks into a well-structured sentence, without changing the order of the chunks.

Example

A better way is to give the translators a full sentence, including markers for the HTML tags and the placeholder variable -- something like:

You will <b>win a %(prizeName)s</b> if you <link>Click Here</link>!

That's where this library comes in:

import fromText from 'react-from-text';
import gettext from '...';

function TranslatedComponent({ prize }) {
  // This example uses `gettext()` for the actual translation substitution,
  // but any function that returns a string works (or even a hard-coded string).
  return (
    <div>
      {
        fromText(
          gettext('You will <b>win a %(prizeName)s</b> if you <link>Click Here</link>!'),
          {
            prizeName: prize,
            b: <b/>,
            link: <a href="https://example.com/"/>,
          }
        )
      }
    </div>
  );
}

Also, as this example shows, the names of the tags don't have to actually match the name of the component that replaces it. You can use tag names that will be helpful to communicate the intent to the translators (such as "link" in this case, where a hypothetical translator might not know what an <a> tag represents.

API Reference

This package exports a function fromText() with the following signature:

function fromText(text, placeholders)
  • text (String): The text containing the tags and placeholder markers to replace
  • placeholders (Object): A map of placeholder names (from the text) to their replacements. These can take two different forms:
    • A tag (pair or self-closing) in the text is replaced by a React component with specified props
    • An interpolation placeholder in the text is replaced by a value, stringified. This library does not mandate a specific format for the interpolation placeholders in the text. It uses sprintf-js (installed separately as a peer dependency) to replace interpolation placeholders, so "named" sprintf-js placeholder style should be used:
      '%(name)s', '%(name)d', etc.

Credits/Acknowledgements

v1.0.0 (2020-06-11): For v1.0.0 the core was rewritten by Taylor Everding (@taylor1791) to use a cleaner AST-based parsing approach.

v0.1.0 The core of this package was originally a utility (format-message/react) in format-message, with initial work by @vanwagonet and contributions by Paul Robertson (me).

Since that time, format-message has implemented an alternative approach for supporting tags in translation strings, and has deprecated the format-message/react utility. However, the alternative approach is specific to the ICU MessageFormat syntax for translations. In my case I wasn't using format-message with ICU MessageFormat -- I was just using the utility to replace tags in strings with React components -- so it made sense to extract it into its own package. I had also made some React-specific improvements within a private codebase (for example, allowing the same tag name to be used multiple times in a translation string). Those improvements are also included in this package.

My work (and Taylor's work) on this package was funded by my employer, HireVue, Inc. (@hirevue). It's a great place to work -- check us out!