Implement internationalization in pages and update CMS clients
The commit mainly revamps the code to support internationalization in various pages like pricing, docs, blog, etc. It modifies the code to generate metadata asynchronously, accommodating internationalized page titles and subtitles. Also, the commit restructures CMS Client scripts, particularly for ContentLayer and Wordpress. For Wordpress, it updates API fetch routes and handles embedded children data. Furthermore, unnecessary logging statements are cleaned up, and minor updates are done for better UI and code efficiency.
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
.HTML h1 {
|
||||
@apply mt-14 text-4xl font-bold;
|
||||
}
|
||||
|
||||
.HTML h2 {
|
||||
@apply mb-4 mt-12 text-2xl font-semibold lg:text-3xl;
|
||||
}
|
||||
|
||||
.HTML h3 {
|
||||
@apply mt-10 text-2xl font-bold;
|
||||
}
|
||||
|
||||
.HTML h4 {
|
||||
@apply mt-8 text-xl font-bold;
|
||||
}
|
||||
|
||||
.HTML h5 {
|
||||
@apply mt-6 text-lg font-semibold;
|
||||
}
|
||||
|
||||
.HTML h6 {
|
||||
@apply mt-2 text-base font-medium;
|
||||
}
|
||||
|
||||
/**
|
||||
Tailwind "dark" variants do not work with CSS Modules
|
||||
We work it around using :global(.dark)
|
||||
For more info: https://github.com/tailwindlabs/tailwindcss/issues/3258#issuecomment-770215347
|
||||
*/
|
||||
:global(.dark) .HTML h1,
|
||||
:global(.dark) .HTML h2,
|
||||
:global(.dark) .HTML h3,
|
||||
:global(.dark) .HTML h4,
|
||||
:global(.dark) .HTML h5,
|
||||
:global(.dark) .HTML h6 {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.HTML p {
|
||||
@apply mb-4 mt-2 text-base leading-7;
|
||||
}
|
||||
|
||||
.HTML li {
|
||||
@apply relative my-1.5 text-base leading-7;
|
||||
}
|
||||
|
||||
.HTML ul > li:before {
|
||||
content: '-';
|
||||
|
||||
@apply mr-2;
|
||||
}
|
||||
|
||||
.HTML ol > li:before {
|
||||
@apply inline-flex font-medium;
|
||||
|
||||
content: counters(counts, '.') '. ';
|
||||
font-feature-settings: 'tnum';
|
||||
}
|
||||
|
||||
.HTML b,
|
||||
.HTML strong {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
:global(.dark) .HTML b,
|
||||
:global(.dark) .HTML strong {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.HTML img,
|
||||
.HTML video {
|
||||
@apply rounded-md;
|
||||
}
|
||||
|
||||
.HTML ul,
|
||||
.HTML ol {
|
||||
@apply pl-1;
|
||||
}
|
||||
|
||||
.HTML ol > li {
|
||||
counter-increment: counts;
|
||||
}
|
||||
|
||||
.HTML ol > li:before {
|
||||
@apply mr-2 inline-flex font-semibold;
|
||||
|
||||
content: counters(counts, '.') '. ';
|
||||
font-feature-settings: 'tnum';
|
||||
}
|
||||
|
||||
.HTML blockquote {
|
||||
@apply my-4 border-l-8 border border-primary px-6 py-4 text-lg font-medium text-muted-foreground;
|
||||
}
|
||||
|
||||
.HTML pre {
|
||||
@apply my-6 text-sm text-current;
|
||||
}
|
||||
@@ -10,35 +10,32 @@ export const PostHeader: React.FC<{
|
||||
}> = ({ post }) => {
|
||||
const { title, publishedAt, description, image } = post;
|
||||
|
||||
// NB: change this to display the post's image
|
||||
const displayImage = true;
|
||||
const preloadImage = true;
|
||||
console.log(post);
|
||||
|
||||
return (
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<div className={'flex flex-col space-y-8'}>
|
||||
<div className={'flex flex-col space-y-2'}>
|
||||
<Heading level={1}>{title}</Heading>
|
||||
|
||||
<Heading level={3}>
|
||||
<span className={'font-normal text-muted-foreground'}>
|
||||
{description}
|
||||
</span>
|
||||
<p
|
||||
className={'font-normal text-muted-foreground'}
|
||||
dangerouslySetInnerHTML={{ __html: description ?? '' }}
|
||||
/>
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
<div className="flex">
|
||||
<div className="flex flex-row items-center space-x-2 text-sm text-gray-600 dark:text-gray-400">
|
||||
<div>
|
||||
<div className="flex flex-row items-center space-x-2 text-muted-foreground">
|
||||
<div className={'text-sm'}>
|
||||
<DateFormatter dateString={publishedAt.toISOString()} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<If condition={displayImage && image}>
|
||||
<If condition={image}>
|
||||
{(imageUrl) => (
|
||||
<div className="relative mx-auto h-[378px] w-full justify-center">
|
||||
<CoverImage
|
||||
preloadImage={preloadImage}
|
||||
preloadImage
|
||||
className="rounded-md"
|
||||
title={title}
|
||||
src={imageUrl}
|
||||
|
||||
@@ -21,14 +21,14 @@ export function PostPreview({
|
||||
}: React.PropsWithChildren<Props>) {
|
||||
const { title, image, publishedAt, description } = post;
|
||||
const height = imageHeight ?? DEFAULT_IMAGE_HEIGHT;
|
||||
const url = post.url;
|
||||
const slug = `/blog/${post.slug}`;
|
||||
|
||||
return (
|
||||
<div className="rounded-xl transition-shadow duration-500">
|
||||
<If condition={image}>
|
||||
{(imageUrl) => (
|
||||
<div className="relative mb-2 w-full" style={{ height }}>
|
||||
<Link href={url}>
|
||||
<Link href={slug}>
|
||||
<CoverImage
|
||||
preloadImage={preloadImage}
|
||||
title={title}
|
||||
@@ -42,7 +42,7 @@ export function PostPreview({
|
||||
<div className={'px-1'}>
|
||||
<div className="flex flex-col space-y-1 py-2">
|
||||
<h3 className="text-2xl font-bold leading-snug dark:text-white">
|
||||
<Link href={url} className="hover:underline">
|
||||
<Link href={slug} className="hover:underline">
|
||||
{title}
|
||||
</Link>
|
||||
</h3>
|
||||
@@ -54,9 +54,10 @@ export function PostPreview({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="mb-4 text-sm leading-relaxed text-muted-foreground">
|
||||
{description}
|
||||
</p>
|
||||
<p
|
||||
className="mb-4 text-sm leading-relaxed text-muted-foreground"
|
||||
dangerouslySetInnerHTML={{ __html: description ?? '' }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Cms } from '@kit/cms';
|
||||
import { ContentRenderer } from '@kit/cms';
|
||||
|
||||
import styles from './html-renderer.module.css';
|
||||
import { PostHeader } from './post-header';
|
||||
|
||||
export const Post: React.FC<{
|
||||
@@ -8,10 +9,10 @@ export const Post: React.FC<{
|
||||
content: string;
|
||||
}> = ({ post, content }) => {
|
||||
return (
|
||||
<div className={'mx-auto my-8 max-w-2xl'}>
|
||||
<div className={'mx-auto my-8 flex max-w-2xl flex-col space-y-6'}>
|
||||
<PostHeader post={post} />
|
||||
|
||||
<article className={'mx-auto flex justify-center'}>
|
||||
<article className={styles.HTML}>
|
||||
<ContentRenderer content={content} />
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
import { createCmsClient } from '@kit/cms';
|
||||
|
||||
import { GridList } from '~/(marketing)/_components/grid-list';
|
||||
import { SitePageHeader } from '~/(marketing)/_components/site-page-header';
|
||||
import { PostPreview } from '~/(marketing)/blog/_components/post-preview';
|
||||
import appConfig from '~/config/app.config';
|
||||
import { createI18nServerInstance } from '~/lib/i18n/i18n.server';
|
||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: `Blog - ${appConfig.name}`,
|
||||
description: `Tutorials, Guides and Updates from our team`,
|
||||
export const generateMetadata = async () => {
|
||||
const { t } = await createI18nServerInstance();
|
||||
|
||||
return {
|
||||
title: t('marketing:blog'),
|
||||
description: t('marketing:blogSubtitle'),
|
||||
};
|
||||
};
|
||||
|
||||
async function BlogPage() {
|
||||
const { t } = await createI18nServerInstance();
|
||||
const cms = await createCmsClient();
|
||||
|
||||
const posts = await cms.getContentItems({
|
||||
@@ -24,8 +27,8 @@ async function BlogPage() {
|
||||
<div className={'container mx-auto'}>
|
||||
<div className={'my-8 flex flex-col space-y-16'}>
|
||||
<SitePageHeader
|
||||
title={'Blog'}
|
||||
subtitle={'Tutorials, Guides and Updates from our team'}
|
||||
title={t('marketing:blog')}
|
||||
subtitle={t('marketing:blogSubtitle')}
|
||||
/>
|
||||
|
||||
<GridList>
|
||||
|
||||
Reference in New Issue
Block a user