最近の優先度の高いタスク — 以前の vue プロジェクトのグローバル国際化 時間が急務であったため、より多くの努力が払われましたが、注意が足りず、単語のスペルミスや翻訳の欠落などのエラーが発生しました。英語の文字の長さにより、オンライン効果は理想的ではありません。vue-i18n 国際化言語パック処理プラグインの使用記録です。
vue-i18n 公式 Web サイトのドキュメント
インストール
npm install vue-i18n --save
構成と使用方法
src ディレクトリに新しい i18n ディレクトリを作成します。en.js は英語の言語パック、zh.js は中国語の言語パックです。
en.js ファイルの内容
export default {
common: {
username: '用户名',
password: '密码',
save: '保存',
edit: '编辑',
update: '更新',
delete: '删除',
forever: '永久',
expired: '过期'
}
}
zh.js ファイルの内容
export default {
common: {
username: 'username',
password: 'password',
save: 'Save',
edit: 'Edit',
update: 'Update',
delete: 'Delete',
forever: 'Forever',
expired: 'Expired'
}
}
i18n のindex.jsファイル
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
内
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, // 注入 配置好的国际化语言配置
})
vue で i18n を登録すると、コンポーネントでthis.$i18n
設定された i18n オブジェクトを取得できます。
インポートされたVueI18n
ものをインスタンス化し、new VueI18n() で構成情報を渡します。
- ロケールの現在の言語
- fallbackLocale 現在の言語が存在しない場合は、現在の言語がデフォルトで設定されます
- メッセージのロケール ('en'、'zh'...)
- numberFormats 数値の書式設定を設定します
- dateTimeFormats 時刻と日付の形式を設定し、1 つずつ導入します。
ロケールは主に言語パッケージの設定に使用されます。ロケールを切り替えるにはどうすればよいですか?
//在组件中
import i18n from "@/i18n" //根据项目对应真实路径
i18n.locale="en" // 改变为中文
localStorage.setItem('language',"en")//在localStorage中存入设置
メッセージ
一般に、プロジェクト内の静的言語は、中国語、英語、フランス語など、製品に必要なさまざまな言語に分割されます。例:
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
これは、静的言語の中国語バージョンen
と静的言語の英語バージョンを表します。通常en
、 、zh
は 2 つのモジュールに分かれていますen.js
— 、 zh.js
。これにより、プロジェクトの構造がより簡潔かつ明確になるだけでなく、時間を大幅に節約できます保守および開発段階で。
$t の使用 (フォーマット)
簡単に言うと、messages
あるデータを取得することであり、パラメータは取得する特定のデータを表す文字列です。
知らせ:
data に配置された静的データの国際化は、切り替え時に応答できるように、computed に配置する必要があります。
consts で定義された一部の定数を変換する場合、i18n.t を使用して変換し、関数を使用して戻り、ページが使用されるときに計算された関数を呼び出すと、切り替え時の応答性が向上します。
使いやすい
//template 需要使用 {
{}} 将 name包装起来
{
{$t('save')}}
// js
this.$t('save')
[名前の書式設定]
const messages = {
en: {
message: {
title: 'hello, {name}'
}
}
}
//组件中使用
<p>{
{ $t('message.title', { name: 'Kite' }) }}</p>
//输出
<p>hello, Kite</p>
これは名前付きフォーマットと呼ばれ、情報を地域ごとにフォーマットできます。この場合、$t
2 番目のパラメータは、動的に追加する必要があるすべてのコンテンツを表すオブジェクトです。動的にmessage
追加する必要があるすべての変数が 2 番目のパラメータにあることに注意してください。
1. 2 番目のパラメータは渡されません
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>
上記の例に示すように、2 番目のパラメーターが渡されない場合は、文字列として表示されます。
2. さまざまな命名タイプ
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>
- オブジェクトのオブジェクトタイプが直接出力されます
[object Object]
- boolean ブール型を文字列として出力します。
true-->"true"/false-->"false"
- array配列型の場合、各項目が値または文字列の場合は直接出力し、それ以外の場合は上記のように表示されます。
【リスト形式】
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>
$tc (複数形) の使用
const messages = {
en: {
apple: 'no apples | one apple | {count} apples',
banana: 'no bananas | {n} banana | {n} bananas'
}
}
ここで注意すべき点が 1 つあります。パイプ |
区切り文字でロケールを定義し、パイプ区切り文字で複数形を定義する必要があります。
//在组件内使用
<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. 複数を定義する場合は、パイプ文字を使用して区切る必要があります。2.
|
パイプシンボルが 1 個の場合、インデックスは 1 から始まり、最大インデックスは 2 になります。パイプシンボルが複数ある場合、インデックスは 0 から始まり (配列と同様)、最大インデックスは数値になります。パイプシンボルの3.以下を使用して、
$tc(“复数”,index)
対応する言語テキストを取得します。
dateTimeFormats 日付時刻形式
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'
}
}
}
数値を処理するためのメソッドがあり$n
、日付と時刻の書式設定にも対応するメソッドがあります—$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 は、通貨タイプなどを含む数値の書式設定を設定します。
numberFormats:{
'en': {
currency: { //添加 $
style: 'currency', currency: 'USD'
}
},
'zh': {
currency: { //添加 ¥
style: 'currency', currency: 'JPY', currencyDisplay: 'symbol'
}
}
},
$n (数値ローカリゼーション)
コンポーネントで数値の書式設定を使用する方法についても、同様に$t
、対応するメソッドを提供します$n
。
//组件中使用
<p>{
{ $n(100, 'currency') }}</p>
<p>{
{ $n(100, 'currency', 'zh') }}</p>
//输出
<p>$100.00</p>
<p>¥100</p>
$n(number,'path','locale')
メソッド、3 つのパラメータ:
番号 | ユーザーは番号を渡す必要があります |
道 | 呼び出しのフォーマットスキームを渡す必要があります |
ロケール | 使用される言語。デフォルトは現在の this.$i18n.locale です。 |
8.10 以降の新機能:
$n
このメソッドは、全体としてのみ使用できる完全にフォーマットされた数値を含む結果文字列を返します。小数点など、書式設定された数値の特定の部分を書式設定する必要がある場合には、これでは$n
十分ではありません。この場合、<i18n-n>
機能コンポーネントが役に立ちます。プロパティの最小限のセットを使用すると、
<i18n-n>
生成される出力は$n
構成された DOM 要素と同じになり、構成された DOM 要素にラップされます。
<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>
一般的な方法
getLocaleMessage
this.i18n.getLocaleMessage('key')
、このメソッドは、グローバル言語パック内の特定の言語の言語パックを取得するために使用されます。次に例を示します。
this.i18n.getLocaleMessage('en')//获取英文的语言包 返回的同样是一个对象
マージロケールメッセージ
this.i18n.mergeLocaleMessage('key',localeData)
、これはローカル言語パックを「キー」言語に追加するために使用される方法であり、多くの場合サブコンポーネントで使用されます。特定の地域言語パックを対応する言語のグローバル言語パックにマージします。
this.$i18n.mergeLocaleMessage('zh', local.zh)//向全局中文语言包中补充内容
vt
カスタム命令v-t
.$t
言語パック内のデータを取得するのと同じ機能を持ちますが、大きな違いがあります
v-t
の使用法
//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
vt と $t の違い
$tは拡張された Vue インスタンス メソッドです
[利点] テンプレート内でMustache構文(mustash)構文{ {}}を柔軟に使用できる ほか、Vueインスタンス内で計算プロパティやメソッドを柔軟に使用できます。
[短所] 再レンダリングのたびに実行されるため、パフォーマンスに負荷がかかります。
vtはカスタム ディレクティブです
[利点]キャッシュにカスタム ディレクティブを使用するため、一度変換するとメソッドよりも$t
パフォーマンスが向上します。
[デメリット] vt は非常に複雑なため、$t を柔軟に利用することができません。翻訳されたコンテンツ vt は textContent 要素に挿入されます。
他にもいくつかの使用法があります。詳細については公式ドキュメントを参照してください。
コンポーネントを挿入
そんな場面に遭遇したらどう対処すればいいのでしょうか?
<p>I accept xxx <a href="/term">Terms of Service Agreement</a></p>
私の最初の反応は、それを2 つのフィールドに分割することです。 a タグは、次のように記述されている限り、翻訳の内容には属しません。
<p>{
{ $t('xx1') }}<a href="/term">{
{ $t('xx2') }}</a></p>
公式サイトの紹介を読んで、この種の処理はあまりにも不器用なので、コンポーネントで処理できると言いました。
tag
2 つの変数は、ラベルを作成するための情報を保存し、path
ラベルの内容を定式化するために使用されます。
// 这里使用了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'
}
})
より高度な使用法として、 HTML 内で出現する位置を指定することで、 HTML 要素の挿入位置を制御できます。place
<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>
言語パックを動的にロードする
特に言語パックが使用されている場合は、すべての言語パックを一度にロードする必要はありません。私も以前この問題を提起しましたが、公式 Web サイトに解決策が記載されていました。
//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())
})