Bladeren bron

feat: 首页i18配置

liangan 1 week geleden
bovenliggende
commit
37fa090435

+ 1 - 0
eslint.config.mjs

@@ -27,6 +27,7 @@ export default uniHelper({
     'jsdoc/require-returns-description': 'off',
     'ts/no-empty-object-type': 'off',
     'no-extend-native': 'off',
+    'vue/no-v-text-v-html-on-component': 'off', // 允许在 uni-app 组件上使用 v-html
   },
   formatters: {
     /**

+ 26 - 0
src/components/TextWithBreaks/TextWithBreaks.vue

@@ -0,0 +1,26 @@
+<script lang="ts" setup>
+interface Props {
+  /** 要显示的文本内容 */
+  text?: string
+  /** 自定义CSS类名 */
+  customClass?: string
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  text: '',
+  customClass: '',
+})
+
+// 将 \n 转换为 <br> 标签
+const formattedText = computed(() => {
+  return props.text.replace(/\n/g, '<br>')
+})
+</script>
+
+<template>
+  <view :class="props.customClass" v-html="formattedText" />
+</template>
+
+<style lang="scss" scoped>
+// 可以在这里添加默认样式
+</style>

+ 10 - 1
src/locale/bn.json

@@ -1,3 +1,12 @@
 {
-  "tabbar.home": "HomeMjl"
+  "home.missionCenter": "মিশন\nসেন্টার",
+  "home.refer&earn": "রেফার\nএবং আয়",
+  "home.vip": "ভিআইপি\nসদস্যতা",
+  "home.bestSellers": "সেরা\nবিক্রেতা",
+  "home.topChampions": "শীর্ষ\nচ্যাম্পিয়ন",
+  "home.news": "নতুন",
+  "home.priceTab.300spot": "৩০০স্পট",
+  "home.priceTab.500spot": "৫০০স্পট",
+  "home.priceTab.1000spot": "১০০০স্পট",
+  "home.priceTab.2000spot": "২০০০স্পট"
 }

+ 10 - 5
src/locale/en.json

@@ -1,9 +1,14 @@
 {
-  "home.missionCenter": "Mission Center",
-  "home.refer&earn": "Refer & Earn",
-  "home.vip": "VIP Membership",
-  "home.bestSellers": "Best Sellers",
-  "home.topChampions": "Top Champions",
+  "home.missionCenter": "Mission\nCenter",
+  "home.refer&earn": "Refer\n&Earn",
+  "home.vip": "VIP\nMembership",
+  "home.bestSellers": "Best\nSellers",
+  "home.topChampions": "Top\nChampions",
+  "home.news": "News",
+  "home.priceTab.300spot": "300Spot",
+  "home.priceTab.500spot": "500Spot",
+  "home.priceTab.1000spot": "1000Spot",
+  "home.priceTab.2000spot": "2000Spot",
   "search.placeholder": "Search",
   "search.filterPrice": "All Price",
   "search.filterCategory": "Category",

+ 22 - 0
src/locale/index.ts

@@ -79,4 +79,26 @@ function formatI18n(template: string, data?: any) {
 export function t(key, data?) {
   return formatI18n(getTemplateByKey(key), data)
 }
+
+/**
+ * 处理文本中的换行符,将 \n 转换为 <br> 标签
+ * @param text 包含换行符的文本
+ * @returns 转换后的HTML字符串
+ */
+export function formatTextWithBreaks(text: string): string {
+  if (!text)
+    return ''
+  return text.replace(/\n/g, '<br>')
+}
+
+/**
+ * 带换行处理的国际化函数
+ * @param key 多语言的key
+ * @param data 需要传递的数据对象
+ * @returns 处理换行符后的HTML字符串
+ */
+export function tWithBreaks(key: string, data?: any): string {
+  const text = t(key, data)
+  return formatTextWithBreaks(text)
+}
 export default i18n

+ 10 - 1
src/locale/zh-Hans.json

@@ -1,3 +1,12 @@
 {
-
+  "home.missionCenter": "任务中心",
+  "home.refer&earn": "推荐赚钱",
+  "home.vip": "VIP会员",
+  "home.bestSellers": "热销商品",
+  "home.topChampions": "顶级冠军",
+  "home.news": "新品",
+  "home.priceTab.300spot": "300积分",
+  "home.priceTab.500spot": "500积分",
+  "home.priceTab.1000spot": "1000积分",
+  "home.priceTab.2000spot": "2000积分"
 }

+ 2 - 0
src/main.ts

@@ -2,6 +2,7 @@ import { createSSRApp } from 'vue'
 import App from './App.vue'
 import { prototypeInterceptor, requestInterceptor, routeInterceptor } from './interceptors'
 import i18n from './locale/index'
+import i18nHelpers from './plugins/i18n-helpers'
 import store from './store'
 import '@/style/index.scss'
 import 'virtual:uno.css'
@@ -17,6 +18,7 @@ export function createApp() {
   const app = createSSRApp(App)
   app.use(store)
   app.use(i18n)
+  app.use(i18nHelpers)
   app.use(routeInterceptor)
   app.use(requestInterceptor)
   app.use(prototypeInterceptor)

+ 7 - 7
src/pages/index/index.vue

@@ -95,25 +95,25 @@ const priceTab = ref<number>(0)
 // 300Spot    500Spot    1000Spot    2000Spot
 const priceTabList = ref([
   {
-    title: '300Spot',
+    title: 'home.priceTab.300spot',
     value: 300,
     minPrice: 0,
     maxPrice: 300,
   },
   {
-    title: '500Spot',
+    title: 'home.priceTab.500spot',
     value: 500,
     minPrice: 300,
     maxPrice: 500,
   },
   {
-    title: '1000Spot',
+    title: 'home.priceTab.1000spot',
     value: 1000,
     minPrice: 500,
     maxPrice: 1000,
   },
   {
-    title: '2000Spot',
+    title: 'home.priceTab.2000spot',
     value: 2000,
     minPrice: 1000,
     maxPrice: 2000,
@@ -173,14 +173,14 @@ onLoad(() => {
       <view class="flex items-end justify-between pb-22rpx pt-24rpx">
         <view v-for="(item, index) in navIcons" :key="index" class="flex flex-col items-center" @click="toPage(item.url)">
           <image :src="item.image" :style="`width: ${item.size}; height: ${item.size};`" />
-          <view class="mt-14rpx text-center text-22rpx text-#898989 font-bold">
+          <view class="mt-14rpx whitespace-pre-line text-center text-22rpx text-#898989 font-bold">
             {{ $t(item.title) }}
           </view>
         </view>
       </view>
       <view v-if="newProducts.length">
         <view class="mb-16rpx text-32rpx">
-          News
+          {{ $t('home.news') }}
         </view>
         <scroll-view scroll-x>
           <view class="flex items-center gap-22rpx pb-24rpx">
@@ -191,7 +191,7 @@ onLoad(() => {
       <view>
         <wd-tabs v-model="priceTab" :line-width="0" :line-height="0" @change="onPriceTabChange">
           <template v-for="item in priceTabList" :key="item">
-            <wd-tab :title="item.title" />
+            <wd-tab :title="$t(item.title)" />
           </template>
         </wd-tabs>
         <view class="grid grid-cols-2 gap-22rpx">

+ 1 - 1
src/pages/referEarn/referEarn.vue

@@ -45,7 +45,7 @@ async function queryList(pageNo: number, pageSize: number) {
 </script>
 
 <template>
-  <wd-navbar custom-class="bg-transparent!" :bordered="false" fixed>
+  <wd-navbar custom-class="bg-transparent!" safe-area-inset-top :bordered="false" fixed>
     <template #left>
       <wd-icon name="thin-arrow-left" color="#fff" size="32rpx" @click="goBack" />
     </template>

+ 18 - 0
src/plugins/i18n-helpers.ts

@@ -0,0 +1,18 @@
+import type { App } from 'vue'
+import { formatTextWithBreaks, tWithBreaks } from '@/locale/index'
+
+// 声明全局属性类型
+declare module '@vue/runtime-core' {
+  interface ComponentCustomProperties {
+    $tWithBreaks: typeof tWithBreaks
+    $formatTextWithBreaks: typeof formatTextWithBreaks
+  }
+}
+
+export default {
+  install(app: App) {
+    // 注册全局方法
+    app.config.globalProperties.$tWithBreaks = tWithBreaks
+    app.config.globalProperties.$formatTextWithBreaks = formatTextWithBreaks
+  },
+}

BIN
src/static/images/TOP-.png