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.js
en 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.$i18n
Después de registrar i18n en vue, podemos obtener el objeto i18n configurado en el componente
Cree una instancia del importado VueI18n
y 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'
}
}
}
zh
Representa la versión china del lenguaje estático en
y la versión en inglés del lenguaje estático. Generalmente en
, , zh
se divide en dos módulos—— en.js
, zh.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 messages
ciertos 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, $t
el segundo parámetro es un objeto, que representa todo el contenido que debe agregarse dinámicamente. Tenga en cuenta que todas las message
variables 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ía3.
$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 $t
misma 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-t
Tiene $t
la misma función que obtener un dato en el paquete de idioma, pero hay grandes diferencias
v-t
uso 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 tag
producir etiquetas path
y 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 , place
especificando 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())
})