diff --git a/theme/src/node/defaultOptions.ts b/theme/src/node/defaultOptions.ts index be3b3d20..9164b778 100644 --- a/theme/src/node/defaultOptions.ts +++ b/theme/src/node/defaultOptions.ts @@ -1,55 +1,137 @@ +import type { App } from '@vuepress/core' +import { deepClone, deepMerge } from '@pengzhanbo/utils' import type { PlumeThemeLocaleOptions } from '../shared/index.js' +import { pathJoin } from './utils.js' +import { resolveLocaleOptions } from './resolveLocaleOptions.js' -export const defaultLocaleOption: Partial = { - article: '/article', +const defaultLocales: NonNullable = { + 'en-US': { + selectLanguageName: 'English', + selectLanguageText: 'Languages', + editLinkText: 'Edit this page', + lastUpdatedText: 'Last Updated', + contributorsText: 'Contributors', + }, + 'zh-CN': { + selectLanguageName: '简体中文', + selectLanguageText: '选择语言', + + blog: { pagination: { prevPageText: '上一页', nextPageText: '下一页' } }, + + outlineLabel: '内容大纲', + returnToTopLabel: '返回顶部', + editLinkText: '编辑此页', + lastUpdatedText: '上次更新', + prevPageLabel: '上一页', + nextPageLabel: '下一页', + + notFound: { + code: '404', + title: '页面未找到', + quote: '但是,如果你不改变方向,并且一直寻找,最终可能会到达你要去的地方。', + linkText: '返回首页', + }, + }, +} + +export const fallbackLocaleOption: Partial = { + article: '/article/', notes: { link: '/note', dir: 'notes', notes: [] }, + appearance: true, + // page meta + editLink: true, + lastUpdated: true, + contributors: true, footer: { message: 'Power by VuePress & vuepress-theme-plume', }, - appearance: true, - // page meta - editLink: true, - editLinkText: 'Edit this page', - lastUpdated: true, - lastUpdatedText: 'Last Updated', - contributors: true, - contributorsText: 'Contributors', } -export function mergeLocaleOptions(options: PlumeThemeLocaleOptions) { - if (!options.locales) - options.locales = {} +interface PresetLocale { + home: string + blog: string +} + +const presetLocales: Record = { + 'zh-CN': { + home: '首页', + blog: '博客', + }, + 'en-US': { + home: 'Home', + blog: 'Blog', + }, +} + +export function mergeLocaleOptions(app: App, options: PlumeThemeLocaleOptions) { + options.locales ??= {} if (options.notes) { options.notes = { - ...defaultLocaleOption.notes, + ...fallbackLocaleOption.notes, ...(options.notes ?? {}), } } if (options.footer) { options.footer = { - ...defaultLocaleOption.footer, + ...fallbackLocaleOption.footer, ...options.footer, } } const { locales, ...otherOptions } = options - - if (!locales['/']) - locales['/'] = {} + locales['/'] ??= {} Object.assign(options, { - ...defaultLocaleOption, + ...fallbackLocaleOption, ...options, }) Object.assign(locales['/'], { - ...{ selectLanguageName: 'English' }, - ...JSON.parse(JSON.stringify(otherOptions)), + ...deepClone(otherOptions), ...locales['/'], }) + const langs: Record = {} + Object.keys(app.siteData.locales || {}).forEach((locale) => { + const lang = app.siteData.locales![locale]?.lang || 'en-US' + langs[locale] = lang + if (defaultLocales[lang]) { + locales[locale] = deepMerge( + {}, + defaultLocales[lang], + locales[locale] || {}, + ) + } + }) + + const base = app.siteData.base || '/' + const defaultLang = app.siteData.lang || 'en-US' + const defaultBlog = resolveLocaleOptions(options, 'blog') + Object.keys(locales).forEach((locale) => { + const option = locales[locale] + const lang = langs[locale] || defaultLang + + // 当用户未配置导航栏时,生成默认导航栏 + if (!option.navbar || !option.navbar.length) { + option.navbar = [{ + link: pathJoin(base, locale), + text: presetLocales[lang]?.home || presetLocales[defaultLang].home, + icon: 'material-symbols:home-outline', + }] + const blog = option.blog + const link = blog?.link + ? blog.link + : pathJoin(base, locale, defaultBlog?.link || '/blog/') + link && option.navbar.push({ + link, + text: presetLocales[lang]?.blog || presetLocales[defaultLang].blog, + icon: 'material-symbols:article-outline', + }) + } + }) + return options } diff --git a/theme/src/node/theme.ts b/theme/src/node/theme.ts index 7af76c53..9e0b3969 100644 --- a/theme/src/node/theme.ts +++ b/theme/src/node/theme.ts @@ -13,23 +13,25 @@ export function plumeTheme({ plugins, ...localeOptions }: PlumeThemeOptions = {}): Theme { - localeOptions = mergeLocaleOptions(localeOptions) const pluginsOptions = plugins ?? themePlugins ?? {} const pkg = getThemePackage() - return app => ({ - name: THEME_NAME, - templateBuild: templates('build.html'), - clientConfigFile: resolve('client/config.js'), - plugins: setupPlugins(app, pluginsOptions, localeOptions), - onInitialized: app => setupPage(app, localeOptions), - extendsPage: page => extendsPageData(app, page as Page, localeOptions), - templateBuildRenderer(template, context) { - template = template - .replace('{{ themeVersion }}', pkg.version || '') - .replace(/^\s+|\s+$/gm, '') - .replace(/\n/g, '') - return templateRenderer(template, context) - }, - }) + return (app) => { + localeOptions = mergeLocaleOptions(app, localeOptions) + return { + name: THEME_NAME, + templateBuild: templates('build.html'), + clientConfigFile: resolve('client/config.js'), + plugins: setupPlugins(app, pluginsOptions, localeOptions), + onInitialized: app => setupPage(app, localeOptions), + extendsPage: page => extendsPageData(app, page as Page, localeOptions), + templateBuildRenderer(template, context) { + template = template + .replace('{{ themeVersion }}', pkg.version || '') + .replace(/^\s+|\s+$/gm, '') + .replace(/\n/g, '') + return templateRenderer(template, context) + }, + } + } }