DEV Community

Kinga
Kinga

Posted on

Rendering localized JSX in React Components

Imagine the following scenario:

  • you are localizing your solution
  • the messages should include variables provided at runtime
  • some messages need to be rendered as HTML

The first two requirements are quite simple, but rendering HTML embedded in JSX component is not, because by default, React DOM escapes any values embedded in JSX before rendering them.
Luckily, there's also a way to natively embed HTML in a React component using dangerouslySetInnerHTML.

myStrings.d.ts
declare interface ICustomStrings {
  LocalizedString_Variable:string;
  LocalizedString_HTML:string;
}
declare module 'CustomStrings' {
  const strings: ICustomStrings ;
  export = strings;
}
Enter fullscreen mode Exit fullscreen mode
en-us.js
define([], function() {
  return {
  "LocalizedString_Variable":"Copying {0} item(s) to {1}...",
  "LocalizedString_HTML":"<Label >If needed, you will find the deleted items in the</Label> <a href='{0}' target='_blank' underline >Recycle Bin</a>"
  }
});
Enter fullscreen mode Exit fullscreen mode

Here we simply insert some variables into the LocalizedString_Variable string.

ReactComponent1.tsx
import { format } from '@fluentui/utilities';
import * as strings from 'CustomStrings';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
...

export default function CopyItemsForm1(props: ICopyItemsFormProps) {
    const [spinnerTxt, setSpinnerTxt] = React.useState<string>(strings.Spinner_PleaseWait);

    async function handleSubmit(): Promise<void> { 
        setSpinnerTxt(format(strings.Spinner_Coyping, props.selectedRows.length, props.targetListName));
    }
    ...
    return <>

        <Spinner size={SpinnerSize.large} label={spinnerTxt} ariaLive="assertive" />
    </>;
}

Enter fullscreen mode Exit fullscreen mode

And here we make sure that the HTML is not escaped by the React DOM:

ReactComponent2.tsx
import { format } from '@fluentui/utilities';
import * as strings from 'CustomStrings';
import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar';
...
export default function CopyItemsForm2(props: ICopyItemsFormProps) {
    ...
    return <>
        <MessageBar messageBarType={MessageBarType.warning} isMultiline={true} >
        {
            <div dangerouslySetInnerHTML={{ __html: format(strings.LocalizedString_HTML, recycleBinUrl) }} ></div>
        }
        </MessageBar>
    </>;
}

Enter fullscreen mode Exit fullscreen mode

Y, voilà!
I know it's a bit RTFM situation, but maybe it will help someone =)

Top comments (0)