-
Notifications
You must be signed in to change notification settings - Fork 56
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
Translation of HTML context (e.g. paragraph with links inside) #48
Comments
Hi @infinite-dao, I have seen this functionality in vue-i18n and think it is an important use case. Unfortunately, vuex-i18n does currently not support this. In my opinion, the solution of vue-i18n might also have some room for improvement. For now, we are using the locale detection with $i18n.locale() and render different components based on the respective locale. |
One quick work around I could find was to use en: {
info: 'You can {action} until {limit} minutes from departure.',
change: 'change your flight'
} … can be coded as: <p v-html="$t(
'info', {
'action': 'html composed string',
'limit': 'html composed string'
})">
</p> |
Bump! This is a must have feature for us. |
I will try to look into this sometime during the next two weeks. |
bump on that. I need to translate a text with an inside, like this
currently it doesnt even render the translate output and outs $t( in the html |
Hi everyone, I will look into this again as I am preparing a presentation of the vuex-i18n library for a vue meet up in Switzerland in November. It will probably boil down to using a custom component that will take component functions as props. |
Bump, same here, thanks! |
You can use
|
an issue on the i18next-node repository points at a similar problem (albeit from another point of view, and at a lower level). the idea is to add a markdown plugin (though you can also write your own), so you wouldn't have to parse HTML (it's not a regular language!), but only markdown. the template output would still be HTML, after the i18next post-processor had done its job. any thoughts? @tikiatua @infinite-dao @acidic9 @mnedoszytko @awakash @dcshiman |
@dcshiman, note that the |
Hi @eliranmal Thank you for your input. I am finally getting around to tackle some of the harder problems with this library. Interpolation of html and components is definitely on the list. I was thinking that interpolation could be achieved on an opt-in basis. Where the developer defines, which tags are allowed to be used for interpolation and all others are automatically stripped (with a warning in debug mode). This could probably look something like this <div>
{{ $t(
'lookupIdentifierForMessage', {
// components to make available in the translation
components: {
// strings can be used to interpolate html elements
title: 'h1',
// custom components can be used with a different tag
bold: MyBoldComponent,
// or with the default tag, i.e. <blinking>..</blinking>
Blinking
},
// data to make available in the translation
data: {
what: 'something like this'
}
) }}
</div> And in the translation, one would be allowed to use only the specified tags. const translations = {
'lookupIdentifierForMessage': '<title>this is important</title>\nWe should <bold>not</bold>forget the security implications of <blinking>{what}</blinking>!'
} |
@tikiatua, thanx, it's great to hear that you're on it! the imperative API is well done - it's both very expressive and flexible. IMHO, introducing markup inside translation values would unnecessarily complicate the code, as it will include new responsibilities to bare (sanitizing the HTML). $t(
'lookupIdentifierForMessage', {
plugins: {
beforeRender(translation) {
// a chance to use an external library for keeping all the XSS shenanigans out
return HtmlCleaner.sanitize(translation);
}
},
// ...
}
) or maybe just incorporate the above implementation (a general sanitizing library) into vuex-i18n, as long as only placeholders are used, not tags. i hope that makes sense in the context of this issue; i'm not very familiar with vuex-i18n, and i only swept through the code. |
Good point. My idea was, that element attributes would be limited to props of the respective components. In addition, we would not actually evaluate the html, but parse the content and build a custom render function to create the respective virtual dom. Something like this: message: '<h1>This is my <blinking cadence="10">title</blinking></h1>'
// is complied to
render: function(createElement){
return createElement('h1', [
"This is my",
createElement(MyBlinkingComponent, {
props: { cadence: 10 }
}, "title" )
])
} |
@tikiatua, that sounds like a great idea - if we don't evaluate any markup, we lower the risk of injections. also, if the code eventually prepares a the added complexity is presumably still there - we'd have to keep so the parsing and keep a whitelist of tags, but if all attributes are just derived from the component's by the way - it's worth investigating how does vue itself interprets templates to generate imperative instructions for building the virtual dom - you may be able reuse that code for your purposes (will probably be found in some auxilary code, like vue-template-loader?). |
I liked how @Gvade's solution worked, but it wasn't very practical for doing simple things like bolding a word in a sentence. I expanded on it by having it check if the translation key + '__html' exists in the JSON translation file and then compiling it as HTML instead of text, but otherwise working the same way. The only caveat is you can't use slot arguments in attributes, but regular arguments work. Gist of the component can be found here Note that I have my translation files grouped by modules so there are a few extra component props to handle that. There is also a whitelist of elements and attributes at the top as well as a way to specify what vuex-i18n identifiers you want to use. (Currently '{{' and '}}') |
Hi,
by default all HTML in a translation key is rendered as string and no possibility is given to render also translated HTML within a translation key. Right? How is it possible to capacitate the package and having something like the component interpolation of
<i18n>
in vue-i18n? So the code would look like:… that renders to something like this:
Or more advanced to put HTML to named target-“places” in the parent translation context:
… coded as:
… renders to:
What can I code to get this functionality? Or how can one implement this?
Or is there another work around to come to this?
The text was updated successfully, but these errors were encountered: