Souradeep Nanda
Souradeep Nanda

Reputation: 3288

How to extract all string constants from HTML or JSX?

EDIT: I ended up making a babel plugin CLI tool myself called i18nize-react :D


I am trying to translate an existing react app from English to another language. All the string constants in the JSX are hard coded. Is there an easy way to extract all the string constants and dump them in a .json file?

Here is an example of what I am trying to do.

// Original js file
class Component1 extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      // ...
    }
  }

  render(){
    return(
      <div>
        Some Text
        <p>
          Some more text
          <a href="/some/route">
            Some link
          </a>
        </p>
      </div>
    )
  }
}

STRINGS.json

{
  "ENGLISH":{
    "TEXT1":"Some Text",
    "TEXT2":"Some more text",
    "TEXT3":"Some link"
  },
  "OTHER_LANGUAGE":{
    "TEXT1":"asfsadfasfd",
    "TEXT2":"sadfsfd",
    "TEXT3":"sdfsdfsfdfd"
  }
}

New component

// After the strings are extracted
import STRINGS from strings.json

class Component1 extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      // ...
    }
  }

  render(){
    return(
      <div>
        {STRINGS[this.props.language].TEXT1}
        <p>
          {STRINGS[this.props.language].TEXT2}
          <a href="/some/route">
            {STRINGS[this.props.language].TEXT3}
          </a>
        </p>
      </div>
    )
  }
}

Upvotes: 4

Views: 3950

Answers (1)

intentionally-left-nil
intentionally-left-nil

Reputation: 8304

You're going to want to use a javascript abstract syntax tree parser. A popular one is acorn, another one is espree. If you're using acorn, you'll want the acorn-jsx plugin

Here's an example that spits out the JSON files you want (although it does it for every function. If you wanted to be more specific, you could scope it to the render function):

const fs = require('fs');
const acorn = require('acorn-jsx-walk');
const walk = acorn.default;
const { MethodDefinition, Literal } = acorn.base;

const file = fs.readFileSync('./file.js', 'utf8');

const strings = [];

walk(file, {
  Literal({ value }) {
    strings.push(value.trim());
  }
});

const ENGLISH = strings.reduce((acc, item, i) => {
  acc[`TEXT${i+1}`] = item;
  return acc;
}, {});

console.log(JSON.stringify({ ENGLISH }, null, 2));

returns:

{
  "ENGLISH": {
    "TEXT1": "Some Text",
    "TEXT2": "Some more text",
    "TEXT3": "Some link",
    "TEXT4": "",
    "TEXT5": ""
  }
}

Creating a new javascript file is more complicated, but it would involve adding logic around the AST and then re-generating the javascript file from it. (It's probably worth a separate question once you pick the tools you're going to use)

Upvotes: 2

Related Questions