mirror of
https://github.com/d0zingcat/NotionNext.git
synced 2026-05-20 07:26:46 +00:00
多语言支持初版,不支持static export
This commit is contained in:
@@ -9,6 +9,7 @@ import { getPostBlocks, getSingleBlock } from '@/lib/notion/getPostBlocks'
|
||||
import { compressImage, mapImgUrl } from '@/lib/notion/mapImage'
|
||||
import { deepClone } from '@/lib/utils'
|
||||
import { idToUuid } from 'notion-utils'
|
||||
import { extractLangId, extractLangPrefix } from '../utils/pageId'
|
||||
|
||||
export { getAllTags } from '../notion/getAllTags'
|
||||
export { getPost } from '../notion/getNotionPost'
|
||||
@@ -18,18 +19,62 @@ export { getPostBlocks } from '../notion/getPostBlocks'
|
||||
* 获取博客数据; 基于Notion实现
|
||||
* @param {*} pageId
|
||||
* @param {*} from
|
||||
* @param latestPostCount 截取最新文章数量
|
||||
* @param categoryCount
|
||||
* @param tagsCount 截取标签数量
|
||||
* @param pageType 过滤的文章类型,数组格式 ['Page','Post']
|
||||
* @param {*} locale 语言 zh|en|jp 等等
|
||||
* @returns
|
||||
*
|
||||
*/
|
||||
export async function getGlobalData({ pageId = BLOG.NOTION_PAGE_ID, from }) {
|
||||
// 从notion获取
|
||||
const data = await getNotionPageData({ pageId, from })
|
||||
export async function getGlobalData({
|
||||
pageId = BLOG.NOTION_PAGE_ID,
|
||||
from,
|
||||
locale
|
||||
}) {
|
||||
// 获取站点数据 , 如果pageId有逗号隔开则分次取数据
|
||||
const siteIds = pageId.split(',')
|
||||
let data = EmptyData(pageId)
|
||||
|
||||
try {
|
||||
for (let index = 0; index < siteIds.length; index++) {
|
||||
const siteId = siteIds[index]
|
||||
const id = extractLangId(siteId)
|
||||
const prefix = extractLangPrefix(siteId)
|
||||
// 第一个id站点默认语言
|
||||
if (index === 0 || locale === prefix) {
|
||||
data = await getNotionPageData({
|
||||
pageId: id,
|
||||
from
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('异常', error)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定notion的collection数据
|
||||
* @param pageId
|
||||
* @param from 请求来源
|
||||
* @returns {Promise<JSX.Element|*|*[]>}
|
||||
*/
|
||||
export async function getNotionPageData({ pageId, from }) {
|
||||
// 尝试从缓存获取
|
||||
const cacheKey = 'page_block_' + pageId
|
||||
let data = await getDataFromCache(cacheKey)
|
||||
if (data && data.pageIds?.length > 0) {
|
||||
// console.log('[API<<--缓存]', `from:${from}`, `root-page-id:${pageId}`)
|
||||
// return data
|
||||
} else {
|
||||
// 从接口读取
|
||||
data = await getDataBaseInfoByNotionAPI({ pageId, from })
|
||||
// 存入缓存
|
||||
if (data) {
|
||||
await setDataToCache(cacheKey, data)
|
||||
}
|
||||
}
|
||||
|
||||
// 返回给前端的数据做处理
|
||||
const db = deepClone(data)
|
||||
// 减少返回给前端的数据,减少流量损耗
|
||||
delete db.block
|
||||
delete db.schema
|
||||
delete db.rawMetadata
|
||||
@@ -47,10 +92,12 @@ export async function getGlobalData({ pageId = BLOG.NOTION_PAGE_ID, from }) {
|
||||
if (db?.post) {
|
||||
db.post = cleanBlock(db?.post)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理block数据
|
||||
*/
|
||||
function cleanBlock(post) {
|
||||
const pageBlock = post?.blockMap?.block
|
||||
for (const i in pageBlock) {
|
||||
@@ -98,28 +145,6 @@ function getLatestPosts({ allPages, from, latestPostCount }) {
|
||||
return latestPosts.slice(0, latestPostCount)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定notion的collection数据
|
||||
* @param pageId
|
||||
* @param from 请求来源
|
||||
* @returns {Promise<JSX.Element|*|*[]>}
|
||||
*/
|
||||
export async function getNotionPageData({ pageId, from }) {
|
||||
// 尝试从缓存获取
|
||||
const cacheKey = 'page_block_' + pageId
|
||||
const data = await getDataFromCache(cacheKey)
|
||||
if (data && data.pageIds?.length > 0) {
|
||||
// console.log('[API<<--缓存]', `from:${from}`, `root-page-id:${pageId}`)
|
||||
return data
|
||||
}
|
||||
const db = await getDataBaseInfoByNotionAPI({ pageId, from })
|
||||
// 存入缓存
|
||||
if (db) {
|
||||
await setDataToCache(cacheKey, db)
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户自定义单页菜单
|
||||
* 旧版本,不读取Menu菜单,而是读取type=Page生成菜单
|
||||
@@ -308,6 +333,7 @@ const EmptyData = pageId => {
|
||||
status: 'Published',
|
||||
type: 'Post',
|
||||
slug: '13a171332816461db29d50e9f575b00d',
|
||||
pageCoverThumbnail: BLOG.HOME_BANNER_IMAGE,
|
||||
date: {
|
||||
start_date: '2023-04-24',
|
||||
lastEditedDay: '2023-04-24',
|
||||
|
||||
26
lib/lang.js
26
lib/lang.js
@@ -1,11 +1,11 @@
|
||||
import zhCN from './lang/zh-CN'
|
||||
import { getQueryVariable, isBrowser, mergeDeep } from '@/lib/utils'
|
||||
import enUS from './lang/en-US'
|
||||
import frFR from './lang/fr-FR'
|
||||
import jaJP from './lang/ja-JP'
|
||||
import trTR from './lang/tr-TR'
|
||||
import zhCN from './lang/zh-CN'
|
||||
import zhHK from './lang/zh-HK'
|
||||
import zhTW from './lang/zh-TW'
|
||||
import frFR from './lang/fr-FR'
|
||||
import trTR from './lang/tr-TR'
|
||||
import jaJP from './lang/ja-JP'
|
||||
import { getQueryVariable, isBrowser, mergeDeep } from '@/lib/utils'
|
||||
|
||||
/**
|
||||
* 在这里配置所有支持的语言
|
||||
@@ -43,7 +43,9 @@ export function generateLocaleDict(langString) {
|
||||
|
||||
// 然后尝试匹配只有语言匹配的情况
|
||||
if (!userLocale) {
|
||||
const languageOnlyLocales = supportedLocales.filter(locale => locale.startsWith(language))
|
||||
const languageOnlyLocales = supportedLocales.filter(locale =>
|
||||
locale.startsWith(language)
|
||||
)
|
||||
if (languageOnlyLocales.length > 0) {
|
||||
userLocale = LANGS[languageOnlyLocales[0]]
|
||||
}
|
||||
@@ -51,7 +53,9 @@ export function generateLocaleDict(langString) {
|
||||
|
||||
// 如果还没匹配到,则返回最接近的语言包
|
||||
if (!userLocale) {
|
||||
const fallbackLocale = supportedLocales.find(locale => locale.startsWith('en'))
|
||||
const fallbackLocale = supportedLocales.find(locale =>
|
||||
locale.startsWith('en')
|
||||
)
|
||||
userLocale = LANGS[fallbackLocale]
|
||||
}
|
||||
|
||||
@@ -64,7 +68,11 @@ export function generateLocaleDict(langString) {
|
||||
*/
|
||||
export function initLocale(lang, locale, changeLang, changeLocale) {
|
||||
if (isBrowser) {
|
||||
const queryLang = getQueryVariable('lang') || loadLangFromLocalStorage()
|
||||
// 用户请求的预研
|
||||
const queryLang =
|
||||
getQueryVariable('locale') ||
|
||||
getQueryVariable('lang') ||
|
||||
loadLangFromLocalStorage()
|
||||
let currentLang = lang
|
||||
if (queryLang && queryLang !== 'undefined' && queryLang !== lang) {
|
||||
currentLang = queryLang
|
||||
@@ -91,6 +99,6 @@ export const loadLangFromLocalStorage = () => {
|
||||
* 保存语言
|
||||
* @param newTheme
|
||||
*/
|
||||
export const saveLangToLocalStorage = (lang) => {
|
||||
export const saveLangToLocalStorage = lang => {
|
||||
localStorage.setItem('lang', lang)
|
||||
}
|
||||
|
||||
@@ -22,17 +22,27 @@ const mapImgUrl = (img, block, type = 'block', from = 'post') => {
|
||||
}
|
||||
|
||||
// Notion 图床转换为永久地址
|
||||
const isNotionSignImg = ret.indexOf('https://www.notion.so/image') !== 0 && (ret.indexOf('secure.notion-static.com') > 0 || ret.indexOf('prod-files-secure') > 0)
|
||||
const isNotionSignImg =
|
||||
ret.indexOf('https://www.notion.so/image') !== 0 &&
|
||||
(ret.indexOf('secure.notion-static.com') > 0 ||
|
||||
ret.indexOf('prod-files-secure') > 0)
|
||||
const isImgBlock = BLOG.IMG_URL_TYPE === 'Notion' || type !== 'block'
|
||||
if (isNotionSignImg && isImgBlock) {
|
||||
ret = BLOG.NOTION_HOST + '/image/' + encodeURIComponent(ret) + '?table=' + type + '&id=' + block.id
|
||||
ret =
|
||||
BLOG.NOTION_HOST +
|
||||
'/image/' +
|
||||
encodeURIComponent(ret) +
|
||||
'?table=' +
|
||||
type +
|
||||
'&id=' +
|
||||
block.id
|
||||
}
|
||||
|
||||
if (!isEmoji(ret) && ret.indexOf('notion.so/images/page-cover') < 0) {
|
||||
if (BLOG.RANDOM_IMAGE_URL) {
|
||||
// 只有配置了随机图片接口,才会替换图片
|
||||
const texts = BLOG.RANDOM_IMAGE_REPLACE_TEXT
|
||||
let isReplace = false;
|
||||
let isReplace = false
|
||||
if (texts) {
|
||||
const textArr = texts.split(',')
|
||||
// 判断是否包含替换的文本
|
||||
@@ -58,7 +68,11 @@ const mapImgUrl = (img, block, type = 'block', from = 'post') => {
|
||||
}
|
||||
|
||||
// 统一压缩图片
|
||||
if (from === 'pageCoverThumbnail' || block.type === 'image' || block.type === 'page') {
|
||||
if (
|
||||
from === 'pageCoverThumbnail' ||
|
||||
block?.type === 'image' ||
|
||||
block?.type === 'page'
|
||||
) {
|
||||
const width = block?.format?.block_width
|
||||
ret = compressImage(ret, width)
|
||||
}
|
||||
@@ -72,8 +86,9 @@ const mapImgUrl = (img, block, type = 'block', from = 'post') => {
|
||||
* @returns
|
||||
*/
|
||||
function isEmoji(str) {
|
||||
const emojiRegex = /[\u{1F300}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{1F018}-\u{1F270}\u{238C}\u{2B06}\u{2B07}\u{2B05}\u{27A1}\u{2194}-\u{2199}\u{2194}\u{21A9}\u{21AA}\u{2934}\u{2935}\u{25AA}\u{25AB}\u{25FE}\u{25FD}\u{25FB}\u{25FC}\u{25B6}\u{25C0}\u{1F200}-\u{1F251}]/u;
|
||||
return emojiRegex.test(str);
|
||||
const emojiRegex =
|
||||
/[\u{1F300}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{1F018}-\u{1F270}\u{238C}\u{2B06}\u{2B07}\u{2B05}\u{27A1}\u{2194}-\u{2199}\u{2194}\u{21A9}\u{21AA}\u{2934}\u{2935}\u{25AA}\u{25AB}\u{25FE}\u{25FD}\u{25FB}\u{25FC}\u{25B6}\u{25C0}\u{1F200}-\u{1F251}]/u
|
||||
return emojiRegex.test(str)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +112,10 @@ const compressImage = (image, width, quality = 50, fmt = 'webp') => {
|
||||
const params = new URLSearchParams(urlObj.search)
|
||||
|
||||
// Notion图床
|
||||
if (image.indexOf(BLOG.NOTION_HOST) === 0 && image.indexOf('amazonaws.com') > 0) {
|
||||
if (
|
||||
image.indexOf(BLOG.NOTION_HOST) === 0 &&
|
||||
image.indexOf('amazonaws.com') > 0
|
||||
) {
|
||||
params.set('width', width)
|
||||
params.set('cache', 'v2')
|
||||
// 生成新的URL
|
||||
@@ -117,11 +135,11 @@ const compressImage = (image, width, quality = 50, fmt = 'webp') => {
|
||||
return urlObj.toString()
|
||||
} else if (image.indexOf('https://your_picture_bed') === 0) {
|
||||
// 此处还可以添加您的自定义图传的封面图压缩参数。
|
||||
// .e.g
|
||||
// .e.g
|
||||
return 'do_somethin_here'
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
export { mapImgUrl, compressImage }
|
||||
export { compressImage, mapImgUrl }
|
||||
|
||||
33
lib/utils/pageId.js
Normal file
33
lib/utils/pageId.js
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 截取page-id的语言前缀
|
||||
* notionPageId的格式可以是 en:xxxxx
|
||||
* @param {*} str
|
||||
* @returns en|zh|xx
|
||||
*/
|
||||
function extractLangPrefix(str) {
|
||||
const match = str.match(/^(.+?):/)
|
||||
if (match && match[1]) {
|
||||
return match[1]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取page-id的id
|
||||
* notionPageId的格式可以是 en:xxxxx * @param {*} str
|
||||
* @returns xxxxx
|
||||
*/
|
||||
function extractLangId(str) {
|
||||
// 使用正则表达式匹配字符串
|
||||
const match = str.match(/:\s*(.+)/)
|
||||
// 如果匹配成功,则返回匹配到的内容
|
||||
if (match && match[1]) {
|
||||
return match[1]
|
||||
} else {
|
||||
// 如果没有匹配到,则返回空字符串或者其他你想要返回的值
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { extractLangPrefix, extractLangId }
|
||||
Reference in New Issue
Block a user