Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the i18n documentation #740

Merged
merged 2 commits into from
Sep 6, 2023
Merged

Update the i18n documentation #740

merged 2 commits into from
Sep 6, 2023

Conversation

lslezak
Copy link
Contributor

@lslezak lslezak commented Sep 6, 2023

Just adding more content to the i18n documentation.

Note: switch to the rich diff to see the formatted text, that's better readable.

doc/i18n.md Outdated
```js
// do NOT use this! it is difficult to translate "enabled" and "not enabled"
// differently in the target language!
const msgNot = enabled ? "" : "not";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this example also not should be translated

@lslezak lslezak merged commit efee0b5 into master Sep 6, 2023
8 checks passed
@lslezak lslezak deleted the i18n_documentation branch September 6, 2023 15:14
Copy link
Contributor

@mvidner mvidner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was surprised by the string splitting technique

```js
// do NOT use this! it is difficult to translate the parts correctly
// so they build a nice text after merging
return <div>{_("User ")}<b>{user}</b>{_(" will be created")}</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this is wrong, but...

// TRANSLATORS: %s will be replaced by the user name
const [msg1, msg2] = _("User %s will be created").split("%s");
...
return <div>{msg1}<b>{user}</b>{msg2}</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... this is not much of an improvement to me. I think this is better:

const bold_user = <b>{user}</b>;
return <div>{ sprintf(_("User %s will be created"), bold_user)}</div>

or am I missing a catch related to differences between JSX and strings, <b>foo</b> and "<b>foo</b>"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does not work, that bold_user constant is not a string, it is an object. This would be rendered as:

User [object Object] will be created

To avoid code injection React by default escapes all inserted texts so you cannot use HTML tags in translations:

{sprintf(_("User <b>%s</b> will be created"), "USER")}

is rendered as User &lt;b&gt;USER&lt;/b&gt; will be created HTML so the user will see:

User <b>USER</b> will be created

There is a way to inject unescaped text but it is insecure and not recommended: https://legacy.reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah so what I was missing is: in React you cannot make HTML from strings, only from React objects

const [msgStart, msgLink, msgEnd] = _("An error occurred. \
Check the [details] for more information.").split(/[[\]]/);
...
return <p>{msgStart}<a>{msgLink}</a>{msgEnd}</p>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK here it makes more sense, especially if <a> gets some attributes that we don't want the translator to touch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants