Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1208420a0 | |||
| 575d1a7008 | |||
| 4d3bb6cfd8 |
@@ -750,6 +750,18 @@ const App: React.FC = () => {
|
||||
>
|
||||
Español
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setLanguage('chs'); setIsLangMenuOpen(false); }}
|
||||
className={`w-full px-4 py-2 text-sm text-left hover:bg-gray-700 transition-colors ${language === 'chs' ? 'text-plex-orange font-bold' : 'text-gray-300'}`}
|
||||
>
|
||||
简体中文
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { setLanguage('cht'); setIsLangMenuOpen(false); }}
|
||||
className={`w-full px-4 py-2 text-sm text-left hover:bg-gray-700 transition-colors ${language === 'cht' ? 'text-plex-orange font-bold' : 'text-gray-300'}`}
|
||||
>
|
||||
繁體中文
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -78,7 +78,7 @@ const STRATEGIES: StrategyOption[] = [
|
||||
}
|
||||
];
|
||||
|
||||
const WEEK_DAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
||||
const WEEK_DAY_INDEXES = [0, 1, 2, 3, 4, 5, 6];
|
||||
|
||||
// Color Theme Variables for Mapping Editors
|
||||
const MAPPING_THEME = {
|
||||
@@ -818,12 +818,12 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
|
||||
{/* Middle Row: Full Width Capsules */}
|
||||
<div className={`grid grid-cols-7 w-full transition-opacity duration-200 mb-3 ${localSchedule.mode !== ScheduleMode.WEEKLY ? 'opacity-50 pointer-events-none' : ''}`}>
|
||||
{WEEK_DAYS.map((day, index) => {
|
||||
const isSelected = localSchedule.weeklyDays.includes(index);
|
||||
{WEEK_DAY_INDEXES.map((dayIndex) => {
|
||||
const isSelected = localSchedule.weeklyDays.includes(dayIndex);
|
||||
return (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => toggleWeekDay(index)}
|
||||
key={dayIndex}
|
||||
onClick={() => toggleWeekDay(dayIndex)}
|
||||
className={`h-9 text-xs font-bold border-y border-l last:border-r border-gray-600/50 transition-colors
|
||||
first:rounded-l-lg last:rounded-r-lg
|
||||
${isSelected
|
||||
@@ -832,7 +832,7 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
}
|
||||
`}
|
||||
>
|
||||
{day}
|
||||
{t(`schedule.weekdaysNarrow.${dayIndex}`)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
export const cht = {
|
||||
app: {
|
||||
title: 'PlexSync',
|
||||
manager: '管理',
|
||||
footer: '© {year} PMS Playlist Sync。已連線至 Docker 後端。',
|
||||
},
|
||||
common: {
|
||||
save: '儲存',
|
||||
cancel: '取消',
|
||||
revert: '還原',
|
||||
delete: '刪除',
|
||||
done: '完成',
|
||||
loading: '載入中…',
|
||||
refresh: '重新整理',
|
||||
close: '關閉',
|
||||
none: '無',
|
||||
disabled: '已停用',
|
||||
add: '新增',
|
||||
switchLanguage: '切換語言',
|
||||
},
|
||||
server: {
|
||||
local: '本機伺服器',
|
||||
cloud: '雲端伺服器',
|
||||
playlists: '{count} 個播放清單',
|
||||
notConnected: '未連線',
|
||||
connectionFailed: '連線失敗',
|
||||
connecting: '連線中…',
|
||||
waiting: '等待中…',
|
||||
syncing: '同步中…',
|
||||
noPlaylists: '找不到播放清單。',
|
||||
cancelRefresh: '取消重新整理',
|
||||
refreshPlaylists: '重新整理播放清單',
|
||||
},
|
||||
playlist: {
|
||||
trackCount: '曲目數',
|
||||
lastUpdated: '上次更新',
|
||||
},
|
||||
dashboard: {
|
||||
mapping: '路徑對應',
|
||||
backup: '備份',
|
||||
autoSync: '自動同步',
|
||||
watch: '監看',
|
||||
watchModeActive: '監看模式:啟用',
|
||||
watchModeDisabled: '監看模式:停用',
|
||||
notSet: '未設定',
|
||||
retain: '保留:{count}',
|
||||
keep: '保留 {count}',
|
||||
connected: '已連線至 Plex',
|
||||
disconnected: '未連線',
|
||||
synchronizing: 'SYNCHRONIZING',
|
||||
syncComplete: 'SYNC COMPLETE',
|
||||
},
|
||||
strategies: {
|
||||
title: '同步策略',
|
||||
localOverwrite: {
|
||||
label: '本機覆寫',
|
||||
desc: '本機播放清單完全覆寫雲端。(無 Diff)',
|
||||
},
|
||||
cloudOverwrite: {
|
||||
label: '雲端覆寫',
|
||||
desc: '雲端播放清單完全覆寫本機。(無 Diff)',
|
||||
},
|
||||
mergeLocal: {
|
||||
label: '雙向合併(本機優先)',
|
||||
desc: '合併兩端。衝突以本機版本為準。',
|
||||
},
|
||||
mergeCloud: {
|
||||
label: '雙向合併(雲端優先)',
|
||||
desc: '合併兩端。衝突以雲端版本為準。',
|
||||
},
|
||||
syncNow: '立即同步',
|
||||
syncing: '同步進行中…',
|
||||
saveWarning: '同步前請先儲存待處理的變更(備份/路徑對應)。',
|
||||
},
|
||||
mapping: {
|
||||
title: '路徑對應',
|
||||
simple: '簡易對應',
|
||||
regex: 'Regex 規則',
|
||||
simpleTitle: '路徑對應',
|
||||
simpleSubtitle: '使用簡單字串比對將本機路徑對應到雲端路徑',
|
||||
regexPre: '前處理(同步前)',
|
||||
regexPost: '後處理(同步後 / 結果)',
|
||||
localPath: '本機路徑',
|
||||
cloudPath: '雲端路徑',
|
||||
pattern: '模式',
|
||||
replace: '取代',
|
||||
saveRules: '儲存規則',
|
||||
noRules: '尚未定義規則。',
|
||||
},
|
||||
backup: {
|
||||
title: '備份保留',
|
||||
enable: '啟用備份',
|
||||
enableDesc: '變更前建立副本',
|
||||
maxVersions: '保留的最大版本數:',
|
||||
noAutoDelete: '不自動刪除',
|
||||
autoDelete: '自動刪除最舊版本',
|
||||
},
|
||||
schedule: {
|
||||
title: '排程任務',
|
||||
cron: 'Cron',
|
||||
daily: '每日',
|
||||
weekly: '每週',
|
||||
weekdaysNarrow: {
|
||||
0: '日',
|
||||
1: '一',
|
||||
2: '二',
|
||||
3: '三',
|
||||
4: '四',
|
||||
5: '五',
|
||||
6: '六',
|
||||
},
|
||||
enableCron: '啟用 Cron 排程',
|
||||
enableDaily: '啟用每日執行',
|
||||
enableWeekly: '啟用每週執行',
|
||||
watchLocal: '監看本機變更',
|
||||
watchDesc: '本機播放清單更新時自動同步',
|
||||
schedule: '排程',
|
||||
notConfigured: '尚未設定',
|
||||
today: '今天',
|
||||
tomorrow: '明天',
|
||||
},
|
||||
connection: {
|
||||
titleConnected: '伺服器已連線',
|
||||
titleConnect: '連線 Plex 伺服器',
|
||||
serverDetails: '伺服器詳細資訊',
|
||||
authentication: '驗證',
|
||||
protocol: '通訊協定',
|
||||
address: 'IP 位址或網域',
|
||||
port: '連接埠',
|
||||
token: 'X-Plex-Token(選填)',
|
||||
username: '使用者名稱 / 電子郵件',
|
||||
password: '密碼',
|
||||
advanced: '進階選項',
|
||||
timeout: '連線逾時(秒)',
|
||||
connectBtn: '連線伺服器',
|
||||
connecting: '連線中…',
|
||||
connectedSuccess: '連線成功',
|
||||
selectLibrary: '選擇要同步的媒體庫',
|
||||
},
|
||||
toasts: {
|
||||
localRefreshCancelled: '已取消本機重新整理。',
|
||||
cloudRefreshCancelled: '已取消雲端重新整理。',
|
||||
strategySaved: '已儲存選擇的策略「{strategy}」。',
|
||||
strategySaveFailed: '儲存同步策略失敗。',
|
||||
mappingSaved: '已儲存路徑對應規則。',
|
||||
mappingSaveFailed: '儲存路徑對應規則失敗。',
|
||||
backupSaved: '已儲存備份設定。',
|
||||
backupFailed: '儲存備份設定失敗。',
|
||||
scheduleDisabled: '已停用排程任務。',
|
||||
scheduleEmpty: '已停用排程任務(Cron 為空)。',
|
||||
scheduleStarted: '排程任務更新成功。',
|
||||
scheduleFailed: '更新排程失敗。',
|
||||
syncFailed: '同步失敗。請檢查連線。',
|
||||
backgroundSyncSuccess: '背景同步已成功完成。',
|
||||
backgroundSyncFailed: '背景同步失敗:{error}',
|
||||
librarySwitched: '媒體庫已切換為 {library}',
|
||||
connectedTo: '已成功連線到 {name}',
|
||||
connectionCancelled: '使用者已取消連線。',
|
||||
librarySaveFailed: '儲存媒體庫選擇失敗。',
|
||||
},
|
||||
};
|
||||
@@ -100,6 +100,15 @@ export const en = {
|
||||
cron: 'Cron',
|
||||
daily: 'Daily',
|
||||
weekly: 'Weekly',
|
||||
weekdaysNarrow: {
|
||||
0: 'S',
|
||||
1: 'M',
|
||||
2: 'T',
|
||||
3: 'W',
|
||||
4: 'T',
|
||||
5: 'F',
|
||||
6: 'S',
|
||||
},
|
||||
enableCron: 'Enable Cron Schedule',
|
||||
enableDaily: 'Enable Daily Run',
|
||||
enableWeekly: 'Enable Weekly Run',
|
||||
|
||||
@@ -100,6 +100,15 @@ export const es = {
|
||||
cron: 'Cron',
|
||||
daily: 'Diario',
|
||||
weekly: 'Semanal',
|
||||
weekdaysNarrow: {
|
||||
0: 'D',
|
||||
1: 'L',
|
||||
2: 'M',
|
||||
3: 'X',
|
||||
4: 'J',
|
||||
5: 'V',
|
||||
6: 'S',
|
||||
},
|
||||
enableCron: 'Habilitar Cron',
|
||||
enableDaily: 'Habilitar Ejecución Diaria',
|
||||
enableWeekly: 'Habilitar Ejecución Semanal',
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
export const zh = {
|
||||
app: {
|
||||
title: 'PlexSync',
|
||||
manager: '管理',
|
||||
footer: '© {year} PMS Playlist Sync。已连接到 Docker 后端。',
|
||||
},
|
||||
common: {
|
||||
save: '保存',
|
||||
cancel: '取消',
|
||||
revert: '恢复',
|
||||
delete: '删除',
|
||||
done: '完成',
|
||||
loading: '加载中...',
|
||||
refresh: '刷新',
|
||||
close: '关闭',
|
||||
none: '无',
|
||||
disabled: '已禁用',
|
||||
add: '添加',
|
||||
switchLanguage: '切换语言',
|
||||
},
|
||||
server: {
|
||||
local: '本地服务器',
|
||||
cloud: '云端服务器',
|
||||
playlists: '{count} 个播放列表',
|
||||
notConnected: '未连接',
|
||||
connectionFailed: '连接失败',
|
||||
connecting: '正在连接...',
|
||||
waiting: '等待中...',
|
||||
syncing: '同步中...',
|
||||
noPlaylists: '未找到播放列表。',
|
||||
cancelRefresh: '取消刷新',
|
||||
refreshPlaylists: '刷新播放列表',
|
||||
},
|
||||
playlist: {
|
||||
trackCount: '曲目数',
|
||||
lastUpdated: '最近更新',
|
||||
},
|
||||
dashboard: {
|
||||
mapping: '路径映射',
|
||||
backup: '备份',
|
||||
autoSync: '自动同步',
|
||||
watch: '监听',
|
||||
watchModeActive: '监听模式:启用',
|
||||
watchModeDisabled: '监听模式:禁用',
|
||||
notSet: '未设置',
|
||||
retain: '保留:{count}',
|
||||
keep: '保留 {count}',
|
||||
connected: '已连接 Plex',
|
||||
disconnected: '未连接',
|
||||
synchronizing: 'SYNCHRONIZING',
|
||||
syncComplete: 'SYNC COMPLETE',
|
||||
},
|
||||
strategies: {
|
||||
title: '同步策略',
|
||||
localOverwrite: {
|
||||
label: '本地覆盖',
|
||||
desc: '本地播放列表完全覆盖云端。(无 Diff)',
|
||||
},
|
||||
cloudOverwrite: {
|
||||
label: '云端覆盖',
|
||||
desc: '云端播放列表完全覆盖本地。(无 Diff)',
|
||||
},
|
||||
mergeLocal: {
|
||||
label: '双向合并(本地优先)',
|
||||
desc: '合并两端。冲突以本地版本为准。',
|
||||
},
|
||||
mergeCloud: {
|
||||
label: '双向合并(云端优先)',
|
||||
desc: '合并两端。冲突以云端版本为准。',
|
||||
},
|
||||
syncNow: '立即同步',
|
||||
syncing: '同步进行中...',
|
||||
saveWarning: '同步前请先保存待处理的更改(备份/路径映射)。',
|
||||
},
|
||||
mapping: {
|
||||
title: '路径映射',
|
||||
simple: '简单映射',
|
||||
regex: '正则规则',
|
||||
simpleTitle: '路径映射',
|
||||
simpleSubtitle: '使用简单字符串匹配将本地路径映射到云端路径',
|
||||
regexPre: '预处理(同步前)',
|
||||
regexPost: '后处理(同步后 / 结果)',
|
||||
localPath: '本地路径',
|
||||
cloudPath: '云端路径',
|
||||
pattern: '模式',
|
||||
replace: '替换',
|
||||
saveRules: '保存规则',
|
||||
noRules: '尚未定义规则。',
|
||||
},
|
||||
backup: {
|
||||
title: '备份保留',
|
||||
enable: '启用备份',
|
||||
enableDesc: '在更改前创建副本',
|
||||
maxVersions: '保留的最大版本数:',
|
||||
noAutoDelete: '不自动删除',
|
||||
autoDelete: '自动删除最旧版本',
|
||||
},
|
||||
schedule: {
|
||||
title: '定时任务',
|
||||
cron: 'Cron',
|
||||
daily: '每日',
|
||||
weekly: '每周',
|
||||
weekdaysNarrow: {
|
||||
0: '日',
|
||||
1: '一',
|
||||
2: '二',
|
||||
3: '三',
|
||||
4: '四',
|
||||
5: '五',
|
||||
6: '六',
|
||||
},
|
||||
enableCron: '启用 Cron 计划',
|
||||
enableDaily: '启用每日运行',
|
||||
enableWeekly: '启用每周运行',
|
||||
watchLocal: '监听本地更改',
|
||||
watchDesc: '本地播放列表更新时自动同步',
|
||||
schedule: '计划',
|
||||
notConfigured: '未配置',
|
||||
today: '今天',
|
||||
tomorrow: '明天',
|
||||
},
|
||||
connection: {
|
||||
titleConnected: '服务器已连接',
|
||||
titleConnect: '连接 Plex 服务器',
|
||||
serverDetails: '服务器详情',
|
||||
authentication: '认证',
|
||||
protocol: '协议',
|
||||
address: 'IP 地址或域名',
|
||||
port: '端口',
|
||||
token: 'X-Plex-Token(可选)',
|
||||
username: '用户名 / 邮箱',
|
||||
password: '密码',
|
||||
advanced: '高级选项',
|
||||
timeout: '连接超时(秒)',
|
||||
connectBtn: '连接服务器',
|
||||
connecting: '连接中...',
|
||||
connectedSuccess: '连接成功',
|
||||
selectLibrary: '选择要同步的媒体库',
|
||||
},
|
||||
toasts: {
|
||||
localRefreshCancelled: '本地刷新已取消。',
|
||||
cloudRefreshCancelled: '云端刷新已取消。',
|
||||
strategySaved: '已保存选择的策略“{strategy}”。',
|
||||
strategySaveFailed: '保存同步策略失败。',
|
||||
mappingSaved: '已保存路径映射规则。',
|
||||
mappingSaveFailed: '保存路径映射规则失败。',
|
||||
backupSaved: '已保存备份设置。',
|
||||
backupFailed: '保存备份设置失败。',
|
||||
scheduleDisabled: '已禁用定时任务。',
|
||||
scheduleEmpty: '已禁用定时任务(Cron 为空)。',
|
||||
scheduleStarted: '定时任务更新成功。',
|
||||
scheduleFailed: '更新定时任务失败。',
|
||||
syncFailed: '同步失败。请检查连接。',
|
||||
backgroundSyncSuccess: '后台同步已成功完成。',
|
||||
backgroundSyncFailed: '后台同步失败:{error}',
|
||||
librarySwitched: '媒体库已切换为 {library}',
|
||||
connectedTo: '已成功连接到 {name}',
|
||||
connectionCancelled: '用户已取消连接。',
|
||||
librarySaveFailed: '保存媒体库选择失败。',
|
||||
},
|
||||
};
|
||||
@@ -1,9 +1,13 @@
|
||||
import { en } from './locales/en';
|
||||
import { es } from './locales/es';
|
||||
import { zh as chs } from './locales/zh';
|
||||
import { cht } from './locales/cht';
|
||||
|
||||
export const translations = {
|
||||
en,
|
||||
es,
|
||||
chs,
|
||||
cht,
|
||||
};
|
||||
|
||||
export type Language = keyof typeof translations;
|
||||
|
||||
Reference in New Issue
Block a user