weebcli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/releases.yml +39 -0
- package/LICENSE +400 -0
- package/README-EN.md +134 -0
- package/README.md +134 -0
- package/aur/.SRCINFO +16 -0
- package/aur/PKGBUILD +43 -0
- package/eslint.config.js +49 -0
- package/jsconfig.json +9 -0
- package/package.json +45 -0
- package/src/constants.js +13 -0
- package/src/functions/episodes.js +38 -0
- package/src/functions/time.js +27 -0
- package/src/functions/variables.js +3 -0
- package/src/i18n/en.json +351 -0
- package/src/i18n/index.js +80 -0
- package/src/i18n/tr.json +348 -0
- package/src/index.js +307 -0
- package/src/jsdoc.js +72 -0
- package/src/sources/allanime.js +195 -0
- package/src/sources/animecix.js +223 -0
- package/src/sources/animely.js +100 -0
- package/src/sources/handlers/allanime.js +318 -0
- package/src/sources/handlers/animecix.js +316 -0
- package/src/sources/handlers/animely.js +338 -0
- package/src/sources/handlers/base.js +391 -0
- package/src/sources/handlers/index.js +4 -0
- package/src/sources/index.js +80 -0
- package/src/utils/anilist.js +193 -0
- package/src/utils/data_manager.js +27 -0
- package/src/utils/discord.js +86 -0
- package/src/utils/download/concurrency.js +27 -0
- package/src/utils/download/download.js +485 -0
- package/src/utils/download/progress.js +84 -0
- package/src/utils/players/mpv.js +251 -0
- package/src/utils/players/vlc.js +120 -0
- package/src/utils/process_queue.js +121 -0
- package/src/utils/resume_watch.js +137 -0
- package/src/utils/search.js +39 -0
- package/src/utils/search_download.js +21 -0
- package/src/utils/speedtest.js +30 -0
- package/src/utils/spinner.js +7 -0
- package/src/utils/storage/cache.js +42 -0
- package/src/utils/storage/config.js +71 -0
- package/src/utils/storage/history.js +69 -0
- package/src/utils/storage/queue.js +43 -0
- package/src/utils/storage/watch_progress.js +104 -0
- package/src/utils/system.js +176 -0
- package/src/utils/ui/box.js +140 -0
- package/src/utils/ui/settings_ui.js +322 -0
- package/src/utils/ui/show_history.js +92 -0
- package/src/utils/ui/stats.js +67 -0
- package/start.js +21 -0
- package/tanitim-en.md +66 -0
- package/tanitim-tr.md +66 -0
package/src/i18n/en.json
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app": {
|
|
3
|
+
"title": "Animely CLI",
|
|
4
|
+
"goodbye": "See you later!",
|
|
5
|
+
"unexpectedError": "An unexpected error occurred, please try again later.",
|
|
6
|
+
"errorDetail": "Error detail: {message}"
|
|
7
|
+
},
|
|
8
|
+
"update": {
|
|
9
|
+
"available": "New update available: {current} -> {latest}",
|
|
10
|
+
"starting": "Starting automatic update...",
|
|
11
|
+
"completed": "Update completed! Restarting application...",
|
|
12
|
+
"failed": "Automatic update failed.",
|
|
13
|
+
"manualInstall": "Please run 'npm install -g animely' manually."
|
|
14
|
+
},
|
|
15
|
+
"setup": {
|
|
16
|
+
"welcome": "Welcome to Animely. Let's complete the initial setup.",
|
|
17
|
+
"languagePrompt": "Dil seçin / Select language:",
|
|
18
|
+
"playerConfig": "Media player configuration:",
|
|
19
|
+
"playerQuestion": "Do you have a media player (VLC/MPV) installed on your system?",
|
|
20
|
+
"playerYes": "Yes, I do",
|
|
21
|
+
"playerInstall": "No, install automatically (Winget)",
|
|
22
|
+
"playerWeb": "No, open in browser (VideoLAN.org)",
|
|
23
|
+
"playerSelect": "Which player would you like to install?",
|
|
24
|
+
"mpvRecommended": "MPV Player (Recommended)",
|
|
25
|
+
"vlcPlayer": "VLC Media Player",
|
|
26
|
+
"installing": "Installing {player}, please wait...",
|
|
27
|
+
"installSuccess": "Installation completed successfully.",
|
|
28
|
+
"installFailed": "Automatic installation failed. Please download manually.",
|
|
29
|
+
"webOpened": "Download page opened in browser. Complete the installation and come back.",
|
|
30
|
+
"defaultPlayerPrompt": "Which player should be used as default:",
|
|
31
|
+
"mpvWithResume": "MPV Player (Recommended - Resume playback support)",
|
|
32
|
+
"settingsSaved": "Settings saved, starting application..."
|
|
33
|
+
},
|
|
34
|
+
"menu": {
|
|
35
|
+
"browsingMenu": "Browsing menu",
|
|
36
|
+
"incompleteDownloads": "{count} incomplete download task(s)!",
|
|
37
|
+
"selectAction": "Select an action:",
|
|
38
|
+
"searchAnime": "Search Anime",
|
|
39
|
+
"watchHistory": "Watch History",
|
|
40
|
+
"settings": "Settings",
|
|
41
|
+
"resume": "Resume: {name} (Episode {episode})",
|
|
42
|
+
"startQueue": "Start Download Queue ({count} Episodes)",
|
|
43
|
+
"clearQueue": "Clear Download Queue",
|
|
44
|
+
"exit": "Exit"
|
|
45
|
+
},
|
|
46
|
+
"search": {
|
|
47
|
+
"enterName": "Enter the anime name to search (Type 'cancel' to cancel):",
|
|
48
|
+
"invalidName": "Please enter a valid anime name.",
|
|
49
|
+
"cancel": "cancel",
|
|
50
|
+
"searching": "Searching...",
|
|
51
|
+
"searchFailed": "Search failed.",
|
|
52
|
+
"noResults": "No results found.",
|
|
53
|
+
"notFound": "Sorry, no anime matching your criteria was found.",
|
|
54
|
+
"foundCount": "{count} anime found:",
|
|
55
|
+
"selectAnime": "Which anime would you like to select?",
|
|
56
|
+
"goBack": "Go Back",
|
|
57
|
+
"season": "Season",
|
|
58
|
+
"episodes": "Episodes"
|
|
59
|
+
}
|
|
60
|
+
,
|
|
61
|
+
"episodes": {
|
|
62
|
+
"loading": "Loading episodes...",
|
|
63
|
+
"loadFailed": "Failed to load episodes.",
|
|
64
|
+
"notFound": "No episodes found for this anime.",
|
|
65
|
+
"noEpisodes": "No episodes available for this anime yet.",
|
|
66
|
+
"episodeCount": "{count} episodes",
|
|
67
|
+
"selectAction": "Select an action:",
|
|
68
|
+
"watch": "Watch Episode",
|
|
69
|
+
"download": "Download Episodes",
|
|
70
|
+
"goBack": "Go Back",
|
|
71
|
+
"selectEpisode": "Select the episode you want to watch:",
|
|
72
|
+
"lastWatched": "Last watched",
|
|
73
|
+
"nextUp": "Next up",
|
|
74
|
+
"episode": "Episode",
|
|
75
|
+
"episodeNumber": "Episode {number}"
|
|
76
|
+
},
|
|
77
|
+
"player": {
|
|
78
|
+
"gettingLink": "Getting stream link...",
|
|
79
|
+
"linkFailed": "Failed to get stream link.",
|
|
80
|
+
"sourceNotFound": "No streaming source found.",
|
|
81
|
+
"selectQuality": "Select quality:",
|
|
82
|
+
"default": "Default",
|
|
83
|
+
"opening": "{name} — Episode {episode} opening with {player}...",
|
|
84
|
+
"resumePrompt": "Would you like to resume from where you left off? ({time})",
|
|
85
|
+
"markWatched": "Would you like to mark this episode as 'Watched'?",
|
|
86
|
+
"historyUpdated": "Watch history updated!",
|
|
87
|
+
"anilistUpdated": "Anilist updated successfully!",
|
|
88
|
+
"anilistSearching": "Searching in Anilist database...",
|
|
89
|
+
"anilistUpdating": "Updating Anilist...",
|
|
90
|
+
"playerError": "Player error: {message}",
|
|
91
|
+
"episodeNotFound": "Episode {episode} not found (May not be released yet).",
|
|
92
|
+
"linkNotFound": "Stream link not found.",
|
|
93
|
+
"episodeOpening": "{name} — Episode {episode} opening ({player})..."
|
|
94
|
+
},
|
|
95
|
+
"download": {
|
|
96
|
+
"downloadTitle": "{name} - Download",
|
|
97
|
+
"selectionMethod": "How would you like to select episodes?",
|
|
98
|
+
"selectFromList": "Select from list (One by one)",
|
|
99
|
+
"enterRange": "Enter range (e.g., 1-12, 15)",
|
|
100
|
+
"downloadAll": "Download all",
|
|
101
|
+
"goBack": "Go Back",
|
|
102
|
+
"episodeSelection": "{name} - Episode Selection",
|
|
103
|
+
"selectEpisodes": "Select episodes to download (Space to select, Enter to confirm):",
|
|
104
|
+
"rangeSelection": "{name} - Range Selection",
|
|
105
|
+
"enterRangePrompt": "Enter episode range (e.g., 1-12, 15, 20-25):",
|
|
106
|
+
"invalidRange": "Please enter a valid range.",
|
|
107
|
+
"noEpisodeSelected": "No episode selected.",
|
|
108
|
+
"gettingQualities": "Getting quality options...",
|
|
109
|
+
"selectQuality": "Select download quality:",
|
|
110
|
+
"episodesSelected": "{count} episodes selected. Maximum {limit} concurrent downloads.",
|
|
111
|
+
"downloadComplete": "Download completed.",
|
|
112
|
+
"episodeDownloaded": "{name} — Episode {episode} downloaded successfully.",
|
|
113
|
+
"gettingLink": "Getting link for episode {episode}...",
|
|
114
|
+
"linkNotFound": "Download link not found.",
|
|
115
|
+
"addToQueue": "Add to Download Queue",
|
|
116
|
+
"downloadNow": "Download Now",
|
|
117
|
+
"whatToDo": "What would you like to do?",
|
|
118
|
+
"addedToQueue": "{count} episodes added to queue.",
|
|
119
|
+
"downloadStarting": "Download starting...",
|
|
120
|
+
"fileSizeTooSmall": "File size too small, download may be corrupted."
|
|
121
|
+
},
|
|
122
|
+
"queue": {
|
|
123
|
+
"title": "Download Queue",
|
|
124
|
+
"totalEpisodes": "Total Episodes: {count}",
|
|
125
|
+
"estimatedSize": "Estimated Size: ~{size} GB",
|
|
126
|
+
"estimatedTime": "Estimated Time: ~{minutes} min (at {speed} Mbps)",
|
|
127
|
+
"confirmStart": "Do you want to start the download?",
|
|
128
|
+
"downloading": "{count} episodes will be downloaded. Concurrent download limit: {limit}",
|
|
129
|
+
"allComplete": "All downloads completed.",
|
|
130
|
+
"notificationComplete": "Download completed.",
|
|
131
|
+
"confirmClear": "Are you sure you want to clear the download queue?",
|
|
132
|
+
"cleared": "Download queue cleared successfully!"
|
|
133
|
+
}
|
|
134
|
+
,
|
|
135
|
+
"history": {
|
|
136
|
+
"title": "Watch History",
|
|
137
|
+
"selectList": "Which list would you like to view?",
|
|
138
|
+
"statistics": "Statistics",
|
|
139
|
+
"inProgress": "In Progress ({count})",
|
|
140
|
+
"completed": "Completed ({count})",
|
|
141
|
+
"goBack": "Go Back",
|
|
142
|
+
"completedTitle": "Completed Anime",
|
|
143
|
+
"noCompleted": "No completed anime yet.",
|
|
144
|
+
"noWatching": "No anime being watched yet.",
|
|
145
|
+
"selectForDetails": "Select anime to view details:",
|
|
146
|
+
"lastEpisode": "Last watched: Episode {episode}",
|
|
147
|
+
"lastEpisodeLabel": "Last watched episode: {episode}",
|
|
148
|
+
"totalEpisodes": "Total episodes: {count}",
|
|
149
|
+
"lastWatchedDate": "Last watched: {date}",
|
|
150
|
+
"pressEnter": "Press Enter to go back..."
|
|
151
|
+
},
|
|
152
|
+
"stats": {
|
|
153
|
+
"emptyHistory": "Your watch history is empty...",
|
|
154
|
+
"totalAnime": "Total Anime:",
|
|
155
|
+
"completedAnime": "Completed:",
|
|
156
|
+
"watchingAnime": "In Progress:",
|
|
157
|
+
"totalEpisodes": "Total Episodes:",
|
|
158
|
+
"watchTime": "Watch Time:",
|
|
159
|
+
"hours": "{hours} hours",
|
|
160
|
+
"days": "approximately {days} days",
|
|
161
|
+
"lastWatched": "Last Watched:",
|
|
162
|
+
"pressEnter": "Press Enter to go back",
|
|
163
|
+
"timeAgo": {
|
|
164
|
+
"years": "{count} years ago",
|
|
165
|
+
"months": "{count} months ago",
|
|
166
|
+
"days": "{count} days ago",
|
|
167
|
+
"hours": "{count} hours ago",
|
|
168
|
+
"minutes": "{count} min ago",
|
|
169
|
+
"justNow": "just now"
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
"settings": {
|
|
173
|
+
"title": "Settings",
|
|
174
|
+
"whatToChange": "What would you like to change?",
|
|
175
|
+
"language": "Language (Current: {current})",
|
|
176
|
+
"animeSource": "Anime Source (Current: {current})",
|
|
177
|
+
"player": "Player (Current: {current})",
|
|
178
|
+
"aria2": "Download Manager (Aria2) ({status})",
|
|
179
|
+
"aria2Connections": " ↳ Aria2 Connection Count (Current: {count}x)",
|
|
180
|
+
"ytDlp": "M3U8 Download Manager (yt-dlp) ({status})",
|
|
181
|
+
"ytDlpConnections": " ↳ yt-dlp Connection Count (Current: {count}x)",
|
|
182
|
+
"concurrentLimit": "Concurrent Download Limit (Current: {count})",
|
|
183
|
+
"downloadLocation": "Download Location (Current: {path})",
|
|
184
|
+
"retryDownload": "Download Retry (Current: {status})",
|
|
185
|
+
"retrySettings": " ↳ Retry Settings (Current: {count}x / {delay}s)",
|
|
186
|
+
"showDetails": "Show Anime Details (Current: {status})",
|
|
187
|
+
"anilist": "Anilist Integration (Status: {status})",
|
|
188
|
+
"anilistLogout": " ↳ Disconnect",
|
|
189
|
+
"telemetry": "Telemetry (Anonymous) (Status: {status})",
|
|
190
|
+
"backToMenu": "Back to Main Menu",
|
|
191
|
+
"active": "Active",
|
|
192
|
+
"inactive": "Inactive",
|
|
193
|
+
"notSelected": "Not Selected",
|
|
194
|
+
"notConnected": "Not Connected",
|
|
195
|
+
"advancedSearch": "Advanced search",
|
|
196
|
+
"selectSource": "Select anime source:",
|
|
197
|
+
"sourceUpdated": "Anime source updated.",
|
|
198
|
+
"detailsEnabled": "Anime details view enabled.",
|
|
199
|
+
"detailsDisabled": "Anime details view disabled.",
|
|
200
|
+
"anilistDisconnectConfirm": "Are you sure you want to disconnect Anilist?",
|
|
201
|
+
"anilistDisconnected": "Anilist disconnected.",
|
|
202
|
+
"operationCancelled": "Operation cancelled.",
|
|
203
|
+
"telemetryEnabled": "Telemetry enabled.",
|
|
204
|
+
"telemetryDisabled": "Telemetry disabled.",
|
|
205
|
+
"selectPlayer": "Select default player:",
|
|
206
|
+
"playerNotFound": "Warning: {player} not found on system.",
|
|
207
|
+
"autoInstallPrompt": "Would you like to install it automatically?",
|
|
208
|
+
"installingPlayer": "Starting installation, please wait...",
|
|
209
|
+
"playerInstalled": "{player} installed successfully!",
|
|
210
|
+
"installFailed": "Installation failed. Still selected as player.",
|
|
211
|
+
"playerUpdated": "Default player updated.",
|
|
212
|
+
"concurrentPrompt": "Concurrent download count (1-10):",
|
|
213
|
+
"concurrentValidation": "Please enter a value between 1 and 10.",
|
|
214
|
+
"concurrentUpdated": "Download limit updated.",
|
|
215
|
+
"aria2Enabled": "Aria2 enabled.",
|
|
216
|
+
"aria2Disabled": "Aria2 disabled.",
|
|
217
|
+
"aria2ConnectionsPrompt": "Aria2 connection count (1-32):",
|
|
218
|
+
"aria2ConnectionsValidation": "Please enter a value between 1 and 32.",
|
|
219
|
+
"aria2ConnectionsUpdated": "Aria2 connection count updated.",
|
|
220
|
+
"ytDlpEnabled": "yt-dlp enabled (M3U8 downloads accelerated).",
|
|
221
|
+
"ytDlpDisabled": "yt-dlp disabled (FFmpeg will be used).",
|
|
222
|
+
"ytDlpConnectionsPrompt": "yt-dlp connection count (1-32):",
|
|
223
|
+
"ytDlpConnectionsValidation": "Please enter a value between 1 and 32.",
|
|
224
|
+
"ytDlpConnectionsUpdated": "yt-dlp connection count updated.",
|
|
225
|
+
"downloadDirPrompt": "New download location:",
|
|
226
|
+
"downloadDirValidation": "This field cannot be empty.",
|
|
227
|
+
"downloadDirUpdated": "Download location updated.",
|
|
228
|
+
"retryEnabled": "Download retry enabled.",
|
|
229
|
+
"retryDisabled": "Download retry disabled.",
|
|
230
|
+
"retryCountPrompt": "Maximum retry count (0-10):",
|
|
231
|
+
"retryCountValidation": "Please enter a value between 0 and 10.",
|
|
232
|
+
"retryDelayPrompt": "Delay between retries (seconds):",
|
|
233
|
+
"retryDelayValidation": "Please enter a positive value.",
|
|
234
|
+
"retryUpdated": "Retry settings updated.",
|
|
235
|
+
"selectLanguage": "Select language:",
|
|
236
|
+
"languageUpdated": "Language updated.",
|
|
237
|
+
"turkish": "Türkçe",
|
|
238
|
+
"english": "English"
|
|
239
|
+
}
|
|
240
|
+
,
|
|
241
|
+
"anilist": {
|
|
242
|
+
"verifying": "Verifying token...",
|
|
243
|
+
"loginSuccess": "Login successful! Welcome, {username}.",
|
|
244
|
+
"verifyFailed": "Token received but verification failed.",
|
|
245
|
+
"loginFailed": "Login failed: {message}",
|
|
246
|
+
"browserOpening": "Opening browser... Please log in with your AniList account.",
|
|
247
|
+
"manualLink": "If it doesn't open, click this link: {url}",
|
|
248
|
+
"loggingIn": "Logging in...",
|
|
249
|
+
"loginSuccessPage": "Login successful! You can close this window.",
|
|
250
|
+
"tokenNotFound": "Token not found. Please try again.",
|
|
251
|
+
"updateError": "Anilist update error:",
|
|
252
|
+
"historyUpdating": "Updating history..."
|
|
253
|
+
},
|
|
254
|
+
"spinner": {
|
|
255
|
+
"loading": "Executing command, please wait.",
|
|
256
|
+
"listUpdating": "Updating list...",
|
|
257
|
+
"fetchingEpisodes": "Fetching episode list for {name}..."
|
|
258
|
+
},
|
|
259
|
+
"progress": {
|
|
260
|
+
"waiting": "Waiting",
|
|
261
|
+
"downloading": "Downloading",
|
|
262
|
+
"retrying": "Retrying",
|
|
263
|
+
"completed": "Completed",
|
|
264
|
+
"error": "Error",
|
|
265
|
+
"errorRetrying": "Error, retrying",
|
|
266
|
+
"gettingLink": "Getting link",
|
|
267
|
+
"processing": "Processing",
|
|
268
|
+
"remaining": "remaining",
|
|
269
|
+
"downloadStarting": "Download starting...",
|
|
270
|
+
"downloadingPercent": "Downloading: {percent}% ({downloaded} / {total})",
|
|
271
|
+
"uploading": "Loading: {downloaded}",
|
|
272
|
+
"uploadingSpeed": "Loading: {downloaded} - {speed}/s",
|
|
273
|
+
"progressBar": "[{bar}] {percent}% ({downloaded} / {total}) - {speed}/s - Remaining: {eta}",
|
|
274
|
+
"aria2Progress": "[{bar}] {percent}% - Speed: {speed}",
|
|
275
|
+
"ytDlpProgress": "[{bar}] {percent}% - Speed: {speed} - ETA: {eta}",
|
|
276
|
+
"processingPercent": "Processing: {percent}% ({downloaded})"
|
|
277
|
+
},
|
|
278
|
+
"errors": {
|
|
279
|
+
"animeListFailed": "Failed to get anime list. Check your internet connection.",
|
|
280
|
+
"episodesFailed": "Failed to get anime episodes. Please try again later.",
|
|
281
|
+
"invalidUrl": "Invalid URL",
|
|
282
|
+
"noInternet": "No internet connection found.",
|
|
283
|
+
"timeout": "Connection timed out.",
|
|
284
|
+
"downloadFailed": "Download failed to start: {message}",
|
|
285
|
+
"serverError": "Server error: {status} {statusText}",
|
|
286
|
+
"fileSaved": "File saved successfully: {path}",
|
|
287
|
+
"fileExists": "File already downloaded: {path}",
|
|
288
|
+
"fileExistsAria2": "File already downloaded (Aria2): {path}",
|
|
289
|
+
"fileExistsM3U8": "File already downloaded (M3U8): {path}",
|
|
290
|
+
"resumingDownload": "Resuming download: {downloaded} / {total}",
|
|
291
|
+
"fileWriteError": "File write error: {message}",
|
|
292
|
+
"ffmpegError": "FFmpeg error: {message}",
|
|
293
|
+
"aria2Starting": "Starting Aria2 download manager...",
|
|
294
|
+
"aria2Error": "Aria2c closed with error code: {code}",
|
|
295
|
+
"aria2StartFailed": "Failed to start Aria2c: {message}",
|
|
296
|
+
"downloadCompleted": "Download completed: {path}",
|
|
297
|
+
"m3u8Processing": "Downloading and processing M3U8 (This may take a while)...",
|
|
298
|
+
"retrying": "Retrying ({attempt}/{total})...",
|
|
299
|
+
"packageNotFound": "Package definition not found: {name}",
|
|
300
|
+
"wingetNotFound": "Winget package manager not found.",
|
|
301
|
+
"brewNotFound": "Homebrew package manager not found.",
|
|
302
|
+
"packageManagerNotFound": "Supported package manager (apt/pacman) not found.",
|
|
303
|
+
"installError": "Installation error: {message}",
|
|
304
|
+
"vlcNotFound": "VLC Player not found. Trying to install with {manager}...",
|
|
305
|
+
"vlcInstalled": "VLC installed successfully!",
|
|
306
|
+
"vlcInstallFailed": "VLC installation failed.",
|
|
307
|
+
"vlcNotFoundAndFailed": "VLC Player not found and could not be installed.",
|
|
308
|
+
"vlcPathNotFound": "VLC file path not found.",
|
|
309
|
+
"vlcStarting": "Starting VLC...",
|
|
310
|
+
"mpvNotFound": "MPV Player not found. Trying to install with {manager}...",
|
|
311
|
+
"mpvInstalled": "MPV installed successfully!",
|
|
312
|
+
"mpvInstallFailed": "MPV installation failed. Please install manually: https://mpv.io/installation/",
|
|
313
|
+
"mpvInstallFailedMac": "MPV installation failed. Please install manually or make sure Homebrew is installed.",
|
|
314
|
+
"mpvNotFoundAndFailed": "MPV Player not found and could not be installed.",
|
|
315
|
+
"mpvPathNotFound": "MPV Player file path not found.",
|
|
316
|
+
"managerDetected": "{manager} detected. Starting installation (sudo may be required)...",
|
|
317
|
+
"ytDlpStarting": "Starting download with yt-dlp (fast mode)...",
|
|
318
|
+
"ytDlpFailed": "yt-dlp failed, falling back to FFmpeg...",
|
|
319
|
+
"ytDlpError": "yt-dlp closed with error code: {code}",
|
|
320
|
+
"ytDlpStartFailed": "Failed to start yt-dlp: {message}",
|
|
321
|
+
"ytDlpNotFound": "yt-dlp not found. Required for M3U8 downloads.",
|
|
322
|
+
"ytDlpInstalling": "Installing yt-dlp automatically...",
|
|
323
|
+
"ytDlpInstalled": "yt-dlp installed successfully!",
|
|
324
|
+
"ytDlpInstallFailed": "yt-dlp installation failed. FFmpeg will be used."
|
|
325
|
+
},
|
|
326
|
+
"common": {
|
|
327
|
+
"yes": "Yes",
|
|
328
|
+
"no": "No",
|
|
329
|
+
"confirm": "Confirm",
|
|
330
|
+
"cancel": "Cancel",
|
|
331
|
+
"back": "Back",
|
|
332
|
+
"next": "Next",
|
|
333
|
+
"save": "Save",
|
|
334
|
+
"delete": "Delete",
|
|
335
|
+
"edit": "Edit",
|
|
336
|
+
"close": "Close",
|
|
337
|
+
"loading": "Loading...",
|
|
338
|
+
"speed": "Speed"
|
|
339
|
+
},
|
|
340
|
+
"ui": {
|
|
341
|
+
"nowPlaying": "Now Playing"
|
|
342
|
+
},
|
|
343
|
+
"discord": {
|
|
344
|
+
"download": "Download"
|
|
345
|
+
},
|
|
346
|
+
"allanime": {
|
|
347
|
+
"selectAudioType": "Select audio type:",
|
|
348
|
+
"subbed": "Subbed",
|
|
349
|
+
"dubbed": "Dubbed"
|
|
350
|
+
}
|
|
351
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
/** @type {Object.<string, any>} */
|
|
10
|
+
const translations = {
|
|
11
|
+
tr: JSON.parse(fs.readFileSync(path.join(__dirname, "tr.json"), "utf-8")),
|
|
12
|
+
en: JSON.parse(fs.readFileSync(path.join(__dirname, "en.json"), "utf-8"))
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** @type {string} */
|
|
16
|
+
let currentLanguage = "tr";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {string} lang
|
|
20
|
+
*/
|
|
21
|
+
export function setLanguage(lang) {
|
|
22
|
+
if (translations[lang]) {
|
|
23
|
+
currentLanguage = lang;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @returns {string}
|
|
29
|
+
*/
|
|
30
|
+
export function getLanguage() {
|
|
31
|
+
return currentLanguage;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @returns {string[]}
|
|
36
|
+
*/
|
|
37
|
+
export function getAvailableLanguages() {
|
|
38
|
+
return Object.keys(translations);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} key - Dot notation key (e.g., "menu.searchAnime")
|
|
43
|
+
* @param {Object.<string, string|number>} [params] - Parameters to replace in the string
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
export function t(key, params = {}) {
|
|
47
|
+
const keys = key.split(".");
|
|
48
|
+
let value = translations[currentLanguage];
|
|
49
|
+
|
|
50
|
+
for (const k of keys) {
|
|
51
|
+
if (value && typeof value === "object" && k in value) {
|
|
52
|
+
value = value[k];
|
|
53
|
+
} else {
|
|
54
|
+
// Fallback to Turkish if key not found
|
|
55
|
+
value = translations["tr"];
|
|
56
|
+
for (const fallbackKey of keys) {
|
|
57
|
+
if (value && typeof value === "object" && fallbackKey in value) {
|
|
58
|
+
value = value[fallbackKey];
|
|
59
|
+
} else {
|
|
60
|
+
return key; // Return key if not found in fallback
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (typeof value !== "string") {
|
|
68
|
+
return key;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Replace parameters
|
|
72
|
+
let result = value;
|
|
73
|
+
for (const [paramKey, paramValue] of Object.entries(params)) {
|
|
74
|
+
result = result.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const i18n = { t, setLanguage, getLanguage, getAvailableLanguages };
|