Internacionalización de proyectos Vue (usando vue-i18n)

Una tarea reciente de alta prioridad: la internacionalización global del proyecto vue anterior. Aunque el tiempo era urgente y se hicieron más esfuerzos, debido a la falta de cuidado, hubo errores como palabras mal escritas y traducciones faltantes. El problema de estilo causado por la diferencia en la longitud de los caracteres en inglés, el efecto en línea no es ideal. Aquí hay un registro del uso del complemento de procesamiento del paquete de idioma de internacionalización vue-i18n.

documento del sitio web oficial de vue-i18n

Instalar

npm install vue-i18n --save

Configuración y uso

Cree un nuevo directorio i18n en el directorio src, en.js es el paquete de idioma inglés, zh.js es el paquete de idioma chino

contenido del archivo en.js

export default {
    common: {
      username: '用户名',
      password: '密码',
      save: '保存',
      edit: '编辑',
      update: '更新',
      delete: '删除',
      forever: '永久',
      expired: '过期'
    }
}

contenido del archivo zh.js

export default {
    common: {
      username: 'username',
      password: 'password',
      save: 'Save',
      edit: 'Edit',
      update: 'Update',
      delete: 'Delete',
      forever: 'Forever',
      expired: 'Expired'
    }
}

 archivo index.js bajo i18n

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import Cookies from 'js-cookie'
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang导入Element的语言包 英文
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang g导入Element的语言包 中文
import enLocale from './en' // 导入项目中用到的英文语言包
import zhLocale from './zh'// 导入项目中用到的中文语言包
Vue.use(VueI18n)
const messages = {
  en: {
    ...enLocale,
    ...elementEnLocale
  },
  zh: {
    ...zhLocale,
    ...elementZhLocale,
  },

}

const i18n = new VueI18n({
  locale: localStorage.getItem('language') || 'zh', // 设置语种
  messages, // 设置全局当地语言包,
  fallbackLocale: 'zh',
  numberFormats:{ //设置 数字本地化
    'en': {
      currency: { //添加 $
        style: 'currency', currency: 'USD'
      }
    },
    'zh': {
      currency: { //添加 ¥
        style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'
      }
    }
  },
    dateTimeFormats:{//设置 日期时间本地化
    'en': {
      short: { 
        year: 'numeric', month: 'short', day: 'numeric'
      },
      long: {
        year: 'numeric', month: 'short', day: 'numeric',
        weekday: 'short', hour: 'numeric', minute: 'numeric'
      }
    },
    'zh': {
      short: {
        year: 'numeric', month: 'short', day: 'numeric'
      },
      long: {
            year: 'numeric', month: 'short', day: 'numeric',
            weekday: 'short', hour: 'numeric', minute: 'numeric'  
      }
    }
  }
})

export default i18n

main.jsen el archivo de entrada principal

import Vue from 'vue'
import Element from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//导入配置好的国际化语言包
import i18n from './i18n' // Internationalization

Vue.use(Element, {
  size: 'medium', // set element-ui default size设置元素默认大小
  i18n: (key, value) => i18n.t(key, value)// 在注册Element时设置i18n的处理方法
})
Vue.config.productionTip = false// 生产提示
new Vue({
  el: '#app',
  i18n, // 注入 配置好的国际化语言配置
})


this.$i18nDespués de registrar i18n en vue, podemos obtener el objeto i18n configurado en el componente

Cree una instancia del importado VueI18ny pase la información de configuración en el nuevo VueI18n():

  • configuración regional idioma actual
  • fallbackLocale Si el idioma actual no existe, el idioma actual se establece de forma predeterminada
  • configuración regional de mensajes ('en', 'zh'...)
  • numberFormats establece el formato de número
  • dateTimeFormats Establezca el formato de hora y fecha y luego introduzca uno por uno:

La configuración regional se utiliza principalmente para configurar el paquete de idioma. ¿Cómo cambiar la configuración regional?

//在组件中
import i18n from "@/i18n" //根据项目对应真实路径

i18n.locale="en" // 改变为中文
localStorage.setItem('language',"en")//在localStorage中存入设置

 mensajes 

Generalmente, el idioma estático en el proyecto se dividirá en varios idiomas requeridos por el producto, incluidos chino, inglés, francés, etc. Por ejemplo:


message:{
  zh: {
    common: {
      username: '用户名',
      password: '密码',
      save: '保存',
      edit: '编辑',
      update: '更新',
      delete: '删除',
      forever: '永久',
      expired: '过期'
    }

  },
  en: {
    common: {
      username: 'username',
      password: 'password',
      save: 'Save',
      edit: 'Edit',
      update: 'Update',
      delete: 'Delete',
      forever: 'Forever',
      expired: 'Expired'
    }
  }
}

zhRepresenta la versión china del lenguaje estático eny la versión en inglés del lenguaje estático. Generalmente en, , zhse divide en dos módulos—— en.jszh.js. Esto no solo hace que la estructura del proyecto sea más concisa y clara, sino que también ahorra mucho tiempo. en fase de mantenimiento y desarrollo.

Uso de $t (formato)

En pocas palabras, es obtener messagesciertos datos, y el parámetro es una cadena, que representa una determinada pieza de datos que se obtendrán.

Aviso:

 La internacionalización de los datos estáticos colocados en data necesita ser computada, para que responda al cambiar;

 Al traducir algunas constantes definidas en consts, use i18n.t para traducir y luego use la función para regresar, y llame a la función en el cálculo cuando se usa la página, y luego habrá capacidad de respuesta al cambiar ;

  fácil de usar

//template 需要使用 {
   
   {}} 将 name包装起来
{
   
   {$t('save')}}

// js
this.$t('save')

[formato de nombre]

const messages = {
  en: {
    message: {
      title: 'hello, {name}'
    }
  }
}
//组件中使用
<p>{
   
   { $t('message.title', { name: 'Kite' }) }}</p>

//输出
<p>hello, Kite</p>

Esto se denomina formato con nombre y puede dar formato a la información regionalmente. En este caso, $tel segundo parámetro es un objeto, que representa todo el contenido que debe agregarse dinámicamente. Tenga en cuenta que todas las messagevariables que deben agregarse dinámicamente están en el segundo parámetro.

1. No se pasa el segundo parámetro

const message = {
  en: {
    message: {
      title: '{a}{b}哈哈'
    }
  }
}
//组件中使用1
<p>{
   
   { $t('message.title') }}</p>
//输出
<p>{a}{b}哈哈</p>

//组件中使用2, 
<p>{
   
   { $t('message.title',{a:1,b:2) }}</p>
//输出
<p>12哈哈</p>

Como se muestra en el ejemplo anterior, si no se pasa el segundo parámetro, se mostrará como una cadena.


2. Diferentes tipos de nombres

const messages = {
  en: {
    message: {
      title: '{a}{b}哈哈'
    }
  }
}
//组件中使用  数值型与字符串类型 1
<p>{
   
   { $t('message.title',{a:1,b:"2") }}</p>
//输出
<p>12哈哈</p>

//组件中使用2 对象类型
<p>{
   
   { $t('message.title',{a:{},b:"2") }}</p>
//输出
<p>[object Object]2哈哈</p>

//组件中使用3 数组类型(内含布尔,对象类型)
<p>{
   
   { $t('message.title',{a:[1,2,3,true,{}],b:"2") }}</p>
//输出
<p>123true[object Object]2哈哈</p>
  • El tipo de objeto objeto se generará directamente  [object Object]
  • booleano El tipo booleano se generará como una cadena  true-->"true"/false-->"false"
  • En el tipo de matriz de matriz, si cada elemento es un valor o una cadena, luego imprímalo directamente; de ​​lo contrario, se mostrará como arriba

 [formato de lista]

const message = {
  en: {
    message: {
      sing: '{0}{1}{2}忘了想念'
    }
  }
}
// 组件内使用 1 列表格式
<p>{
   
   { $t('message.sing', ['我','以','为']) }}</p>
//输出
<p>我以为忘了想念</p>


// 组件内使用 2 类似命名格式的方式
<p>{
   
   { $t('message.sing', { '0':"我",'1':'以','2':'为' }) }}</p>
//输出
<p>我以为忘了想念</p>

Uso de $tc (plural)

const messages = {
  en: {
    apple: 'no apples | one apple | {count} apples',
    banana: 'no bananas | {n} banana | {n} bananas'
  }
}

Una cosa a tener en cuenta aquí: debe definir la configuración regional con el  | separador de tuberías y definir el plural en el separador de tuberías

//在组件内使用
<p>{
   
   { $tc('apple', 10, { count: 10 }) }}</p>
<p>{
   
   { $tc('apple', 10) }}</p>

<p>{
   
   { $tc('banana', 1, { n: 1 }) }}</p>
<p>{
   
   { $tc('banana', 1) }}</p>
<p>{
   
   { $tc('banana', 100, { n: 'too many' }) }}</p>

//输出
<p>10 apples</p>
<p>10 apples</p>

<p>1 banana</p>
<p>1 banana</p>
<p>too many bananas</p>

1. Al definir plurales, es necesario usar |el carácter de barra vertical para separarlos.

2. Cuando |hay 1 símbolo de tubería, el índice comienza desde 1 y el índice máximo es 2. Cuando hay más de 1 símbolo de tubería, el índice comienza desde 0 (similar a una matriz) y el índice máximo es el número de símbolos de tubería

3. $tc(“复数”,index)Obtenga el texto del idioma correspondiente usando


 dateTimeFormats formato de fecha y hora

dateTimeFormats:{//设置 日期时间本地化
    'en': {
  short: { //显示英文 年月日
    year: 'numeric', month: 'short', day: 'numeric'
  },
  long: { //显示英文 年月日 星期 小时 分钟
    year: 'numeric', month: 'short', day: 'numeric',
    weekday: 'short', hour: 'numeric', minute: 'numeric'
 }
    },
    'zh': {
  short: {
    year: 'numeric', month: 'short', day: 'numeric'
  },
  long: {
    year: 'numeric', month: 'short', day: 'numeric',
    weekday: 'short', hour: 'numeric', minute: 'numeric'  
  }
    }
  }

Hay métodos para tratar con números $n, y hay métodos correspondientes para el formato de fecha y hora——$d

//在组件中使用
<div id="app">
  <p>{
   
   { $d(new Date(), 'short') }}</p>
   <p>{
   
   { $d(new Date(), 'long') }}</p>
    <p>{
   
   { $d(new Date(), 'short','zh') }}</p>
  <p>{
   
   { $d(new Date(), 'long', 'zh') }}</p>
</div>

//输出
Jul 31, 2022
Sat, Jul 31, 2022, 5:55 PM

2022年07月23日
2018年07月23日 周六 下午5:55

numberFormats establece el formato de número, incluido el tipo de moneda, etc.

numberFormats:{ 
    'en': {
  currency: { //添加 $
   style: 'currency', currency: 'USD'
  }
    },
    'zh': {
  currency: { //添加 ¥
    style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'
  }
    }
  },

$n (localización numérica)

Para saber cómo usar el formato de números en los componentes, ya que de la $tmisma manera, también proporciona el método correspondiente $n.

//组件中使用
  <p>{
   
   { $n(100, 'currency') }}</p>
  <p>{
   
   { $n(100, 'currency', 'zh') }}</p>

//输出
  <p>$100.00</p>
  <p>¥100</p>

$n(number,'path','locale')método, tres parámetros:

número El usuario debe pasar el número
camino Se debe pasar el esquema de formato de la convocatoria
lugar El idioma utilizado, el predeterminado es el actual this.$i18n.locale

Nuevo en 8.10+ : $n el método devuelve una cadena de resultado con un número con formato completo que solo se puede usar como un todo. $n no es suficiente en los casos en que es necesario formatear ciertas partes del número formateado, como los lugares decimales . En este caso, <i18n-n> los componentes funcionales ayudarán.

Con un conjunto mínimo de propiedades, <i18n-n> la salida producida es  $n idéntica y está envuelta en elementos DOM configurados.

<i18n-n :value="1234" :format="{ key: 'currency', currency: 'EUR' }">
  <span v-slot:currency="slotProps" styles="color: green">{
   
   { slotProps.currency }}</span>
  <span v-slot:integer="slotProps" styles="font-weight: bold">{
   
   { slotProps.integer }}</span>
  <span v-slot:group="slotProps" styles="font-weight: bold">{
   
   { slotProps.group }}</span>
  <span v-slot:fraction="slotProps" styles="font-size: small">{
   
   { slotProps.fraction }}</span>
</i18n-n>


// 结果
<span>
  <span styles="color: green">€</span>
  <span styles="font-weight: bold">1</span>
  <span styles="font-weight: bold">,</span>
  <span styles="font-weight: bold">234</span>
  <span styles="font-size: small">00</span>
</span>

 método común

getLocaleMessage

this.i18n.getLocaleMessage('key'), este método se utiliza para obtener el paquete de idioma de un determinado idioma en el paquete de idioma global, por ejemplo:

 this.i18n.getLocaleMessage('en')//获取英文的语言包 返回的同样是一个对象

mergeLocaleMessage

this.i18n.mergeLocaleMessage('key',localeData), este es el método utilizado para agregar paquetes de idiomas locales al idioma 'clave', a menudo en un subcomponente, fusionaremos un determinado paquete de idioma regional en el paquete de idioma global del idioma correspondiente

this.$i18n.mergeLocaleMessage('zh', local.zh)//向全局中文语言包中补充内容

Vermont

Instrucción personalizada v-tTiene $tla misma función que obtener un dato en el paquete de idioma, pero hay grandes diferencias

v-tuso de

//locale='en'
const messages = {
  en: {
    message: {
      title: hello'
    }
  },
  zh:{
   message: {
      title: '哈哈{name}'
    }
  }
}
//组件中使用1 字符串用法
 <p v-t="'message.title'"></p>
 //输出
 hello
 
 //组件中使用2 对象用法
<p v-t="{ path: 'message.title', locale: 'zh', args: { name: 'cfz' } }"></p>
 //输出
 哈哈cfz

La diferencia entre vt y $t

$t es el método de instancia extendido de Vue

[Ventajas]   Puede usar de manera flexible la sintaxis de bigote (mustash) sintaxis { {}} en plantillas , y también puede usar de manera flexible accesorios y métodos de cálculo en instancias de Vue.

[ Desventaja ] Se ejecuta cada vez que se vuelve a renderizar, por lo que requiere más rendimiento.

vt es una directiva personalizada

[ Ventajas$t ] Cuando se traduce una vez, tiene un mejor rendimiento que los métodos debido a su uso de directivas personalizadas para el almacenamiento en caché .

[ Desventajas ] vt no puede usar $t de manera flexible, porque es bastante complicado. El contenido traducido vt se insertará en el elemento textContent.

Hay algunos otros usos, consulte la documentación oficial para obtener más detalles.


insertar componente

Si te encuentras con una escena así, ¿cómo lidiar con ella?

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

Mi primera reacción es dividirlo en dos campos.La etiqueta a no pertenece al contenido de la traducción, siempre que esté escrita como:

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

Después de leer la introducción en el sitio web oficial, dije que este tipo de procesamiento es demasiado torpe y puede ser procesado por componentes .

Se utilizan dos variables para almacenar información para tagproducir etiquetas pathy para formular el contenido de las etiquetas.

// 这里使用了i18n 组件
<i18n path="term" tag="p" for="tos">
    <a :href="url" target="_blank">{
   
   { $t('tos') }}</a>
</i18n>

const messages = {
  en: {
    tos: 'Term of Service',
    term: 'I accept xxx {0}.'
  }
}

new Vue({
  el: '#app',
  i18n,
  data: {
    url: '/term'
  }
})

Para un uso más avanzado, puede controlar la posición de inserción del elemento html , placeespecificando la posición en la que aparece en el html.

<i18n path="info" tag="p">
    <span place="limit">{
   
   { changeLimit }}</span>
    <a place="action" :href="changeUrl">{
   
   { $t('change') }}</a>
</i18n>

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')

// result
<p>
    You can <a href="/change">change your flight</a> until <span>15</span> minutes from departure.
</p>

Cargar paquetes de idioma dinámicamente

No es necesario cargar todos los paquetes de idioma a la vez, especialmente cuando se han usado los paquetes de idioma.También planteé este problema antes y descubrí que el sitio web oficial dio una solución.

//i18n-setup.js
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from '@/i18n' // 语言包的地址,随项目本身设置修改
import axios from 'axios' // 根据项目中使用api请求模块去设置,不一定是axios

Vue.use(VueI18n)

export const i18n = new VueI18n({
  locale: 'en', // set locale
  fallbackLocale: 'en', // 默认语言设置,当其他语言没有的情况下,使用en作为默认语言
  messages // set locale messages
})

const loadedLanguages = ['en'] // our default language that is prelaoded 

function setI18nLanguage (lang) {
  i18n.locale = lang
  axios.defaults.headers.common['Accept-Language'] = lang // 设置请求头部
  document.querySelector('html').setAttribute('lang', lang) // 根元素增加lang属性
  return lang
}

export function loadLanguageAsync (lang) {
  if (i18n.locale !== lang) {
    if (!loadedLanguages.includes(lang)) {
      return import(/* webpackChunkName: "lang-[request]" */ `@/lang/${lang}`).then(msgs => {
        i18n.setLocaleMessage(lang, msgs.default)
        loadedLanguages.push(lang)
        return setI18nLanguage(lang)
      })
    } 
    return Promise.resolve(setI18nLanguage(lang))
  }
  return Promise.resolve(lang)
}


// 在vue-router的beforeEach的全局钩子处理
router.beforeEach((to, from, next) => {
  const lang = to.params.lang
  loadLanguageAsync(lang).then(() => next())
})

Supongo que te gusta

Origin blog.csdn.net/qq_44376306/article/details/125949595
Recomendado
Clasificación