Skip to content

Commit 7b81b25

Browse files
committed
feat(docs): add locale toggler component and support for multiple languages in layouts
1 parent 4de2bbf commit 7b81b25

File tree

8 files changed

+82
-5
lines changed

8 files changed

+82
-5
lines changed

docs/locales/en.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@ intro:
1212
aka: Also known as
1313
whats-your-name: What's your name?
1414
not-found: Not found
15+
locale:
16+
en: English
17+
zh-CN: Chinese
18+
layout:
19+
default: Default Layout
20+
home: Home Layout
21+
about: About Layout

docs/locales/zh-CN.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@ intro:
1212
aka: 也叫
1313
whats-your-name: 输入你的名字
1414
not-found: 未找到页面
15+
locale:
16+
en: 英语
17+
zh-CN: 中文
18+
layout:
19+
default: 默认布局
20+
home: 首页布局
21+
about: 关于布局
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue';
3+
import type { MenuOptionData } from '@soybeanjs/ui';
4+
import { availableLocales, loadLanguageAsync } from '@/modules/i18n';
5+
6+
const { t, locale } = useI18n();
7+
8+
const items = computed(() => {
9+
return availableLocales.map(item => {
10+
return {
11+
label: t(`locale.${item}`),
12+
value: item
13+
};
14+
});
15+
});
16+
17+
const onSelectLocale = async (item: MenuOptionData<string>) => {
18+
await loadLanguageAsync(item.value);
19+
locale.value = item.value;
20+
};
21+
</script>
22+
23+
<template>
24+
<SDropdownMenuRadio :model-value="locale" :items="items" @select="onSelectLocale">
25+
<template #trigger>
26+
<SButtonIcon icon="lucide:languages" size="lg" />
27+
</template>
28+
</SDropdownMenuRadio>
29+
</template>

docs/src/components/tool-bar.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script setup lang="ts"></script>
2+
3+
<template>
4+
<div class="flex items-center gap-2">
5+
<LocaleToggler />
6+
<ThemeSchemaToggler />
7+
</div>
8+
</template>

docs/src/layouts/404.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ useHead({
1818
<div class="h-full p-4">
1919
<SCard :title="t('not-found')" class="h-full">
2020
<template #extra>
21-
<ThemeSchemaToggler />
21+
<ToolBar />
2222
</template>
2323
<div>
2424
<h3 class="text-center">The page {{ route.path }} is {{ t('not-found') }}</h3>

docs/src/layouts/default.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
<script setup lang="ts">
2+
const { t } = useI18n();
3+
4+
useHead({
5+
title: () => t('layout.default')
6+
});
7+
</script>
8+
19
<template>
210
<div class="h-full p-4">
3-
<SCard title="Default Layout" class="h-full">
11+
<SCard :title="t('layout.default')" class="h-full">
412
<template #extra>
5-
<ThemeSchemaToggler />
13+
<ToolBar />
614
</template>
715
<RouterView />
816
</SCard>

docs/src/layouts/home.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
<script setup lang="ts">
2+
const { t } = useI18n();
3+
4+
useHead({
5+
title: () => t('layout.home')
6+
});
7+
</script>
8+
19
<template>
210
<div class="h-full p-4">
3-
<SCard title="Home Layout" class="h-full">
11+
<SCard :title="t('layout.home')" class="h-full">
412
<template #extra>
5-
<ThemeSchemaToggler />
13+
<ToolBar />
614
</template>
715
<RouterView />
816
</SCard>

docs/src/typings/components.d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,39 @@ export {}
1212
/* prettier-ignore */
1313
declare module 'vue' {
1414
export interface GlobalComponents {
15+
LocaleToggler: typeof import('./../components/locale-toggler.vue')['default']
1516
RouterLink: typeof import('vue-router')['RouterLink']
1617
RouterView: typeof import('vue-router')['RouterView']
1718
SButton: typeof import('@soybeanjs/ui')['SButton']
19+
SButtonIcon: typeof import('@soybeanjs/ui')['SButtonIcon']
1820
SButtonLink: typeof import('@soybeanjs/ui')['SButtonLink']
1921
SCard: typeof import('@soybeanjs/ui')['SCard']
2022
SConfigProvider: typeof import('@soybeanjs/ui')['SConfigProvider']
2123
SDialog: typeof import('@soybeanjs/ui')['SDialog']
24+
SDropdownMenu: typeof import('@soybeanjs/ui')['SDropdownMenu']
25+
SDropdownMenuRadio: typeof import('@soybeanjs/ui')['SDropdownMenuRadio']
2226
SIcon: typeof import('@soybeanjs/ui')['SIcon']
2327
SSwitch: typeof import('@soybeanjs/ui')['SSwitch']
2428
ThemeSchemaToggler: typeof import('./../components/theme-schema-toggler.vue')['default']
29+
ToolBar: typeof import('./../components/tool-bar.vue')['default']
2530
}
2631
}
2732

2833
// For TSX support
2934
declare global {
35+
const LocaleToggler: typeof import('./../components/locale-toggler.vue')['default']
3036
const RouterLink: typeof import('vue-router')['RouterLink']
3137
const RouterView: typeof import('vue-router')['RouterView']
3238
const SButton: typeof import('@soybeanjs/ui')['SButton']
39+
const SButtonIcon: typeof import('@soybeanjs/ui')['SButtonIcon']
3340
const SButtonLink: typeof import('@soybeanjs/ui')['SButtonLink']
3441
const SCard: typeof import('@soybeanjs/ui')['SCard']
3542
const SConfigProvider: typeof import('@soybeanjs/ui')['SConfigProvider']
3643
const SDialog: typeof import('@soybeanjs/ui')['SDialog']
44+
const SDropdownMenu: typeof import('@soybeanjs/ui')['SDropdownMenu']
45+
const SDropdownMenuRadio: typeof import('@soybeanjs/ui')['SDropdownMenuRadio']
3746
const SIcon: typeof import('@soybeanjs/ui')['SIcon']
3847
const SSwitch: typeof import('@soybeanjs/ui')['SSwitch']
3948
const ThemeSchemaToggler: typeof import('./../components/theme-schema-toggler.vue')['default']
49+
const ToolBar: typeof import('./../components/tool-bar.vue')['default']
4050
}

0 commit comments

Comments
 (0)