i18n-webpack-plugin
i18n-webpack-plugin copied to clipboard
I18N for HTML fragments
per #26 It's almost guaranteed anyone doing a serious I18N roll out will run into a scenario like this:
Hello {user}, Please <a href={dial}>call</a> or <a href={mailto}>email</a> us for support
This plugin currently offers no native way to create this as a single i18n string for translation.
Breaking it up into
Hello
Please
call
or
email
us for support
Is not a valid solution as the order of the words are likely to change in other languages. This needs to be handled as a single string.
In React, I created a work around seen here: https://github.com/webpack-contrib/i18n-webpack-plugin/issues/26#issuecomment-286724094
But this required us to use the dangerous inner html of React and uglifies the code writing HTML inside of strings.
We need a solution for this problem so that this plugin can be a complete i18n solution (along with #6)
Proposal: JS comment tags? JSX example
const str =
/* @i18n */
<span>Hello {user}, Please <a href={dial}>call</a> or <a href={mailto}>email</a> us for support</span>
/* @i18n:start */;
Or maybe support:
__(<span>Hello {user}, Please <a href={dial}>call</a> or <a href={mailto}>email</a> us for support</span>)
Then of course no react environments would need consideration too.
Though, Solving this would also require this plugin to include an extractor too (which is a good idea overall), as other tools would not know how to extract it.
@aikar If you have time and interest to give it a shot please feel free to do so 😛
I have another idea to solve this without the necessary to modify the plugin.
We just need to implement a simple function say assembleAsArray
which turns this
assembleAsArray(__('Hello ${user}, Please ${call} or ${email} us for support'), {user: user, call : <a href={dial}>__('call')</a>, email: <a href={mailto}>__('email')</a>})
to an array ['Hello ', user, ', Please ', <a href={dial}>call</a>, ...]
.
And you can use it directly in React:
render() {
<div>
...
{assembleAsArray(__('Hello ${user}, Please ${call} or ${email} us for support'), {user: user, call : <a href={dial}>__('call')</a>, email: <a href={mailto}>__('email')</a>})}
...
</div>
}
If you are not using React and just want to assemble strings, you can use it as well: assembleAsArray(__('Hello ${user}, Please ${call} or ${email} us for support'), {user: user, call : `<a href={dial}>${__('call')}</a>`, email: `<a href={mailto}>${__('email')}</a>`}).join('')
This could be also be a solution to #26 and #6.
@xiao-hu In my understanding, your idea won't solve the problem, because assembleAsArray
has fixed the order of each part. But in some languages, order of each part might be different.
Actually your idea is the same as solution like the one below, which simply splits one sentence into multiple separate parts. (You can see this https://github.com/webpack-contrib/i18n-webpack-plugin/issues/26#issuecomment-280917200)
__('Hello ') + ${user} + __(', Please ')...
assembleAsArray
would not need to return an array with the same ordering as the input. For example:
Given this mapping:
Please call ${0} or email ${1} to contact us for more information
->
Pour plus de renseignements veuillez nous contacter par email au $[1} ou sur le ${0}
This code:
__asArray(`Please call ${<PhoneElement />} or email ${<EmailElement />} to contact us for more information`)
Should return:
[ "Pour plus de renseignements veuillez nous contacter par email au ", <EmailElement />, " ou sur le ", <PhoneElement /> ]