v-t.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // directives/vT.js
  2. import { watch } from 'vue'
  3. import { lang } from '@/composables/config'
  4. /**
  5. * 解析绑定值
  6. * 支持:'key' 或 ['key', param]
  7. */
  8. const parseBinding = (val) => {
  9. if (Array.isArray(val)) {
  10. const [key, ...rest] = val
  11. if (rest.length === 0) return { key, param: undefined }
  12. if (rest.length === 1) return { key, param: rest[0] }
  13. return { key, param: rest }
  14. }
  15. return { key: val, param: undefined }
  16. }
  17. /**
  18. * 更新元素的文本内容
  19. */
  20. const updateElementText = (el, text) => {
  21. if (!el) return
  22. if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
  23. el.value = text
  24. } else if ('textContent' in el) {
  25. el.textContent = text
  26. } else if ('innerText' in el) {
  27. el.innerText = text
  28. }
  29. }
  30. /**
  31. * 获取全局 i18n 实例
  32. */
  33. const getI18n = () => {
  34. return typeof globalThis !== 'undefined' && globalThis.__i18n ? globalThis.__i18n : null
  35. }
  36. export default {
  37. mounted(el, binding) {
  38. const setState = (val) => {
  39. const { key, param } = parseBinding(val)
  40. el._vTKey = key
  41. el._vTParam = param
  42. }
  43. const update = () => {
  44. const i18n = getI18n()
  45. const key = el._vTKey
  46. const param = el._vTParam
  47. // 无 key 时显示 --
  48. if (!key) {
  49. updateElementText(el, '')
  50. return
  51. }
  52. let text = ''
  53. if (i18n) {
  54. const translated = i18n.global.t(key, param)
  55. // 如果翻译结果等于 key 本身,说明未找到翻译,显示 --
  56. text = translated === key ? '' : translated
  57. } else {
  58. text = ''
  59. }
  60. updateElementText(el, text)
  61. }
  62. setState(binding.value)
  63. update()
  64. el._vTSetState = setState
  65. el._vTUpdate = update
  66. // 监听语言变化,更新文本
  67. el._vTStopWatch = watch(
  68. () => lang.value,
  69. () => {
  70. const i18n = getI18n()
  71. if (i18n?.global?.locale?.value !== undefined) {
  72. i18n.global.locale.value = lang.value
  73. }
  74. update()
  75. },
  76. { immediate: false, flush: 'sync' }
  77. )
  78. },
  79. updated(el, binding) {
  80. if (el._vTSetState) el._vTSetState(binding.value)
  81. if (el._vTUpdate) el._vTUpdate()
  82. },
  83. unmounted(el) {
  84. if (el._vTStopWatch) {
  85. el._vTStopWatch()
  86. delete el._vTStopWatch
  87. }
  88. if (el._vTUpdate) delete el._vTUpdate
  89. if (el._vTSetState) delete el._vTSetState
  90. if (el._vTKey) delete el._vTKey
  91. if (el._vTParam) delete el._vTParam
  92. }
  93. }