diff --git a/content-collections.ts b/content-collections.ts
index c29130b..36d7544 100644
--- a/content-collections.ts
+++ b/content-collections.ts
@@ -8,6 +8,7 @@ import remarkGfm from 'remark-gfm';
import { createHighlighter } from 'shiki';
import path from "path";
import { getBaseUrl } from "@/lib/urls/get-base-url";
+import { LOCALES, DEFAULT_LOCALE } from "@/i18n/routing";
/**
* Content Collections documentation
@@ -26,11 +27,18 @@ export const authors = defineCollection({
schema: (z) => ({
slug: z.string(),
name: z.string(),
- avatar: z.string()
+ avatar: z.string(),
+ locale: z.enum(LOCALES as [string, ...string[]]).optional()
}),
transform: async (data, context) => {
+ // Determine the locale from the file path or use the provided locale
+ const pathParts = data._meta.path.split(path.sep);
+ const localeFromPath = LOCALES.includes(pathParts[0]) ? pathParts[0] : null;
+ const locale = data.locale || localeFromPath || DEFAULT_LOCALE;
+
return {
...data,
+ locale,
avatar: getBaseUrl() + data.avatar
};
}
@@ -46,25 +54,44 @@ export const categories = defineCollection({
schema: (z) => ({
slug: z.string(),
name: z.string(),
- description: z.string()
- })
+ description: z.string(),
+ locale: z.enum(LOCALES as [string, ...string[]]).optional()
+ }),
+ transform: async (data, context) => {
+ // Determine the locale from the file path or use the provided locale
+ const pathParts = data._meta.path.split(path.sep);
+ const localeFromPath = LOCALES.includes(pathParts[0]) ? pathParts[0] : null;
+ const locale = data.locale || localeFromPath || DEFAULT_LOCALE;
+
+ return {
+ ...data,
+ locale
+ };
+ }
});
/**
* Blog Post collection
*
- * 1. For a blog post file at content/blog/2023/year-review.mdx:
+ * 1. For a blog post file at content/en/blog/2023/year-review.mdx:
+ * locale: en
* slug: /blog/2023/year-review
* slugAsParams: 2023/year-review
*
- * 2. For a blog post at content/blog/first-post.mdx:
+ * 2. For a blog post at content/en/blog/first-post.mdx:
+ * locale: en
+ * slug: /blog/first-post
+ * slugAsParams: first-post
+ *
+ * 3. For a blog post at content/zh/blog/first-post.mdx:
+ * locale: zh
* slug: /blog/first-post
* slugAsParams: first-post
*/
export const posts = defineCollection({
name: 'post',
directory: 'content',
- include: '**/blog/*.mdx',
+ include: '**/blog/**/*.mdx',
schema: (z) => ({
title: z.string(),
description: z.string(),
@@ -72,7 +99,8 @@ export const posts = defineCollection({
date: z.string().datetime(),
published: z.boolean().default(true),
categories: z.array(z.string()),
- author: z.string()
+ author: z.string(),
+ locale: z.enum(LOCALES as [string, ...string[]]).optional()
}),
transform: async (data, context) => {
const body = await compileMDX(context, data, {
@@ -92,13 +120,32 @@ export const posts = defineCollection({
const blogCategories = context
.documents(categories)
.filter((c) => data.categories.includes(c.slug));
+
+ // Determine the locale from the file path or use the provided locale
+ const pathParts = data._meta.path.split(path.sep);
+ const localeFromPath = LOCALES.includes(pathParts[0]) ? pathParts[0] : null;
+ const locale = data.locale || localeFromPath || DEFAULT_LOCALE;
+
+ // Create a slug without the locale in the path
+ let slugPath = data._meta.path;
+ if (localeFromPath) {
+ // Remove the locale from the path for the slug
+ const pathWithoutLocale = pathParts.slice(1).join(path.sep);
+ slugPath = pathWithoutLocale;
+ }
+
+ // Create slugAsParams without the locale
+ const slugParamsParts = slugPath.split(path.sep).slice(1);
+ const slugAsParams = slugParamsParts.join('/');
+
return {
...data,
+ locale,
author: blogAuthor,
categories: blogCategories,
image: getBaseUrl() + data.image,
- slug: `/${data._meta.path}`,
- slugAsParams: data._meta.path.split(path.sep).slice(1).join('/'),
+ slug: `/${slugPath}`,
+ slugAsParams,
body: {
raw: data.content,
code: body
diff --git a/content/author/indiehub.mdx b/content/en/author/indiehub.mdx
similarity index 100%
rename from content/author/indiehub.mdx
rename to content/en/author/indiehub.mdx
diff --git a/content/author/mkdirs.mdx b/content/en/author/mkdirs.mdx
similarity index 100%
rename from content/author/mkdirs.mdx
rename to content/en/author/mkdirs.mdx
diff --git a/content/author/mksaas.mdx b/content/en/author/mksaas.mdx
similarity index 100%
rename from content/author/mksaas.mdx
rename to content/en/author/mksaas.mdx
diff --git a/content/blog/what-is-indiehub.mdx b/content/en/blog/what-is-indiehub.mdx
similarity index 99%
rename from content/blog/what-is-indiehub.mdx
rename to content/en/blog/what-is-indiehub.mdx
index 37fc9da..fdef8fc 100644
--- a/content/blog/what-is-indiehub.mdx
+++ b/content/en/blog/what-is-indiehub.mdx
@@ -63,12 +63,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
-
+/> */}
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.
diff --git a/content/blog/what-is-mkdirs.mdx b/content/en/blog/what-is-mkdirs.mdx
similarity index 99%
rename from content/blog/what-is-mkdirs.mdx
rename to content/en/blog/what-is-mkdirs.mdx
index 8eaced7..4a0a72f 100644
--- a/content/blog/what-is-mkdirs.mdx
+++ b/content/en/blog/what-is-mkdirs.mdx
@@ -63,12 +63,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
-
+/> */}
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.
diff --git a/content/blog/what-is-mksaas.mdx b/content/en/blog/what-is-mksaas.mdx
similarity index 99%
rename from content/blog/what-is-mksaas.mdx
rename to content/en/blog/what-is-mksaas.mdx
index cd44d2f..0d7de69 100644
--- a/content/blog/what-is-mksaas.mdx
+++ b/content/en/blog/what-is-mksaas.mdx
@@ -6,6 +6,7 @@ date: 2024-11-24T12:00:00.000Z
published: true
categories: [news, guide]
author: mksaas
+locale: en
---
Until now, trying to style an article, document, or blog post with Tailwind has been a tedious task that required a keen eye for typography and a lot of complex custom CSS.
@@ -63,12 +64,12 @@ Something a wise person once told me about typography is:
It's probably important that images look okay here by default as well:
-
+/> */}
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old.
diff --git a/content/category/guide.mdx b/content/en/category/guide.mdx
similarity index 100%
rename from content/category/guide.mdx
rename to content/en/category/guide.mdx
diff --git a/content/category/news.mdx b/content/en/category/news.mdx
similarity index 100%
rename from content/category/news.mdx
rename to content/en/category/news.mdx
diff --git a/content/zh/blog/what-is-mksaas.mdx b/content/zh/blog/what-is-mksaas.mdx
new file mode 100644
index 0000000..290a32d
--- /dev/null
+++ b/content/zh/blog/what-is-mksaas.mdx
@@ -0,0 +1,211 @@
+---
+title: MkSaaS 是什么?
+description: MkSaaS 是构建 AI SaaS 网站的最佳样板。
+image: /images/blog/mksaas-og.png
+date: 2024-11-24T12:00:00.000Z
+published: true
+categories: [news, guide]
+author: mksaas
+locale: zh
+---
+
+到目前为止,尝试使用 Tailwind 来设计文章、文档或博客文章的样式一直是一项繁琐的任务,需要对排版有敏锐的眼光,并且需要大量复杂的自定义 CSS。
+
+默认情况下,Tailwind 会删除段落、标题、列表等所有默认的浏览器样式。这对于构建应用程序 UI 非常有用,因为您花更少的时间撤销用户代理样式,但是当您真的只是尝试设置来自 CMS 中富文本编辑器或 markdown 文件的内容的样式时,这可能会令人惊讶和不直观。
+
+我们实际上收到了很多关于它的投诉,人们经常问我们这样的问题:
+
+> 为什么 Tailwind 删除了我的 `h1` 元素上的默认样式?我如何禁用这个?你说我也会失去所有其他基本样式是什么意思?
+> 我们听到了您的声音,但我们并不确信简单地禁用我们的基本样式就是您真正想要的。您不希望每次在仪表板 UI 的一部分中使用 `p` 元素时都必须删除烦人的边距。而且我怀疑您真的希望您的博客文章使用用户代理样式——您希望它们看起来很棒,而不是糟糕。
+
+`@tailwindcss/typography` 插件是我们尝试给您真正想要的东西,而不会有做一些愚蠢的事情(比如禁用我们的基本样式)的任何缺点。
+
+它添加了一个新的 `prose` 类,您可以将其应用于任何普通 HTML 内容块,并将其转变为一个美丽、格式良好的文档:
+
+```html
+
+