Skip to content

Commit 50a4e55

Browse files
committed
添加 '30-布局支持多语言'
1 parent 53d445c commit 50a4e55

File tree

1 file changed

+292
-0
lines changed

1 file changed

+292
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
## 目标
2+
完成布局配置多语言的功能
3+
4+
## 遗留问题解决
5+
上节课我们遗留了一个多语言的问题,当我们切换多语言的时候,我们需要同时修改i18n中的多语言信息,上节课我们只修改了我们自定义的多语言。我们先来解决一下这个遗留的问题。
6+
在auto-lang.ts中添加:
7+
```typescript
8+
import { defaultLocale, loadLanguageAsync } from '~/locales'
9+
10+
export const useAppLocale = createGlobalState(() => useStorage('locale', defaultLocale))
11+
12+
export const useAutoLang = () => {
13+
const appLocale = useAppLocale()
14+
+ const { locale, getLocaleMessage } = useI18n()
15+
const setLanguage = async (lang: string) => {
16+
try {
17+
await loadLanguageAsync(lang)
18+
appLocale.value = lang
19+
+ locale.value = lang
20+
}
21+
catch (e) {
22+
23+
}
24+
}
25+
26+
watch(appLocale, (lang) => {
27+
+ if (lang && lang !== locale.value)
28+
setLanguage(lang).then(() => {})
29+
})
30+
31+
+ const naiveLocale = computed(() => getLocaleMessage(appLocale.value).naiveUI || {})
32+
return {
33+
naiveLocale,
34+
}
35+
}
36+
37+
```
38+
测试效果在pages/index.vue.
39+
40+
## 布局支持多语言
41+
接下来将我们之前所实现的布局功能我们来支持一下多语言。
42+
首先我们先在lang目录下创建一个global的文件夹,然后创建zh-CN.ts和en-US.ts的文件。
43+
在zh-CN.ts中:
44+
```typescript
45+
export default {
46+
'global.layout.setting.drawer.style': '整体风格设置',
47+
'global.layout.setting.drawer.style.light': '亮色菜单风格',
48+
'global.layout.setting.drawer.style.inverted': '反转色菜单风格',
49+
'global.layout.setting.drawer.style.dark': '黑暗菜单风格',
50+
'global.layout.setting.drawer.theme': '主题色',
51+
'global.layout.setting.drawer.theme.default': '极光绿(默认)',
52+
'global.layout.setting.drawer.theme.dustRed': '薄暮',
53+
'global.layout.setting.drawer.theme.volcano': '火山',
54+
'global.layout.setting.drawer.theme.orange': '日暮',
55+
'global.layout.setting.drawer.theme.cyan': '明青',
56+
'global.layout.setting.drawer.theme.blue': '拂晓蓝',
57+
'global.layout.setting.drawer.theme.purple': '酱紫',
58+
'global.layout.setting.drawer.theme.magenta': '洋红',
59+
'global.layout.setting.drawer.layout': '导航模式',
60+
'global.layout.setting.drawer.layout.side': '侧边菜单布局',
61+
'global.layout.setting.drawer.layout.mix': '混合菜单布局',
62+
'global.layout.setting.drawer.layout.top': '顶部菜单布局',
63+
}
64+
65+
```
66+
在 en-US.ts中:
67+
```typescript
68+
export default {
69+
'global.layout.setting.drawer.style': 'Page style setting',
70+
'global.layout.setting.drawer.style.light': 'Light menu style',
71+
'global.layout.setting.drawer.style.inverted': 'Inverted menu style',
72+
'global.layout.setting.drawer.style.dark': 'Dark menu style',
73+
'global.layout.setting.drawer.theme': 'Theme color',
74+
'global.layout.setting.drawer.theme.default': 'Pine green (default)',
75+
'global.layout.setting.drawer.theme.dustRed': 'Dust Red',
76+
'global.layout.setting.drawer.theme.volcano': 'Volcano',
77+
'global.layout.setting.drawer.theme.orange': 'Sunset',
78+
'global.layout.setting.drawer.theme.cyan': 'Cyan',
79+
'global.layout.setting.drawer.theme.blue': 'Blue',
80+
'global.layout.setting.drawer.theme.purple': 'Purple',
81+
'global.layout.setting.drawer.theme.magenta': 'Magenta',
82+
'global.layout.setting.drawer.layout': 'Navigation mode',
83+
'global.layout.setting.drawer.layout.side': 'Side menu layout',
84+
'global.layout.setting.drawer.layout.mix': 'Mix menu layout',
85+
'global.layout.setting.drawer.layout.top': 'Top menu layout',
86+
}
87+
88+
```
89+
然后我们在lang文件夹中的zh-CN.ts和en-US.ts中分别引入:
90+
zh-CN.ts
91+
```typescript
92+
import { dateZhCN, zhCN } from 'naive-ui'
93+
+ import global from './global/zh-CN'
94+
95+
export default {
96+
+ ...global,
97+
naiveUI: {
98+
locale: zhCN,
99+
dateLocale: dateZhCN,
100+
},
101+
}
102+
103+
```
104+
en-US.ts
105+
```typescript
106+
import { dateEnUS, enUS } from 'naive-ui'
107+
+ import global from './global/en-US'
108+
export default {
109+
+ ...global,
110+
naiveUI: {
111+
locale: enUS,
112+
dateLocale: dateEnUS,
113+
},
114+
}
115+
```
116+
117+
接下来我们在setting-drawer中进行配置支持多语言:
118+
在index.vue中
119+
```vue
120+
<template>
121+
<n-drawer-content>
122+
+- <Container v-if="layoutStyleList" :title="$t('global.layout.setting.drawer.style')">
123+
<n-space size="large">
124+
<template v-for="item in layoutStyleList" :key="item.id">
125+
<CheckboxLayout
126+
+- :title="$t(item.title)"
127+
:layout="item.key"
128+
:inverted="item.inverted"
129+
:dark="item.dark"
130+
:checked="item.id === layoutStyle"
131+
@click="() => $emit('update:layoutStyle', item.id)"
132+
/>
133+
</template>
134+
</n-space>
135+
</Container>
136+
+- <Container v-if="themeList" :title="$t('global.layout.setting.drawer.theme')">
137+
<n-space>
138+
<CheckboxTheme
139+
v-for="item in themeList"
140+
:key="item.key"
141+
:color="item.color"
142+
:checked="item.key === theme"
143+
@click="onThemeChange(item.key)"
144+
/>
145+
</n-space>
146+
</Container>
147+
<n-divider />
148+
+- <Container v-if="layoutList" :title="$t('global.layout.setting.drawer.layout')">
149+
<n-space size="large">
150+
<template v-for="item in layoutList" :key="item.key">
151+
<CheckboxLayout
152+
+- :title="$t(item.title)"
153+
:layout="item.key"
154+
:checked="item.key === layout"
155+
@click="() => $emit('update:layout', item.key)"
156+
/>
157+
</template>
158+
</n-space>
159+
</Container>
160+
</n-drawer-content>
161+
</template>
162+
```
163+
164+
接下来我们让我们的主题色也支持一下提示,在checkbox-theme.vue中。
165+
```vue
166+
<script lang="ts" setup>
167+
import { CheckOutlined } from '@vicons/antd'
168+
169+
defineProps<{
170+
color: string
171+
checked?: boolean
172+
+ title?: string
173+
}>()
174+
175+
+ defineEmits(['click'])
176+
</script>
177+
178+
<template>
179+
+ <n-tooltip trigger="hover">
180+
+ <template #trigger>
181+
<div
182+
:style="{ background: color }"
183+
class="flex items-center justify-center w-20px h-20px"
184+
@click="$emit('click', $event)"
185+
>
186+
<n-icon v-if="checked" size="16">
187+
<CheckOutlined />
188+
</n-icon>
189+
</div>
190+
+ </template>
191+
+ {{ title }}
192+
+ </n-tooltip>
193+
</template>
194+
195+
<style scoped>
196+
197+
</style>
198+
199+
```
200+
201+
然后在index.vue中主题色的多语言的支持:
202+
```vue
203+
<template>
204+
<CheckboxTheme
205+
v-for="item in themeList"
206+
:key="item.key"
207+
:title="$t(item.title)"
208+
:color="item.color"
209+
:checked="item.key === theme"
210+
@click="onThemeChange(item.key)"
211+
/>
212+
</template>
213+
```
214+
215+
接下来我们在stores/app.ts中做调整如下:
216+
```typescript
217+
const layoutList = computed<LayoutType[]>(() => {
218+
return [{
219+
id: 'side',
220+
key: 'side',
221+
title: 'global.layout.setting.drawer.layout.side',
222+
}, {
223+
id: 'top',
224+
225+
key: 'top',
226+
title: 'global.layout.setting.drawer.layout.top',
227+
}, {
228+
id: 'mix',
229+
key: 'mix',
230+
title: 'global.layout.setting.drawer.layout.mix',
231+
}]
232+
})
233+
234+
235+
const layoutStyleList = computed<LayoutType[]>(() => {
236+
const list: LayoutType[] = [
237+
{
238+
id: 'light',
239+
key: 'side',
240+
title: 'global.layout.setting.drawer.style.light',
241+
},
242+
]
243+
244+
if (layout.layout !== 'mix') {
245+
list.push({
246+
id: 'inverted',
247+
key: 'side',
248+
inverted: true,
249+
title: 'global.layout.setting.drawer.style.inverted',
250+
})
251+
}
252+
else {
253+
if (layout.layoutStyle !== 'dark')
254+
updateLayoutStyle('light')
255+
}
256+
list.push({
257+
id: 'dark',
258+
key: 'side',
259+
title: 'global.layout.setting.drawer.style.dark',
260+
dark: true,
261+
})
262+
return list
263+
})
264+
265+
```
266+
然后让主题色支持多语言的提示信息。
267+
在config/theme.ts中增加类型
268+
```typescript
269+
export interface ThemeType {
270+
color: string
271+
key: string
272+
+ title?: string
273+
}
274+
275+
```
276+
然后在app.ts中增加:
277+
```typescript
278+
const themeList = computed<ThemeType[]>(() => {
279+
const list = []
280+
const myColors = isDark.value ? darkColors : colors
281+
for (const key in myColors) {
282+
const value = myColors[key]
283+
list.push({
284+
color: value.common?.primaryColor as string,
285+
key,
286+
+ title: `global.layout.setting.drawer.theme.${key}`,
287+
})
288+
}
289+
return list
290+
})
291+
```
292+
然后测试效果。

0 commit comments

Comments
 (0)