# Interpolação de componentes

# Exemplo básico

Suporta a versão

🆕 7.0+

Às vezes, precisamos localizar uma mensagem de um localidade incluída em uma tag ou um componente HTML.

Por exemplo:

<p>I accept xxx <a href="/term">Terms of Service Agreement</a></p>

Na mensagem acima, se quisermos usar $t, provavelmente tentaremos obtê-lo vinculando as seguintes mensagens de localização:

const messages = {
  en: {
    term1: "I Accept xxx's",
    term2: 'Terms of Service Agreement'
  }
}

Como resultado o template terá a seguinte aparência:

<p>{{ $t('term1') }}<a href="/term">{{ $t('term2') }}</a></p>

O resultado será o seguinte:

<p>I accept xxx <a href="/term">Terms of Service Agreement</a></p>

Isso é muito complicado, e se você mover a tag <a> para a mensagem de localização, você adicionará a possibilidade de uma vulnerabilidade XSS devido ao uso de v-html="$t('term')".

Isso pode ser evitado usando o componente funcional i18n.

Por exemplo:

<div id="app">
  <!-- ... -->
  <i18n path="term" tag="label" for="tos">
    <a :href="url" target="_blank">{{ $t('tos') }}</a>
  </i18n>
  <!-- ... -->
</div>
const messages = {
  en: {
    tos: 'Term of Service',
    term: 'I accept xxx {0}.'
  },
  pt: {
    tos: 'Termos de serviço',
    term: 'Eu concordo xxx {0}.'
  }
}

const i18n = new VueI18n({
  locale: 'pt',
  messages
})
new Vue({
  i18n,
  data: {
    url: '/term'
  }
}).$mount('#app')

O resultado será o seguinte:

<div id="app">
  <!-- ... -->
  <label for="tos">
    Eu concordo xxx <a href="/term" target="_blank">Termos de serviço</a>.
  </label>
  <!-- ... -->
</div>

Mais detalhes sobre o exemplo acima, veja o exemplo (opens new window)

Descendentes do componente funcional i18n interpola mensagens de localização pelo caminho do parâmetro de path.

No exemplo acima:

<a :href="url" target="_blank">{{ $t('tos') }}</a>

interpolado com o term da mensagem de localização.

No exemplo acima, a interpolação de componentes usa formatação de lista. Os descendentes do componente da função i18n são interpolados na ordem em que aparecem.

Você pode especificar o tipo do elemento raiz usando o parâmetro de entrada tag. Se nenhum parâmetro de entrada for especificado, o padrão é 'span'. Você também pode defini-lo com o valor booleano false para inserir os nós filhos diretamente sem criar um elemento raiz.

# Usando a sintaxe de slots

Suporta a versão

🆕 8.14+

É mais conveniente usar a sintaxe de slots nomeados.

Por exemplo:

<div id="app">
  <!-- ... -->
  <i18n path="info" tag="p">
    <template v-slot:limit>
      <span>{{ changeLimit }}</span>
    </template>
    <template v-slot:action>
      <a :href="changeUrl">{{ $t('change') }}</a>
    </template>
  </i18n>
  <!-- ... -->
</div>
const messages = {
  en: {
    info: 'You can {action} until {limit} minutes from departure.',
    change: 'change your flight',
    refund: 'refund the ticket'
  }
}

const i18n = new VueI18n({
  locale: 'en',
  messages
})

new Vue({
  i18n,
  data: {
    changeUrl: '/change',
    refundUrl: '/refund',
    changeLimit: 15,
    refundLimit: 30
  }
}).$mount('#app')

O resultado será o seguinte:

<div id="app">
  <!-- ... -->
  <p>
    You can <a href="/change">change your flight</a> until
    <span>15</span> minutes from departure.
  </p>
  <!-- ... -->
</div>

Desde o Vue 2.6, você pode usar a seguinte sintaxe de slots nos templates:

<div id="app">
  <!-- ... -->
  <i18n path="info" tag="p">
    <template #limit>
      <span>{{ changeLimit }}</span>
    </template>
    <template #action>
      <a :href="changeUrl">{{ $t('change') }}</a>
    </template>
  </i18n>
  <!-- ... -->
</div>

Limitação

⚠️ Os parâmetros de entrada do slot não são suportados no componente i18n.

# Usando a sintaxe de place

Atenção!

Na próxima versão principal, os parâmetros de entrada place e places serão descontinuados. Recomendamos usar a sintaxe de slot.

Suporta a versão

🆕 7.2+

Nota

⚠️ No componente i18n, o conteúdo de texto consistindo apenas em espaços em branco será omitido.

A formatação nomeada é suportada com a ajuda do atributo place.

Por exemplo:

<div id="app">
  <!-- ... -->
  <i18n path="info" tag="p">
    <span place="limit">{{ changeLimit }}</span>
    <a place="action" :href="changeUrl">{{ $t('change') }}</a>
  </i18n>
  <!-- ... -->
</div>
const messages = {
  en: {
    info: 'You can {action} until {limit} minutes from departure.',
    change: 'change your flight',
    refund: 'refund the ticket'
  }
}

const i18n = new VueI18n({
  locale: 'en',
  messages
})
new Vue({
  i18n,
  data: {
    changeUrl: '/change',
    refundUrl: '/refund',
    changeLimit: 15,
    refundLimit: 30
  }
}).$mount('#app')

O resultado será o seguinte:

<div id="app">
  <!-- ... -->
  <p>
    You can <a href="/change">change your flight</a> until
    <span>15</span> minutes from departure.
  </p>
  <!-- ... -->
</div>

Nota

⚠️ Para usar formatação nomeada, todos os descendentes do componente i18n devem ter o atributo place definido. Caso contrário, a formatação de lista será usada.

Se você ainda precisa interpolar o conteúdo do texto usando formatação nomeada, você pode definir a propriedade places no componente i18n.

Por exemplo:

<div id="app">
  <!-- ... -->
  <i18n path="info" tag="p" :places="{ limit: refundLimit }">
    <a place="action" :href="refundUrl">{{ $t('refund') }}</a>
  </i18n>
  <!-- ... -->
</div>

O resultado será o seguinte:

<div id="app">
  <!-- ... -->
  <p>
    You can <a href="/refund">refund your ticket</a> until 30 minutes from
    departure.
  </p>
  <!-- ... -->
</div>