webpack-contrib / i18n-webpack-plugin

[DEPRECATED] Embed localization into your bundle
MIT License
318 stars 74 forks source link

How do I do I18n in REACT #26

Closed adithyan closed 7 years ago

adithyan commented 7 years ago

Let's say I have a component such as below, I would like to translate the message "click here to test".

How do I achieve it?

(<span><a href="/test">Click here</a> to test</span>)

Thanks in advance

aikar commented 7 years ago

<span><a ....>{__('Click Here')}</a> {__('to test')}</span>

adithyan commented 7 years ago

For I18n, you can't break up a sentence.

Because while translating to other languages it may change the context.

Here is an example

English - > Click here to test French - > Cliquez ici pour tester

English - > Click here French - > Cliquez ici

English - > to test French -> tester

aikar commented 7 years ago

That is a fair point we are also running into.

oreqizer commented 7 years ago
<span
  dangerouslySetInnerHTML={{ __innerHTML: __('<a href="/test">Click here</a> to test') }}
/>

since you are relying on your translations being safe (no script tags etc) anyway, you can use dangerouslySetInnerHTML as shown above

aikar commented 7 years ago

Our solution was this:

import React from "react";
import {AllHtmlEntities as entities} from "html-entities";

export default class UnescapedString extends React.PureComponent {
    static propTypes = {
        children: React.PropTypes.string.isRequired
    };

    render() {
        let el = this.props.children;
        for (const [key, value] of Object.entries(this.props)) {
            if (key === "children") {
                continue;
            }
            if (typeof value !== "string") {
                console.error("Property value", key, "must be a string, it is:", typeof value, value);
                continue;
            }
            const val = entities.encode(value);
            el = el.replace(new RegExp(`{${key}}`), val);
            el = el.replace(new RegExp(`{link:${key}:?(.*?)?}(.*?){/link}`), `<a href="${val}" title="$1">$2</a>`);
        }
        return <span // eslint-disable-next-line
                dangerouslySetInnerHTML={{__html: el}} />;
    }
}

Then use like:

<UnescapedString name="Daniel" google='https://google.com'>{__('Hello <b>{name}</b>, Try this {link:google:Title Text}Link Text{/link}')}</UnescapedString>

This keeps the link details out of the i18n string, making it easier on the translators, and allows passing dynamic input to the string that's still 'safe'.

It has been perfect for solving this problem.

aikar commented 7 years ago

@michael-ciniawsky why was this closed? WE only have workarounds. A proper solution for this is still needed.

joshwiens commented 7 years ago

If there is a bug in this somewhere, an issue needs to be created with a specific, reproducible problem.

Issues aren't the place for framework specific implementation questions, thus this issue has been closed.

aikar commented 7 years ago

@d3viant0ne The situation is that there is a fundamental missing concept of this plugin to handle a critical aspect of I18N.

We are looking for the project maintainers to understand this problem, and brainstorm ideas to solve it, with community feedback.

The problem is we need this:

Hello, Visit <a href={url}>this link.</a>

to become a single entry in the language table.

That is the "bug", that it's not possible to do this currently.

Sure the OP worded it as a question, but the question exposes the bug.

Would you prefer I open a new ticket with this description in the OP?

michael-ciniawsky commented 7 years ago

@aikar Yep, please open a new issue which describes the problem in more detail, sry I thought this was resolved by your comments :)