diff --git a/docs/site/mobile.js b/docs/site/mobile.js index 8757dcc0e..198af61c1 100644 --- a/docs/site/mobile.js +++ b/docs/site/mobile.js @@ -1,130 +1,129 @@ -// import Vue from 'vue'; -// import Locale from '../../src/locale'; +import Locale from '../../src-next/locale'; +import enUS from '../../src-next/locale/lang/en-US'; +import { get } from '../../src/utils'; +import { camelize } from '../../src/utils/format/string'; // import Lazyload from '../../src/lazyload'; -// import { get } from '../../src/utils'; -// import { camelize } from '../../src/utils/format/string'; -// import enUS from '../../src/locale/lang/en-US'; +const { app } = window; + +// TODO // Vue.use(Lazyload, { // lazyComponent: true, // }); -// Locale.add({ -// 'en-US': enUS, -// }); +Locale.add({ + 'en-US': enUS, +}); -// // flag for vant-weapp demos -// const isWeapp = location.search.indexOf('weapp=1') !== -1; +let demoUid = 0; -// let demoUid = 0; +// helper for demo locales +app.mixin({ + computed: { + t() { + const { name } = this.$options; + const prefix = name ? camelize(name) + '.' : ''; + const messages = Locale.messages(); -// // helper for demo locales -// Vue.mixin({ -// computed: { -// t() { -// const { name } = this.$options; -// const { lang = 'zh-CN' } = (this.$route && this.$route.meta) || {}; -// const prefix = name ? camelize(name) + '.' : ''; -// const messages = this.$vantMessages[lang]; + return (path, ...args) => { + const message = get(messages, prefix + path) || get(messages, path); + return typeof message === 'function' ? message(...args) : message; + }; + }, -// return (path, ...args) => { -// const message = get(messages, prefix + path) || get(messages, path); -// return typeof message === 'function' ? message(...args) : message; -// }; -// }, + // flag for vant-weapp demos + isWeapp() { + return location.search.indexOf('weapp=1') !== -1; + }, + }, -// isWeapp() { -// return isWeapp; -// }, -// }, + beforeCreate() { + if (!this.$options.name) { + this.$options.name = `demo-${demoUid++}`; + } -// beforeCreate() { -// if (!this.$options.name) { -// this.$options.name = `demo-${demoUid++}`; -// } + const { i18n, name } = this.$options; -// const { i18n, name } = this.$options; + if (i18n && name) { + const locales = {}; + const camelizedName = camelize(name); -// if (i18n && name) { -// const locales = {}; -// const camelizedName = camelize(name); + Object.keys(i18n).forEach((key) => { + locales[key] = { [camelizedName]: i18n[key] }; + }); -// Object.keys(i18n).forEach((key) => { -// locales[key] = { [camelizedName]: i18n[key] }; -// }); + Locale.add(locales); + } + }, +}); -// Locale.add(locales); -// } -// }, -// }); +// switch lang after routing +if (window.vueRouter) { + window.vueRouter.afterEach((to) => { + const { lang } = to.meta || {}; -// // switch lang after routing -// if (window.vueRouter) { -// window.vueRouter.afterEach((to) => { -// const { lang } = to.meta || {}; + if (lang) { + Locale.use(lang); + } + }); +} -// if (lang) { -// Locale.use(lang); -// } -// }); -// } - -// // add some basic locale messages -// Locale.add({ -// 'zh-CN': { -// add: '增加', -// decrease: '减少', -// red: '红色', -// orange: '橙色', -// yellow: '黄色', -// purple: '紫色', -// tab: '标签', -// tag: '标签', -// desc: '描述信息', -// back: '返回', -// title: '标题', -// status: '状态', -// button: '按钮', -// option: '选项', -// search: '搜索', -// content: '内容', -// custom: '自定义', -// username: '用户名', -// password: '密码', -// disabled: '禁用状态', -// uneditable: '不可编辑', -// basicUsage: '基础用法', -// advancedUsage: '高级用法', -// loadingStatus: '加载状态', -// usernamePlaceholder: '请输入用户名', -// passwordPlaceholder: '请输入密码', -// }, -// 'en-US': { -// add: 'Add', -// decrease: 'Decrease', -// red: 'Red', -// orange: 'Orange', -// yellow: 'Yellow', -// purple: 'Purple', -// tab: 'Tab', -// tag: 'Tag', -// desc: 'Description', -// back: 'Back', -// title: 'Title', -// status: 'Status', -// button: 'Button', -// option: 'Option', -// search: 'Search', -// content: 'Content', -// custom: 'Custom', -// username: 'Username', -// password: 'Password', -// loadingStatus: 'Loading', -// disabled: 'Disabled', -// uneditable: 'Uneditable', -// basicUsage: 'Basic Usage', -// advancedUsage: 'Advanced Usage', -// usernamePlaceholder: 'Username', -// passwordPlaceholder: 'Password', -// }, -// }); +// add some basic locale messages +Locale.add({ + 'zh-CN': { + add: '增加', + decrease: '减少', + red: '红色', + orange: '橙色', + yellow: '黄色', + purple: '紫色', + tab: '标签', + tag: '标签', + desc: '描述信息', + back: '返回', + title: '标题', + status: '状态', + button: '按钮', + option: '选项', + search: '搜索', + content: '内容', + custom: '自定义', + username: '用户名', + password: '密码', + disabled: '禁用状态', + uneditable: '不可编辑', + basicUsage: '基础用法', + advancedUsage: '高级用法', + loadingStatus: '加载状态', + usernamePlaceholder: '请输入用户名', + passwordPlaceholder: '请输入密码', + }, + 'en-US': { + add: 'Add', + decrease: 'Decrease', + red: 'Red', + orange: 'Orange', + yellow: 'Yellow', + purple: 'Purple', + tab: 'Tab', + tag: 'Tag', + desc: 'Description', + back: 'Back', + title: 'Title', + status: 'Status', + button: 'Button', + option: 'Option', + search: 'Search', + content: 'Content', + custom: 'Custom', + username: 'Username', + password: 'Password', + loadingStatus: 'Loading', + disabled: 'Disabled', + uneditable: 'Uneditable', + basicUsage: 'Basic Usage', + advancedUsage: 'Advanced Usage', + usernamePlaceholder: 'Username', + passwordPlaceholder: 'Password', + }, +}); diff --git a/src-next/icon/index.js b/src-next/icon/index.js index 0feda2433..35721b637 100644 --- a/src-next/icon/index.js +++ b/src-next/icon/index.js @@ -1,5 +1,5 @@ // Utils -import { addUnit, isDef } from '../../src/utils'; +import { addUnit } from '../../src/utils'; import { createNamespace } from '../utils/create'; // Components diff --git a/src-next/locale/README.md b/src-next/locale/README.md new file mode 100644 index 000000000..45e81da88 --- /dev/null +++ b/src-next/locale/README.md @@ -0,0 +1,51 @@ +# Internationalization + +### Intro + +The default language of Vant is Chinese. If you want to use other languages, you can follow the instructions below. + +### Switch languages + +Vant supports multiple languages with the Locale component, and the `Locale.use` method allows you to switch to different languages. + +```js +import { Locale } from 'vant'; +import enUS from 'vant/lib/locale/lang/en-US'; + +Locale.use('en-US', enUS); +``` + +### Modify default configs + +Use `Locale.add` method to modify the default configs. + +```js +import { Locale } from 'vant'; + +const messages = { + 'en-US': { + vanPicker: { + confirm: 'Close', + }, + }, +}; + +Locale.add(messages); +``` + +### Config files + +Current supported languages: + +| Language | Filename | +| ------------------------ | -------- | +| Chinese | zh-CN | +| Traditional Chinese (HK) | zh-HK | +| Traditional Chinese (TW) | zh-TW | +| English | en-US | +| Turkish | tr-TR | +| Spanish (Spain) | es-ES | +| Japanese | ja-JP | +| Romanian | ro-RO | + +> View all language configs [Here](https://github.com/youzan/vant/tree/dev/src/locale/lang). diff --git a/src-next/locale/README.zh-CN.md b/src-next/locale/README.zh-CN.md new file mode 100644 index 000000000..87d754e02 --- /dev/null +++ b/src-next/locale/README.zh-CN.md @@ -0,0 +1,55 @@ +# 国际化 + +### 介绍 + +Vant 默认采用中文作为语言,如果需要使用其他语言,可以参考下面的方案。 + +### 多语言切换 + +Vant 通过 Locale 组件实现多语言支持,使用 `Locale.use` 方法可以切换当前使用的语言。 + +```js +import { Locale } from 'vant'; +import enUS from 'vant/lib/locale/lang/en-US'; + +Locale.use('en-US', enUS); +``` + +### 修改默认文案 + +通过 `Locale.add` 方法可以实现文案的修改和扩展,示例如下: + +```js +import { Locale } from 'vant'; + +const messages = { + 'zh-CN': { + vanPicker: { + confirm: '关闭', // 将'确认'修改为'关闭' + }, + }, +}; + +Locale.add(messages); +``` + +### 配置文件 + +目前支持的语言: + +| 语言 | 文件名 | +| -------------- | ------ | +| 简体中文 | zh-CN | +| 繁體中文(港) | zh-HK | +| 繁體中文(台) | zh-TW | +| 英语 | en-US | +| 土耳其语 | tr-TR | +| 西班牙语 | es-ES | +| 日语 | ja-JP | +| 罗马尼亚语 | ro-RO | + +> 在 [这里](https://github.com/youzan/vant/tree/dev/src/locale/lang) 查看所有的 i18n 配置文件。 + +### Sku 组件 + +语言包中默认不包含 Sku 业务组件的语言配置,因此如果有 Sku 组件的国际化需求,请自行配置国际化文案。 diff --git a/src-next/locale/index.ts b/src-next/locale/index.ts new file mode 100644 index 000000000..6b148cc0b --- /dev/null +++ b/src-next/locale/index.ts @@ -0,0 +1,25 @@ +import { ref } from 'vue'; +import { deepAssign } from '../../src/utils/deep-assign'; +import defaultMessages from './lang/zh-CN'; + +type Messages = Record>; + +const lang = ref('zh-CN'); +const messages = ref({ + 'zh-CN': defaultMessages, +}); + +export default { + messages() { + return messages.value[lang.value]; + }, + + use(newLang: string, newMessages?: object) { + lang.value = newLang; + this.add({ [newLang]: newMessages }); + }, + + add(newMessages = {}) { + deepAssign(messages.value, newMessages); + }, +}; diff --git a/src-next/locale/lang/en-US.ts b/src-next/locale/lang/en-US.ts new file mode 100644 index 000000000..99268eae0 --- /dev/null +++ b/src-next/locale/lang/en-US.ts @@ -0,0 +1,77 @@ +export default { + name: 'Name', + tel: 'Phone', + save: 'Save', + confirm: 'Confirm', + cancel: 'Cancel', + delete: 'Delete', + complete: 'Complete', + loading: 'Loading...', + telEmpty: 'Please fill in the tel', + nameEmpty: 'Please fill in the name', + nameInvalid: 'Malformed name', + confirmDelete: 'Are you sure you want to delete?', + telInvalid: 'Malformed phone number', + vanCalendar: { + end: 'End', + start: 'Start', + title: 'Calendar', + startEnd: 'Start/End', + weekdays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + monthTitle: (year: number, month: number) => `${year}/${month}`, + rangePrompt: (maxRange: number) => `Choose no more than ${maxRange} days`, + }, + vanContactCard: { + addText: 'Add contact info', + }, + vanContactList: { + addText: 'Add new contact', + }, + vanPagination: { + prev: 'Previous', + next: 'Next', + }, + vanPullRefresh: { + pulling: 'Pull to refresh...', + loosing: 'Loose to refresh...', + }, + vanSubmitBar: { + label: 'Total:', + }, + vanCoupon: { + unlimited: 'Unlimited', + discount: (discount: number) => `${discount * 10}% off`, + condition: (condition: number) => `At least ${condition}`, + }, + vanCouponCell: { + title: 'Coupon', + tips: 'No coupons', + count: (count: number) => `You have ${count} coupons`, + }, + vanCouponList: { + empty: 'No coupons', + exchange: 'Exchange', + close: 'Close', + enable: 'Available', + disabled: 'Unavailable', + placeholder: 'Coupon code', + }, + vanAddressEdit: { + area: 'Area', + postal: 'Postal', + areaEmpty: 'Please select a receiving area', + addressEmpty: 'Address can not be empty', + postalEmpty: 'Wrong postal code', + defaultAddress: 'Set as the default address', + telPlaceholder: 'Phone', + namePlaceholder: 'Name', + areaPlaceholder: 'Area', + }, + vanAddressEditDetail: { + label: 'Address', + placeholder: 'Address', + }, + vanAddressList: { + add: 'Add new address', + }, +}; diff --git a/src-next/locale/lang/es-ES.ts b/src-next/locale/lang/es-ES.ts new file mode 100644 index 000000000..85dc38d7f --- /dev/null +++ b/src-next/locale/lang/es-ES.ts @@ -0,0 +1,77 @@ +export default { + name: 'Nombre', + tel: 'Teléfono', + save: 'Guardar', + confirm: 'Confirmar', + cancel: 'Cancelar', + delete: 'Eliminar', + complete: 'Completado', + loading: 'Cargando...', + telEmpty: 'Por favor rellena el teléfono', + nameEmpty: 'Por favor rellena el nombre', + nameInvalid: 'nombre inválido', + confirmDelete: 'Estás seguro de eliminarlo?', + telInvalid: 'Teléfono inválido', + vanCalendar: { + end: 'Fin', + start: 'Inicio', + title: 'Calendario', + startEnd: 'Inicio/Fin', + weekdays: ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'], + monthTitle: (year: number, month: number) => `${year}/${month}`, + rangePrompt: (maxRange: number) => `Elija no más de ${maxRange} días`, + }, + vanContactCard: { + addText: 'Añadir información de contacto', + }, + vanContactList: { + addText: 'Añadir nuevo contacto', + }, + vanPagination: { + prev: 'Anterior', + next: 'Siguiente', + }, + vanPullRefresh: { + pulling: 'Tira para recargar...', + loosing: 'Suelta para recargar...', + }, + vanSubmitBar: { + label: 'Total:', + }, + vanCoupon: { + unlimited: 'Ilimitado', + discount: (discount: number) => `${discount * 10}% de descuento`, + condition: (condition: number) => `Al menos ${condition}`, + }, + vanCouponCell: { + title: 'Cupón', + tips: 'Sin cupones', + count: (count: number) => `You have ${count} coupons`, + }, + vanCouponList: { + empty: 'Sin cupones', + exchange: 'Intercambio', + close: 'Cerrar', + enable: 'Disponible', + disabled: 'No disponible', + placeholder: 'Código del cupón', + }, + vanAddressEdit: { + area: 'Área', + postal: 'Código Postal', + areaEmpty: 'Por favor selecciona una área de recogida', + addressEmpty: 'La dirección no puede estar vacia', + postalEmpty: 'Código postal inválido', + defaultAddress: 'Establecer como dirección por defecto', + telPlaceholder: 'Teléfono', + namePlaceholder: 'Nombre', + areaPlaceholder: 'Área', + }, + vanAddressEditDetail: { + label: 'Dirección', + placeholder: 'Dirección', + }, + vanAddressList: { + add: 'Anadir dirección', + }, +}; diff --git a/src-next/locale/lang/ja-JP.ts b/src-next/locale/lang/ja-JP.ts new file mode 100644 index 000000000..83e2b9497 --- /dev/null +++ b/src-next/locale/lang/ja-JP.ts @@ -0,0 +1,78 @@ +export default { + name: 'お名前', + tel: '電話番号', + save: 'セーブ', + confirm: '確認', + cancel: 'キャンセル', + delete: '削除', + complete: '完了', + loading: '読み込み中...', + telEmpty: '電話番号を入力してください', + nameEmpty: '名前を入力してください', + nameInvalid: '正しい名前を入力してください', + confirmDelete: '本当に削除しますか', + telInvalid: '正しい電話番号を入力してください', + vanCalendar: { + end: '終了', + start: '開始', + title: '日付選択', + confirm: '確認', + startEnd: '開始/終了', + weekdays: ['日', '月', '火', '水', '木', '金', '土'], + monthTitle: (year: number, month: number) => `${year}年${month}月`, + rangePrompt: (maxRange: number) => `${maxRange}日以内を選択してください`, + }, + vanContactCard: { + addText: '連絡先を追加', + }, + vanContactList: { + addText: '新しい連絡先を追加', + }, + vanPagination: { + prev: '前のページ', + next: '次のページ', + }, + vanPullRefresh: { + pulling: 'プルダウンして更新...', + loosing: 'リリース時に更新...', + }, + vanSubmitBar: { + label: '合計:', + }, + vanCoupon: { + unlimited: '入場ありません', + discount: (discount: number) => `${10 - discount}割引`, + condition: (condition: number) => `${condition}円以上で利用可能`, + }, + vanCouponCell: { + title: 'クーポン', + tips: '利用可能なクーポンがありません', + count: (count: number) => `${count}枚が利用可能`, + }, + vanCouponList: { + empty: 'クーポンはありません', + exchange: '両替', + close: 'クーポンを使用しません', + enable: '利用可能', + disabled: '利用できません', + placeholder: '割引コードを入力してください', + }, + vanAddressEdit: { + area: '地域', + postal: '郵便番号', + areaEmpty: '地域を選択してください', + addressEmpty: '詳しい住所を入力してください', + postalEmpty: '邮政编码格式不正确', + defaultAddress: 'デフォルトの住所に設定', + telPlaceholder: '荷受人の携帯番号', + namePlaceholder: '荷受人の名前', + areaPlaceholder: '县 / 市 / 町を選択', + }, + vanAddressEditDetail: { + label: '詳しい住所', + placeholder: '番地、階の部屋番号など', + }, + vanAddressList: { + add: '住所を追加', + }, +}; diff --git a/src-next/locale/lang/ro-RO.ts b/src-next/locale/lang/ro-RO.ts new file mode 100644 index 000000000..95ec534db --- /dev/null +++ b/src-next/locale/lang/ro-RO.ts @@ -0,0 +1,77 @@ +export default { + name: 'Nume', + tel: 'Telefon', + save: 'Salvează', + confirm: 'Confirmă', + cancel: 'Anulează', + delete: 'Șterge', + complete: 'Finalizează', + loading: 'Încărcare...', + telEmpty: 'Te rugăm să completezi telefonul', + nameEmpty: 'Te rugăm să completezi numele', + nameInvalid: 'Nume incorect', + confirmDelete: 'Ești sigur ca vrei sa stergi?', + telInvalid: 'Număr de telefon invalid', + vanCalendar: { + end: 'Sfârșit', + start: 'Început', + title: 'Calendar', + startEnd: 'Început/Sfârsit', + weekdays: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'], + monthTitle: (year: number, month: number) => `${year}/${month}`, + rangePrompt: (maxRange: number) => `Alege maxim ${maxRange} zile`, + }, + vanContactCard: { + addText: 'Adaugă informațiile de contact', + }, + vanContactList: { + addText: 'Adaugă contact nou', + }, + vanPagination: { + prev: 'Precedenta', + next: 'Urmatoarea', + }, + vanPullRefresh: { + pulling: 'Trage pentru a da împrospăta...', + loosing: 'Eliberează pentru a împrospăta...', + }, + vanSubmitBar: { + label: 'Total:', + }, + vanCoupon: { + unlimited: 'Nelimitat', + discount: (discount: number) => `${discount * 10}% discount`, + condition: (condition: number) => `Cel puțin ${condition}`, + }, + vanCouponCell: { + title: 'Cupon', + tips: 'Fără cupoane', + count: (count: number) => `Ai ${count} cupoane`, + }, + vanCouponList: { + empty: 'Fără cupoane', + exchange: 'Schimbă', + close: 'Închide', + enable: 'Disponibil', + disabled: 'Indisponibil', + placeholder: 'Cod cupon', + }, + vanAddressEdit: { + area: 'Zonă', + postal: 'Cod postal', + areaEmpty: 'Te rugăm sa selectezi o zona de primire', + addressEmpty: 'Adresa nu poate fi goală', + postalEmpty: 'Cod postal invalid', + defaultAddress: 'Setează ca adresă de pornire', + telPlaceholder: 'Telefon', + namePlaceholder: 'Nume', + areaPlaceholder: 'Zonă', + }, + vanAddressEditDetail: { + label: 'Adresă', + placeholder: 'Adresă', + }, + vanAddressList: { + add: 'Adaugă adresă nouă', + }, +}; diff --git a/src-next/locale/lang/tr-TR.ts b/src-next/locale/lang/tr-TR.ts new file mode 100644 index 000000000..76218b8fa --- /dev/null +++ b/src-next/locale/lang/tr-TR.ts @@ -0,0 +1,77 @@ +export default { + name: 'İsim', + tel: 'Telefon', + save: 'Kaydet', + confirm: 'Onayla', + cancel: 'İptal', + delete: 'Sil', + complete: 'Tamamla', + loading: 'Yükleniyor...', + telEmpty: 'Lütfen tel. no giriniz', + nameEmpty: 'Lütfen isim giriniz', + nameInvalid: 'Geçersiz isim', + confirmDelete: 'Silmek istediğinize emin misiniz?', + telInvalid: 'Geçersiz tel. numarası', + vanCalendar: { + end: 'Son', + start: 'Başlat', + title: 'Takvim', + startEnd: 'Başlat/Son', + weekdays: ['Paz', 'Pzt', 'Sal', 'Çar', 'Per', 'Cum', 'Cmt'], + monthTitle: (year: number, month: number) => `${year}/${month}`, + rangePrompt: (maxRange: number) => `En fazla ${maxRange} gün seçin`, + }, + vanContactCard: { + addText: 'Kişi bilgisi ekle', + }, + vanContactList: { + addText: 'Yeni kişi ekle', + }, + vanPagination: { + prev: 'Önceki', + next: 'Sonraki', + }, + vanPullRefresh: { + pulling: 'Yenilemek için çekin...', + loosing: 'Yenilemek için bırakın...', + }, + vanSubmitBar: { + label: 'Toplam:', + }, + vanCoupon: { + unlimited: 'Sınırsız', + discount: (discount: number) => `%${discount * 10} indirim`, + condition: (condition: number) => `En az ${condition}`, + }, + vanCouponCell: { + title: 'Kupon', + tips: 'Kupon yok', + count: (count: number) => `${count} adet teklif var`, + }, + vanCouponList: { + empty: 'Kupon yok', + exchange: 'Takas', + close: 'Kapat', + enable: 'Mevcut', + disabled: 'Mevcut değil', + placeholder: 'Kupon kodu', + }, + vanAddressEdit: { + area: 'Alan', + postal: 'Posta', + areaEmpty: 'Lütfen alıcı alanını seçin', + addressEmpty: 'Adres boş olamaz!', + postalEmpty: 'Yanlış posta kodu', + defaultAddress: 'Varsayılan adres olarak ayarla', + telPlaceholder: 'Telefone', + namePlaceholder: 'İsim', + areaPlaceholder: 'Alan', + }, + vanAddressEditDetail: { + label: 'Adres', + placeholder: 'Adres', + }, + vanAddressList: { + add: 'Yeni adres ekle', + }, +}; diff --git a/src-next/locale/lang/zh-CN.ts b/src-next/locale/lang/zh-CN.ts new file mode 100644 index 000000000..c9010ff82 --- /dev/null +++ b/src-next/locale/lang/zh-CN.ts @@ -0,0 +1,78 @@ +export default { + name: '姓名', + tel: '电话', + save: '保存', + confirm: '确认', + cancel: '取消', + delete: '删除', + complete: '完成', + loading: '加载中...', + telEmpty: '请填写电话', + nameEmpty: '请填写姓名', + nameInvalid: '请输入正确的姓名', + confirmDelete: '确定要删除吗', + telInvalid: '请输入正确的手机号', + vanCalendar: { + end: '结束', + start: '开始', + title: '日期选择', + confirm: '确定', + startEnd: '开始/结束', + weekdays: ['日', '一', '二', '三', '四', '五', '六'], + monthTitle: (year: number, month: number) => `${year}年${month}月`, + rangePrompt: (maxRange: number) => `选择天数不能超过 ${maxRange} 天`, + }, + vanContactCard: { + addText: '添加联系人', + }, + vanContactList: { + addText: '新建联系人', + }, + vanPagination: { + prev: '上一页', + next: '下一页', + }, + vanPullRefresh: { + pulling: '下拉即可刷新...', + loosing: '释放即可刷新...', + }, + vanSubmitBar: { + label: '合计:', + }, + vanCoupon: { + unlimited: '无使用门槛', + discount: (discount: number) => `${discount}折`, + condition: (condition: number) => `满${condition}元可用`, + }, + vanCouponCell: { + title: '优惠券', + tips: '暂无可用', + count: (count: number) => `${count}张可用`, + }, + vanCouponList: { + empty: '暂无优惠券', + exchange: '兑换', + close: '不使用优惠券', + enable: '可用', + disabled: '不可用', + placeholder: '请输入优惠码', + }, + vanAddressEdit: { + area: '地区', + postal: '邮政编码', + areaEmpty: '请选择地区', + addressEmpty: '请填写详细地址', + postalEmpty: '邮政编码格式不正确', + defaultAddress: '设为默认收货地址', + telPlaceholder: '收货人手机号', + namePlaceholder: '收货人姓名', + areaPlaceholder: '选择省 / 市 / 区', + }, + vanAddressEditDetail: { + label: '详细地址', + placeholder: '街道门牌、楼层房间号等信息', + }, + vanAddressList: { + add: '新增地址', + }, +}; diff --git a/src-next/locale/lang/zh-HK.ts b/src-next/locale/lang/zh-HK.ts new file mode 100644 index 000000000..3d567b08f --- /dev/null +++ b/src-next/locale/lang/zh-HK.ts @@ -0,0 +1,78 @@ +export default { + name: '姓名', + tel: '電話', + save: '保存', + confirm: '確認', + cancel: '取消', + delete: '刪除', + complete: '完成', + loading: '加載中...', + telEmpty: '請填寫電話', + nameEmpty: '請填寫姓名', + nameInvalid: '請輸入正確的姓名', + confirmDelete: '確定要刪除嗎', + telInvalid: '請填寫正確的電話', + vanCalendar: { + end: '結束', + start: '開始', + title: '日期選擇', + confirm: '確定', + startEnd: '開始/結束', + weekdays: ['日', '壹', '二', '三', '四', '五', '六'], + monthTitle: (year: number, month: number) => `${year}年${month}月`, + rangePrompt: (maxRange: number) => `選擇天數不能超過 ${maxRange} 天`, + }, + vanContactCard: { + addText: '添加聯系人', + }, + vanContactList: { + addText: '新建聯系人', + }, + vanPagination: { + prev: '上一頁', + next: '下一頁', + }, + vanPullRefresh: { + pulling: '下拉即可刷新...', + loosing: '釋放即可刷新...', + }, + vanSubmitBar: { + label: '合計:', + }, + vanCoupon: { + unlimited: '無使用門檻', + discount: (discount: number) => `${discount}折`, + condition: (condition: number) => `滿${condition}元可用`, + }, + vanCouponCell: { + title: '優惠券', + tips: '暫無可用', + count: (count: number) => `${count}張可用`, + }, + vanCouponList: { + empty: '暫無優惠券', + exchange: '兌換', + close: '不使用優惠', + enable: '可使用優惠券', + disabled: '不可使用優惠券', + placeholder: '請輸入優惠碼', + }, + vanAddressEdit: { + area: '地區', + postal: '郵政編碼', + areaEmpty: '請選擇地區', + addressEmpty: '請填寫詳細地址', + postalEmpty: '郵政編碼格式不正確', + defaultAddress: '設為默認收貨地址', + telPlaceholder: '收貨人手機號', + namePlaceholder: '收貨人姓名', + areaPlaceholder: '選擇省 / 市 / 區', + }, + vanAddressEditDetail: { + label: '詳細地址', + placeholder: '街道門牌、樓層房間號等信息', + }, + vanAddressList: { + add: '新增地址', + }, +}; diff --git a/src-next/locale/lang/zh-TW.ts b/src-next/locale/lang/zh-TW.ts new file mode 100644 index 000000000..aecda17ec --- /dev/null +++ b/src-next/locale/lang/zh-TW.ts @@ -0,0 +1,78 @@ +export default { + name: '姓名', + tel: '電話', + save: '儲存', + confirm: '確認', + cancel: '取消', + delete: '刪除', + complete: '完成', + loading: '載入中...', + telEmpty: '請填寫電話', + nameEmpty: '請填寫姓名', + nameInvalid: '請輸入正確的姓名', + confirmDelete: '確定要刪除嗎', + telInvalid: '請填寫正確的電話', + vanCalendar: { + end: '結束', + start: '開始', + title: '日期選擇', + confirm: '確定', + startEnd: '開始/結束', + weekdays: ['日', '壹', '二', '三', '四', '五', '六'], + monthTitle: (year: number, month: number) => `${year}年${month}月`, + rangePrompt: (maxRange: number) => `選擇天數不能超過 ${maxRange} 天`, + }, + vanContactCard: { + addText: '新增聯絡人', + }, + vanContactList: { + addText: '建立聯絡人', + }, + vanPagination: { + prev: '上一頁', + next: '下一頁', + }, + vanPullRefresh: { + pulling: '下拉即可刷新...', + loosing: '釋放即可刷新...', + }, + vanSubmitBar: { + label: '合計:', + }, + vanCoupon: { + unlimited: '無使用門檻', + discount: (discount: number) => `${discount}折`, + condition: (condition: number) => `滿${condition}元可用`, + }, + vanCouponCell: { + title: '優惠券', + tips: '暫無可用', + count: (count: number) => `${count}張可用`, + }, + vanCouponList: { + empty: '暫無優惠券', + exchange: '兌換', + close: '不使用優惠', + enable: '可使用優惠券', + disabled: '不可使用優惠券', + placeholder: '請輸入優惠代碼', + }, + vanAddressEdit: { + area: '地區', + postal: '郵遞區號', + areaEmpty: '請選擇地區', + addressEmpty: '請填寫詳細地址', + postalEmpty: '郵遞區號格式不正確', + defaultAddress: '設為預設收貨地址', + telPlaceholder: '收貨人手機號碼', + namePlaceholder: '收貨人姓名', + areaPlaceholder: '選擇縣 / 市', + }, + vanAddressEditDetail: { + label: '詳細地址', + placeholder: '街道門牌、樓層房號等資訊', + }, + vanAddressList: { + add: '新增地址', + }, +}; diff --git a/src-next/utils/create/i18n.ts b/src-next/utils/create/i18n.ts new file mode 100644 index 000000000..7236fbc6b --- /dev/null +++ b/src-next/utils/create/i18n.ts @@ -0,0 +1,16 @@ +import { get, isFunction } from '../../../src/utils'; +import { camelize } from '../../../src/utils/format/string'; +import locale from '../../locale'; + +export function createI18N(name: string) { + const prefix = camelize(name) + '.'; + + return function (path: string, ...args: any[]): string { + const messages = locale.messages(); + const message = get(messages, prefix + path) || get(messages, path); + + return isFunction(message) ? message(...args) : message; + }; +} + +export type Translate = ReturnType; diff --git a/src-next/utils/create/index.ts b/src-next/utils/create/index.ts index 0b89a657b..8a7b40bcf 100644 --- a/src-next/utils/create/index.ts +++ b/src-next/utils/create/index.ts @@ -1,11 +1,11 @@ import { createBEM, BEM } from './bem'; import { createComponent } from './component'; -// import { createI18N, Translate } from './i18n'; +import { createI18N, Translate } from './i18n'; type CreateNamespaceReturn = [ ReturnType, BEM, - // Translate + Translate ]; export function createNamespace(name: string): CreateNamespaceReturn { @@ -13,6 +13,6 @@ export function createNamespace(name: string): CreateNamespaceReturn { return [ createComponent(name), createBEM(name), - // createI18N(name) + createI18N(name) ]; } diff --git a/src/utils/index.ts b/src/utils/index.ts index b17f4eabc..feffd5dbf 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,9 +1,9 @@ -import Vue from 'vue'; +// import Vue from 'vue'; -export { createNamespace } from './create'; +// export { createNamespace } from './create'; export { addUnit } from './format/unit'; -export const isServer: boolean = Vue.prototype.$isServer; +// export const isServer: boolean = Vue.prototype.$isServer; // eslint-disable-next-line @typescript-eslint/no-empty-function export function noop() {}