EN/JP対応
This commit is contained in:
parent
005fb72a48
commit
2a94e1124c
52
src/content/ui/i18n.ts
Normal file
52
src/content/ui/i18n.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
type MessageKey =
|
||||
| "colIndex"
|
||||
| "colTitle"
|
||||
| "colChannel"
|
||||
| "colDuration"
|
||||
| "colAddedBy"
|
||||
| "colVotes"
|
||||
| "filterTitle"
|
||||
| "filterChannel"
|
||||
| "filterAddedBy"
|
||||
| "badgeLive"
|
||||
| "headerVideos";
|
||||
|
||||
const messages: Record<string, Record<MessageKey, string>> = {
|
||||
ja: {
|
||||
colIndex: "#",
|
||||
colTitle: "タイトル",
|
||||
colChannel: "チャンネル",
|
||||
colDuration: "長さ",
|
||||
colAddedBy: "追加者",
|
||||
colVotes: "投票",
|
||||
filterTitle: "タイトル検索...",
|
||||
filterChannel: "チャンネル...",
|
||||
filterAddedBy: "追加者...",
|
||||
badgeLive: "ライブ",
|
||||
headerVideos: "本の動画",
|
||||
},
|
||||
en: {
|
||||
colIndex: "#",
|
||||
colTitle: "Title",
|
||||
colChannel: "Channel",
|
||||
colDuration: "Duration",
|
||||
colAddedBy: "Added by",
|
||||
colVotes: "Votes",
|
||||
filterTitle: "Search title...",
|
||||
filterChannel: "Channel...",
|
||||
filterAddedBy: "Added by...",
|
||||
badgeLive: "LIVE",
|
||||
headerVideos: "videos",
|
||||
},
|
||||
};
|
||||
|
||||
function detectLang(): string {
|
||||
const htmlLang = document.documentElement.lang;
|
||||
if (htmlLang?.startsWith("ja")) return "ja";
|
||||
return "en";
|
||||
}
|
||||
|
||||
export function t(key: MessageKey): string {
|
||||
const lang = detectLang();
|
||||
return (messages[lang] ?? messages.en)[key];
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import type { PlaylistData, PlaylistVideo } from "../../types/playlist";
|
||||
import { t } from "./i18n";
|
||||
|
||||
type SortKey = "index" | "title" | "channel" | "duration" | "addedBy" | "votes";
|
||||
type SortDir = "asc" | "desc";
|
||||
|
|
@ -10,14 +11,16 @@ interface Column {
|
|||
collab?: boolean; // only shown for collaborative playlists
|
||||
}
|
||||
|
||||
const allColumns: Column[] = [
|
||||
{ label: "#", cls: "ytpf-col-index", key: "index" },
|
||||
{ label: "Title", cls: "ytpf-col-title", key: "title" },
|
||||
{ label: "Channel", cls: "ytpf-col-channel", key: "channel" },
|
||||
{ label: "Duration", cls: "ytpf-col-duration", key: "duration" },
|
||||
{ label: "Added by", cls: "ytpf-col-addedby", key: "addedBy", collab: true },
|
||||
{ label: "Votes", cls: "ytpf-col-votes", key: "votes", collab: true },
|
||||
];
|
||||
function getAllColumns(): Column[] {
|
||||
return [
|
||||
{ label: t("colIndex"), cls: "ytpf-col-index", key: "index" },
|
||||
{ label: t("colTitle"), cls: "ytpf-col-title", key: "title" },
|
||||
{ label: t("colChannel"), cls: "ytpf-col-channel", key: "channel" },
|
||||
{ label: t("colDuration"), cls: "ytpf-col-duration", key: "duration" },
|
||||
{ label: t("colAddedBy"), cls: "ytpf-col-addedby", key: "addedBy", collab: true },
|
||||
{ label: t("colVotes"), cls: "ytpf-col-votes", key: "votes", collab: true },
|
||||
];
|
||||
}
|
||||
|
||||
interface TagInput {
|
||||
container: HTMLElement;
|
||||
|
|
@ -251,7 +254,7 @@ function buildRow(
|
|||
if (video.isLive) {
|
||||
const badge = document.createElement("span");
|
||||
badge.className = "ytpf-live";
|
||||
badge.textContent = "LIVE";
|
||||
badge.textContent = t("badgeLive");
|
||||
tdDuration.appendChild(badge);
|
||||
} else {
|
||||
tdDuration.textContent = video.durationText ?? "--";
|
||||
|
|
@ -279,7 +282,7 @@ export function renderPlaylistTable(data: PlaylistData): HTMLElement {
|
|||
const isCollab = data.videos.some(
|
||||
(v) => v.addedBy != null || v.voteCount != null,
|
||||
);
|
||||
const columns = allColumns.filter((c) => !c.collab || isCollab);
|
||||
const columns = getAllColumns().filter((c) => !c.collab || isCollab);
|
||||
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "ytpf-wrapper";
|
||||
|
|
@ -290,7 +293,7 @@ export function renderPlaylistTable(data: PlaylistData): HTMLElement {
|
|||
|
||||
const titleSpan = document.createElement("span");
|
||||
titleSpan.className = "ytpf-header-title";
|
||||
titleSpan.textContent = `${data.metadata.title} — ${data.extractedCount} videos`;
|
||||
titleSpan.textContent = `${data.metadata.title} — ${data.extractedCount} ${t("headerVideos")}`;
|
||||
|
||||
const metaSpan = document.createElement("span");
|
||||
metaSpan.className = "ytpf-header-meta";
|
||||
|
|
@ -313,12 +316,12 @@ export function renderPlaylistTable(data: PlaylistData): HTMLElement {
|
|||
titleInput.className = "ytpf-filter-input";
|
||||
titleInput.type = "text";
|
||||
titleInput.name = "ytpf-title-filter";
|
||||
titleInput.placeholder = "タイトル検索...";
|
||||
titleInput.placeholder = t("filterTitle");
|
||||
filters.appendChild(titleInput);
|
||||
|
||||
// Channel tag input
|
||||
const channelNames = [...new Set(data.videos.map((v) => v.channel.name))].sort();
|
||||
const channelTagInput = createTagInput("チャンネル...", channelNames, () => applyFilters());
|
||||
const channelTagInput = createTagInput(t("filterChannel"), channelNames, () => applyFilters());
|
||||
filters.appendChild(channelTagInput.container);
|
||||
|
||||
// Added-by tag input (collab only)
|
||||
|
|
@ -327,7 +330,7 @@ export function renderPlaylistTable(data: PlaylistData): HTMLElement {
|
|||
const addedByNames = [...new Set(
|
||||
data.videos.map((v) => v.addedBy).filter((n): n is string => n != null),
|
||||
)].sort();
|
||||
addedByTagInput = createTagInput("追加者...", addedByNames, () => applyFilters());
|
||||
addedByTagInput = createTagInput(t("filterAddedBy"), addedByNames, () => applyFilters());
|
||||
filters.appendChild(addedByTagInput.container);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user