2

I have a REACTSjs application and am trying to solve a problem with localization.

I receive some text from the API in which there are some special characters marking the text that should be localized. Something like this:

This is a translated text: [labels.example]. Awesome!

I am using react-redux-localize to translate the keys so the result should look like this:

This is a translated text: <Translate id="labels.example" />. Awesome!

I tried solving this problem with renderHTML from react-render-html:

function localizeNames(text) {
    text = text.replace("[", "<Translate id=\"");
    text = text.replace("]", "\" />");
    return text;
}

and calling this function in my render function:

<div>{renderHTML(localizeNames(text))}</div>

but it throws an exception:

Warning: The tag <translate> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.

Can anybody help me with this use-case? I am quite new to javascript.

1
  • The warning message seems to contain small t whereas your expectation is Capital T. Can you confirm if that is right or it was a mistake in posting? Commented Mar 22, 2019 at 14:36

2 Answers 2

2

I assume that renderHTML from the react-render-html package does not instantiate React components from a text string and therefore turns the <Translate> tag into an invalid HTML element, which in turn gets detected by the React framework as unrecognized.

You need to roll your own function that transforms your API's response into React components. The following function uses a regular expression for finding your API's language tags and splitting the input text into an array of React-compatible text pieces and <Translate> component instances

// This is just to make this code snippet work
const Translate = () => 1;

function toReactTranslate(text) {
  let langTagRegex = /\[([\w\.]+)\]/g
  let result = [];
  let nextStart = 0;
  let tagMatch;
  
  do {
    tagMatch = langTagRegex.exec(text);

    if (tagMatch) {
      let id = tagMatch[1];
      let before = text.substring(nextStart, tagMatch.index);
      
      if (before) {
      	result.push(before);
      }
      
      // Add React Translate component to result
      result.push(<Translate id={id}/>);
      nextStart = tagMatch.index + tagMatch[0].length;
    }
  } while(tagMatch);
	
  if (nextStart) {
    let after = text.substr(nextStart);
    
    if (after) {
    	result.push(after);
    }
  }

  return result.length ? result : text;
}

let text = "This is a translated text: [labels.example]. Awesome!";
document.write(JSON.stringify(toReactTranslate(text)));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Sign up to request clarification or add additional context in comments.

1 Comment

To be honest, I was hoping for some more "automated" solution, but your code works great. Thank you :)
1
function localizeNames(text) {
    text = text.replace("[", "<Translate id=\"").replace("]", "\" />")
     return String(text)
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
}

5 Comments

I am already using react-redux-localize. The only problem is with dynamically generated text.
My bad i misunderstood your question, so in short you want to convert <Translate id="labels.example" /> to [labels.example] am i right here ?
The other way aroung... [labels.example] is the output and I need to render <Translate id="labels.example" /> in my react component
the problem is that is being treated as text and you want it as html try this replaces in your function in the end : .replace(/&/g, '&amp;') .replace(/"/g, '&quot;') .replace(/'/g, '&#39;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;');
Unfortunately, this still renders the result as text.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.