mirror of https://github.com/YunYouJun/valaxy
parent
a77872498d
commit
00ed99b171
|
@ -6,3 +6,18 @@ excerpt:
|
|||
|
||||
siteConfig:
|
||||
title: Site Config Title
|
||||
subtitle: Next Generation Static Blog Framework.
|
||||
description: Valaxy Theme Yun Preview
|
||||
author:
|
||||
name: YunYouJun
|
||||
social:
|
||||
bilibili: Bilibili
|
||||
sponsor:
|
||||
alipay: Alipay
|
||||
wechatpay: WeChat Pay
|
||||
|
||||
tag:
|
||||
notes: Notes
|
||||
|
||||
category:
|
||||
test: Test
|
||||
|
|
|
@ -9,3 +9,18 @@ post:
|
|||
|
||||
siteConfig:
|
||||
title: 自定义博客名称
|
||||
subtitle: 下一代静态博客框架
|
||||
description: Valaxy 主题云预览
|
||||
author:
|
||||
name: 云游君
|
||||
social:
|
||||
bilibili: 哔哩哔哩
|
||||
sponsor:
|
||||
alipay: 支付宝
|
||||
wechatpay: 微信支付
|
||||
|
||||
tag:
|
||||
notes: 笔记
|
||||
|
||||
category:
|
||||
test: 测试
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Aplayer 测试
|
||||
aplayer: false
|
||||
categories:
|
||||
- Test
|
||||
- $locale:category.test
|
||||
---
|
||||
|
||||
```md
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Code Block Test
|
||||
categories:
|
||||
- Test
|
||||
- $locale:category.test
|
||||
---
|
||||
|
||||
```dockerfile
|
||||
|
|
|
@ -3,7 +3,7 @@ title: Valaxy 开发笔记
|
|||
date: 2022-03-23
|
||||
cover: https://cos.yunle.fun/images/bg/astronaut.webp
|
||||
tags:
|
||||
- 笔记
|
||||
- $locale:tag.notes
|
||||
- valaxy
|
||||
---
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ updated: 2022-03-23 19:00:00
|
|||
categories: Valaxy Notes
|
||||
tags:
|
||||
- valaxy
|
||||
- 笔记
|
||||
- $locale:tag.notes
|
||||
top: 1
|
||||
outline: deep
|
||||
excerpt: Valaxy aims to be a next generation of static blogging frameworks/generators.
|
||||
|
|
|
@ -3,7 +3,7 @@ title:
|
|||
en: Markdown Styles
|
||||
zh-CN: Markdown 样式
|
||||
categories:
|
||||
- Test
|
||||
- $locale:category.test
|
||||
- Markdown
|
||||
---
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ title:
|
|||
en: Markdown Extensions Test
|
||||
zh-CN: Markdown 扩展测试
|
||||
categories:
|
||||
- Test
|
||||
- $locale:category.test
|
||||
- Markdown
|
||||
---
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
title: Markdown File Inclusion By @include
|
||||
categories:
|
||||
- Test
|
||||
- $locale:category.test
|
||||
---
|
||||
|
||||
Include content:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Time Warning Test
|
||||
date: 2020-10-01
|
||||
categories:
|
||||
- test
|
||||
- $locale:category.test
|
||||
time_warning: true
|
||||
---
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { defineSiteConfig } from 'valaxy'
|
||||
import { $t, defineSiteConfig } from 'valaxy'
|
||||
|
||||
export default defineSiteConfig({
|
||||
frontmatter: {
|
||||
|
@ -9,14 +9,15 @@ export default defineSiteConfig({
|
|||
// disable show language switch
|
||||
// languages: ['zh-CN'],
|
||||
|
||||
title: 'siteConfig.title',
|
||||
title: $t('siteConfig.title'),
|
||||
subtitle: $t('siteConfig.subtitle'),
|
||||
timezone: 'Asia/Shanghai',
|
||||
url: 'https://yun.valaxy.site/',
|
||||
author: {
|
||||
avatar: 'https://www.yunyoujun.cn/images/avatar.jpg',
|
||||
name: '云游君',
|
||||
name: $t('siteConfig.author.name'),
|
||||
},
|
||||
description: 'Valaxy Theme Yun Preview.',
|
||||
description: $t('siteConfig.description'),
|
||||
social: [
|
||||
{
|
||||
name: 'RSS',
|
||||
|
@ -61,7 +62,7 @@ export default defineSiteConfig({
|
|||
color: '#0084FF',
|
||||
},
|
||||
{
|
||||
name: '哔哩哔哩',
|
||||
name: $t('siteConfig.social.bilibili'),
|
||||
link: 'https://space.bilibili.com/1579790',
|
||||
icon: 'i-ri-bilibili-line',
|
||||
color: '#FF8EB3',
|
||||
|
@ -124,7 +125,7 @@ export default defineSiteConfig({
|
|||
enable: true,
|
||||
methods: [
|
||||
{
|
||||
name: '支付宝',
|
||||
name: $t('siteConfig.sponsor.alipay'),
|
||||
url: 'https://cdn.yunyoujun.cn/img/donate/alipay-qrcode.jpg',
|
||||
color: '#00A3EE',
|
||||
icon: 'i-ri-alipay-line',
|
||||
|
@ -136,7 +137,7 @@ export default defineSiteConfig({
|
|||
icon: 'i-ri-qq-line',
|
||||
},
|
||||
{
|
||||
name: '微信支付',
|
||||
name: $t('siteConfig.sponsor.wechatpay'),
|
||||
url: 'https://cdn.yunyoujun.cn/img/donate/wechatpay-qrcode.jpg',
|
||||
color: '#2DC100',
|
||||
icon: 'i-ri-wechat-pay-line',
|
||||
|
|
|
@ -6,18 +6,36 @@ categories:
|
|||
- guide
|
||||
---
|
||||
|
||||
## 在配置中使用国际化
|
||||
|
||||
如果你想要为 `siteConfig.title`/`siteConfig.description` 添加国际化支持,可以在 `siteConfig` 中设定键值。
|
||||
|
||||
例如:
|
||||
## 设置支持的语言
|
||||
|
||||
```ts [site.config.ts]
|
||||
import { defineSiteConfig } from 'valaxy'
|
||||
|
||||
export default defineSiteConfig({
|
||||
title: 'siteConfig.title',
|
||||
description: 'siteConfig.description',
|
||||
languages: ['zh-CN', 'en'],
|
||||
})
|
||||
```
|
||||
|
||||
## 在配置中使用国际化
|
||||
|
||||
如果你想要为 `siteConfig.title`/`siteConfig.description` 添加国际化支持,可以在 `siteConfig` 中设定键值。
|
||||
|
||||
::: tip
|
||||
|
||||
`$t` 是 Valaxy 提供的一个虚拟函数,它会添加特定的前缀 `$locale:` 以标记此处的文本需要国际化处理。
|
||||
随后,Valaxy 会在页面中自动替换为对应语言的文本。
|
||||
因此,它在页面上仍然是支持响应式的。
|
||||
|
||||
:::
|
||||
|
||||
例如:
|
||||
|
||||
```ts [site.config.ts]
|
||||
import { $t, defineSiteConfig } from 'valaxy'
|
||||
|
||||
export default defineSiteConfig({
|
||||
title: $t('siteConfig.title'),
|
||||
description: $t('siteConfig.description'),
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -165,3 +183,39 @@ description:
|
|||
zh-CN: 一个简单的 i18n 示例
|
||||
---
|
||||
```
|
||||
|
||||
### 分类/标签 i18n {lang="zh-CN"}
|
||||
|
||||
### Category/Tag i18n {lang="en"}
|
||||
|
||||
::: tip
|
||||
|
||||
**为什么这里不是使用类似 `title`/`description` 的对象方式,而是使用特殊前缀 `$locale:tag.notes` 的方式?**
|
||||
|
||||
因为分类和标签仍然需要一个唯一的键值,且它们通常是在多篇文章中复用的。
|
||||
如果使用对象方式,你将不得不在每篇文章的 `frontmatter` 中重复定义分类和标签的多种语言。
|
||||
|
||||
:::
|
||||
|
||||
```md [posts/hello-world.md]
|
||||
---
|
||||
categories:
|
||||
- $locale:category.test
|
||||
tags:
|
||||
- $locale:tag.notes
|
||||
---
|
||||
```
|
||||
|
||||
```yaml [locales/zh-CN.yml]
|
||||
category:
|
||||
test: 测试
|
||||
tag:
|
||||
notes: 笔记
|
||||
```
|
||||
|
||||
```yaml [locales/en.yml]
|
||||
category:
|
||||
test: Test
|
||||
tag:
|
||||
notes: Notes
|
||||
```
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import type { CategoryList, Post } from 'valaxy'
|
||||
import { useInvisibleElement } from 'valaxy'
|
||||
import { useInvisibleElement, useValaxyI18n } from 'valaxy'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
@ -25,6 +25,7 @@ const router = useRouter()
|
|||
|
||||
const collapse = ref(props.collapsable)
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const postCollapseElRef = ref<HTMLElement>()
|
||||
const { show } = useInvisibleElement(postCollapseElRef)
|
||||
|
@ -79,7 +80,7 @@ if (props.level === 1) {
|
|||
@click="jumpToDisplayCategory(parentKey)"
|
||||
>
|
||||
<span>
|
||||
{{ category.name === 'Uncategorized' ? t('category.uncategorized') : category.name }}
|
||||
{{ category.name === 'Uncategorized' ? t('category.uncategorized') : $t(category.name) }}
|
||||
</span>
|
||||
<span class="rounded-full px-1.5 bg-black/5 shadow-sm op-60" text="xs">
|
||||
{{ category.total }}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { useSiteConfig, useValaxyConfig, useValaxyDark } from 'valaxy'
|
||||
import { useSiteConfig, useValaxyConfig, useValaxyDark, useValaxyI18n } from 'valaxy'
|
||||
import pkg from 'valaxy/package.json'
|
||||
import { capitalize, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
@ -21,6 +21,7 @@ const gradientStyles = computed(() => {
|
|||
})
|
||||
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
const config = useValaxyConfig()
|
||||
const siteConfig = useSiteConfig()
|
||||
const themeConfig = useThemeConfig()
|
||||
|
@ -72,7 +73,7 @@ const footerIcon = computed(() => themeConfig.value.footer.icon || {
|
|||
>
|
||||
<div :class="footerIcon.name" />
|
||||
</a>
|
||||
<span>{{ siteConfig.author.name }}</span>
|
||||
<span>{{ $t(siteConfig.author.name) }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="themeConfig.footer.powered" class="powered" m="2">
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { useValaxyI18n } from 'valaxy'
|
||||
import { ref } from 'vue'
|
||||
import { useYunSpringAnimation } from '../composables/animation'
|
||||
|
||||
|
@ -8,6 +9,8 @@ const props = defineProps<{
|
|||
count: number
|
||||
}>()
|
||||
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const tagRef = ref<HTMLElement>()
|
||||
useYunSpringAnimation(tagRef, {
|
||||
i: props.i || 0,
|
||||
|
@ -21,7 +24,7 @@ useYunSpringAnimation(tagRef, {
|
|||
inline-flex my="2" p="1"
|
||||
class="post-tag cursor-pointer items-baseline leading-4"
|
||||
>
|
||||
<span inline-flex>#{{ title }}</span>
|
||||
<span inline-flex>#{{ $t(title) }}</span>
|
||||
<span inline-flex text="xs">[{{ count }}]</span>
|
||||
</span>
|
||||
</template>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
const siteConfig = useSiteConfig()
|
||||
</script>
|
||||
|
||||
|
@ -16,14 +15,14 @@ const siteConfig = useSiteConfig()
|
|||
<YunAuthorName />
|
||||
<YunSiteTitle />
|
||||
<h4
|
||||
v-if="siteConfig.subtitle"
|
||||
v-if="$t(siteConfig.subtitle)"
|
||||
class="site-subtitle block"
|
||||
text="xs"
|
||||
>
|
||||
{{ t(siteConfig.subtitle) }}
|
||||
{{ $t(siteConfig.subtitle) }}
|
||||
</h4>
|
||||
<div v-if="siteConfig.description" class="site-description">
|
||||
{{ t(siteConfig.description) }}
|
||||
{{ $t(siteConfig.description) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { SocialLink } from 'valaxy/types'
|
||||
import { useAppStore } from 'valaxy'
|
||||
import { useAppStore, useValaxyI18n } from 'valaxy'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
social: SocialLink
|
||||
}>()
|
||||
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const appStore = useAppStore()
|
||||
const color = computed(() => {
|
||||
return (appStore.isDark && props.social.color === 'black') ? 'white' : props.social.color
|
||||
|
@ -16,7 +18,7 @@ const color = computed(() => {
|
|||
<template>
|
||||
<a
|
||||
class="links-of-author-item yun-icon-btn"
|
||||
rel="noopener" :href="social.link" :title="social.name"
|
||||
rel="noopener" :href="social.link" :title="$t(social.name)"
|
||||
target="_blank"
|
||||
:style="`color:${color}`"
|
||||
>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const showQr = ref(false)
|
||||
|
@ -35,7 +36,7 @@ const sponsorBtnTitle = computed(() => {
|
|||
:href="method.url" target="_blank"
|
||||
:style="`color:${method.color}`"
|
||||
>
|
||||
<img class="sponsor-method-img" border="~ rounded" p="1" loading="lazy" :src="method.url" :title="method.name">
|
||||
<img class="sponsor-method-img" border="~ rounded" p="1" loading="lazy" :src="method.url" :title="$t(method.name)">
|
||||
<div text="xl" m="2" :class="method.icon" />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="siteConfig.author.intro" class="site-author-intro" m="t-0 b-4">
|
||||
{{ t(siteConfig.author.intro) }}
|
||||
{{ $t(siteConfig.author.intro) }}
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const { $t } = useValaxyI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -9,6 +10,6 @@ const siteConfig = useSiteConfig()
|
|||
class="site-author-name font-black font-serif text-$va-c-text op-80 hover:op-100 flex-center"
|
||||
to="/about"
|
||||
>
|
||||
{{ siteConfig.author.name }}
|
||||
{{ $t(siteConfig.author.name) }}
|
||||
</RouterLink>
|
||||
</template>
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
import { tObject, useFrontmatter, useSiteConfig } from 'valaxy'
|
||||
import { tObject, useFrontmatter, useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useYunAppStore } from '../../stores'
|
||||
|
||||
const { t, locale } = useI18n()
|
||||
const { $t, locale } = useValaxyI18n()
|
||||
|
||||
const yunApp = useYunAppStore()
|
||||
const fm = useFrontmatter()
|
||||
|
@ -71,7 +70,7 @@ function goToLink() {
|
|||
</span>
|
||||
</div>
|
||||
<span v-if="showSiteTitle" class="font-light truncate">
|
||||
{{ t(siteConfig.title) }}
|
||||
{{ $t(siteConfig.title) }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { useMotion } from '@vueuse/motion'
|
||||
import { ref } from 'vue'
|
||||
import { useValaxyI18n } from 'valaxy/client'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
social: {
|
||||
|
@ -12,7 +13,7 @@ const props = defineProps<{
|
|||
// animation
|
||||
delay: number
|
||||
}>()
|
||||
|
||||
const { $t } = useValaxyI18n()
|
||||
const iconRef = ref<HTMLElement>()
|
||||
useMotion(iconRef, {
|
||||
initial: {
|
||||
|
@ -34,18 +35,20 @@ useMotion(iconRef, {
|
|||
},
|
||||
},
|
||||
})
|
||||
|
||||
const socialName = computed(() => $t(props.social.name))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-tooltip="social.name"
|
||||
v-tooltip="socialName"
|
||||
class="size-10 inline-flex-center"
|
||||
>
|
||||
<a
|
||||
ref="iconRef"
|
||||
class="prologue-social-icon inline-flex-center w-full h-full text-white bg-$c-brand hover:bg-white hover:text-$c-brand"
|
||||
rel="noopener"
|
||||
:href="social.link" :title="social.name"
|
||||
:href="social.link" :title="socialName"
|
||||
target="_blank"
|
||||
:style="`--c-brand:${social.color}`"
|
||||
>
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const { t } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="siteConfig.description" class="site-description text-$va-c-text text-sm">
|
||||
{{ t(siteConfig.description) }}
|
||||
{{ $t(siteConfig.description) }}
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { useSiteConfig } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useThemeConfig } from '../../composables'
|
||||
|
||||
|
@ -8,8 +7,7 @@ const router = useRouter()
|
|||
const siteConfig = useSiteConfig()
|
||||
const themeConfig = useThemeConfig()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const { $t } = useValaxyI18n()
|
||||
// bg-gradient-to-r gradient-text from-#1e3c72 to-dark dark:(from-#66a6ff to-blue-500)
|
||||
</script>
|
||||
|
||||
|
@ -19,14 +17,14 @@ const { t } = useI18n()
|
|||
class="site-name text-lg leading-loose"
|
||||
:class="themeConfig.banner.siteNameClass"
|
||||
>
|
||||
{{ t(siteConfig.title) }}
|
||||
{{ $t(siteConfig.title) }}
|
||||
</RouterLink>
|
||||
<span
|
||||
v-else
|
||||
class="site-name text-lg leading-loose"
|
||||
:class="themeConfig.banner.siteNameClass"
|
||||
>
|
||||
{{ t(siteConfig.title) }}
|
||||
{{ $t(siteConfig.title) }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -2,20 +2,21 @@
|
|||
import { defineArticle, useSchemaOrg } from '@unhead/schema-org/vue'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
import { tObject, useFrontmatter, useSiteConfig } from 'valaxy'
|
||||
import { tObject, useFrontmatter, useSiteConfig, useValaxyI18n } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const frontmatter = useFrontmatter()
|
||||
|
||||
const { locale } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
const article: Parameters<typeof defineArticle>[0] = {
|
||||
'@type': 'BlogPosting',
|
||||
'headline': tObject(frontmatter.value.title || '', locale.value),
|
||||
'description': tObject(frontmatter.value.description || '', locale.value),
|
||||
'author': [
|
||||
{
|
||||
name: siteConfig.value.author.name,
|
||||
name: $t(siteConfig.value.author.name),
|
||||
url: siteConfig.value.author.link,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useValaxyI18n } from '../composables'
|
||||
import { useSiteConfig } from '../config'
|
||||
|
||||
withDefaults(defineProps<{
|
||||
|
@ -10,6 +11,7 @@ withDefaults(defineProps<{
|
|||
})
|
||||
|
||||
const { t, locale } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
|
||||
|
@ -31,7 +33,7 @@ const licenseHtml = computed(() => {
|
|||
<strong>
|
||||
{{ t('post.copyright.author') + t('symbol.colon') }}
|
||||
</strong>
|
||||
<span>{{ t(siteConfig.author.name) }}</span>
|
||||
<span>{{ $t(siteConfig.author.name) }}</span>
|
||||
</li>
|
||||
<li v-if="url" class="post-copyright-link">
|
||||
<strong>
|
||||
|
|
|
@ -6,7 +6,7 @@ import { computed } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { tObject } from '../../../shared/utils/i18n'
|
||||
import { useFrontmatter, useValaxyHead } from '../../composables'
|
||||
import { useFrontmatter, useValaxyHead, useValaxyI18n } from '../../composables'
|
||||
|
||||
import { useTimezone } from '../../composables/global'
|
||||
// https://github.com/vueuse/head
|
||||
|
@ -20,6 +20,7 @@ export function useValaxyApp() {
|
|||
const fm = useFrontmatter()
|
||||
|
||||
const { locale } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const title = computed(() => tObject(fm.value.title || '', locale.value))
|
||||
|
||||
|
@ -45,7 +46,7 @@ export function useValaxyApp() {
|
|||
// https://unhead.unjs.io/docs/schema-org/guides/recipes/identity
|
||||
// Personal Website or Blog
|
||||
definePerson({
|
||||
name: siteConfig.value.author.name,
|
||||
name: $t(siteConfig.value.author.name),
|
||||
url: siteUrl.value,
|
||||
image: siteConfig.value.author.avatar,
|
||||
sameAs: siteConfig.value.social.map(s => s.link),
|
||||
|
|
|
@ -3,12 +3,13 @@ import pkg from 'valaxy/package.json'
|
|||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useFrontmatter } from '../../composables'
|
||||
import { useFrontmatter, useValaxyI18n } from '../../composables'
|
||||
import { useSiteConfig } from '../../config'
|
||||
import { tObject } from '../../utils'
|
||||
|
||||
export function useValaxyHead() {
|
||||
const { locale, t } = useI18n()
|
||||
const { locale } = useI18n()
|
||||
const { $t } = useValaxyI18n()
|
||||
|
||||
const fm = useFrontmatter()
|
||||
const siteConfig = useSiteConfig()
|
||||
|
@ -17,7 +18,7 @@ export function useValaxyHead() {
|
|||
useHead({
|
||||
title: $title,
|
||||
titleTemplate: (title) => {
|
||||
const siteTitle = t(siteConfig.value.title)
|
||||
const siteTitle = $t(siteConfig.value.title)
|
||||
return fm.value.titleTemplate || (title ? `${title} - ${siteTitle}` : siteTitle)
|
||||
},
|
||||
link: [
|
||||
|
|
|
@ -6,6 +6,7 @@ import { computed } from 'vue'
|
|||
// not optimize deps all locales
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { tObject } from '../../shared/utils/i18n'
|
||||
import { LOCALE_PREFIX } from '../utils'
|
||||
import 'dayjs/locale/en'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
|
@ -63,3 +64,23 @@ export function useLocaleTitle(fm: Ref<{
|
|||
return tObject(fm.value.title || '', lang) || ''
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* 以 `$locale:` 开头的 key 会被认为是国际化的 key
|
||||
* 会从 locales/ 目录中获取对应的翻译
|
||||
*/
|
||||
export function useValaxyI18n() {
|
||||
const { t, locale } = useI18n()
|
||||
|
||||
return {
|
||||
locale,
|
||||
|
||||
$t: (key: string) => {
|
||||
if (key.startsWith(LOCALE_PREFIX)) {
|
||||
return t(key.slice(LOCALE_PREFIX.length))
|
||||
}
|
||||
return key
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ export function containerPlugin(md: MarkdownItAsync, containerOptions: Container
|
|||
tokens[idx].nesting === 1 ? `<div class="vp-raw">\n` : `</div>\n`,
|
||||
})
|
||||
|
||||
const languages = ['zh-CN', 'en']
|
||||
const languages = containerOptions.siteConfig?.languages || ['zh-CN', 'en']
|
||||
languages.forEach((lang) => {
|
||||
md.use(container, lang, {
|
||||
render: (tokens: Token[], idx: number) =>
|
||||
|
|
|
@ -59,6 +59,7 @@ export async function setupMarkdownPlugins(
|
|||
.use(preWrapperPlugin, { theme, siteConfig })
|
||||
.use(snippetPlugin, options?.userRoot)
|
||||
.use(containerPlugin, {
|
||||
siteConfig,
|
||||
...mdOptions.blocks,
|
||||
...mdOptions?.container,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* @experimental 试验性
|
||||
* @see https://github.com/YunYouJun/valaxy/issues/566
|
||||
* @param key
|
||||
*
|
||||
* 声明这是一个使用国际化的 key
|
||||
* 从 locales/ 目录中获取对应的翻译
|
||||
*/
|
||||
export function $t(key: string) {
|
||||
return `$locale:${key}`
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
export * from './getGitTimestamp'
|
||||
export * from './helper'
|
||||
export * from './i18n'
|
||||
export * from './resolve'
|
||||
|
|
|
@ -4,7 +4,7 @@ import { toAtFS } from '../utils'
|
|||
|
||||
export const templateLocales: VirtualModuleTemplate = {
|
||||
id: '/@valaxyjs/locales',
|
||||
async getContent({ roots }) {
|
||||
async getContent({ roots, config }) {
|
||||
const imports: string[] = [
|
||||
'import { createDefu } from "defu"',
|
||||
'const messages = { "zh-CN": {}, en: {} }',
|
||||
|
@ -17,8 +17,7 @@ export const templateLocales: VirtualModuleTemplate = {
|
|||
})
|
||||
`,
|
||||
]
|
||||
const languages = ['zh-CN', 'en']
|
||||
|
||||
const languages = config.siteConfig.languages || ['zh-CN', 'en']
|
||||
roots.forEach((root, i) => {
|
||||
languages.forEach((lang) => {
|
||||
const langYml = `${root}/locales/${lang}.yml`
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
* 标识这是一个使用国际化的 key
|
||||
* 从 locales/ 目录中获取对应的翻译
|
||||
*/
|
||||
export const LOCALE_PREFIX = '$locale:'
|
||||
|
|
Loading…
Reference in New Issue