vue-i18n use more than one word to translate - vue.js

Maybe the title isn't to clear so let me explain a little bit.I am using vue-i18n with Laravel and succesfully generated translation files too.But in my translation file I used more that one word to translate. a snap of my messages
messages:{
"Your email"="Your email",
"Email"=>"Email"
}
Same with other language like thai language.
Inside of vue template when I use
{{ $t('messages.Email')}}
Translation works but when i use
{{ $t('messages.Your email')}}
It shows messages.Your email
Can anyone help me to use two or more word translation??
N.B: this works in Laravel blade though
{{ trans('messages.Your email') }}

You can access those properties with the usual bracket syntax.
Example in plain JS:
const object = { 'my key': 'ABC' }
object.my key //Syntax error
object['my key'] //ABC
In your case with vue-i18n:
{{ $t("messages['Your email']")}}

Related

Dynamic Value in Translation

What I am looking to do is have a some way to have a placeholder in my translations file that on runtime when called I can pass in what i18next should replace that placeholder with and I am unable to find documentation on this.
// translations
{
“label”: “Message has {{count}} total messages”
“person”: “Welcome {{full_name}} to your new site”
}
In the component I am using it I have the following
<button aria-label={t(‘label’, { count: total_count})}>
<svg></svg>
</button>
But this is not working. Am I missing something? Thanks
What you are looking for is called interpolation.
Check out this: https://www.i18next.com/translation-function/interpolation

$te method doesn't find existing key if it contains spaces

I have already made a [issue][1] on the official vue-i18n page, but solving this issue would really help me out thats why I'm asking here too.
I'm using the translation key directly as the english translation so some translation keys look like this 'Next':'Weiter' and others contain spaces or even full sentences: 'This text is translated.':'Dieser Text ist übersetzt.'.
So to prevent a million warnings about the missing english translations I want to check for the key first(this.$te('key')) but this doesn't seem to work when the key contains spaces. It returns false even if the translation key is there and the translation is working.
Does someone know a solution to this or do I have to wait until someone addresses my issue on the github page/fixes it on the package itself?
Edit: The problem is fixed in the latest version of vue-i18n. My other problem still stands though. The missing handler option doesn't prevent the warning being thrown, so this doesn't work either.
I solved it by adding my own translation method on the vue instance:
Vue.prototype.$trans = function (key) {
return i18n.te(key) ? i18n.t(key) : key;
}
This way it only translates the key if it actually exists, but still will get complicated if I want to use pluralization etc. so its not a long term solution.
[1]: https://github.com/kazupon/vue-i18n/issues/1309
The problem you are describing indeed exists in a version 7.3.2 but that version is almost 4 years old and current version 8.24.5 works as expected - see example below
Also it seems to me that better way to avoid unneeded error messages would be to supply custom missing handler
var messages = {
en: {},
de: {
'Test translation': 'Test Übersetzung'
}
}
Vue.use(VueI18n)
var i18n = new VueI18n({
locale: 'de',
messages: messages
})
new Vue({
i18n: i18n
}).$mount('#app')
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/vue-i18n#8"></script>
<!-- <script src="https://unpkg.com/vue-i18n#7.3.2/dist/vue-i18n.js"></script> -->
<div id="app">
<p>de (implicit): {{ $te("Test translation") }}</p>
<p>de: {{ $te("Test translation", 'de') }}</p>
<p>en: {{ $te("Test translation", 'en') }}</p>
</div>

How to get in script tag of vue file of / pages / when using Nuxt.js and nuxt-i18n

https://qiita.com/munieru_jp/items/d7e9f98b5ab5960e7a93
If you do as above, you can get the contents of {{$ t ('HELLO_WORLD')}} in the <template> tag.
How can I get {{$ t ('HELLO_WORLD')}} in the <script> tag in the same file?
The reason is that I want to manage title descriptions and og related items with head.
We apologize for the inconvenience, but we would appreciate it if you could teach us.
Then thank you.
You have access to the nuxt-i18n translation helper in the script of your page with this.$t and the head method on the other hand has access to the this context.
So you could do something like this:
export default {
head () {
return {
title: this.$t('HELLO_WORLD')
}
}
}
Use the head method to set the HTML Head tags for the current page.
https://nuxtjs.org/api/pages-head/

Event handling after HTML injection with Vue.js

Vue is not registering event handler for HTML injected objects. How do I do this manually or what is a better way to work around my problem?
Specifically, I send a query to my server to find a token in text and return the context (surrounding text) of that token as it exists in unstructured natural language. The server also goes through the context and finds a list of those words that also happen to be in my token set.
When I render to my page I want all of these found tokens in the list to be clickable so that I can send the text of that token as a new search query. The big problem I am having is my issue does not conform to a template. The clickable text varies in number and positioning.
An example of what I am talking about is that my return may look like:
{
"context": "When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected",
"chunks": ['human events', 'one people', 'political bands']
}
And the resulting output I am looking for is the sentence looks something like this in psuedocode:
When in the Course of <a #click='search("human events")'>human events</a>, it becomes necessary for <a #click='search("one people")'>one people</a> to dissolve the <a #click='search("political bands")'>political bands</a> which have connected
This is what I have tried so far though the click handler is not registered and the function never gets called:
<v-flex xs10 v-html="addlink(context.context, context.chunks)"></v-flex>
and in my methods section:
addlink: function(words, matchterms){
for(var index in matchterms){
var regquery = matchterms[index].replace(this.regEscape, '\\$&');
var query = matchterms[index];
var regEx = new RegExp(regquery, "ig");
words = words.replace(regEx, '<a href=\'#\' v-on:click.prevent=\'doSearch("'+ query +'")\'>' + query + '</a>');
}
return words;
}
As I said, this does not work and I know why. This is just showing that because of the nature of the problem is seems like regex is the correct solution but that gets me into a v-html injection situation. Is there something I can do in Vue to register the event handlers or can some one tell me a better way to load this data so I keep my links inline with the sentence and make them functional as well?
I've already posted one answer but I've just realised that there's a totally different approach that might work depending on your circumstances.
You could use event delegation. So rather than putting click listeners on each <a> you could put a single listener on the wrapper element. Within the listener you could then check whether the clicked element was an <a> (using event.target) and act accordingly.
Here's one way you could approach it:
<template>
<div>
<template v-for="segment in textSegments">
<a v-if="segment.link" href="#" #click.prevent="search(segment.text)">
{{ segment.text }}
</a>
<template v-else>
{{ segment.text }}
</template>
</template>
</div>
</template>
<script>
export default {
data () {
return {
"context": "When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected",
"chunks": ['human events', 'one people', 'political bands']
}
},
computed: {
textSegments () {
const chunks = this.chunks
// This needs escaping correctly
const re = new RegExp('(' + chunks.join('|') + ')', 'gi')
// The filter removes empty strings
const segments = this.context.split(re).filter(text => text)
return segments.map(segment => {
return {
link: segment.match(re),
text: segment
}
})
}
},
methods: {
search (chunk) {
console.log(chunk)
}
}
}
</script>
I've parsed the context text into an array of segments that can then be handled cleanly using Vue's template syntax.
I've used a single RegExp and split, which will not discard matches if you wrap them in a capture group, (...).
Going back to your original example, v-html only supports native HTML, not Vue template syntax. So you can add events using onclick attributes but not #click or v-on:click. However, using onclick wouldn't provide easy access to your search method, which is scoped to your component.

Vue.js auto-convert HTML and Unicode entities

I'm building a simple book browsing app using the open Google Books API. The problem is that in the API response, there are quotes and unicode entities. Now, when rendering, Vue.js is converting the quotes to HTML entities, and while it's converting unicode back to text, it doesn't apply HTML tags where they should. Let me give you an example:
Pronunciation Guide for \u003cb\u003eElixir\u003c/b\u003e Aether: EE-ther Ananke: ah-NAN-key Agapi: ah-\u003cbr\u003e\nGAH-pee Apollyon: a-POL-ee-on Atropos: ah-TRO-poes Clothe: KL O-tho \u003cbr\u003e\nDaimon: DEE-mun Hematoi: HEM-a-toy Khalkotauroi: kal-koh-TOR-oy CHAPTER \u003cbr\u003e\n1 ALEX ...
The text above (from the raw API response) gets converted into this:
You can see that the <b> tags were left untouched. I can understand this because one decoding was definitely done (from Unicode to HTML), but how can I make it to actually interpret and apply the HTML?
Here's another example, where I'd like to convert a quote code to the actual quotation mark, but it doesn't happen:
Raw API response:
ABOUT THE AUTHOR Benedict Anderson is one of the world's leading authorities on South East Asian nationalism and particularly on Indonesia.
Rendering:
Here's the code I'm using in my component (rather simple):
<template>
<div class="book-listing">
<div class="book-image">
<img :src="book.volumeInfo.imageLinks.smallThumbnail">
</div>
<div class="book-title">
{{ book.volumeInfo.title }}
</div>
<div class="book-description">
{{ book.searchInfo.textSnippet }}
</div>
</div>
</template>
<script>
export default {
props: [ 'book' ]
}
</script>
Maybe you can use v-html
<div class="book-title" v-html="book.volumeInfo.title">
Btw - v-html sets the whole inner html content of element, if wonder if exists some simple way to use result as attribute:
// Amortisseur arri\ère >> Amortisseur arrière
function decodeHtml(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}