Skip to content

Commit b5c6ab5

Browse files
Neko-233autofix-ci[bot]nekomeowww
authored
feat(docs): Japanese translated & minor issues fixed (#865)
--------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Neko <neko@ayaka.moe>
1 parent ad874fe commit b5c6ab5

File tree

63 files changed

+4934
-202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+4934
-202
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<script setup lang="ts">
2+
import { useData } from 'vitepress'
3+
import { computed, onMounted, onUnmounted, ref, watch, nextTick } from 'vue'
4+
5+
const props = withDefaults(defineProps<{
6+
src?: string
7+
light?: string
8+
dark?: string
9+
poster?: string
10+
autoplay?: boolean
11+
controls?: boolean
12+
muted?: boolean
13+
loop?: boolean
14+
}>(), {
15+
autoplay: false,
16+
controls: true,
17+
muted: true,
18+
loop: true,
19+
})
20+
21+
const { isDark } = useData()
22+
23+
const currentSrc = computed(() => {
24+
if (props.light && props.dark) {
25+
return isDark.value ? props.dark : props.light
26+
}
27+
return props.src
28+
})
29+
30+
const videoRef = ref<HTMLVideoElement | null>(null)
31+
let observer: IntersectionObserver | null = null
32+
const isVisible = ref(false)
33+
34+
function handleVisibility(entries: IntersectionObserverEntry[]) {
35+
entries.forEach((entry) => {
36+
if (!videoRef.value)
37+
return
38+
39+
if (entry.isIntersecting) {
40+
isVisible.value = true
41+
if (props.autoplay) {
42+
videoRef.value.play().catch(() => {
43+
// Auto-play was prevented
44+
})
45+
}
46+
}
47+
else {
48+
isVisible.value = false
49+
if (props.autoplay) {
50+
videoRef.value.pause()
51+
}
52+
}
53+
})
54+
}
55+
56+
onMounted(() => {
57+
if (props.autoplay && videoRef.value) {
58+
observer = new IntersectionObserver(handleVisibility, {
59+
threshold: 0.2, // Lower threshold to start loading earlier
60+
rootMargin: '100px 0px', // Preload when close to viewport
61+
})
62+
observer.observe(videoRef.value)
63+
}
64+
})
65+
66+
onUnmounted(() => {
67+
if (observer) {
68+
observer.disconnect()
69+
}
70+
})
71+
72+
watch(currentSrc, async () => {
73+
if (props.autoplay && videoRef.value && isVisible.value) {
74+
// If src changes while visible (e.g. theme toggle), ensure we play the new src
75+
// Using nextTick to allow DOM update
76+
await nextTick()
77+
videoRef.value?.play().catch(() => {})
78+
}
79+
})
80+
</script>
81+
82+
<template>
83+
<div class="themed-video-wrapper my-4 overflow-hidden rounded-xl">
84+
<video
85+
ref="videoRef"
86+
:src="currentSrc"
87+
:poster="poster"
88+
:controls="controls"
89+
:muted="muted"
90+
:loop="loop"
91+
playsinline
92+
class="block w-full"
93+
preload="none"
94+
>
95+
<slot>
96+
Your browser does not support the video tag.
97+
</slot>
98+
</video>
99+
</div>
100+
</template>
101+
102+
<style scoped>
103+
.themed-video-wrapper video {
104+
max-height: 60vh;
105+
object-fit: contain;
106+
}
107+
</style>

docs/.vitepress/config.ts

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,33 @@ export default defineConfig({
9999
{ text: 'Release Notes ', link: releases },
100100
],
101101
},
102+
{
103+
text: 'About',
104+
items: [
105+
{ text: 'Privacy Policy', link: withBase('/en/about/privacy') },
106+
{ text: 'Terms of Use', link: withBase('/en/about/terms') },
107+
],
108+
},
102109
],
103110
outline: {
104111
level: 'deep',
112+
label: 'このページの内容',
113+
},
114+
docFooter: {
115+
prev: '前のページ',
116+
next: '次のページ',
117+
},
118+
editLink: {
119+
pattern: 'https://github.com/moeru-ai/airi/edit/main/docs/content/:path',
120+
text: 'GitHub でこのページを編集',
121+
},
122+
lastUpdated: {
123+
text: '最終更新',
105124
},
125+
darkModeSwitchLabel: '外観モード',
126+
sidebarMenuLabel: 'メニュー',
127+
returnToTopLabel: 'トップに戻る',
128+
langMenuLabel: '言語を変更',
106129
logo: withBase('/favicon.svg'),
107130

108131
sidebar: [
@@ -180,6 +203,13 @@ export default defineConfig({
180203
{ text: '发布说明 ', link: releases },
181204
],
182205
},
206+
{
207+
text: '关于',
208+
items: [
209+
{ text: '隐私政策', link: withBase('/zh-Hans/about/privacy') },
210+
{ text: '使用条款', link: withBase('/zh-Hans/about/terms') },
211+
],
212+
},
183213
],
184214
outline: {
185215
level: 'deep',
@@ -211,13 +241,9 @@ export default defineConfig({
211241
text: '参与贡献',
212242
items: [
213243
{ text: '贡献代码', link: withBase('/zh-Hans/docs/overview/contributing/') },
214-
{
215-
text: '贡献设计',
216-
items: [
217-
{ text: '参考资源', link: withBase('/zh-Hans/docs/overview/contributing/design-guidelines/resources') },
218-
{ text: '工具', link: withBase('/zh-Hans/docs/overview/contributing/design-guidelines/tools') },
219-
],
220-
},
244+
{ text: '贡献设计', link: withBase('/zh-Hans/docs/overview/contributing/design-guidelines/') },
245+
{ text: '参考资源', link: withBase('/zh-Hans/docs/overview/contributing/design-guidelines/resources') },
246+
{ text: '工具', link: withBase('/zh-Hans/docs/overview/contributing/design-guidelines/tools') },
221247
],
222248
},
223249
{ text: '有关 AI VTuber', link: withBase('/zh-Hans/docs/overview/about-ai-vtuber') },
@@ -261,6 +287,13 @@ export default defineConfig({
261287
{ text: 'リリースノート', link: releases },
262288
],
263289
},
290+
{
291+
text: '概要',
292+
items: [
293+
{ text: 'プライバシーポリシー', link: withBase('/ja/about/privacy') },
294+
{ text: '利用規約', link: withBase('/ja/about/terms') },
295+
],
296+
},
264297
],
265298
outline: {
266299
level: 'deep',
@@ -278,46 +311,42 @@ export default defineConfig({
278311
items: [
279312
{
280313
text: 'デスクトップ版のガイド',
281-
link: withBase('/en/docs/overview/guide/tamagotchi/'),
314+
link: withBase('/ja/docs/overview/guide/tamagotchi/'),
282315
items: [],
283316
},
284317
{
285318
text: 'Web 版のガイド',
286-
link: withBase('/en/docs/overview/guide/web/'),
319+
link: withBase('/ja/docs/overview/guide/web/'),
287320
items: [],
288321
},
289322
],
290323
},
291324
{
292325
text: 'コントリビューション',
293326
items: [
294-
{ text: 'コードで貢献', link: withBase('/en/docs/overview/contributing/') },
295-
{
296-
text: 'デザインで貢献',
297-
items: [
298-
{ text: 'リソース', link: withBase('/en/docs/overview/contributing/design-guidelines/resources') },
299-
{ text: 'ツール', link: withBase('/en/docs/overview/contributing/design-guidelines/tools') },
300-
],
301-
},
327+
{ text: 'コードで貢献', link: withBase('/ja/docs/overview/contributing/') },
328+
{ text: 'デザインで貢献', link: withBase('/ja/docs/overview/contributing/design-guidelines/') },
329+
{ text: 'リソース', link: withBase('/ja/docs/overview/contributing/design-guidelines/resources') },
330+
{ text: 'ツール', link: withBase('/ja/docs/overview/contributing/design-guidelines/tools') },
302331
],
303332
},
304-
{ text: 'AI VTuber について', link: withBase('/en/docs/overview/about-ai-vtuber') },
305-
{ text: 'Neuro-sama について', link: withBase('/en/docs/overview/about-neuro-sama') },
333+
{ text: 'AI VTuber について', link: withBase('/ja/docs/overview/about-ai-vtuber') },
334+
{ text: 'Neuro-sama について', link: withBase('/ja/docs/overview/about-neuro-sama') },
306335
],
307336
},
308337
{
309338
text: 'マニュアル',
310339
icon: 'lucide:book-open',
311340
items: [
312-
{ text: 'バージョン一覧', link: withBase('/en/docs/manual/versions') },
341+
{ text: 'バージョン一覧', link: withBase('/ja/docs/manual/versions') },
313342
],
314343
},
315344
{
316345
text: '年表',
317346
icon: 'lucide:calendar-days',
318347
items: [
319-
{ text: '初公開 v0.1.0', link: withBase('/en/docs/chronicles/version-v0.1.0/') },
320-
{ text: '前日譚 v0.0.1', link: withBase('/en/docs/chronicles/version-v0.0.1/') },
348+
{ text: '初公開 v0.1.0', link: withBase('/ja/docs/chronicles/version-v0.1.0/') },
349+
{ text: '前日譚 v0.0.1', link: withBase('/ja/docs/chronicles/version-v0.0.1/') },
321350
],
322351
},
323352
{

docs/.vitepress/custom/Docs.vue

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
<script setup lang="ts">
22
import type { DefaultTheme } from 'vitepress/theme'
33
4-
import { CollapsibleContent, CollapsibleRoot, CollapsibleTrigger } from 'reka-ui'
54
import { Content, useData, useRoute } from 'vitepress'
65
import { computed, toRefs } from 'vue'
76
@@ -82,20 +81,6 @@ const isCharactersPage = computed(() => path.value.includes('characters'))
8281
</aside>
8382

8483
<div class="flex-1 overflow-x-hidden px-6 py-6 md:px-24 md:py-12">
85-
<CollapsibleRoot
86-
v-if="isOutlineEnabled"
87-
:key="path"
88-
class="mb-4 block xl:hidden"
89-
>
90-
<CollapsibleTrigger class="mb-2 border border-muted rounded-lg bg-card px-4 py-2 text-sm data-[state=open]:bg-muted">
91-
On this page
92-
</CollapsibleTrigger>
93-
94-
<CollapsibleContent class="ml-4 overflow-hidden data-[state=closed]:animate-slideUp data-[state=open]:animate-slideDown">
95-
<DocOutline collapsible />
96-
</CollapsibleContent>
97-
</CollapsibleRoot>
98-
9984
<div class="mb-2 text-sm text-primary font-bold">
10085
{{ activeSection?.text }}
10186
</div>

docs/.vitepress/functions/blog.data.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function withDirname(url?: string, cwd?: string) {
7070
}
7171

7272
if (url.startsWith('/')) {
73-
return join(cwd, url)
73+
return url
7474
}
7575

7676
return join(cwd, url)
@@ -99,12 +99,18 @@ export default createContentLoader('**/blog/**/*.md', {
9999
return file
100100

101101
const parsed = parse(file)
102-
const hash = createHash('sha256')
103-
.update(await readFile(join(config.srcDir, file)))
104-
.digest('hex')
105-
.slice(0, 8)
102+
try {
103+
const hash = createHash('sha256')
104+
.update(await readFile(join(config.srcDir, file)))
105+
.digest('hex')
106+
.slice(0, 8)
106107

107-
return `/assets/${parsed.name}.${hash}${parsed.ext}`
108+
return `/assets/${parsed.name}.${hash}${parsed.ext}`
109+
}
110+
catch (e) {
111+
console.error(`[blog.data.ts] Failed to read file: ${join(config.srcDir, file)}`, e)
112+
return file
113+
}
108114
}
109115

110116
const previewCoverLight = withBase(await fileToUrl(withDirname(fromAtAssets(frontmatter['preview-cover']?.light), cwdFromUrl(url))), base)

docs/.vitepress/plugins/vite-frontmatter-assets.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,16 @@ export function frontmatterAssets(): Plugin {
129129
}
130130

131131
recursivelyFindAtAssets(data, (matched) => {
132-
mAssetAbsoluteUrlMetadata.set(join(dirname(file), fromAtAssets(matched)), { url: file, builtUrl: file, hash: '' })
132+
const assetPath = fromAtAssets(matched)
133+
let absoluteAssetPath: string
134+
if (assetPath.startsWith('/')) {
135+
absoluteAssetPath = join(resolvedConfig?.vitepress.srcDir || '', assetPath)
136+
}
137+
else {
138+
absoluteAssetPath = join(dirname(file), assetPath)
139+
}
140+
141+
mAssetAbsoluteUrlMetadata.set(absoluteAssetPath, { url: file, builtUrl: file, hash: '' })
133142
return undefined
134143
})
135144
}

docs/.vitepress/theme/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import '@fontsource-variable/comfortaa'
2424
export default {
2525
Layout,
2626
enhanceApp({ app, siteData }) {
27-
if (!import.meta.env.SSR) {
27+
if (!import.meta.env.SSR && import.meta.env.PROD) {
2828
import('../modules/posthog')
2929
}
3030

0 commit comments

Comments
 (0)