mirror of https://github.com/YunYouJun/valaxy
feat: support i18n for frontmatter title/description, close #561
This commit is contained in:
parent
89b1ce5c05
commit
e537ac80b5
|
@ -81,6 +81,7 @@ declare module 'vue-router/auto-routes' {
|
|||
'/posts/mermaid': RouteRecordInfo<'/posts/mermaid', '/posts/mermaid', Record<never, never>, Record<never, never>>,
|
||||
'/posts/nested/a/b/c': RouteRecordInfo<'/posts/nested/a/b/c', '/posts/nested/a/b/c', Record<never, never>, Record<never, never>>,
|
||||
'/posts/nested/z/': RouteRecordInfo<'/posts/nested/z/', '/posts/nested/z', Record<never, never>, Record<never, never>>,
|
||||
'/posts/post-i18n': RouteRecordInfo<'/posts/post-i18n', '/posts/post-i18n', Record<never, never>, Record<never, never>>,
|
||||
'/posts/post-updated': RouteRecordInfo<'/posts/post-updated', '/posts/post-updated', Record<never, never>, Record<never, never>>,
|
||||
'/posts/redirect': RouteRecordInfo<'/posts/redirect', '/posts/redirect', Record<never, never>, Record<never, never>>,
|
||||
'/posts/test': RouteRecordInfo<'/posts/test', '/posts/test', Record<never, never>, Record<never, never>>,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Code height limit
|
||||
title_zh: 代码块高度限制
|
||||
title:
|
||||
zh-CN: 代码块高度限制
|
||||
en: Code height limit
|
||||
toc: true
|
||||
categories:
|
||||
- examples
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Demo Sites
|
||||
title_zh: 站点示例
|
||||
title:
|
||||
zh-CN: 站点示例
|
||||
en: Demo Sites
|
||||
layout: docs
|
||||
categories:
|
||||
- Docs
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Markdown Styles
|
||||
title_zh: Markdown 样式
|
||||
title:
|
||||
en: Markdown Styles
|
||||
zh-CN: Markdown 样式
|
||||
categories:
|
||||
- Test
|
||||
- Markdown
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Markdown Extensions Test
|
||||
title_zh: Markdown 扩展测试
|
||||
title:
|
||||
en: Markdown Extensions Test
|
||||
zh-CN: Markdown 扩展测试
|
||||
categories:
|
||||
- Test
|
||||
- Markdown
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
title:
|
||||
zh-CN: 帖子国际化
|
||||
en: Post i18n
|
||||
description:
|
||||
zh-CN: 帖子国际化测试描述
|
||||
en: Post i18n test description
|
||||
---
|
||||
|
||||
::: zh-CN
|
||||
帖子国际化测试内容
|
||||
:::
|
||||
|
||||
::: en
|
||||
Post i18n test content
|
||||
:::
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Valaxy Addons Gallery
|
||||
title_zh: Valaxy 插件橱窗
|
||||
title:
|
||||
en: Valaxy Addons Gallery
|
||||
zh-CN: Valaxy 插件橱窗
|
||||
categories:
|
||||
- addon
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Use Addon
|
||||
title_zh: 使用插件
|
||||
title:
|
||||
zh-CN: 使用插件
|
||||
en: Use Addon
|
||||
categories:
|
||||
- addon
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Why Addon?
|
||||
title_zh: 为什么需要插件?
|
||||
title:
|
||||
en: Why Addon?
|
||||
zh-CN: 为什么需要插件?
|
||||
categories:
|
||||
- addon
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Write an Addon
|
||||
title_zh: 编写一个插件
|
||||
title:
|
||||
en: Write an Addon
|
||||
zh-CN: 编写一个插件
|
||||
categories:
|
||||
- addon
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Participate in Docs
|
||||
title_zh: 参与文档
|
||||
title:
|
||||
en: Participate in Docs
|
||||
zh-CN: 参与文档
|
||||
categories:
|
||||
- dev
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: FAQ
|
||||
title_zh: 常见问题
|
||||
title:
|
||||
en: FAQ
|
||||
zh-CN: 常见问题
|
||||
categories:
|
||||
- dev
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Participate in Development
|
||||
title_zh-CN: 参与开发
|
||||
title:
|
||||
en: Participate in Development
|
||||
zh-CN: 参与开发
|
||||
categories:
|
||||
- dev
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Client
|
||||
title_zh: 客户端
|
||||
title:
|
||||
en: Client
|
||||
zh-CN: 客户端
|
||||
categories:
|
||||
- ecosystem
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Community
|
||||
title_zh: 社区
|
||||
title:
|
||||
en: Community
|
||||
zh-CN: 社区
|
||||
categories:
|
||||
- ecosystem
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: News
|
||||
title_zh: 新闻
|
||||
title:
|
||||
en: News
|
||||
zh-CN: 新闻
|
||||
categories:
|
||||
- ecosystem
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: VSCode Extension
|
||||
title_zh: VSCode 扩展
|
||||
title:
|
||||
en: VSCode Extension
|
||||
zh-CN: VSCode 扩展
|
||||
categories:
|
||||
- ecosystem
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Code height limit
|
||||
title_zh: 代码块高度限制
|
||||
title:
|
||||
zh-CN: 代码块高度限制
|
||||
en: Code height limit
|
||||
toc: true
|
||||
categories:
|
||||
- examples
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Partial Content Encryption
|
||||
title_zh: 部分内容加密
|
||||
title:
|
||||
en: Partial Content Encryption
|
||||
zh-CN: 部分内容加密
|
||||
toc: true
|
||||
categories:
|
||||
- examples
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: 示例站点
|
||||
title_zh: 示例站点
|
||||
title:
|
||||
en: Example Sites
|
||||
zh-CN: 示例站点
|
||||
categories:
|
||||
- ecosystem
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: FAQ
|
||||
title_zh: 常见问题
|
||||
title:
|
||||
en: FAQ
|
||||
zh-CN: 常见问题
|
||||
categories:
|
||||
- guide
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Best Practice
|
||||
title_zh: 最佳实践
|
||||
title:
|
||||
en: Best Practice
|
||||
zh-CN: 最佳实践
|
||||
categories:
|
||||
- guide
|
||||
top: 1
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Components
|
||||
title_zh: 组件
|
||||
title:
|
||||
en: Components
|
||||
zh-CN: 组件
|
||||
categories:
|
||||
- guide
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Commands
|
||||
title_zh: 命令行
|
||||
title:
|
||||
en: Commands
|
||||
zh-CN: 命令行
|
||||
categories:
|
||||
- guide
|
||||
top: 99
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Extend Config
|
||||
title_zh: 扩展配置
|
||||
title:
|
||||
en: Extend Config
|
||||
zh-CN: 扩展配置
|
||||
categories:
|
||||
- config
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Config
|
||||
title_zh: 基础配置
|
||||
title:
|
||||
en: Config
|
||||
zh-CN: 基础配置
|
||||
categories:
|
||||
- config
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: UnoCSS Options
|
||||
title_zh: UnoCSS 配置
|
||||
title:
|
||||
en: UnoCSS Options
|
||||
zh-CN: UnoCSS 配置
|
||||
categories:
|
||||
- config
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Components
|
||||
title_zh: 自定义组件
|
||||
title:
|
||||
en: Custom Components
|
||||
zh-CN: 自定义组件
|
||||
categories:
|
||||
- custom
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Custom Extensions
|
||||
title_zh: 自定义扩展
|
||||
title:
|
||||
en: Custom Extensions
|
||||
zh-CN: 自定义扩展
|
||||
categories:
|
||||
- custom
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Hooks
|
||||
title_zh: 钩子
|
||||
title:
|
||||
en: Hooks
|
||||
zh-CN: 钩子
|
||||
categories:
|
||||
- custom
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Custom Styles
|
||||
title_zh: 自定义样式
|
||||
title:
|
||||
en: Custom Styles
|
||||
zh-CN: 自定义样式
|
||||
categories:
|
||||
- custom
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Custom Post Templates
|
||||
title_zh: 自定义文章模板
|
||||
title:
|
||||
en: Custom Post Templates
|
||||
zh-CN: 自定义文章模板
|
||||
categories:
|
||||
- custom
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Deployment
|
||||
title_zh: 部署
|
||||
title:
|
||||
en: Deployment
|
||||
zh-CN: 部署
|
||||
categories:
|
||||
- getting-started
|
||||
top: 99
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Features
|
||||
title_zh: 亮点
|
||||
title:
|
||||
en: Features
|
||||
zh-CN: 亮点
|
||||
categories:
|
||||
- getting-started
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Getting Started
|
||||
title_zh: 开始
|
||||
title:
|
||||
en: Getting Started
|
||||
zh-CN: 开始
|
||||
categories:
|
||||
- getting-started
|
||||
top: 100
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: i18n in One Page
|
||||
title_zh: 单页 i18n
|
||||
title:
|
||||
en: i18n in One Page
|
||||
zh-CN: 单页 i18n
|
||||
categories:
|
||||
- guide
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title_zh: Markdown 扩展
|
||||
title: Markdown Extensions
|
||||
title:
|
||||
en: Markdown Extensions
|
||||
zh-CN: Markdown 扩展
|
||||
categories:
|
||||
- guide
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Page
|
||||
title_zh: 页面
|
||||
title:
|
||||
en: Page
|
||||
zh-CN: 页面
|
||||
categories:
|
||||
- guide
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Post
|
||||
title_zh: 文章
|
||||
title:
|
||||
en: Post
|
||||
zh-CN: 文章
|
||||
categories:
|
||||
- guide
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Third Comment System
|
||||
title_zh: 第三方评论系统
|
||||
title:
|
||||
en: Third Comment System
|
||||
zh-CN: 第三方评论系统
|
||||
categories:
|
||||
- third
|
||||
---
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Third Party
|
||||
title_zh: 第三方集成
|
||||
title:
|
||||
en: Third Party Integration
|
||||
zh-CN: 第三方集成
|
||||
categories:
|
||||
- third
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Schema.org And OPG for SEO
|
||||
title_zh: Schema.org And OPG for SEO
|
||||
title:
|
||||
en: Schema.org And OPG for SEO
|
||||
zh-CN: Schema.org 和 OPG 用于 SEO
|
||||
categories:
|
||||
- third
|
||||
top: 0
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Use Vite/Vue Plugin
|
||||
title_zh: 使用 Vite/Vue 插件
|
||||
title:
|
||||
en: Use Vite/Vue Plugin
|
||||
zh-CN: 使用 Vite/Vue 插件
|
||||
categories:
|
||||
- third
|
||||
---
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
---
|
||||
cover: https://cos.yunle.fun/images/bg/girl-in-water-tank.webp
|
||||
title: Why Valaxy
|
||||
title_zh: 为什么选 Valaxy
|
||||
title:
|
||||
en: Why Valaxy
|
||||
zh-CN: 为什么选 Valaxy
|
||||
date: 2022-03-22
|
||||
categories:
|
||||
- getting-started
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Migration from Other
|
||||
title_zh: 从其他博客框架迁移
|
||||
title:
|
||||
en: Migration from Other
|
||||
zh-CN: 从其他博客框架迁移
|
||||
categories:
|
||||
- migration
|
||||
top: 10
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Version Migration
|
||||
title_zh: 版本迁移
|
||||
title:
|
||||
en: Version Migration
|
||||
zh-CN: 版本迁移
|
||||
categories:
|
||||
- migration
|
||||
top: 8
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: How to realize CSS i18n?
|
||||
title_zh: 如何实现 CSS i18n?
|
||||
title:
|
||||
en: How to realize CSS i18n?
|
||||
zh-CN: 如何实现 CSS i18n?
|
||||
date: 2022-04-09
|
||||
categories: Valaxy 开发笔记
|
||||
tags:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Valaxy Themes Gallery
|
||||
title_zh: Valaxy 主题橱窗
|
||||
title:
|
||||
en: Valaxy Themes Gallery
|
||||
zh-CN: Valaxy 主题橱窗
|
||||
categories:
|
||||
- theme
|
||||
end: false
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: Use Theme
|
||||
title_zh: 使用主题
|
||||
title:
|
||||
en: Use Theme
|
||||
zh-CN: 使用主题
|
||||
categories:
|
||||
- theme
|
||||
top: 100
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
title: How to write a theme?
|
||||
title_zh: 如何编写一个 Valaxy 主题
|
||||
title:
|
||||
en: How to write a theme?
|
||||
zh-CN: 如何编写一个 Valaxy 主题
|
||||
categories:
|
||||
- theme
|
||||
end: false
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { useFrontmatter, useSiteStore } from 'valaxy'
|
||||
import { tObject, useFrontmatter, useSiteStore } from 'valaxy'
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getLocaleTitle } from '../utils'
|
||||
|
||||
const frontmatter = useFrontmatter()
|
||||
|
||||
|
@ -19,7 +18,7 @@ const nextPost = computed(() => site.postList[findCurrentIndex() - 1])
|
|||
const prevPost = computed(() => site.postList[findCurrentIndex() + 1])
|
||||
|
||||
const { locale } = useI18n()
|
||||
const localeTitle = computed(() => getLocaleTitle(locale.value, frontmatter.value))
|
||||
const $title = computed(() => tObject(frontmatter.value.title || '', locale.value))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -36,7 +35,7 @@ const localeTitle = computed(() => getLocaleTitle(locale.value, frontmatter.valu
|
|||
md:text-5xl md:leading-14
|
||||
"
|
||||
>
|
||||
{{ localeTitle }}
|
||||
{{ $title }}
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Category, Post } from 'valaxy'
|
||||
import { isCategoryList } from 'valaxy'
|
||||
import { isCategoryList, tObject } from 'valaxy'
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
|
@ -23,8 +23,7 @@ const { t, locale } = useI18n()
|
|||
|
||||
function getTitle(post: Post | any) {
|
||||
const lang = locale.value
|
||||
const localeTitle = post[`title_${lang}`] || post[`title_${lang.split('-')[0]}`]
|
||||
return localeTitle || post.title
|
||||
return tObject(post.title || '', lang)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import type { PageData, Post } from 'valaxy'
|
||||
import { onClickHref, onContentUpdated, scrollTo, useFrontmatter, useLayout, useSidebar, useSiteConfig } from 'valaxy'
|
||||
import { onClickHref, onContentUpdated, scrollTo, tObject, useFrontmatter, useLayout, useSidebar, useSiteConfig } from 'valaxy'
|
||||
import { computed, nextTick } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { targetPadding } from '../client'
|
||||
import { getLocaleTitle } from '../utils'
|
||||
|
||||
defineProps<{
|
||||
frontmatter: Post
|
||||
|
@ -20,7 +19,7 @@ const isHome = useLayout('home')
|
|||
const layout = useLayout()
|
||||
|
||||
const { locale } = useI18n()
|
||||
const localeTitle = computed(() => getLocaleTitle(locale.value, frontmatter.value))
|
||||
const $title = computed(() => tObject(frontmatter.value.title || '', locale.value))
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
@ -64,9 +63,9 @@ onContentUpdated(() => {
|
|||
<slot name="main-content-before" />
|
||||
|
||||
<ValaxyMd class="mx-auto w-full max-w-4xl" :frontmatter="frontmatter">
|
||||
<h1 v-if="hasSidebar && !isHome && frontmatter.title" :id="frontmatter.title" tabindex="-1">
|
||||
{{ localeTitle }}
|
||||
<a class="header-anchor" :href="`#${frontmatter.title}`" aria-hidden="true" />
|
||||
<h1 v-if="hasSidebar && !isHome && $title" :id="$title" tabindex="-1">
|
||||
{{ $title }}
|
||||
<a class="header-anchor" :href="`#${$title}`" aria-hidden="true" />
|
||||
</h1>
|
||||
<slot name="main-content-md" />
|
||||
<slot />
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/**
|
||||
* get locale title
|
||||
* @param locale
|
||||
* @param frontmatter
|
||||
*/
|
||||
export function getLocaleTitle(locale: string, frontmatter: any) {
|
||||
return frontmatter[`title${locale === 'en' ? '' : `_${locale}`}`] || frontmatter.title
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { Post } from 'valaxy'
|
||||
import { isCategoryList } from 'valaxy'
|
||||
import { isCategoryList, tObject } from 'valaxy'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
@ -16,8 +16,7 @@ defineProps<{
|
|||
*/
|
||||
const { locale } = useI18n()
|
||||
function getTitle(post: Post | any) {
|
||||
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
|
||||
return post[`title_${lang}`] ? post[`title_${lang}`] : post.title
|
||||
return tObject(post.title || '', locale.value)
|
||||
}
|
||||
const route = useRoute()
|
||||
const categoryList = computed(() => {
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
<script lang="ts" setup>
|
||||
import { usePrevNext } from 'valaxy'
|
||||
import { useLocaleTitle, usePrevNext } from 'valaxy'
|
||||
|
||||
const [prev, next] = usePrevNext()
|
||||
|
||||
const prevTitle = useLocaleTitle(prev)
|
||||
const nextTitle = useLocaleTitle(next)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="post-nav">
|
||||
<div class="post-nav-item">
|
||||
<RouterLink v-if="prev" class="post-nav-prev" :to="prev.path || ''" :title="prev.title">
|
||||
<RouterLink v-if="prev" class="post-nav-prev" :to="prev.path || ''" :title="prevTitle">
|
||||
<div class="icon" i-ri-arrow-left-s-line />
|
||||
<span class="title truncate" text="sm">{{ prev.title }}</span>
|
||||
<span class="title truncate" text="sm">{{ prevTitle }}</span>
|
||||
</RouterLink>
|
||||
</div>
|
||||
<div class="post-nav-item">
|
||||
<RouterLink v-if="next" :to="next.path || ''" :title="next.title" class="post-nav-next">
|
||||
<span class="title truncate" text="sm">{{ next.title }}</span>
|
||||
<RouterLink v-if="next" :to="next.path || ''" :title="nextTitle" class="post-nav-next">
|
||||
<span class="title truncate" text="sm">{{ nextTitle }}</span>
|
||||
<div class="icon" i-ri-arrow-right-s-line />
|
||||
</RouterLink>
|
||||
</div>
|
||||
|
|
|
@ -2,15 +2,17 @@
|
|||
import { defineArticle, useSchemaOrg } from '@unhead/schema-org/vue'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
import { useFrontmatter, useSiteConfig } from 'valaxy'
|
||||
import { tObject, useFrontmatter, useSiteConfig } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const siteConfig = useSiteConfig()
|
||||
const frontmatter = useFrontmatter()
|
||||
|
||||
const { locale } = useI18n()
|
||||
const article: Parameters<typeof defineArticle>[0] = {
|
||||
'@type': 'BlogPosting',
|
||||
'headline': frontmatter.value.title,
|
||||
'description': frontmatter.value.description,
|
||||
'headline': tObject(frontmatter.value.title || '', locale.value),
|
||||
'description': tObject(frontmatter.value.description || '', locale.value),
|
||||
'author': [
|
||||
{
|
||||
name: siteConfig.value.author.name,
|
||||
|
|
|
@ -5,9 +5,10 @@ import { useSeoMeta } from '@unhead/vue'
|
|||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { tObject } from '../../../shared/utils/i18n'
|
||||
import { useFrontmatter, useValaxyHead } from '../../composables'
|
||||
import { useTimezone } from '../../composables/global'
|
||||
|
||||
import { useTimezone } from '../../composables/global'
|
||||
// https://github.com/vueuse/head
|
||||
// you can use this to manipulate the document head in any components,
|
||||
// they will be rendered correctly in the html results with vite-ssg
|
||||
|
@ -20,7 +21,7 @@ export function useValaxyApp() {
|
|||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const title = computed(() => fm.value[`title_${locale.value}`] || fm.value.title)
|
||||
const title = computed(() => tObject(fm.value.title || '', locale.value))
|
||||
|
||||
// seo
|
||||
// todo: get first image url from markdown
|
||||
|
@ -33,7 +34,7 @@ export function useValaxyApp() {
|
|||
ogLocale: computed(() => locale.value || fm.value.lang || siteConfig.value.lang || 'en'),
|
||||
ogLocaleAlternate: computed(() => siteConfig.value.languages.filter(l => l !== locale.value)),
|
||||
ogSiteName: computed(() => siteConfig.value.title),
|
||||
ogTitle: computed(() => fm.value.title || siteConfig.value.title),
|
||||
ogTitle: computed(() => tObject(fm.value.title || siteConfig.value.title, locale.value)),
|
||||
ogImage: computed(() => fm.value.ogImage || fm.value.cover || siteConfig.value.favicon),
|
||||
ogType: 'website',
|
||||
ogUrl: siteUrl,
|
||||
|
|
|
@ -5,15 +5,16 @@ import { useI18n } from 'vue-i18n'
|
|||
|
||||
import { useFrontmatter } from '../../composables'
|
||||
import { useSiteConfig } from '../../config'
|
||||
import { tObject } from '../../utils'
|
||||
|
||||
export function useValaxyHead() {
|
||||
const { locale } = useI18n()
|
||||
|
||||
const fm = useFrontmatter()
|
||||
const siteConfig = useSiteConfig()
|
||||
const title = computed<string>(() => fm.value[`title_${locale.value}`] || fm.value.title)
|
||||
const $title = computed(() => tObject(fm.value.title || '', locale.value))
|
||||
useHead({
|
||||
title,
|
||||
title: $title,
|
||||
titleTemplate: (title) => {
|
||||
return fm.value.titleTemplate || (title ? `${title} - ${siteConfig.value.title}` : siteConfig.value.title)
|
||||
},
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import type { Ref } from 'vue'
|
||||
import { isClient, useStorage } from '@vueuse/core'
|
||||
import dayjs from 'dayjs'
|
||||
import { computed } from 'vue'
|
||||
|
||||
// not optimize deps all locales
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { tObject } from '../../shared/utils/i18n'
|
||||
import 'dayjs/locale/en'
|
||||
import 'dayjs/locale/zh-cn'
|
||||
|
||||
|
@ -34,3 +37,29 @@ export function useLocale() {
|
|||
toggleLocales,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get locale title
|
||||
*
|
||||
* ```md
|
||||
* ---
|
||||
* title:
|
||||
* zh-CN: Valaxy - Vue 驱动的静态站点生成器
|
||||
* en: Valaxy - Vue Powered Static Site Generator
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* @param fm
|
||||
*/
|
||||
export function useLocaleTitle(fm: Ref<{
|
||||
title?: string | Record<string, string>
|
||||
} | null>) {
|
||||
const { locale } = useI18n()
|
||||
return computed(() => {
|
||||
if (!fm.value)
|
||||
return ''
|
||||
|
||||
const lang = locale.value
|
||||
return tObject(fm.value.title || '', lang) || ''
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { ComputedRef } from 'vue'
|
|||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouterStore } from '../../stores'
|
||||
import { sortByDate } from '../../utils'
|
||||
import { sortByDate, tObject } from '../../utils'
|
||||
|
||||
export * from './usePagination'
|
||||
export * from './usePrevNext'
|
||||
|
@ -11,8 +11,7 @@ export * from './usePrevNext'
|
|||
export function usePostTitle(post: ComputedRef<Post>) {
|
||||
const { locale } = useI18n()
|
||||
return computed(() => {
|
||||
const lang = locale.value === 'zh-CN' ? 'zh' : locale.value
|
||||
return post.value[`title_${lang}`] || post.value.title
|
||||
return tObject(post.value.title || '', locale.value)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ export const i18n = createI18n({
|
|||
legacy: false,
|
||||
locale: '',
|
||||
messages: valaxyMessages,
|
||||
// use key
|
||||
missingWarn: false,
|
||||
})
|
||||
|
||||
export async function install({ app, router }: ViteSSGContext, config: ComputedRef<ValaxyConfig<DefaultTheme.Config>>) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from '../../shared'
|
||||
export * from './cdn'
|
||||
export * from './code'
|
||||
export * from './content'
|
||||
|
@ -5,4 +6,5 @@ export * from './helper'
|
|||
export * from './router'
|
||||
export * from './time'
|
||||
export * from './types'
|
||||
|
||||
export * from './wrap'
|
||||
|
|
|
@ -16,6 +16,7 @@ import MarkdownIt from 'markdown-it'
|
|||
|
||||
import ora from 'ora'
|
||||
import { getBorderCharacters, table } from 'table'
|
||||
import { tObject } from '../../../shared'
|
||||
import { matterOptions } from '../../plugins/markdown/transform/matter'
|
||||
import { isExternal } from '../../utils'
|
||||
import { getCreatedTime, getUpdatedTime } from '../../utils/date'
|
||||
|
@ -36,6 +37,7 @@ export async function build(options: ResolvedValaxyOptions) {
|
|||
|
||||
const { config } = options
|
||||
const siteConfig = config.siteConfig
|
||||
const lang = siteConfig.lang || 'en'
|
||||
|
||||
if (!siteConfig.url || siteConfig.url === '/') {
|
||||
consola.error('You must set `url` (like `https://example.com`) in `site.config.ts` to generate rss.')
|
||||
|
@ -62,9 +64,11 @@ export async function build(options: ResolvedValaxyOptions) {
|
|||
Object.keys(feedNameMap).forEach((key) => {
|
||||
feedLinks[key] = `${siteUrl}${feedNameMap[key]}`
|
||||
})
|
||||
const title = tObject(siteConfig.title, lang)
|
||||
const description = tObject(siteConfig.description, lang)
|
||||
const feedOptions: FeedOptions = {
|
||||
title: siteConfig.title || 'Valaxy Blog',
|
||||
description: siteConfig.description,
|
||||
title: title || 'Valaxy Blog',
|
||||
description,
|
||||
id: siteUrl || 'valaxy',
|
||||
link: siteUrl,
|
||||
copyright: `CC ${siteConfig.license?.type?.toUpperCase()} ${ccVersion} ${new Date().getFullYear()} © ${siteConfig.author?.name}`,
|
||||
|
@ -172,8 +176,9 @@ export async function getPosts(params: {
|
|||
}</p>`
|
||||
|
||||
posts.push({
|
||||
title: data.title,
|
||||
...data,
|
||||
title: tObject(data.title, lang),
|
||||
description: tObject(data.description, lang),
|
||||
date: new Date(data.date),
|
||||
published: new Date(data.updated || data.date),
|
||||
content: html + tip,
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
"client",
|
||||
"dist",
|
||||
"index.d.ts",
|
||||
"shared",
|
||||
"shims.d.ts",
|
||||
"types"
|
||||
],
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './utils'
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* translate object
|
||||
*
|
||||
* { 'en': 'English', 'zh-CN': '中文' }
|
||||
*
|
||||
* ```ts
|
||||
* tObject({ 'en': 'English', 'zh-CN': '中文' }, 'zh-CN') // 中文
|
||||
* tObject({ 'en': 'English', 'zh-CN': '中文' }, 'en') // English
|
||||
* tObject({ 'en': 'English', 'zh-CN': '中文' }, 'fr') // English
|
||||
* ```
|
||||
*/
|
||||
export function tObject(data: string | Record<string, string>, lang: string): string {
|
||||
if (typeof data === 'object') {
|
||||
return data[lang] || Object.values(data)[0] || ''
|
||||
}
|
||||
return data
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './i18n'
|
|
@ -44,8 +44,22 @@ export interface PageFrontMatter extends Record<string, any> {
|
|||
/**
|
||||
* Title
|
||||
* @description 文章标题
|
||||
*
|
||||
* ```md
|
||||
* ---
|
||||
* title: Post Title
|
||||
* ---
|
||||
* ```
|
||||
*
|
||||
* ```md
|
||||
* ---
|
||||
* title:
|
||||
* en: Post Title
|
||||
* zh-CN: 文章标题
|
||||
* ---
|
||||
* ```
|
||||
*/
|
||||
title: string
|
||||
title: string | Record<string, string>
|
||||
date: string | number | Date
|
||||
/**
|
||||
* Updated Time
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface FuseListItem extends Record<string, any> {
|
||||
title: string
|
||||
title: string | Record<string, string>
|
||||
excerpt?: string
|
||||
author: string
|
||||
tags: string[]
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import { tObject } from '../packages/valaxy/shared/utils/i18n'
|
||||
|
||||
describe('i18n', () => {
|
||||
it('tObject with lang', () => {
|
||||
const result = tObject({ 'en': 'English', 'zh-CN': '中文' }, 'zh-CN')
|
||||
expect(result).toBe('中文')
|
||||
})
|
||||
|
||||
it('tObject not found', () => {
|
||||
const result = tObject({ 'en': 'English', 'zh-CN': '中文' }, 'es')
|
||||
expect(result).toBe('English') // Fallback to first language
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue