Reputation: 1372
I'm using i18n single file component to have translation support on my application. To do so, I'm using the tag as following
<i18n>
{
"fr": {
"text": "blabla in french
blabla
bla"
},
"en": {
"text": "blabla in english
bla"
}
}
</i18n>
But I have multiple lines text with html formating, how can I use language handling for long html text ?
Upvotes: 17
Views: 22616
Reputation: 943
Question is asking to solve it from the json. to do it in this way is the v-html must be used in the .vue file, ex. paragraph.vue:
<div v-html="$t('translatable_text')" />
now the json language filesare able to use the key with html format, ex. en.json:
{
"translatable_text": "<h1>Title<h1> <p>Some text <br> and breaklines <br> to make it view <br> like a paragraph.<p>"
}
Upvotes: 0
Reputation: 11
I am using Vue 2.x
, and Vuetify
If you use v-card-text
to render it, You can simply use a class: text-pre-wrap
<v-card-text v-show="!!message" class="text-pre-wrap">
{{ message }}
</v-card-text>
Now this message can contain new line \n
and it will split into new lines
Upvotes: 0
Reputation: 11
None of the "common" solutions to the problem work well for me:
That being said, I don't think there is a perfect solution to the problem and maybe this is where the vue-i18n can be improved. But for my use case I found a pretty good solution: I created a custom wrapper around component, that allows me to:
I18nCustom.vue:
<template>
<div>
<i18n
v-bind="$attrs"
v-on="$listeners"
:class="paragraphClass"
v-for="idx in (Array.isArray(paragraphs) ? paragraphs : [paragraphs]).length"
:key="`${path}.${idx - 1}`"
:path="Array.isArray(paragraphs) ? `${path}.${idx - 1}` : path"
>
<template v-for="(_, name) in $slots" v-slot:[name]>
<slot :name="name"/>
</template>
<template #br>
<br>
</template>
</i18n>
</div>
</template>
<script>
export default {
data: () => ({
paragraphs: null
}),
props: {
path: {
type: String,
required: true
},
paragraphClass: {
type: String,
default: ''
},
},
mounted() {
this.paragraphs = this.$t(this.path)
}
};
</script>
How to use it: You can use the wrapper in the same way you would you the element: all the props and slots are supported
en.json
{
"paragraphsNewLine": "line1{br}line2{br}line3{slot-example}{br}",
"slotExample": "slot",
"styledParagraphs": [
"paragraph1",
"paragraph2",
"paragraph3"
],
}
In the components:
<!-- new line example -->
new line example:
<i18n-custom
tag="p"
path="paragraphsNewLine"
>
<template #slot-example>
<b>
{{ $t('slotExample') }}
</b>
</template>
</i18n-custom>
<!-- styled paragraphs example -->
styled paragraphs example:
<i18n-custom
tag="p"
path="styledParagraphs"
paragraph-class="mb-3"
/>
The results: the results
Upvotes: 1
Reputation: 5508
#1. You can use backticks:
i18n file:
{
text: `Content
With some
Break lines`
}
#2. You can use combination of js and css
{
text: 'Content \n With some \n Break lines'
}
css:
.class {
white-space: pre-line
}
#3. You can use HTML and v-html (but becareful because without sanitizing your HTML you lead to XSS attacks!)
{
text: 'Content <br /> With some <br /> Break lines'
}
template:
<div v-html="yourI18nRule" />
Learn more about sanitizing HTML here:
https://www.npmjs.com/package/sanitize-html
Upvotes: 20
Reputation: 12974
You can set-up a placeholder and use it more than once in your translation. In this exmmple I'm using {br}, and I also have a placeholder for an email address.
Body:
"Email was sent to {EmailAddress}{br}{br}Please enter the validation code below.{br}{br}If you have not received this email, please check your spam folder.",
And then in the vue component I put this
<i18n-t tag="h3" keypath="Body">
<template v-slot:br><br /></template>
<template v-slot:EmailAddress> [email protected] </template>
</i18n-t>
Upvotes: 2
Reputation: 11
Have your tried yaml format? You only have to install 'yaml-loader' and modify your vue.config.js file as described in the documentation. Then, you can do something like that:
<i18n>
fr:
text: |
blabla in french
blabla
bla
en:
text: |
blabla in english
bla
</i18n>
Upvotes: 1
Reputation: 392
Found a pretty cool solution here.
It is possible to achieve this with Interpolation. In this example, the {0}
placeholder will be replaced with what you put into the <i18n>
tag.
en.json
{
"footer": "Built with Vue and Vue I18n{0}Powered by an excessive amount of coffee"
}
Footer.vue
<template>
<i18n path="footer" tag="p" class="footer">
<br />
</i18n>
</template>
Upvotes: 11
Reputation: 763
You could always use backticks:
<i18n>
{
"fr": {
"text": `blabla in french
blabla
bla`
},
"en": {
"text": `blabla in english
bla`
}
}
</i18n>
You will get some (harmless) warning about something concerning POJO strings though.
Upvotes: 7
Reputation: 293
<i18n>
{
"fr": {
"text": "blabla in french <br /> blabla <br /> bla"
},
"en": {
"text": "blabla in english <br /> bla"
}
}
</i18n>
<span v-html="$t('text')"></span>
Upvotes: 4