diff --git a/README.md b/README.md index 2cd83c12b..d70675c76 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ - 🚀 支持 APP、H5、微信小程序 等平台. - 🚀 60+ 个高质量组件,覆盖移动端主流场景. - 💪 使用 Typescript 构建,提供良好的组件类型系统. -- 💪 采用 Vue3 最新特性,提升组件性能. +- 🌍 支持国际化,内置 6 种语言包. - 📖 提供丰富的文档和组件示例. - 🎨 支持修改 CSS 变量实现主题定制. - 🍭 支持暗黑模式 diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 2baf7add4..fd01dafe4 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,17 +1,17 @@ /* * @Author: weisheng * @Date: 2023-07-27 10:26:09 - * @LastEditTime: 2024-01-06 22:20:13 + * @LastEditTime: 2024-01-26 13:32:22 * @LastEditors: weisheng * @Description: - * @FilePath: /wot-design-uni/docs/.vitepress/config.ts + * @FilePath: \wot-design-uni\docs\.vitepress\config.ts * 记得注释 */ import { defineConfig } from 'vitepress'; export default defineConfig({ title: `Wot Design Uni`, - description: '一个参照Wot-design打造的uni-app组件库', + description: '一个参照wot-design打造的uni-app组件库', head: [ ['link', { rel: 'icon', href: '/favicon.ico' }], ['script', {}, ` @@ -69,15 +69,17 @@ export default defineConfig({ { text: '字体', link: '/guide/typography', + }, { + text: '常见问题', + link: '/guide/common-problems', }, { + text: '国际化', + link: '/guide/locale', + }, { text: '更新日志', link: '/guide/changelog', }, - { - text: '常见问题', - link: '/guide/common-problems', - } ] }, { @@ -133,13 +135,17 @@ export default defineConfig({ link: '/guide/typography', }, { - text: '更新日志', - link: '/guide/changelog', + text: '国际化', + link: '/guide/locale', }, { text: '常见问题', link: '/guide/common-problems', - } + }, + { + text: '更新日志', + link: '/guide/changelog', + }, ], '/reward/': [ { @@ -151,7 +157,7 @@ export default defineConfig({ link: '/reward/donor', }, ], - + '/component/': [ { text: '基础', @@ -184,7 +190,7 @@ export default defineConfig({ ] }, { - + text: "导航", items: [{ link: "/component/pagination", @@ -209,7 +215,7 @@ export default defineConfig({ text: "Sidebar 侧边栏" }] }, { - + text: "数据输入", items: [{ link: "/component/calendar", @@ -324,7 +330,7 @@ export default defineConfig({ text: "NumberKeyboard 数字键盘" }] }, { - + text: "数据展示", items: [{ link: "/component/badge", @@ -384,7 +390,7 @@ export default defineConfig({ } ] } - + }, }) \ No newline at end of file diff --git a/docs/component/picker.md b/docs/component/picker.md index 5dd7d59d7..2a57bce96 100644 --- a/docs/component/picker.md +++ b/docs/component/picker.md @@ -87,7 +87,7 @@ const columns = ref([ 传入 `column-change` 属性,其类型为 `function`,接收 pickerView 实例、选中项、当前修改列的下标、resolve 作为入参,根据选中项和列下标进行判断,通过 pickerView 实例暴露出来的 `setColumnData` 方法修改其他列的数据源,当修改完成后需要执行 `resolve()` 告知组件修改完成以继续执行,如果 `column-change` 包含异步操作,也可以使组件按照异步顺序进行执行。 -> resolve 参数为 1.4.0 添加,每次修改完后都需要调用 resolve() 通知组件。 +> 每次修改完后都需要调用 resolve() 通知组件。 ```html 0.2.20 + +Wot Design Uni 默认使用中文语言,同时支持多语言切换,如果你希望使用其他语言,你可以参考下面的方案。 + +:::warning 注意点 +目前组件库发布到 npm 上的包是未经编译的`vue`与`ts`,而 Vite 会将[预构建](https://cn.vitejs.dev/guide/dep-pre-bundling.html)的依赖项缓存到 `node_modules/.vite`,组件库的国际化的实现是基于`reactive`实现的数据共享,在`dev`阶段就会出现页面使用预构建产物中的国际化数据,而组件库使用组件库内部的国际化数据,所以在非`uni_modules`模式引入时,需要在`vite.config.ts`中增加以下配置: + +```ts +import { defineConfig } from 'vite' +import uni from '@dcloudio/vite-plugin-uni' + +export default defineConfig({ + ... + optimizeDeps: { + exclude: process.env.UNI_PLATFORM === 'h5' && process.env.NODE_ENV === 'development' ? ['wot-design-uni'] : [] + } + ... +}) + +``` + +使用[optimizeDeps.exclude](https://cn.vitejs.dev/config/dep-optimization-options.html#optimizedeps-exclude)在预构建中强制排除`wot-design-uni`模块,在`uni_modules`模式下,不需要做任何处理。 + +::: + +## 使用其他语言 + +我们通过 **Locale** 组件实现多语言支持,使用 **Locale.use** 方法可以切换当前使用的语言。 + +```typescript +import { Locale } from 'wot-design-uni' +// 引入英文语言包 +import enUS from 'wot-design-uni/locale/lang/en-US' + +Locale.use('en-US', enUS) +``` + +## 覆盖语言包 + +通过 **Locale.add** 方法可以实现文案的修改和扩展,示例如下: + +```typescript +import { Locale } from 'wot-design-uni' + +const messages = { + 'zh-CN': { + calendar: { + title: '请选择日期' // 将'选择日期'修改为'请选择日期' + } + } +} + +Locale.add(messages) +``` + +## 支持的语言 + +| 语言 | 文件名 | 版本 | +| ---------------- | --------- | --------- | +| 简体中文 | zh-CN | `v0.2.20` | +| 繁体中文(台湾) | zh-TW | `v0.2.20` | +| 繁体中文(香港) | zh-HK | `v0.2.20` | +| 英文 | en-US | `v0.2.20` | +| 泰文 | th-TH | `v0.2.20` | +| 越南文 | vi-VN | `v0.2.20` | + +如果你需要使用其他的语言,欢迎贡献 [PR](https://github.com/Moonofweisheng/wot-design-uni/pulls),只需在[这里](https://github.com/Moonofweisheng/wot-design-uni/tree/master/src/uni_modules/wot-design-uni/locale/lang)添加一个语言配置文件即可。 diff --git a/docs/index.md b/docs/index.md index aac8e5d4f..ee6fad189 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,12 +2,12 @@ layout: home title: Wot Design Uni -titleTemplate: 一个参照Wot-design打造的uni-app组件库 +titleTemplate: 基于Vue3+TS开发的uni-app组件库 hero: name: Wot Design Uni text: - tagline: 一个参照Wot-design打造的uni-app组件库 + tagline: 基于Vue3+TS开发的uni-app组件库 image: src: /wot-design.png alt: Wot Design @@ -30,17 +30,17 @@ features: title: 60+ 组件 details: 超过 60 个高质量组件,覆盖移动端主流场景。 - icon: 💪 - title: 支持 TypeScript + title: TypeScript 支持 details: 使用 Typescript 构建,提供良好的组件类型系统。 - - icon: 💪 - title: 支持 Vue3 - details: 采用 Vue3 最新特性,提升组件性能。 + - icon: 🌍 + title: 支持国际化 + details: 支持国际化,内置 6 种语言包。 - icon: 📖 title: 提供丰富的文档和组件示例 details: 文档和组件示例为开发者提供稳定的后勤保障。 - icon: 🍭 title: 支持暗黑模式和主题定制 - details: 可以定制scss变量以及组件的样式自定义。 + details: 可以定制css变量以及组件的样式自定义。 footer: false --- diff --git a/src/main.ts b/src/main.ts index a1584bad3..43eb9a91a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,7 @@ /* * @Author: weisheng * @Date: 2023-03-09 19:23:03 - * @LastEditTime: 2023-08-22 23:02:46 + * @LastEditTime: 2024-01-26 14:08:43 * @LastEditors: weisheng * @Description: * @FilePath: \wot-design-uni\src\main.ts diff --git a/src/uni_modules/wot-design-uni/components/common/lodash/debounce.ts b/src/uni_modules/wot-design-uni/components/common/lodash/debounce.ts deleted file mode 100644 index 3ed5213e5..000000000 --- a/src/uni_modules/wot-design-uni/components/common/lodash/debounce.ts +++ /dev/null @@ -1,206 +0,0 @@ -import isObject from './isObject' -import root from './internal/root' - -/** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked, or until the next browser frame is drawn. The debounced function - * comes with a `cancel` method to cancel delayed `func` invocations and a - * `flush` method to immediately invoke them. Provide `options` to indicate - * whether `func` should be invoked on the leading and/or trailing edge of the - * `wait` timeout. The `func` is invoked with the last arguments provided to the - * debounced function. Subsequent calls to the debounced function return the - * result of the last `func` invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until the next tick, similar to `setTimeout` with a timeout of `0`. - * - * If `wait` is omitted in an environment with `requestAnimationFrame`, `func` - * invocation will be deferred until the next frame is drawn (typically about - * 16ms). - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `debounce` and `throttle`. - * - * @since 0.1.0 - * @category Function - * @param {Function} func The function to debounce. - * @param {number} [wait=0] - * The number of milliseconds to delay; if omitted, `requestAnimationFrame` is - * used (if available). - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=false] - * Specify invoking on the leading edge of the timeout. - * @param {number} [options.maxWait] - * The maximum time `func` is allowed to be delayed before it's invoked. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. - * @example - * - * // Avoid costly calculations while the window size is in flux. - * jQuery(window).on('resize', debounce(calculateLayout, 150)) - * - * // Invoke `sendMail` when clicked, debouncing subsequent calls. - * jQuery(element).on('click', debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })) - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * const debounced = debounce(batchLog, 250, { 'maxWait': 1000 }) - * const source = new EventSource('/stream') - * jQuery(source).on('message', debounced) - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel) - * - * // Check for pending invocations. - * const status = debounced.pending() ? "Pending..." : "Ready" - */ -function debounce(func, wait, options?) { - let lastArgs, lastThis, maxWait, result, timerId, lastCallTime - - let lastInvokeTime = 0 - let leading = false - let maxing = false - let trailing = true - - // Bypass `requestAnimationFrame` by explicitly setting `wait=0`. - const useRAF = !wait && wait !== 0 && typeof root.requestAnimationFrame === 'function' - - if (typeof func !== 'function') { - throw new TypeError('Expected a function') - } - wait = +wait || 0 - if (isObject(options)) { - leading = !!options.leading - maxing = 'maxWait' in options - maxWait = maxing ? Math.max(+options.maxWait || 0, wait) : maxWait - trailing = 'trailing' in options ? !!options.trailing : trailing - } - - function invokeFunc(time) { - const args = lastArgs - const thisArg = lastThis - - lastArgs = lastThis = undefined - lastInvokeTime = time - result = func.apply(thisArg, args) - return result - } - - function startTimer(pendingFunc, wait) { - if (useRAF) { - root.cancelAnimationFrame(timerId) - return root.requestAnimationFrame(pendingFunc) - } - return setTimeout(pendingFunc, wait) - } - - function cancelTimer(id) { - if (useRAF) { - return root.cancelAnimationFrame(id) - } - clearTimeout(id) - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time - // Start the timer for the trailing edge. - timerId = startTimer(timerExpired, wait) - // Invoke the leading edge. - return leading ? invokeFunc(time) : result - } - - function remainingWait(time) { - const timeSinceLastCall = time - lastCallTime - const timeSinceLastInvoke = time - lastInvokeTime - const timeWaiting = wait - timeSinceLastCall - - return maxing ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting - } - - function shouldInvoke(time) { - const timeSinceLastCall = time - lastCallTime - const timeSinceLastInvoke = time - lastInvokeTime - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || (maxing && timeSinceLastInvoke >= maxWait) - } - - function timerExpired() { - const time = Date.now() - if (shouldInvoke(time)) { - return trailingEdge(time) - } - // Restart the timer. - timerId = startTimer(timerExpired, remainingWait(time)) - } - - function trailingEdge(time) { - timerId = undefined - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time) - } - lastArgs = lastThis = undefined - return result - } - - function cancel() { - if (timerId !== undefined) { - cancelTimer(timerId) - } - lastInvokeTime = 0 - lastArgs = lastCallTime = lastThis = timerId = undefined - } - - function flush() { - return timerId === undefined ? result : trailingEdge(Date.now()) - } - - function pending() { - return timerId !== undefined - } - - function debounced(this: any, ...args) { - const time = Date.now() - const isInvoking = shouldInvoke(time) - - lastArgs = args - lastThis = this - lastCallTime = time - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime) - } - if (maxing) { - // Handle invocations in a tight loop. - timerId = startTimer(timerExpired, wait) - return invokeFunc(lastCallTime) - } - } - if (timerId === undefined) { - timerId = startTimer(timerExpired, wait) - } - return result - } - - debounced.cancel = cancel - debounced.flush = flush - debounced.pending = pending - return debounced -} - -export default debounce diff --git a/src/uni_modules/wot-design-uni/components/common/lodash/internal/freeGlobal.ts b/src/uni_modules/wot-design-uni/components/common/lodash/internal/freeGlobal.ts deleted file mode 100644 index 59519fe3f..000000000 --- a/src/uni_modules/wot-design-uni/components/common/lodash/internal/freeGlobal.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** Detect free variable `global` from Node.js. */ -const freeGlobal = typeof global === 'object' && global !== null && global.Object === Object && global - -export default freeGlobal diff --git a/src/uni_modules/wot-design-uni/components/common/lodash/internal/root.ts b/src/uni_modules/wot-design-uni/components/common/lodash/internal/root.ts deleted file mode 100644 index 70cb56df6..000000000 --- a/src/uni_modules/wot-design-uni/components/common/lodash/internal/root.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * @Author: weisheng - * @Date: 2023-09-01 21:42:32 - * @LastEditTime: 2023-09-03 11:43:06 - * @LastEditors: weisheng - * @Description: - * @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\common\lodash\internal\root.ts - * 记得注释 - */ -import freeGlobal from './freeGlobal' - -/** Detect free variable `globalThis` */ -// eslint-disable-next-line eqeqeq -const freeGlobalThis = typeof globalThis === 'object' && globalThis !== null && globalThis.Object == Object && globalThis - -/** Detect free variable `self`. */ -const freeSelf = typeof self === 'object' && self !== null && self.Object === Object && self - -/** Used as a reference to the global object. */ -// eslint-disable-next-line no-new-func -const root = freeGlobalThis || freeGlobal || freeSelf || Function('return this')() - -export default root diff --git a/src/uni_modules/wot-design-uni/components/common/lodash/isObject.ts b/src/uni_modules/wot-design-uni/components/common/lodash/isObject.ts deleted file mode 100644 index e9e81bff5..000000000 --- a/src/uni_modules/wot-design-uni/components/common/lodash/isObject.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * isObject({}) - * // => true - * - * isObject([1, 2, 3]) - * // => true - * - * isObject(Function) - * // => true - * - * isObject(null) - * // => false - */ -function isObject(value) { - const type = typeof value - return value != null && (type === 'object' || type === 'function') -} - -export default isObject diff --git a/src/uni_modules/wot-design-uni/components/common/util.ts b/src/uni_modules/wot-design-uni/components/common/util.ts index cb9786198..af35f92dc 100644 --- a/src/uni_modules/wot-design-uni/components/common/util.ts +++ b/src/uni_modules/wot-design-uni/components/common/util.ts @@ -1,6 +1,3 @@ -/* eslint-disable no-prototype-builtins */ -import debounce from './lodash/debounce' - /** * 生成uuid * @returns string @@ -78,8 +75,6 @@ export const defaultFunction = (value: T): T => value */ export const isDef = (value: T): value is NonNullable => value !== undefined && value !== null -export { debounce } - /** * @description 防止数字小于零 * @param {number} num @@ -275,6 +270,15 @@ export function kebabCase(word: string): string { return newWord } +/** + * 将短横线链接转换为驼峰命名 + * @param word 需要转换的短横线链接 + * @returns 转换后的驼峰命名字符串 + */ +export function camelCase(word: string): string { + return word.replace(/-(\w)/g, (_, c) => c.toUpperCase()) +} + /** * 检查给定值是否为数组。 * @param {any} value 要检查的值 @@ -482,6 +486,7 @@ export function deepMerge>(target: T, source: Reco // 遍历源对象的属性 for (const prop in source) { + // eslint-disable-next-line no-prototype-builtins if (!source.hasOwnProperty(prop)) continue // 使用类型断言,告诉 TypeScript 这是有效的属性 @@ -491,6 +496,25 @@ export function deepMerge>(target: T, source: Reco return target } +/** + * 深度合并两个对象。 + * @param target + * @param source + * @returns + */ +export function deepAssign(target: Record, source: Record): Record { + Object.keys(source).forEach((key) => { + const targetValue = target[key] + const newObjValue = source[key] + if (isObj(targetValue) && isObj(newObjValue)) { + deepAssign(targetValue, newObjValue) + } else { + target[key] = newObjValue + } + }) + return target +} + /** * 构建带参数的URL * @param baseUrl 基础URL @@ -510,10 +534,66 @@ export function buildUrlWithParams(baseUrl: string, params: Record any>(func: T, wait: number, options: DebounceOptions = {}): T { + let timeoutId: ReturnType | null = null + let lastArgs: any[] | undefined + let lastThis: any + let result: ReturnType | undefined + const leading = options.leading ?? false + const trailing = options.trailing ?? true + + function invokeFunc() { + if (lastArgs !== undefined) { + result = func.apply(lastThis, lastArgs) + lastArgs = undefined + } + } + + function startTimer() { + timeoutId = setTimeout(() => { + timeoutId = null + if (trailing) { + invokeFunc() + } + }, wait) + } + + function cancelTimer() { + if (timeoutId !== null) { + clearTimeout(timeoutId) + timeoutId = null + } + } + + function debounced(this: any, ...args: Parameters): ReturnType | undefined { + lastArgs = args + lastThis = this + + if (timeoutId === null) { + if (leading) { + invokeFunc() + } + startTimer() + } else if (trailing) { + cancelTimer() + startTimer() + } + + return result + } + + return debounced as T +} + // eslint-disable-next-line @typescript-eslint/ban-types export function throttle(func: Function, wait: number): Function { - let timeout: NodeJS.Timeout | null - let previous = 0 + let timeout: ReturnType | null = null + let previous: number = 0 const throttled = function (this: any, ...args: any[]) { const now = Date.now() diff --git a/src/uni_modules/wot-design-uni/components/composables/useTranslate.ts b/src/uni_modules/wot-design-uni/components/composables/useTranslate.ts new file mode 100644 index 000000000..0c0c326a2 --- /dev/null +++ b/src/uni_modules/wot-design-uni/components/composables/useTranslate.ts @@ -0,0 +1,22 @@ +/* + * @Author: weisheng + * @Date: 2024-01-25 23:06:48 + * @LastEditTime: 2024-01-26 14:00:48 + * @LastEditors: weisheng + * @Description: + * @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\composables\useTranslate.ts + * 记得注释 + */ +import { camelCase, getPropByPath, isFunction } from '../common/util' +import Locale from '../../locale' + +export const useTranslate = (name?: string) => { + const prefix = name ? camelCase(name) + '.' : '' + const translate = (key: string, ...args: unknown[]) => { + const currentMessages = Locale.messages() + const message = getPropByPath(currentMessages, prefix + key) + return isFunction(message) ? message(...args) : message + } + + return { translate } +} diff --git a/src/uni_modules/wot-design-uni/components/wd-calendar-view/month/month.vue b/src/uni_modules/wot-design-uni/components/wd-calendar-view/month/month.vue index 1e9d72466..51b3415ef 100644 --- a/src/uni_modules/wot-design-uni/components/wd-calendar-view/month/month.vue +++ b/src/uni_modules/wot-design-uni/components/wd-calendar-view/month/month.vue @@ -51,6 +51,7 @@ import { } from '../utils' import { useToast } from '../../wd-toast' import { deepClone, getType, isArray } from '../../common/util' +import { useTranslate } from '../../composables/useTranslate' interface Props { type: string @@ -70,6 +71,8 @@ const props = withDefaults(defineProps(), { allowSameDay: false }) +const { translate } = useTranslate('calendar-view') + const days = ref>>([]) const itemClass = computed(() => { @@ -295,7 +298,7 @@ function handleDateRangeChange(date) { const maxEndDate = getDayByOffset(startDate, props.maxRange - 1) value = [startDate, getDate(maxEndDate, true)] toast.show({ - msg: props.rangePrompt || `选择天数不能超过${props.maxRange}天` + msg: props.rangePrompt || translate('rangePrompt', props.maxRange) }) } else { value = [startDate, getDate(date.date, true)] diff --git a/src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue b/src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue index b171f01e7..feabffa6d 100644 --- a/src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue +++ b/src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue @@ -32,7 +32,7 @@ - {{ timeType === 'start' ? '开始' : '结束' }} + {{ timeType === 'start' ? translate('startTime') : translate('endTime') }} (), { showPanelTitle: false, hideSecond: false }) +const { translate } = useTranslate('calendar-view') const title = ref('') const scrollTop = ref(0) // 滚动位置 diff --git a/src/uni_modules/wot-design-uni/components/wd-calendar-view/utils.ts b/src/uni_modules/wot-design-uni/components/wd-calendar-view/utils.ts index 5c4e4e094..b42cfeed8 100644 --- a/src/uni_modules/wot-design-uni/components/wd-calendar-view/utils.ts +++ b/src/uni_modules/wot-design-uni/components/wd-calendar-view/utils.ts @@ -1,6 +1,17 @@ +import { dayjs } from '../common/dayjs' import { getType, padZero } from '../common/util' - -const weeks: string[] = ['日', '一', '二', '三', '四', '五', '六'] +import { useTranslate } from '../composables/useTranslate' +const { translate } = useTranslate('calendar-view') + +const weeks: string[] = [ + translate('weeks.sun'), + translate('weeks.mon'), + translate('weeks.tue'), + translate('weeks.wed'), + translate('weeks.thu'), + translate('weeks.fri'), + translate('weeks.sat') +] /** * 比较两个时间的日期是否相等 @@ -86,12 +97,7 @@ export function getMonthEndDay(year, month) { * @param {timestamp} date */ export function formatMonthTitle(date) { - date = new Date(date) - - const year = date.getFullYear() - const month = date.getMonth() + 1 - - return year + '年' + month + '月' + return dayjs(date).format(translate('monthTitle')) } /** @@ -129,9 +135,7 @@ export function getFirstDayStyle(index: number, date: number, firstDayOfWeek: nu * @param {timestamp} date */ export function formatYearTitle(date: number) { - const year = new Date(date).getFullYear() - - return year + '年' + return dayjs(date).format(translate('yearTitle')) } /** @@ -350,14 +354,14 @@ export function getTimeData({ date, minDate, maxDate, isHideSecond, filter } = { let columns: any[] = [] let hours = times(24, (index) => { return { - label: `${padZero(index)}时`, + label: translate('hour', padZero(index)), value: index, disabled: index < minHour || index > maxHour } }) let minutes = times(60, (index) => { return { - label: `${padZero(index)}分`, + label: translate('minute', padZero(index)), value: index, disabled: index < minMinute || index > maxMinute } @@ -377,7 +381,7 @@ export function getTimeData({ date, minDate, maxDate, isHideSecond, filter } = { if (!isHideSecond) { seconds = times(60, (index) => { return { - label: `${padZero(index)}秒`, + label: translate('second', padZero(index)), value: index, disabled: index < minSecond || index > maxSecond } diff --git a/src/uni_modules/wot-design-uni/components/wd-calendar-view/year/year.vue b/src/uni_modules/wot-design-uni/components/wd-calendar-view/year/year.vue index 316e3e8a0..f489a19ee 100644 --- a/src/uni_modules/wot-design-uni/components/wd-calendar-view/year/year.vue +++ b/src/uni_modules/wot-design-uni/components/wd-calendar-view/year/year.vue @@ -11,7 +11,7 @@ @click="handleDateClick(index)" > {{ item.topInfo }} - {{ item.text }}月 + {{ getMonthLabel(item.date) }} {{ item.bottomInfo }} @@ -29,9 +29,11 @@ export default { diff --git a/src/uni_modules/wot-design-uni/components/wd-tabs/wd-tabs.vue b/src/uni_modules/wot-design-uni/components/wd-tabs/wd-tabs.vue index 6e340ca81..cb7c7ff97 100644 --- a/src/uni_modules/wot-design-uni/components/wd-tabs/wd-tabs.vue +++ b/src/uni_modules/wot-design-uni/components/wd-tabs/wd-tabs.vue @@ -32,7 +32,9 @@ - 全部 + + {{ translate('all') }} + - 全部 + + {{ translate('all') }} + @@ -136,6 +140,7 @@ import { checkNumRange, debounce, getRect, getType, isDef, isNumber, isString, o import { useTouch } from '../composables/useTouch' import { TABS_KEY } from './types' import { useChildren } from '../composables/useChildren' +import { useTranslate } from '../composables/useTranslate' const $item = '.wd-tabs__nav-item' const $container = '.wd-tabs__nav-container' @@ -180,6 +185,8 @@ const props = withDefaults(defineProps(), { duration: 300 }) +const { translate } = useTranslate('tabs') + // 选中值的索引,默认第一个 const state = reactive({ activeIndex: 0 }) // navBar的下划线样式 @@ -227,7 +234,7 @@ const bodyStyle = computed(() => { * @param {Boolean } init - 是否伴随初始化操作 */ const setActive = debounce( - function (value: number = 0, init: boolean = false, setScroll: boolean = true) { + function (value: number | string = 0, init: boolean = false, setScroll: boolean = true) { // 没有tab子元素,不执行任何操作 if (items.value.length === 0) return diff --git a/src/uni_modules/wot-design-uni/components/wd-tag/wd-tag.vue b/src/uni_modules/wot-design-uni/components/wd-tag/wd-tag.vue index 688a3f169..2199c3d1d 100644 --- a/src/uni_modules/wot-design-uni/components/wd-tag/wd-tag.vue +++ b/src/uni_modules/wot-design-uni/components/wd-tag/wd-tag.vue @@ -11,7 +11,7 @@ @@ -41,6 +41,7 @@ export default {