mirror of
https://github.com/snachodog/tok-to-insta-follower-bridge.git
synced 2025-09-13 07:23:32 -06:00
feat: add i18n
This commit is contained in:
@@ -22,7 +22,7 @@ const AsyncButton = ({ onClick, label, className }: Props) => {
|
||||
onClick={handleClick}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? "Processing..." : label}
|
||||
{loading ? chrome.i18n.getMessage("loading") : label}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
@@ -29,16 +29,16 @@ const DetectedUserListItem = ({
|
||||
match(actionMode)
|
||||
.with(ACTION_MODE.FOLLOW, ACTION_MODE.IMPORT_LIST, () => {
|
||||
const follow = {
|
||||
label: "Follow on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_follow_on_bluesky"),
|
||||
class: "btn-primary",
|
||||
};
|
||||
const following = {
|
||||
label: "Following on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_following_on_bluesky"),
|
||||
class:
|
||||
"btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
|
||||
};
|
||||
const unfollow = {
|
||||
label: "Unfollow on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_unfollow_on_bluesky"),
|
||||
class:
|
||||
"text-red-500 hover:bg-transparent hover:border hover:border-red-500",
|
||||
};
|
||||
@@ -52,16 +52,16 @@ const DetectedUserListItem = ({
|
||||
})
|
||||
.with(ACTION_MODE.BLOCK, () => {
|
||||
const block = {
|
||||
label: "Block on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_block_on_bluesky"),
|
||||
class: "btn-primary",
|
||||
};
|
||||
const blocking = {
|
||||
label: "Blocking on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_blocking_on_bluesky"),
|
||||
class:
|
||||
"btn-outline hover:bg-transparent hover:border hover:bg-transparent hover:text-base-content",
|
||||
};
|
||||
const unblock = {
|
||||
label: "Unblock on Bluesky",
|
||||
label: chrome.i18n.getMessage("button_unblock_on_bluesky"),
|
||||
class:
|
||||
"text-red-500 hover:bg-transparent hover:border hover:border-red-500",
|
||||
};
|
||||
@@ -106,12 +106,12 @@ const DetectedUserListItem = ({
|
||||
<div>
|
||||
<div className={`w-full border-l-8 border-${matchTypeColor}`}>
|
||||
<div
|
||||
className={`w-full border-t border-gray-500 text-${matchTypeColor} grid grid-cols-[22%_1fr]`}
|
||||
className={`w-full border-t border-gray-500 text-${matchTypeColor} grid grid-cols-[22%_1fr] text-xs`}
|
||||
>
|
||||
<div className="px-3 bg-slate-100 dark:bg-slate-800">
|
||||
<div className="px-3 bg-slate-100 dark:bg-slate-800" />
|
||||
<div className="px-3">
|
||||
{MATCH_TYPE_LABEL_AND_COLOR[user.matchType].label}
|
||||
</div>
|
||||
<div className="px-3" />
|
||||
</div>
|
||||
<div className="bg-base-100 w-full relative grid grid-cols-[22%_1fr] gap-5">
|
||||
<DetectedUserSource user={user} />
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import React from "react";
|
||||
import { match } from "ts-pattern";
|
||||
import { getMessageWithLink } from "~lib/utils";
|
||||
import type { MatchType, MatchTypeFilterValue } from "../../types";
|
||||
import {
|
||||
ACTION_MODE,
|
||||
@@ -78,18 +79,19 @@ const Sidebar = ({
|
||||
</svg>
|
||||
</div>
|
||||
<div className="stat-title text-lg text-base-content font-bold">
|
||||
Detected users
|
||||
{chrome.i18n.getMessage("sidebar_detected_users")}
|
||||
</div>
|
||||
<div className="stat-value text-base-content">{detectedCount}</div>
|
||||
<div className="stat-desc">
|
||||
Same handle name: {matchTypeStats[BSKY_USER_MATCH_TYPE.HANDLE]}
|
||||
{chrome.i18n.getMessage("same_handle_name")}:{" "}
|
||||
{matchTypeStats[BSKY_USER_MATCH_TYPE.HANDLE]}
|
||||
</div>
|
||||
<div className="stat-desc">
|
||||
Same display name:{" "}
|
||||
{chrome.i18n.getMessage("same_display_name")}:{" "}
|
||||
{matchTypeStats[BSKY_USER_MATCH_TYPE.DISPLAY_NAME]}
|
||||
</div>
|
||||
<div className="stat-desc">
|
||||
Included handle in description:{" "}
|
||||
{chrome.i18n.getMessage("included_handle_in_description")}:{" "}
|
||||
{matchTypeStats[BSKY_USER_MATCH_TYPE.DESCRIPTION]}
|
||||
</div>
|
||||
</div>
|
||||
@@ -118,7 +120,7 @@ const Sidebar = ({
|
||||
<span className="text-sm">
|
||||
{key === BSKY_USER_MATCH_TYPE.FOLLOWING &&
|
||||
actionMode === ACTION_MODE.BLOCK
|
||||
? "Blocked users"
|
||||
? chrome.i18n.getMessage("blocked_user")
|
||||
: MATCH_TYPE_LABEL_AND_COLOR[key].label}
|
||||
</span>
|
||||
<input
|
||||
@@ -151,30 +153,39 @@ const Sidebar = ({
|
||||
</div>
|
||||
{match(actionMode)
|
||||
.with(ACTION_MODE.FOLLOW, () => (
|
||||
<AsyncButton onClick={followAll} label="Follow All" />
|
||||
<AsyncButton
|
||||
onClick={followAll}
|
||||
label={chrome.i18n.getMessage("follow_all")}
|
||||
/>
|
||||
))
|
||||
.with(ACTION_MODE.BLOCK, () => (
|
||||
<AsyncButton onClick={blockAll} label="Block All" />
|
||||
<AsyncButton
|
||||
onClick={blockAll}
|
||||
label={chrome.i18n.getMessage("block_all")}
|
||||
/>
|
||||
))
|
||||
.with(ACTION_MODE.IMPORT_LIST, () => (
|
||||
<AsyncButton onClick={importList} label="Import List" />
|
||||
<AsyncButton
|
||||
onClick={importList}
|
||||
label={chrome.i18n.getMessage("import_list")}
|
||||
/>
|
||||
))
|
||||
.otherwise(() => null)}
|
||||
<p className="text-xs">
|
||||
⚠️ User detection is not perfect and may include false positives.
|
||||
⚠️ {chrome.i18n.getMessage("warning_user_detection")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-auto">
|
||||
<div className="divider" />
|
||||
<p className="mb-2">
|
||||
If you find this tool helpful, I'd appreciate{" "}
|
||||
<a href="https://ko-fi.com/X8X315UWFN" className="link">
|
||||
your support
|
||||
</a>{" "}
|
||||
to help me maintain and improve it ☕
|
||||
</p>
|
||||
<p
|
||||
className="mb-2 text-xs"
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: getMessageWithLink("donate_message"),
|
||||
}}
|
||||
/>
|
||||
<a
|
||||
href="https://ko-fi.com/X8X315UWFN"
|
||||
href="https://ko-fi.com/kawamataryo"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
style={{ display: "inline-block" }}
|
||||
|
@@ -75,19 +75,19 @@ export const MAX_RELOAD_COUNT = 1;
|
||||
|
||||
export const MATCH_TYPE_LABEL_AND_COLOR = {
|
||||
[BSKY_USER_MATCH_TYPE.HANDLE]: {
|
||||
label: "Same handle name",
|
||||
label: chrome.i18n.getMessage("same_handle_name"),
|
||||
color: "info",
|
||||
},
|
||||
[BSKY_USER_MATCH_TYPE.DISPLAY_NAME]: {
|
||||
label: "Same display name",
|
||||
label: chrome.i18n.getMessage("same_display_name"),
|
||||
color: "warning",
|
||||
},
|
||||
[BSKY_USER_MATCH_TYPE.DESCRIPTION]: {
|
||||
label: "Included handle in description",
|
||||
label: chrome.i18n.getMessage("included_handle_in_description"),
|
||||
color: "secondary",
|
||||
},
|
||||
[BSKY_USER_MATCH_TYPE.FOLLOWING]: {
|
||||
label: "Followed users",
|
||||
label: chrome.i18n.getMessage("followed_users"),
|
||||
color: "success",
|
||||
},
|
||||
};
|
||||
@@ -95,6 +95,9 @@ export const MATCH_TYPE_LABEL_AND_COLOR = {
|
||||
export const AUTH_FACTOR_TOKEN_REQUIRED_ERROR_MESSAGE =
|
||||
"AuthFactorTokenRequiredError";
|
||||
|
||||
export const INVALID_IDENTIFIER_OR_PASSWORD_ERROR_MESSAGE =
|
||||
"Invalid identifier or password";
|
||||
|
||||
export const RATE_LIMIT_ERROR_MESSAGE = "Rate limit";
|
||||
|
||||
export const DOCUMENT_LINK = {
|
||||
|
@@ -28,10 +28,7 @@ export class ThreadsService extends AbstractService {
|
||||
'[role="dialog"] [role="tab"]>[role="button"]',
|
||||
);
|
||||
if (!isTargetPage) {
|
||||
return [
|
||||
false,
|
||||
"Invalid page. please open the following or followers view.",
|
||||
];
|
||||
return [false, chrome.i18n.getMessage("error_invalid_page_in_threads")];
|
||||
}
|
||||
return [true, ""];
|
||||
}
|
||||
|
@@ -36,3 +36,21 @@ export const findFirstScrollableElements = (
|
||||
|
||||
return scrollableElements[0] ?? null;
|
||||
};
|
||||
|
||||
export const getMessageWithLink = (
|
||||
key: string,
|
||||
placeholders: string[] = [],
|
||||
) => {
|
||||
const linkPattern = /\[(.*?)\]\((.*?)\)/g;
|
||||
let message = chrome.i18n.getMessage(key, placeholders);
|
||||
const links = message.matchAll(linkPattern);
|
||||
for (const link of links) {
|
||||
const [fullMatch, text, url] = link;
|
||||
message = message.replace(
|
||||
fullMatch,
|
||||
`<a href="${url}" target="_blank" class="link" rel="noreferrer">${text}</a>`,
|
||||
);
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
Reference in New Issue
Block a user