Skip to content

Commit febfef4

Browse files
authored
Merge pull request #123 from techdiary-dev/copilot/add-reading-time-estimate
feat: reading time estimate at 200 wpm with Bengali i18n
2 parents e4081e6 + 867ceb3 commit febfef4

5 files changed

Lines changed: 18 additions & 8 deletions

File tree

src/app/[username]/[articleHandle]/_components/UnpublishedArticleNotice.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ type Props = {
1010
authorId: string;
1111
};
1212

13+
/** Inline reading time label for the article byline. */
14+
export function ArticleReadingTime({ minutes }: { minutes: number }) {
15+
const { _t } = useTranslation();
16+
return <span>{_t("$ min read", [minutes])}</span>;
17+
}
18+
1319
/** Inline label next to the byline date when the article has no `published_at`. */
1420
export function ArticleDraftBylineLabel() {
1521
const { _t } = useTranslation();

src/app/[username]/[articleHandle]/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import ArticleSidebar from "./_components/ArticleSidebar";
2626
import EditArticleButton from "./_components/EditArticleButton";
2727
import {
2828
ArticleDraftBylineLabel,
29+
ArticleReadingTime,
2930
UnpublishedArticleNotice,
3031
} from "./_components/UnpublishedArticleNotice";
3132

@@ -196,7 +197,7 @@ const Page: NextPage<ArticlePageProps> = async ({ params }) => {
196197
<ArticleDraftBylineLabel />
197198
)}
198199
<span className="mx-1.5">·</span>
199-
<span>{readingTime(article?.body ?? "")} min read</span>
200+
<ArticleReadingTime minutes={readingTime(article?.body ?? "")} />
200201
</div>
201202
</div>
202203
</div>

src/components/ArticleCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const ArticleCard = ({
4040
readingTime,
4141
galleryImages,
4242
}: ArticleCardProps) => {
43-
const { lang } = useTranslation();
43+
const { lang, _t } = useTranslation();
4444

4545
const articleUrl = useMemo(() => {
4646
return `/@${author.username}/${handle}`;
@@ -87,7 +87,7 @@ const ArticleCard = ({
8787
{formattedTime(new Date(publishedAt), lang)}
8888
</time>
8989
<span className="mx-1.5">·</span>
90-
<span>{readingTime} min read</span>
90+
<span>{_t("$ min read", [readingTime])}</span>
9191
</div>
9292
</div>
9393
</div>

src/i18n/bn.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,6 @@
150150
"Comment reply": "মন্তব্যের উত্তর",
151151
"Gist comment": "গিস্টে মন্তব্য",
152152
"Reaction": "প্রতিক্রিয়া",
153-
"Notification": "নোটিফিকেশন"
153+
"Notification": "নোটিফিকেশন",
154+
"$ min read": "$ মিনিট পড়া"
154155
}

src/lib/utils.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,12 @@ export function extractImageUrlsFromMarkdown(markdown: string): string[] {
7676
}
7777

7878
export function readingTime(text: string) {
79-
const wordsPerMinute = 120;
80-
const textWithoutPunctuation = text.replace(/[.,!?;:]/g, "");
81-
const wordCount = textWithoutPunctuation.split(/\s+/).length;
82-
const minutes = Math.round(wordCount / wordsPerMinute);
79+
const wordsPerMinute = 200;
80+
const trimmed = text.trim();
81+
if (!trimmed) return 0;
82+
const textWithoutPunctuation = trimmed.replace(/[.,!?;:]/g, "");
83+
const wordCount = textWithoutPunctuation.split(/\s+/).filter(Boolean).length;
84+
const minutes = Math.max(1, Math.round(wordCount / wordsPerMinute));
8385
return minutes;
8486
}
8587

0 commit comments

Comments
 (0)