ttag-org / ttag

:orange_book: simple approach for javascript localization
https://ttag.js.org/
MIT License
345 stars 43 forks source link

How to interpolate JSX? #177

Closed dimaqq closed 5 years ago

dimaqq commented 5 years ago

Kinda related to https://github.com/ttag-org/ttag/issues/93,

How do I localise:

  1. User %s not found where %s is meant to expand to <span>xxx</span>, or
  2. Please <a href="...">continue</a> to blah blah?

I was thinking that for 1. t could perhaps return a fragment? For 2. I can't even think of a good syntax to express that both please and continue are to be translated...

dimaqq commented 5 years ago

I just found https://github.com/ttag-org/ttag/issues/166 which talks about jt formatter :) Perhaps it just needs to be prominently documented :)

AlexMost commented 5 years ago

Hi, @dimaqq! For now, you can use jt :

  1. const userName = <span>xxx</span>
    jt`User ${ username } not found`
  2. const continueLink = <a href="">{t`continue`}</a>;
    jt`${continueLink} to blah blah`

Does it work for you?

benmonro commented 5 years ago

@AlexMost

it would be nice if we could inline jsx in a jt or some other tag. a pretty common use case we have here at Walmart is <div><strong>oh no</strong>you did something wrong!</div>

I'm aware of the example you have above but was hoping there was a way to do this without having to extract the strong out of the JSX.

<div>{jt`<strong>oh no</strong> you did something wrong`}</div>

any thoughts on this? I can do a PR if you have thoughts on if this is feasible. lingui has this ability with <Trans><strong>oh no</strong> you did something wrong</Trans> what do you think of that approach? would a <TTag> JSX component make sense to more easily support this syntax?

as you can imagine the jsx might be part of a much bigger JSX, so having to move a simple 'strong' up out of the JSX it lives in could make things a bit harder to read.

thx in advance!

AlexMost commented 5 years ago

Hi @benmonro! That issue was discussed earlier - https://github.com/ttag-org/ttag/issues/95

So, for now you have an option to extract and use this with --numberedExpressions=true option:

<div>{jt`${ <strong>${ jt`oh no` }</strong>} you did something wrong`}</div>
ttag update --numberedExpressions=true your.po index.jsx

Does it work for you?

benmonro commented 5 years ago

@AlexMost unfortunately not. The "oh no" doesn't get put into the .PO file and frankly it adds a lot of syntax. In that other thread there was a suggestion for a custom component for cases like this. I'd be happy to open a PR of you would be ok with a syntax like: <T><strong>oh no</strong> something went wrong</T>

Thoughts?

dimaqq commented 5 years ago

My 2c:

markup in translations is a complex problem

Today you might have <T><strong>Please</strong>do</T>.

Tomorrow you'll have:

const Strong = styled.span`...`;
... return <T><Strong>Please</Strong>don't</T>;

and what then?

simpler use cases

I often find myself writing stuff like <label htmlFor=...>{tUsername}</label>... and I wish there was some way to make that less verbose, somehow automatic.

At the same time, if it were fully automatic, what would be the boundaries for translatable text or atoms of translatable text in <a>foo<b>bar<c>baz</c></b>quux></a>?

Wrt. syntax, the ES6 template literals are probably the most powerful mechanism there is, as nesting, expressions, etc are all allowed. In fact the power is even a bit too much for ttag and only constants are allowed in the ${} substitution blocks, which IMO is a good choice. I feel that anything else would require own babel plugin that parses superset of JSX, that should probably be a separate project.

AlexMost commented 5 years ago

@dimaqq 100% agree. Markup is a code, that can be broken by translator. It would be difficult to support that code inside locale files. Also it can be used to inject some XSS. So, ttag was designed in a way to avoid these troubles.

@benmonro, we were investigating at this some time ago https://github.com/ttag-org/ttag/issues/3. And decided that if we want some kind of <Trans> components, it should be a separate plugin or ttag extension that is aware of React components ecosystem e.t.c. Currently, jt doesn't depend on the React, it just rendres list of strings instead of a string that makes it work for jsx. That makes ttag a lightweight library without including the React dependency. But, anyway If you will came up with a good idea how we can fix this, we will really appreciate your help!

AlexMost commented 5 years ago

@benmonro

The "oh no" doesn't get put into the .PO file

That seems like a bug, will create a ticket for that.