diff --git a/src/embed/status.ts b/src/embed/status.ts
index 3a6b921..e8bcc55 100644
--- a/src/embed/status.ts
+++ b/src/embed/status.ts
@@ -209,7 +209,8 @@ export const handleStatus = async (
status: status,
thread: thread,
text: newText,
- flags: flags
+ flags: flags,
+ targetLanguage: language ?? status.lang ?? 'en'
});
headers.push(...instructions.addHeaders);
if (instructions.authorText) {
diff --git a/src/render/instantview.ts b/src/render/instantview.ts
index 8224a9c..74aecf8 100644
--- a/src/render/instantview.ts
+++ b/src/render/instantview.ts
@@ -56,11 +56,16 @@ const generateStatusMedia = (status: APIStatus): string => {
// return `${hh}:${min} - ${yyyy}/${mm}/${dd}`;
// }
-const formatDate = (date: Date): string => {
- const yyyy = date.getFullYear();
- const mm = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
- const dd = String(date.getDate()).padStart(2, '0');
- return `${yyyy}/${mm}/${dd}`;
+const formatDate = (date: Date, language: string): string => {
+ if (language.startsWith('en')) {
+ language = 'en-CA'; // Use ISO dates for English to avoid problems with mm/dd vs. dd/mm
+ }
+ const formatter = new Intl.DateTimeFormat(language, {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit'
+ });
+ return formatter.format(date);
};
const htmlifyLinks = (input: string): string => {
@@ -108,15 +113,14 @@ function getTranslatedText(status: APITwitterStatus, isQuote = false): string |
const notApplicableComment = '';
-// 1100 -> 1.1K, 1100000 -> 1.1M
-const truncateSocialCount = (count: number): string => {
- if (count >= 1000000) {
- return `${(count / 1000000).toFixed(1)}M`;
- } else if (count >= 1000) {
- return `${(count / 1000).toFixed(1)}K`;
- } else {
- return String(count);
- }
+const truncateSocialCount = (count: number, locale = 'en-US') => {
+ const formatter = new Intl.NumberFormat(locale, {
+ notation: "compact",
+ compactDisplay: "short",
+ maximumFractionDigits: 1
+ });
+
+ return formatter.format(count);
};
const generateInlineAuthorHeader = (
@@ -166,7 +170,7 @@ const wrapForeignLinks = (url: string) => {
: url;
};
-const generateStatusFooter = (status: APIStatus, isQuote = false, author: APIUser): string => {
+const generateStatusFooter = (status: APIStatus, isQuote = false, author: APIUser, language: string): string => {
let description = author.description;
description = htmlifyLinks(description);
description = htmlifyHashtags(description);
@@ -200,10 +204,10 @@ const generateStatusFooter = (status: APIStatus, isQuote = false, author: APIUse
website: author.website
? `🔗 ${author.website.display_url}`
: '',
- joined: author.joined ? `📆 ${formatDate(new Date(author.joined))}` : '',
- following: truncateSocialCount(author.following),
- followers: truncateSocialCount(author.followers),
- statuses: truncateSocialCount(author.statuses)
+ joined: author.joined ? `📆 ${formatDate(new Date(author.joined), language)}` : '',
+ following: truncateSocialCount(author.following, language),
+ followers: truncateSocialCount(author.followers, language),
+ statuses: truncateSocialCount(author.statuses, language)
})
});
};
@@ -270,6 +274,7 @@ const generateCommunityNote = (status: APITwitterStatus): string => {
const generateStatus = (
status: APIStatus,
author: APIUser,
+ language: string,
isQuote = false,
authorActionType: AuthorActionType | null
): string => {
@@ -295,7 +300,7 @@ const generateStatus = (
${status.poll ? generatePoll(status.poll, status.lang ?? 'en') : notApplicableComment}
- ${!isQuote && status.quote ? generateStatus(status.quote, author, true, null) : notApplicableComment}
+ ${!isQuote && status.quote ? generateStatus(status.quote, author, language, true, null) : notApplicableComment}
${!isQuote ? `${i18next.t('ivViewOriginal')}` : notApplicableComment}
`.format({
quoteHeader: isQuote
@@ -391,10 +396,10 @@ export const renderInstantView = (properties: RenderProperties): ResponseInstruc
previousThreadPieceAuthor = status.author?.id;
- return generateStatus(status, status.author ?? thread?.author, false, authorAction);
+ return generateStatus(status, status.author ?? thread?.author, properties?.targetLanguage ?? 'en', false, authorAction,);
})
.join('')}
- ${generateStatusFooter(status, false, thread?.author ?? status.author)}
+ ${generateStatusFooter(status, false, thread?.author ?? status.author, properties?.targetLanguage ?? 'en')}
${`${i18next.t('ivViewOriginal')}`}
`;
diff --git a/src/types/types.d.ts b/src/types/types.d.ts
index 3b5b947..ae8964e 100644
--- a/src/types/types.d.ts
+++ b/src/types/types.d.ts
@@ -38,6 +38,7 @@ interface RenderProperties {
userAgent?: string;
text?: string;
flags?: InputFlags;
+ targetLanguage?: string;
}
interface TweetAPIResponse {