feat(stage-ui): added language selector for onboarding screen

This commit is contained in:
Neko Ayaka
2026-03-21 01:00:19 +08:00
parent b5bdcad7cb
commit 440bff8514
3 changed files with 35 additions and 8 deletions
+1
View File
@@ -3,6 +3,7 @@ export const all = {
'es': 'Español',
'fr': 'Français',
'ja': '日本語',
'ko': '한국어',
'ru': 'Русский',
'vi': 'Tiếng Việt',
'zh-Hans': '简体中文',
+1 -3
View File
@@ -51,9 +51,7 @@ dialogs:
stateNotGranted: Not granted
language:
title: Language
description: >
Change the language of the AIRI interface. This will not affect the language
of the character's responses.
description: UI language
controls-island:
icon-size:
title: Controls Island Icon Size
@@ -1,28 +1,39 @@
<script setup lang="ts">
import type { OnboardingStepNextHandler } from './types'
import { Button } from '@proj-airi/ui'
import { all } from '@proj-airi/i18n'
import { Button, FieldSelect } from '@proj-airi/ui'
import { storeToRefs } from 'pinia'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import onboardingLogo from '../../../../assets/onboarding.avif'
import { useSettingsGeneral } from '../../../../stores/settings'
interface Props {
onNext: OnboardingStepNextHandler
}
const props = defineProps<Props>()
const { t } = useI18n()
const settingsStore = useSettingsGeneral()
const { language } = storeToRefs(settingsStore)
const languages = computed(() => {
return Object.entries(all).map(([value, label]) => ({ value, label }))
})
</script>
<template>
<div h-full flex flex-col>
<div class="mb-2 text-center md:mb-8" flex flex-1 flex-col justify-center>
<div :class="['mb-2', 'flex', 'flex-1', 'flex-col', 'justify-center', 'text-center', 'md:mb-8']">
<div
v-motion
:initial="{ opacity: 0, scale: 0.5 }"
:enter="{ opacity: 1, scale: 1 }"
:duration="500"
class="mb-1 flex justify-center md:mb-4 lg:pt-16 md:pt-8"
:class="['mb-1', 'flex', 'justify-center', 'md:mb-4', 'md:pt-8', 'lg:pt-16']"
>
<img :src="onboardingLogo" max-h="50" aspect-square h-auto w-auto object-cover>
</div>
@@ -31,7 +42,7 @@ const { t } = useI18n()
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="500"
class="mb-0 text-3xl text-neutral-800 font-bold md:mb-2 dark:text-neutral-100"
:class="['mb-0', 'text-3xl', 'text-neutral-800', 'font-bold', 'md:mb-2', 'dark:text-neutral-100']"
>
{{ t('settings.dialogs.onboarding.title') }}
</h2>
@@ -41,10 +52,27 @@ const { t } = useI18n()
:enter="{ opacity: 1, y: 0 }"
:duration="500"
:delay="100"
class="text-sm text-neutral-600 md:text-lg dark:text-neutral-400"
:class="['text-sm', 'text-neutral-600', 'md:text-lg', 'dark:text-neutral-400']"
>
{{ t('settings.dialogs.onboarding.description') }}
</p>
<div
v-motion
:initial="{ opacity: 0, y: 10 }"
:enter="{ opacity: 1, y: 0 }"
:duration="500"
:delay="150"
:class="['mx-auto', 'mt-6', 'w-full', 'max-w-sm', 'rounded-2xl', 'bg-neutral-100/80', 'backdrop-blur-sm', 'dark:bg-neutral-800/80', 'p-4']"
>
<FieldSelect
v-model="language"
:class="['w-full']"
:label="t('settings.language.title')"
:description="t('settings.language.description')"
:options="languages"
layout="vertical"
/>
</div>
</div>
<Button
v-motion