fix(ui): harden add downloads modal layout

This commit is contained in:
NimBold
2026-08-11 10:51:11 +03:30
parent 753d590aee
commit ae6a00304e
9 changed files with 96 additions and 49 deletions
+2 -1
View File
@@ -653,7 +653,8 @@ const common = {
pauseBeforeReplace: 'Pause {{file}} before replacing it.',
cannotReplace: 'Cannot replace {{file}}: file is not owned by a Firelink download.',
downloadLinks: 'Download Links',
pastePlaceholder: 'Paste HTTP, HTTPS, FTP, SFTP, or magnet URLs here... You can also choose .torrent files below.\n\nFor media downloads, paste links from YouTube, X, TikTok, Instagram, Reddit, etc.',
pastePlaceholder: 'Paste HTTP(S), FTP/SFTP, magnet, or media URLs…',
pasteHint: 'Media links from YouTube, X, TikTok, Instagram, and Reddit are supported.',
playlistSummary: 'Playlist “{{title}}”: {{loaded}}{{total}} entries loaded{{truncated}}{{skipped}}',
safeEntryLimit: ' (safe entry limit reached)',
selectedSummary: '{{ready}} selected ready, {{fallback}} fallback, {{mediaRetry}} media retry, {{blocked}} blocked',
+2 -1
View File
@@ -653,7 +653,8 @@ const fa = {
pauseBeforeReplace: 'قبل از جایگزینی {{file}}، آن را متوقف کنید.',
cannotReplace: 'نمی‌توان {{file}} را جایگزین کرد: فایل متعلق به یک دانلود Firelink نیست.',
downloadLinks: 'پیوندهای دانلود',
pastePlaceholder: 'URLهای HTTP، HTTPS، FTP، SFTP یا magnet را اینجا جای‌گذاری کنید… همچنین می‌توانید فایل‌های .torrent را از پایین انتخاب کنید.\n\nبرای دانلود رسانه، پیوندهایی از \u2066YouTube\u2069، \u2066X\u2069، \u2066TikTok\u2069، \u2066Instagram\u2069، \u2066Reddit\u2069 و غیره جای‌گذاری کنید.',
pastePlaceholder: 'URLهای \u2066HTTP(S)\u2069، \u2066FTP/SFTP\u2069، \u2066magnet\u2069 یا رسانه را اینجا جای‌گذاری کنید',
pasteHint: 'پیوندهای \u2066YouTube\u2069، \u2066X\u2069، \u2066TikTok\u2069، \u2066Instagram\u2069 و \u2066Reddit\u2069 پشتیبانی می‌شوند.',
playlistSummary: 'لیست پخش "{{title}}": {{loaded}} از {{total}} ورودی بارگیری شد{{truncated}}{{skipped}}',
safeEntryLimit: ' (به حد مجاز ایمن ورودی‌ها رسیدیم)',
selectedSummary: '{{ready}} انتخاب‌شده آماده، {{fallback}} اطلاعات جایگزین، {{mediaRetry}} تلاش مجدد رسانه، {{blocked}} مسدودشده',
+2 -1
View File
@@ -653,7 +653,8 @@ const he = {
pauseBeforeReplace: 'השהה את {{file}} לפני החלפתו.',
cannotReplace: 'לא ניתן להחליף את {{file}}: הקובץ אינו שייך להורדת Firelink.',
downloadLinks: 'קישורי הורדה',
pastePlaceholder: 'הדבק כאן כתובות \u2066HTTP\u2069, \u2066HTTPS\u2069, \u2066FTP\u2069, \u2066SFTP\u2069 או magnet… אפשר גם לבחור קובצי ‎.torrent‎ למטה.\n\nעבור הורדות מדיה, הדבק קישורים מ-\u2066YouTube\u2069, \u2066X\u2069, \u2066TikTok\u2069, \u2066Instagram\u2069, \u2066Reddit\u2069 וכו\'.',
pastePlaceholder: 'הדביקו כאן כתובות \u2066HTTP(S)\u2069, \u2066FTP/SFTP\u2069, \u2066magnet\u2069 או מדיה…',
pasteHint: 'קישורי \u2066YouTube\u2069, \u2066X\u2069, \u2066TikTok\u2069, \u2066Instagram\u2069 ו-\u2066Reddit\u2069 נתמכים.',
playlistSummary: 'רשימת השמעה "{{title}}": {{loaded}} מתוך {{total}} פריטים נטענו{{truncated}}{{skipped}}',
safeEntryLimit: ' (הושגה מגבלת הפריטים הבטוחה)',
selectedSummary: '{{ready}} נבחרו ומוכנים, {{fallback}} לגיבוי, {{mediaRetry}} מדיה לניסיון חוזר, {{blocked}} חסומים',
+2 -1
View File
@@ -653,7 +653,8 @@ const ru = {
pauseBeforeReplace: 'Приостановите {{file}} перед заменой.',
cannotReplace: 'Невозможно заменить {{file}}: файл не принадлежит загрузке Firelink.',
downloadLinks: 'Ссылки для скачивания',
pastePlaceholder: 'Вставьте сюда URL-адреса HTTP, HTTPS, FTP, SFTP или magnet… Также можно выбрать файлы .torrent ниже.\n\nДля загрузки медиа вставляйте ссылки с YouTube, X, TikTok, Instagram, Reddit и т. д.',
pastePlaceholder: 'Вставьте URL HTTP(S), FTP/SFTP, magnet или медиа…',
pasteHint: 'Поддерживаются ссылки YouTube, X, TikTok, Instagram и Reddit.',
playlistSummary: 'Плейлист «{{title}}»: загружено {{loaded}} из {{total}} элементов{{truncated}}{{skipped}}',
safeEntryLimit: ' (достигнут безопасный лимит элементов)',
selectedSummary: 'Выбрано: {{ready}} готовых, {{fallback}} с резервными данными, {{mediaRetry}} повторов медиа, {{blocked}} заблокировано',
+2 -1
View File
@@ -653,7 +653,8 @@ const uk = {
pauseBeforeReplace: 'Призупиніть {{file}} перед заміною.',
cannotReplace: 'Неможливо замінити {{file}}: файл не належить до завантажень Firelink.',
downloadLinks: 'Посилання для завантаження',
pastePlaceholder: 'Вставте сюди URL-адреси HTTP, HTTPS, FTP, SFTP або magnet… Також можна вибрати файли .torrent нижче.\n\nДля медіазавантажень вставте посилання з YouTube, X, TikTok, Instagram, Reddit тощо.',
pastePlaceholder: 'Вставте URL HTTP(S), FTP/SFTP, magnet або медіа…',
pasteHint: 'Підтримуються посилання YouTube, X, TikTok, Instagram і Reddit.',
playlistSummary: 'Плейлист “{{title}}”: {{loaded}} з {{total}} елементів завантажено{{truncated}}{{skipped}}',
safeEntryLimit: ' (досягнуто безпечного ліміту елементів)',
selectedSummary: '{{ready}} вибрано готових, {{fallback}} резервних, {{mediaRetry}} повторних медіа, {{blocked}} заблоковано',
+2 -1
View File
@@ -653,7 +653,8 @@ const zhCN = {
pauseBeforeReplace: '请在替换 {{file}} 前暂停它。',
cannotReplace: '无法替换 {{file}}:文件不属于 Firelink 下载。',
downloadLinks: '下载链接',
pastePlaceholder: '在此粘贴 HTTP、HTTPS、FTPSFTPmagnet URL…也可以在下方选择 .torrent 文件。\n\n对于媒体下载,请粘贴来自 YouTube、X、TikTok、Instagram、Reddit 等的链接。',
pastePlaceholder: '在此粘贴 HTTP(S)、FTP/SFTPmagnet 或媒体 URL…',
pasteHint: '支持 YouTube、X、TikTok、Instagram 和 Reddit 链接。',
playlistSummary: '播放列表“{{title}}”:已加载 {{loaded}} / {{total}} 个条目{{truncated}}{{skipped}}',
safeEntryLimit: ' (达到安全条目限制)',
selectedSummary: '准备就绪 {{ready}} 个,后备项 {{fallback}} 个,媒体重试 {{mediaRetry}} 个,已屏蔽 {{blocked}} 个',
+10
View File
@@ -76,6 +76,16 @@ describe('translation catalogs', () => {
expect(allMismatches).toEqual([]);
});
it('isolates mixed-direction Add Downloads guidance in RTL locales', () => {
for (const locale of ['fa', 'he'] as const) {
for (const key of ['addDownloads.pastePlaceholder', 'addDownloads.pasteHint']) {
const value = catalogFor(locale).get(key) ?? '';
expect(value).toContain('\u2066');
expect(value).toContain('\u2069');
}
}
});
it('reports exact English duplicates for translation review', () => {
const english = catalogFor('en');
const duplicates = APP_LOCALES.filter((locale) => locale !== 'en').flatMap((locale) => {