mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 22:26:16 -08:00
feat(switcher): rebuild the playlist switcher as an overlay popover
The switcher's mat-menu becomes a CDK connected overlay (app-playlist-switcher-panel), 440px wide, with a dimmed, blurred backdrop; only its list scrolls and row menus open above it. - Header with the source count, Add playlist and All sources. - Search by name or host, autofocused; the type filter is one segmented control (All / M3U / Xtream / Stalker with counts) instead of three checkboxes, remembered between openings (the old checkbox setting is migrated). The search is no longer kept between openings. - "Recent" (the three most recently opened, kept across restarts) above "All" in the Sources page order, as compact source rows: the current one tinted with a check. Each row's ⋯ menu holds Refresh, Playlist info, Account info, Check again and Remove (with Undo); the footer's info, account and add actions moved there and to the header. - Keyboard: a listbox driven by aria-activedescendant from the search field. Arrow keys move and wrap, Enter opens, Shift+F10 opens the row's menu, Escape closes and returns focus to the trigger. Hints in the footer. - Deleting from a row menu moves focus to the toast's Undo, since the row (and its focus) left the page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
106414c118
commit
9feab4f83b
49 files changed
+1987
-1813
No files matched your search
@@ -245,44 +245,41 @@ test.describe('Electron Playlist Switcher', () => {
|
||||
await waitForM3uCatalog(app.mainWindow);
|
||||
|
||||
await openPlaylistFavorites(app.mainWindow);
|
||||
await expect(channelItemByTitle(app.mainWindow, localAChannelName)).toHaveCount(
|
||||
1
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localBChannelName)).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localAChannelName)
|
||||
).toHaveCount(1);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localBChannelName)
|
||||
).toHaveCount(0);
|
||||
|
||||
await switchPlaylistFromHeader(app.mainWindow, localBDisplayName);
|
||||
await expectPathname(
|
||||
app.mainWindow,
|
||||
/\/workspace\/global-favorites$/
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localBChannelName)).toHaveCount(
|
||||
1
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localAChannelName)).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localBChannelName)
|
||||
).toHaveCount(1);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localAChannelName)
|
||||
).toHaveCount(0);
|
||||
|
||||
await openPlaylistRecent(app.mainWindow);
|
||||
await expect(channelItemByTitle(app.mainWindow, localBChannelName)).toHaveCount(
|
||||
1
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localAChannelName)).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localBChannelName)
|
||||
).toHaveCount(1);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localAChannelName)
|
||||
).toHaveCount(0);
|
||||
|
||||
await switchPlaylistFromHeader(app.mainWindow, localADisplayName);
|
||||
await expectPathname(
|
||||
app.mainWindow,
|
||||
/\/workspace\/global-recent$/
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localAChannelName)).toHaveCount(
|
||||
1
|
||||
);
|
||||
await expect(channelItemByTitle(app.mainWindow, localBChannelName)).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expectPathname(app.mainWindow, /\/workspace\/global-recent$/);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localAChannelName)
|
||||
).toHaveCount(1);
|
||||
await expect(
|
||||
channelItemByTitle(app.mainWindow, localBChannelName)
|
||||
).toHaveCount(0);
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
@@ -319,7 +316,9 @@ test.describe('Electron Playlist Switcher', () => {
|
||||
username: xtreamStressUsername,
|
||||
});
|
||||
|
||||
const overlay = app.mainWindow.locator('.workspace-loading-overlay');
|
||||
const overlay = app.mainWindow.locator(
|
||||
'.workspace-loading-overlay'
|
||||
);
|
||||
await expect(overlay).toBeVisible({ timeout: 15000 });
|
||||
await waitForDbOperationEvent(app.mainWindow, {
|
||||
operation: 'save-content',
|
||||
@@ -428,17 +427,116 @@ test.describe('Electron Playlist Switcher', () => {
|
||||
await switchPlaylistFromHeader(app.mainWindow, offlineXtreamName);
|
||||
await waitForXtreamCatalog(app.mainWindow);
|
||||
await expectXtreamUnavailableWarning(app.mainWindow);
|
||||
await expect(app.mainWindow.locator('.xtream-content-gate')).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expect(
|
||||
app.mainWindow.locator('.xtream-content-gate')
|
||||
).toHaveCount(0);
|
||||
|
||||
app = await restartElectronApp(app, dataDir);
|
||||
|
||||
await waitForXtreamCatalog(app.mainWindow);
|
||||
await expectXtreamUnavailableWarning(app.mainWindow);
|
||||
await expect(app.mainWindow.locator('.xtream-content-gate')).toHaveCount(
|
||||
0
|
||||
await expect(
|
||||
app.mainWindow.locator('.xtream-content-gate')
|
||||
).toHaveCount(0);
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
});
|
||||
|
||||
test('runs from the keyboard: Cmd/Ctrl+P, filter, arrows, Enter and Escape', async ({
|
||||
dataDir,
|
||||
request,
|
||||
}) => {
|
||||
await resetMockServers(request, ['xtream']);
|
||||
const localAPath = writeTemporaryM3uFile(dataDir, localAFileName, [
|
||||
{
|
||||
groupTitle: 'News',
|
||||
name: 'Switcher Local A',
|
||||
url: 'https://streams.example.test/switcher-local-a.m3u8',
|
||||
},
|
||||
]);
|
||||
const localBPath = writeTemporaryM3uFile(dataDir, localBFileName, [
|
||||
{
|
||||
groupTitle: 'Sports',
|
||||
name: 'Switcher Local B',
|
||||
url: 'https://streams.example.test/switcher-local-b.m3u8',
|
||||
},
|
||||
]);
|
||||
const app = await launchElectronApp(dataDir);
|
||||
const page = app.mainWindow;
|
||||
|
||||
try {
|
||||
await importM3uPlaylistFromNativeDialog(app, localAPath);
|
||||
await importM3uPlaylistFromNativeDialog(app, localBPath);
|
||||
await addXtreamPortal(page, { name: xtreamAName });
|
||||
await waitForXtreamCatalog(page);
|
||||
|
||||
const trigger = page.getByTestId('playlist-switcher-trigger');
|
||||
const panel = page.locator('app-playlist-switcher-panel');
|
||||
const search = panel.locator('input[role="combobox"]');
|
||||
await expect(playlistSwitcherTitle(page)).toContainText(
|
||||
xtreamAName
|
||||
);
|
||||
|
||||
await page.keyboard.press('ControlOrMeta+p');
|
||||
await expect(search).toBeFocused();
|
||||
// No list shows a credential: the Xtream row names the account
|
||||
// on purpose, never its password.
|
||||
await expect(panel).not.toContainText(defaultXtreamPassword);
|
||||
await expect(panel).not.toContainText('password=');
|
||||
|
||||
await page.keyboard.type('switcher-local');
|
||||
await expect(switcherOptions(page)).toHaveCount(2);
|
||||
// A search highlights its first match; ↓ moves on, ↑ wraps.
|
||||
const options = switcherOptions(page);
|
||||
const firstId = (await options.nth(0).getAttribute('id')) ?? '';
|
||||
const secondId = (await options.nth(1).getAttribute('id')) ?? '';
|
||||
await expect(search).toHaveAttribute(
|
||||
'aria-activedescendant',
|
||||
firstId
|
||||
);
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(search).toHaveAttribute(
|
||||
'aria-activedescendant',
|
||||
secondId
|
||||
);
|
||||
await page.keyboard.press('ArrowDown');
|
||||
await expect(search).toHaveAttribute(
|
||||
'aria-activedescendant',
|
||||
firstId
|
||||
);
|
||||
await page.keyboard.press('ArrowUp');
|
||||
await expect(search).toHaveAttribute(
|
||||
'aria-activedescendant',
|
||||
secondId
|
||||
);
|
||||
const targetName =
|
||||
(
|
||||
await options
|
||||
.nth(1)
|
||||
.locator('.source-row__name')
|
||||
.textContent()
|
||||
)?.trim() ?? '';
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(panel).toHaveCount(0);
|
||||
await waitForM3uCatalog(page);
|
||||
await expect(playlistSwitcherTitle(page)).toContainText(targetName);
|
||||
|
||||
// Escape closes and puts focus back on the trigger.
|
||||
await page.keyboard.press('ControlOrMeta+p');
|
||||
await expect(search).toBeFocused();
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(panel).toHaveCount(0);
|
||||
await expect(trigger).toBeFocused();
|
||||
|
||||
await openSources(page);
|
||||
await expect(
|
||||
page.locator('app-workspace-sources app-source-row')
|
||||
).toHaveCount(3);
|
||||
await expect(
|
||||
page.locator('app-workspace-sources')
|
||||
).not.toContainText(defaultXtreamPassword);
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
@@ -446,12 +544,12 @@ test.describe('Electron Playlist Switcher', () => {
|
||||
});
|
||||
|
||||
async function openPlaylistSwitcher(page: Page): Promise<void> {
|
||||
await page
|
||||
.locator('app-playlist-switcher .playlist-switcher-trigger')
|
||||
.click();
|
||||
await expect(
|
||||
page.locator('.cdk-overlay-pane .playlist-item').first()
|
||||
).toBeVisible();
|
||||
await page.getByTestId('playlist-switcher-trigger').click();
|
||||
await expect(switcherOptions(page).first()).toBeVisible();
|
||||
}
|
||||
|
||||
function switcherOptions(page: Page) {
|
||||
return page.locator('app-playlist-switcher-panel [role="option"]');
|
||||
}
|
||||
|
||||
async function switchPlaylistFromHeader(
|
||||
@@ -459,16 +557,11 @@ async function switchPlaylistFromHeader(
|
||||
title: string
|
||||
): Promise<void> {
|
||||
await openPlaylistSwitcher(page);
|
||||
const item = page
|
||||
.locator('.cdk-overlay-pane .playlist-item')
|
||||
.filter({ hasText: title })
|
||||
.first();
|
||||
const item = switcherOptions(page).filter({ hasText: title }).first();
|
||||
|
||||
await expect(item).toBeVisible();
|
||||
await item.click();
|
||||
await expect(page.locator('.cdk-overlay-pane .playlist-item')).toHaveCount(
|
||||
0
|
||||
);
|
||||
await expect(page.locator('app-playlist-switcher-panel')).toHaveCount(0);
|
||||
}
|
||||
|
||||
async function expectPathname(page: Page, pattern: RegExp): Promise<void> {
|
||||
@@ -503,16 +596,21 @@ async function selectSettingsOption(
|
||||
}
|
||||
|
||||
async function expectXtreamUnavailableWarning(page: Page): Promise<void> {
|
||||
await expect(
|
||||
page.getByTestId('xtream-offline-warning')
|
||||
).toBeVisible({ timeout: 20000 });
|
||||
await expect(page.getByTestId('xtream-offline-warning')).toBeVisible({
|
||||
timeout: 20000,
|
||||
});
|
||||
}
|
||||
|
||||
async function toggleFavoriteForChannel(page: Page, title: string): Promise<void> {
|
||||
async function toggleFavoriteForChannel(
|
||||
page: Page,
|
||||
title: string
|
||||
): Promise<void> {
|
||||
const item = channelItemByTitle(page, title).first();
|
||||
|
||||
await expect(item).toBeVisible({ timeout: 20000 });
|
||||
await item.hover();
|
||||
await item.locator('.favorite-button').first().click();
|
||||
await expect(item.locator('.favorite-button mat-icon').first()).toHaveText(/star/);
|
||||
await expect(item.locator('.favorite-button mat-icon').first()).toHaveText(
|
||||
/star/
|
||||
);
|
||||
}
|
||||
@@ -175,4 +175,69 @@ test.describe('Electron Sources keyboard', () => {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
});
|
||||
|
||||
test('@m3u @electron deletes from the row menu and undoes from the toast, keyboard only', async ({
|
||||
dataDir,
|
||||
}) => {
|
||||
const alpha = writeTemporaryM3uFile(dataDir, 'undo-alpha.m3u', [
|
||||
{
|
||||
groupTitle: 'News',
|
||||
name: 'Undo Alpha News',
|
||||
url: 'https://streams.example.test/undo-alpha.m3u8',
|
||||
},
|
||||
]);
|
||||
const bravo = writeTemporaryM3uFile(dataDir, 'undo-bravo.m3u', [
|
||||
{
|
||||
groupTitle: 'Sports',
|
||||
name: 'Undo Bravo Sports',
|
||||
url: 'https://streams.example.test/undo-bravo.m3u8',
|
||||
},
|
||||
]);
|
||||
const app = await launchElectronApp(dataDir, {
|
||||
appArgs: [alpha, bravo],
|
||||
});
|
||||
const page = app.mainWindow;
|
||||
const rows = page.locator('app-workspace-sources app-source-row');
|
||||
|
||||
try {
|
||||
await page.waitForURL(/\/workspace\/playlists\/.+/, {
|
||||
timeout: 30_000,
|
||||
});
|
||||
await openSources(page);
|
||||
await expect(rows).toHaveCount(2, { timeout: 30_000 });
|
||||
const before = await rows
|
||||
.locator('.source-row__name')
|
||||
.allTextContents();
|
||||
|
||||
// Focus the first row's ⋯ and open its menu from the keyboard.
|
||||
const row = rows.first();
|
||||
await row.locator('.source-row__more').focus();
|
||||
await page.keyboard.press('Enter');
|
||||
const remove = page.getByRole('menuitem', {
|
||||
name: 'Remove playlist',
|
||||
});
|
||||
await expect(remove).toBeVisible();
|
||||
await page.keyboard.press('End');
|
||||
await expect(remove).toBeFocused();
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
// The row leaves at once; Undo takes the focus the row had.
|
||||
await expect(rows).toHaveCount(1);
|
||||
const undo = page.locator(
|
||||
'mat-snack-bar-container.app-toast .source-removal-toast__undo'
|
||||
);
|
||||
await expect(undo).toBeFocused();
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await expect(rows).toHaveCount(2);
|
||||
expect(
|
||||
await rows.locator('.source-row__name').allTextContents()
|
||||
).toEqual(before);
|
||||
await expect(
|
||||
page.locator('mat-snack-bar-container.app-toast')
|
||||
).toHaveCount(0);
|
||||
} finally {
|
||||
await closeElectronApp(app);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -785,11 +785,20 @@ https://streams.example.test/original-url.m3u8
|
||||
try {
|
||||
await dropM3uPlaylistOntoWorkspace(app.mainWindow, localFilePath);
|
||||
await waitForM3uCatalog(app.mainWindow);
|
||||
// Refresh for the active source lives in its switcher row menu.
|
||||
await app.mainWindow.getByTestId('playlist-switcher-trigger').click();
|
||||
const currentRow = app.mainWindow.locator(
|
||||
'app-playlist-switcher-panel [role="option"][aria-current="true"]'
|
||||
);
|
||||
await currentRow.locator('.source-row__more').click();
|
||||
await expect(
|
||||
app.mainWindow.locator(
|
||||
'app-playlist-switcher .trigger-refresh-button'
|
||||
)
|
||||
app.mainWindow.getByRole('menuitem', { name: 'Refresh playlist' })
|
||||
).toBeVisible();
|
||||
await app.mainWindow.keyboard.press('Escape');
|
||||
await app.mainWindow.keyboard.press('Escape');
|
||||
await expect(
|
||||
app.mainWindow.locator('app-playlist-switcher-panel')
|
||||
).toHaveCount(0);
|
||||
|
||||
await goToDashboard(app.mainWindow);
|
||||
const sourceCard = app.mainWindow
|
||||
|
||||
@@ -80,7 +80,7 @@ export async function importPlaylist(page: Page): Promise<string> {
|
||||
.getByRole('button', { name: 'Add playlist', exact: true })
|
||||
.click(),
|
||||
]);
|
||||
await expect(page.getByText('1 channels')).toBeVisible();
|
||||
await expect(page.getByText('1 channel', { exact: false })).toBeVisible();
|
||||
return page.url();
|
||||
}
|
||||
|
||||
|
||||
@@ -182,12 +182,15 @@ test('@stalker account info dialog shows subscription facts from the portal', as
|
||||
}) => {
|
||||
await addStalkerPortal(page);
|
||||
|
||||
// Open the header playlist switcher and its "Account info" entry for
|
||||
// the active stalker portal.
|
||||
await page.locator('.playlist-switcher-trigger').click();
|
||||
// Open the header playlist switcher and the "Account info" entry in the
|
||||
// active stalker portal's row menu.
|
||||
await page.locator('[data-test-id="playlist-switcher-trigger"]').click();
|
||||
await page
|
||||
.locator('.context-action-item', { hasText: 'Account info' })
|
||||
.locator(
|
||||
'app-playlist-switcher-panel [role="option"][aria-current="true"] .source-row__more'
|
||||
)
|
||||
.click();
|
||||
await page.getByRole('menuitem', { name: 'Account info' }).click();
|
||||
|
||||
const dialog = page.locator('mat-dialog-container');
|
||||
await expect(dialog).toBeVisible();
|
||||
|
||||
@@ -61,18 +61,15 @@ async function openPlaylistDetailsDialog(page: Page, title: string) {
|
||||
await playlistSettingsButton.click();
|
||||
} else {
|
||||
await page
|
||||
.locator('app-playlist-switcher .playlist-switcher-trigger')
|
||||
.locator('[data-test-id="playlist-switcher-trigger"]')
|
||||
.click();
|
||||
|
||||
const switcherMenu = page.getByRole('menu').filter({ hasText: title });
|
||||
const sourceRow = switcherMenu
|
||||
.locator('.playlist-item')
|
||||
const sourceRow = page
|
||||
.locator('app-playlist-switcher-panel [role="option"]')
|
||||
.filter({ hasText: title })
|
||||
.first();
|
||||
await expect(sourceRow).toBeVisible();
|
||||
await sourceRow
|
||||
.getByRole('button', { name: 'Playlist actions' })
|
||||
.click();
|
||||
await sourceRow.locator('.source-row__more').click();
|
||||
await page.getByRole('menuitem', { name: 'Playlist info' }).click();
|
||||
}
|
||||
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "منتهي",
|
||||
"EDIT": "تعديل…",
|
||||
"COPY_URL": "نسخ الرابط",
|
||||
"OPEN": "فتح"
|
||||
"OPEN": "فتح",
|
||||
"CHANNELS_ONE": "قناة واحدة"
|
||||
},
|
||||
"STATUS": "الحالة",
|
||||
"STATUS_ANY": "أي حالة",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "إعادة تعيين عوامل التصفية",
|
||||
"REMOVED": "تمت إزالة «{{name}}»",
|
||||
"REMOVED_SWITCHED": "تمت إزالة «{{name}}»، والانتقال إلى «{{next}}»",
|
||||
"REMOVE_FAILED": "تعذّرت إزالة «{{name}}»"
|
||||
"REMOVE_FAILED": "تعذّرت إزالة «{{name}}»",
|
||||
"ADD_SOURCE": "إضافة مصدر"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "الفئات",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "أضف قائمة تشغيل وسيظهر سجل المشاهدة هنا.",
|
||||
"NO_ITEMS_TITLE": "لا توجد مشاهدات بعد",
|
||||
"NO_ITEMS_BODY": "ابدأ بمشاهدة أي محتوى من مكتبتك وسيظهر هنا."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "ابحث عن قائمة تشغيل…",
|
||||
"RECENT": "الأخيرة",
|
||||
"NO_MATCHES": "لم يُعثر على شيء",
|
||||
"ALL_SOURCES": "كل المصادر",
|
||||
"HINT_SELECT": "تحديد",
|
||||
"HINT_OPEN": "فتح",
|
||||
"HINT_CLOSE": "إغلاق"
|
||||
}
|
||||
},
|
||||
"LOADING": "جارٍ التحميل",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "سالات",
|
||||
"EDIT": "بدّل…",
|
||||
"COPY_URL": "نسخ الرابط",
|
||||
"OPEN": "حلّ"
|
||||
"OPEN": "حلّ",
|
||||
"CHANNELS_ONE": "قناة وحدة"
|
||||
},
|
||||
"STATUS": "الحالة",
|
||||
"STATUS_ANY": "أي حالة",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "رجّع الفلاتر",
|
||||
"REMOVED": "تحيّدات «{{name}}»",
|
||||
"REMOVED_SWITCHED": "تحيّدات «{{name}}»، دوّزنا لـ «{{next}}»",
|
||||
"REMOVE_FAILED": "ما قدرناش نحيّدو «{{name}}»"
|
||||
"REMOVE_FAILED": "ما قدرناش نحيّدو «{{name}}»",
|
||||
"ADD_SOURCE": "زيد مصدر"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "الفئات",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "زيد قائمة تشغيل وسجل التفرج ديالك غادي يبان هنا.",
|
||||
"NO_ITEMS_TITLE": "ما تشاف حتى شي حاجة دابا",
|
||||
"NO_ITEMS_BODY": "بدا تفرج فشي حاجة من المكتبة ديالك وغادي تبان هنا."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "قلّب على ليستة…",
|
||||
"RECENT": "الجداد",
|
||||
"NO_MATCHES": "ما لقينا والو",
|
||||
"ALL_SOURCES": "كاع المصادر",
|
||||
"HINT_SELECT": "ختار",
|
||||
"HINT_OPEN": "حلّ",
|
||||
"HINT_CLOSE": "سدّ"
|
||||
}
|
||||
},
|
||||
"LOADING": "كيتشارجا",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Скончыўся",
|
||||
"EDIT": "Змяніць…",
|
||||
"COPY_URL": "Скапіяваць URL",
|
||||
"OPEN": "Адкрыць"
|
||||
"OPEN": "Адкрыць",
|
||||
"CHANNELS_ONE": "1 канал"
|
||||
},
|
||||
"STATUS": "Статус",
|
||||
"STATUS_ANY": "Любы",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Скінуць фільтры",
|
||||
"REMOVED": "Выдалены «{{name}}»",
|
||||
"REMOVED_SWITCHED": "Выдалены «{{name}}», адкрыты «{{next}}»",
|
||||
"REMOVE_FAILED": "Не ўдалося выдаліць «{{name}}»"
|
||||
"REMOVE_FAILED": "Не ўдалося выдаліць «{{name}}»",
|
||||
"ADD_SOURCE": "Дадаць крыніцу"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Катэгорыі",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Дадайце плэйліст, і гісторыя прагляду з’явіцца тут.",
|
||||
"NO_ITEMS_TITLE": "Праглядаў пакуль няма",
|
||||
"NO_ITEMS_BODY": "Пачніце глядзець што-небудзь з бібліятэкі, і гэта з’явіцца тут."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Знайсці плэйліст…",
|
||||
"RECENT": "Нядаўнія",
|
||||
"NO_MATCHES": "Нічога не знойдзена",
|
||||
"ALL_SOURCES": "Усе крыніцы",
|
||||
"HINT_SELECT": "выбар",
|
||||
"HINT_OPEN": "адкрыць",
|
||||
"HINT_CLOSE": "закрыць"
|
||||
}
|
||||
},
|
||||
"LOADING": "Загрузка",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Abgelaufen",
|
||||
"EDIT": "Bearbeiten…",
|
||||
"COPY_URL": "URL kopieren",
|
||||
"OPEN": "Öffnen"
|
||||
"OPEN": "Öffnen",
|
||||
"CHANNELS_ONE": "1 Sender"
|
||||
},
|
||||
"STATUS": "Status (Erreichbarkeit)",
|
||||
"STATUS_ANY": "Alle",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Filter zurücksetzen",
|
||||
"REMOVED": "„{{name}}“ entfernt",
|
||||
"REMOVED_SWITCHED": "„{{name}}“ entfernt, zu „{{next}}“ gewechselt",
|
||||
"REMOVE_FAILED": "„{{name}}“ konnte nicht entfernt werden"
|
||||
"REMOVE_FAILED": "„{{name}}“ konnte nicht entfernt werden",
|
||||
"ADD_SOURCE": "Quelle hinzufügen"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Kategorien",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Füge eine Wiedergabeliste hinzu, und dein Wiedergabeverlauf erscheint hier.",
|
||||
"NO_ITEMS_TITLE": "Noch nichts angesehen",
|
||||
"NO_ITEMS_BODY": "Beginne, etwas aus deiner Bibliothek anzusehen, dann erscheint es hier."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Playlist suchen…",
|
||||
"RECENT": "Zuletzt geöffnet",
|
||||
"NO_MATCHES": "Nichts gefunden",
|
||||
"ALL_SOURCES": "Alle Quellen",
|
||||
"HINT_SELECT": "auswählen",
|
||||
"HINT_OPEN": "öffnen",
|
||||
"HINT_CLOSE": "schließen"
|
||||
}
|
||||
},
|
||||
"LOADING": "Laden",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Έληξε",
|
||||
"EDIT": "Επεξεργασία…",
|
||||
"COPY_URL": "Αντιγραφή URL",
|
||||
"OPEN": "Άνοιγμα"
|
||||
"OPEN": "Άνοιγμα",
|
||||
"CHANNELS_ONE": "1 κανάλι"
|
||||
},
|
||||
"STATUS": "Κατάσταση",
|
||||
"STATUS_ANY": "Οποιαδήποτε",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Επαναφορά φίλτρων",
|
||||
"REMOVED": "Καταργήθηκε το «{{name}}»",
|
||||
"REMOVED_SWITCHED": "Καταργήθηκε το «{{name}}», μετάβαση στο «{{next}}»",
|
||||
"REMOVE_FAILED": "Δεν ήταν δυνατή η κατάργηση του «{{name}}»"
|
||||
"REMOVE_FAILED": "Δεν ήταν δυνατή η κατάργηση του «{{name}}»",
|
||||
"ADD_SOURCE": "Προσθήκη πηγής"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Κατηγορίες",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Προσθέστε μια λίστα αναπαραγωγής και το ιστορικό προβολής σας θα εμφανιστεί εδώ.",
|
||||
"NO_ITEMS_TITLE": "Δεν έχει παρακολουθηθεί τίποτα ακόμη",
|
||||
"NO_ITEMS_BODY": "Ξεκινήστε να παρακολουθείτε οτιδήποτε από τη βιβλιοθήκη σας και θα εμφανιστεί εδώ."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Εύρεση λίστας…",
|
||||
"RECENT": "Πρόσφατα",
|
||||
"NO_MATCHES": "Δεν βρέθηκε τίποτα",
|
||||
"ALL_SOURCES": "Όλες οι πηγές",
|
||||
"HINT_SELECT": "επιλογή",
|
||||
"HINT_OPEN": "άνοιγμα",
|
||||
"HINT_CLOSE": "κλείσιμο"
|
||||
}
|
||||
},
|
||||
"LOADING": "Φόρτωση",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Expired",
|
||||
"EDIT": "Edit…",
|
||||
"COPY_URL": "Copy URL",
|
||||
"OPEN": "Open"
|
||||
"OPEN": "Open",
|
||||
"CHANNELS_ONE": "1 channel"
|
||||
},
|
||||
"STATUS": "Status",
|
||||
"STATUS_ANY": "Any",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Reset filters",
|
||||
"REMOVED": "Removed “{{name}}”",
|
||||
"REMOVED_SWITCHED": "Removed “{{name}}”, switched to “{{next}}”",
|
||||
"REMOVE_FAILED": "Could not remove “{{name}}”"
|
||||
"REMOVE_FAILED": "Could not remove “{{name}}”",
|
||||
"ADD_SOURCE": "Add a source"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Categories",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Add a playlist and your watching history will appear here.",
|
||||
"NO_ITEMS_TITLE": "Nothing watched yet",
|
||||
"NO_ITEMS_BODY": "Start watching anything from your library and it will show up here."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Find a playlist…",
|
||||
"RECENT": "Recent",
|
||||
"NO_MATCHES": "Nothing found",
|
||||
"ALL_SOURCES": "All sources",
|
||||
"HINT_SELECT": "select",
|
||||
"HINT_OPEN": "open",
|
||||
"HINT_CLOSE": "close"
|
||||
}
|
||||
},
|
||||
"LOADING": "Loading",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Caducada",
|
||||
"EDIT": "Editar…",
|
||||
"COPY_URL": "Copiar URL",
|
||||
"OPEN": "Abrir"
|
||||
"OPEN": "Abrir",
|
||||
"CHANNELS_ONE": "1 canal"
|
||||
},
|
||||
"STATUS": "Estado",
|
||||
"STATUS_ANY": "Cualquiera",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Restablecer filtros",
|
||||
"REMOVED": "Se eliminó «{{name}}»",
|
||||
"REMOVED_SWITCHED": "Se eliminó «{{name}}» y se cambió a «{{next}}»",
|
||||
"REMOVE_FAILED": "No se pudo eliminar «{{name}}»"
|
||||
"REMOVE_FAILED": "No se pudo eliminar «{{name}}»",
|
||||
"ADD_SOURCE": "Añadir una fuente"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Categorías",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Añade una lista de reproducción y tu historial de visualización aparecerá aquí.",
|
||||
"NO_ITEMS_TITLE": "Aún no has visto nada",
|
||||
"NO_ITEMS_BODY": "Empieza a ver cualquier contenido de tu biblioteca y aparecerá aquí."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Buscar una lista…",
|
||||
"RECENT": "Recientes",
|
||||
"NO_MATCHES": "No se encontró nada",
|
||||
"ALL_SOURCES": "Todas las fuentes",
|
||||
"HINT_SELECT": "elegir",
|
||||
"HINT_OPEN": "abrir",
|
||||
"HINT_CLOSE": "cerrar"
|
||||
}
|
||||
},
|
||||
"LOADING": "Cargando",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Expiré",
|
||||
"EDIT": "Modifier…",
|
||||
"COPY_URL": "Copier l’URL",
|
||||
"OPEN": "Ouvrir"
|
||||
"OPEN": "Ouvrir",
|
||||
"CHANNELS_ONE": "1 chaîne"
|
||||
},
|
||||
"STATUS": "État",
|
||||
"STATUS_ANY": "Tous",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Réinitialiser les filtres",
|
||||
"REMOVED": "« {{name}} » supprimée",
|
||||
"REMOVED_SWITCHED": "« {{name}} » supprimée, passage à « {{next}} »",
|
||||
"REMOVE_FAILED": "Impossible de supprimer « {{name}} »"
|
||||
"REMOVE_FAILED": "Impossible de supprimer « {{name}} »",
|
||||
"ADD_SOURCE": "Ajouter une source"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Catégories",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Ajoutez une playlist et votre historique de visionnage apparaîtra ici.",
|
||||
"NO_ITEMS_TITLE": "Rien regardé pour le moment",
|
||||
"NO_ITEMS_BODY": "Commencez à regarder un contenu de votre bibliothèque et il apparaîtra ici."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Trouver une playlist…",
|
||||
"RECENT": "Récentes",
|
||||
"NO_MATCHES": "Aucun résultat",
|
||||
"ALL_SOURCES": "Toutes les sources",
|
||||
"HINT_SELECT": "choisir",
|
||||
"HINT_OPEN": "ouvrir",
|
||||
"HINT_CLOSE": "fermer"
|
||||
}
|
||||
},
|
||||
"LOADING": "Chargement",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Lejárt",
|
||||
"EDIT": "Szerkesztés…",
|
||||
"COPY_URL": "URL másolása",
|
||||
"OPEN": "Megnyitás"
|
||||
"OPEN": "Megnyitás",
|
||||
"CHANNELS_ONE": "1 csatorna"
|
||||
},
|
||||
"STATUS": "Állapot",
|
||||
"STATUS_ANY": "Bármelyik",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Szűrők törlése",
|
||||
"REMOVED": "„{{name}}” eltávolítva",
|
||||
"REMOVED_SWITCHED": "„{{name}}” eltávolítva, váltás erre: „{{next}}”",
|
||||
"REMOVE_FAILED": "„{{name}}” nem távolítható el"
|
||||
"REMOVE_FAILED": "„{{name}}” nem távolítható el",
|
||||
"ADD_SOURCE": "Forrás hozzáadása"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Kategóriák",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Adjon hozzá egy lejátszási listát, és megtekintési előzményei itt fognak megjelenni.",
|
||||
"NO_ITEMS_TITLE": "Még nincs megtekintett tartalom",
|
||||
"NO_ITEMS_BODY": "Indítson el bármit a médiatárából, és itt meg fog jelenni."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Lejátszási lista keresése…",
|
||||
"RECENT": "Legutóbbiak",
|
||||
"NO_MATCHES": "Nincs találat",
|
||||
"ALL_SOURCES": "Összes forrás",
|
||||
"HINT_SELECT": "kijelölés",
|
||||
"HINT_OPEN": "megnyitás",
|
||||
"HINT_CLOSE": "bezárás"
|
||||
}
|
||||
},
|
||||
"LOADING": "Betöltés",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Scaduto",
|
||||
"EDIT": "Modifica…",
|
||||
"COPY_URL": "Copia URL",
|
||||
"OPEN": "Apri"
|
||||
"OPEN": "Apri",
|
||||
"CHANNELS_ONE": "1 canale"
|
||||
},
|
||||
"STATUS": "Stato",
|
||||
"STATUS_ANY": "Qualsiasi",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Reimposta filtri",
|
||||
"REMOVED": "«{{name}}» rimossa",
|
||||
"REMOVED_SWITCHED": "«{{name}}» rimossa, passaggio a «{{next}}»",
|
||||
"REMOVE_FAILED": "Impossibile rimuovere «{{name}}»"
|
||||
"REMOVE_FAILED": "Impossibile rimuovere «{{name}}»",
|
||||
"ADD_SOURCE": "Aggiungi una fonte"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Categorie",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Aggiungi una playlist e la tua cronologia di visione apparirà qui.",
|
||||
"NO_ITEMS_TITLE": "Ancora nessun contenuto guardato",
|
||||
"NO_ITEMS_BODY": "Inizia a guardare qualsiasi contenuto della tua libreria e apparirà qui."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Trova una playlist…",
|
||||
"RECENT": "Recenti",
|
||||
"NO_MATCHES": "Nessun risultato",
|
||||
"ALL_SOURCES": "Tutte le fonti",
|
||||
"HINT_SELECT": "scegli",
|
||||
"HINT_OPEN": "apri",
|
||||
"HINT_CLOSE": "chiudi"
|
||||
}
|
||||
},
|
||||
"LOADING": "Caricamento",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "期限切れ",
|
||||
"EDIT": "編集…",
|
||||
"COPY_URL": "URLをコピー",
|
||||
"OPEN": "開く"
|
||||
"OPEN": "開く",
|
||||
"CHANNELS_ONE": "1 チャンネル"
|
||||
},
|
||||
"STATUS": "状態",
|
||||
"STATUS_ANY": "すべて",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "フィルターをリセット",
|
||||
"REMOVED": "「{{name}}」を削除しました",
|
||||
"REMOVED_SWITCHED": "「{{name}}」を削除し、「{{next}}」に切り替えました",
|
||||
"REMOVE_FAILED": "「{{name}}」を削除できませんでした"
|
||||
"REMOVE_FAILED": "「{{name}}」を削除できませんでした",
|
||||
"ADD_SOURCE": "ソースを追加"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "カテゴリー",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "プレイリストを追加すると、視聴履歴がここに表示されます。",
|
||||
"NO_ITEMS_TITLE": "視聴履歴はまだありません",
|
||||
"NO_ITEMS_BODY": "ライブラリ内のコンテンツを視聴し始めると、ここに表示されます。"
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "プレイリストを検索…",
|
||||
"RECENT": "最近",
|
||||
"NO_MATCHES": "見つかりませんでした",
|
||||
"ALL_SOURCES": "すべてのソース",
|
||||
"HINT_SELECT": "選択",
|
||||
"HINT_OPEN": "開く",
|
||||
"HINT_CLOSE": "閉じる"
|
||||
}
|
||||
},
|
||||
"LOADING": "読み込み中",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "만료됨",
|
||||
"EDIT": "편집…",
|
||||
"COPY_URL": "URL 복사",
|
||||
"OPEN": "열기"
|
||||
"OPEN": "열기",
|
||||
"CHANNELS_ONE": "채널 1개"
|
||||
},
|
||||
"STATUS": "상태",
|
||||
"STATUS_ANY": "전체",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "필터 초기화",
|
||||
"REMOVED": "'{{name}}' 삭제됨",
|
||||
"REMOVED_SWITCHED": "'{{name}}' 삭제됨, '{{next}}'(으)로 전환됨",
|
||||
"REMOVE_FAILED": "'{{name}}'을(를) 삭제할 수 없습니다"
|
||||
"REMOVE_FAILED": "'{{name}}'을(를) 삭제할 수 없습니다",
|
||||
"ADD_SOURCE": "소스 추가"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "카테고리",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "플레이리스트를 추가하면 시청 기록이 여기에 표시됩니다.",
|
||||
"NO_ITEMS_TITLE": "아직 시청 기록이 없습니다",
|
||||
"NO_ITEMS_BODY": "라이브러리의 콘텐츠를 시청하기 시작하면 여기에 표시됩니다."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "재생목록 찾기…",
|
||||
"RECENT": "최근",
|
||||
"NO_MATCHES": "찾은 항목 없음",
|
||||
"ALL_SOURCES": "모든 소스",
|
||||
"HINT_SELECT": "선택",
|
||||
"HINT_OPEN": "열기",
|
||||
"HINT_CLOSE": "닫기"
|
||||
}
|
||||
},
|
||||
"LOADING": "로드 중",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Verlopen",
|
||||
"EDIT": "Bewerken…",
|
||||
"COPY_URL": "URL kopiëren",
|
||||
"OPEN": "Openen"
|
||||
"OPEN": "Openen",
|
||||
"CHANNELS_ONE": "1 zender"
|
||||
},
|
||||
"STATUS": "Bereikbaarheid",
|
||||
"STATUS_ANY": "Alle",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Filters wissen",
|
||||
"REMOVED": "‘{{name}}’ verwijderd",
|
||||
"REMOVED_SWITCHED": "‘{{name}}’ verwijderd, overgeschakeld naar ‘{{next}}’",
|
||||
"REMOVE_FAILED": "‘{{name}}’ kon niet worden verwijderd"
|
||||
"REMOVE_FAILED": "‘{{name}}’ kon niet worden verwijderd",
|
||||
"ADD_SOURCE": "Bron toevoegen"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Categorieën",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Voeg een afspeellijst toe en uw kijkgeschiedenis verschijnt hier.",
|
||||
"NO_ITEMS_TITLE": "Nog niets bekeken",
|
||||
"NO_ITEMS_BODY": "Begin iets uit uw bibliotheek te kijken en het verschijnt hier."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Afspeellijst zoeken…",
|
||||
"RECENT": "Onlangs geopend",
|
||||
"NO_MATCHES": "Niets gevonden",
|
||||
"ALL_SOURCES": "Alle bronnen",
|
||||
"HINT_SELECT": "kiezen",
|
||||
"HINT_OPEN": "openen",
|
||||
"HINT_CLOSE": "sluiten"
|
||||
}
|
||||
},
|
||||
"LOADING": "Laden",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Wygasło",
|
||||
"EDIT": "Edytuj…",
|
||||
"COPY_URL": "Kopiuj URL",
|
||||
"OPEN": "Otwórz"
|
||||
"OPEN": "Otwórz",
|
||||
"CHANNELS_ONE": "1 kanał"
|
||||
},
|
||||
"STATUS": "Stan",
|
||||
"STATUS_ANY": "Dowolny",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Wyczyść filtry",
|
||||
"REMOVED": "Usunięto „{{name}}”",
|
||||
"REMOVED_SWITCHED": "Usunięto „{{name}}”, przełączono na „{{next}}”",
|
||||
"REMOVE_FAILED": "Nie udało się usunąć „{{name}}”"
|
||||
"REMOVE_FAILED": "Nie udało się usunąć „{{name}}”",
|
||||
"ADD_SOURCE": "Dodaj źródło"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Kategorie",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Dodaj listę odtwarzania, a historia oglądania pojawi się tutaj.",
|
||||
"NO_ITEMS_TITLE": "Jeszcze nic nie oglądano",
|
||||
"NO_ITEMS_BODY": "Zacznij oglądać cokolwiek ze swojej biblioteki, a pojawi się tutaj."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Znajdź playlistę…",
|
||||
"RECENT": "Ostatnie",
|
||||
"NO_MATCHES": "Nic nie znaleziono",
|
||||
"ALL_SOURCES": "Wszystkie źródła",
|
||||
"HINT_SELECT": "wybór",
|
||||
"HINT_OPEN": "otwórz",
|
||||
"HINT_CLOSE": "zamknij"
|
||||
}
|
||||
},
|
||||
"LOADING": "Ładowanie",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Expirada",
|
||||
"EDIT": "Editar…",
|
||||
"COPY_URL": "Copiar URL",
|
||||
"OPEN": "Abrir"
|
||||
"OPEN": "Abrir",
|
||||
"CHANNELS_ONE": "1 canal"
|
||||
},
|
||||
"STATUS": "Estado",
|
||||
"STATUS_ANY": "Qualquer",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Repor filtros",
|
||||
"REMOVED": "«{{name}}» removida",
|
||||
"REMOVED_SWITCHED": "«{{name}}» removida, mudou para «{{next}}»",
|
||||
"REMOVE_FAILED": "Não foi possível remover «{{name}}»"
|
||||
"REMOVE_FAILED": "Não foi possível remover «{{name}}»",
|
||||
"ADD_SOURCE": "Adicionar uma fonte"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Categorias",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Adicione uma playlist e seu histórico de visualização aparecerá aqui.",
|
||||
"NO_ITEMS_TITLE": "Nada assistido ainda",
|
||||
"NO_ITEMS_BODY": "Comece a assistir qualquer item da sua biblioteca e ele aparecerá aqui."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Procurar uma lista…",
|
||||
"RECENT": "Recentes",
|
||||
"NO_MATCHES": "Nada encontrado",
|
||||
"ALL_SOURCES": "Todas as fontes",
|
||||
"HINT_SELECT": "escolher",
|
||||
"HINT_OPEN": "abrir",
|
||||
"HINT_CLOSE": "fechar"
|
||||
}
|
||||
},
|
||||
"LOADING": "A carregar",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Истёк",
|
||||
"EDIT": "Изменить…",
|
||||
"COPY_URL": "Копировать URL",
|
||||
"OPEN": "Открыть"
|
||||
"OPEN": "Открыть",
|
||||
"CHANNELS_ONE": "1 канал"
|
||||
},
|
||||
"STATUS": "Статус",
|
||||
"STATUS_ANY": "Любой",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Сбросить фильтры",
|
||||
"REMOVED": "Удалён «{{name}}»",
|
||||
"REMOVED_SWITCHED": "Удалён «{{name}}», открыт «{{next}}»",
|
||||
"REMOVE_FAILED": "Не удалось удалить «{{name}}»"
|
||||
"REMOVE_FAILED": "Не удалось удалить «{{name}}»",
|
||||
"ADD_SOURCE": "Добавить источник"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Категории",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Добавьте плейлист, и история просмотра появится здесь.",
|
||||
"NO_ITEMS_TITLE": "Пока ничего не просмотрено",
|
||||
"NO_ITEMS_BODY": "Начните смотреть любой контент из библиотеки, и он появится здесь."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Найти плейлист…",
|
||||
"RECENT": "Недавние",
|
||||
"NO_MATCHES": "Ничего не найдено",
|
||||
"ALL_SOURCES": "Все источники",
|
||||
"HINT_SELECT": "выбор",
|
||||
"HINT_OPEN": "открыть",
|
||||
"HINT_CLOSE": "закрыть"
|
||||
}
|
||||
},
|
||||
"LOADING": "Загрузка",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "Süresi doldu",
|
||||
"EDIT": "Düzenle…",
|
||||
"COPY_URL": "URL'yi kopyala",
|
||||
"OPEN": "Aç"
|
||||
"OPEN": "Aç",
|
||||
"CHANNELS_ONE": "1 kanal"
|
||||
},
|
||||
"STATUS": "Durum",
|
||||
"STATUS_ANY": "Tümü",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "Filtreleri sıfırla",
|
||||
"REMOVED": "“{{name}}” kaldırıldı",
|
||||
"REMOVED_SWITCHED": "“{{name}}” kaldırıldı, “{{next}}” açıldı",
|
||||
"REMOVE_FAILED": "“{{name}}” kaldırılamadı"
|
||||
"REMOVE_FAILED": "“{{name}}” kaldırılamadı",
|
||||
"ADD_SOURCE": "Kaynak ekle"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "Kategoriler",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "Bir oynatma listesi ekleyin; izleme geçmişiniz burada görünecek.",
|
||||
"NO_ITEMS_TITLE": "Henüz hiçbir şey izlenmedi",
|
||||
"NO_ITEMS_BODY": "Kitaplığınızdaki herhangi bir şeyi izlemeye başlayın, burada görünecek."
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "Oynatma listesi bul…",
|
||||
"RECENT": "Son açılanlar",
|
||||
"NO_MATCHES": "Hiçbir şey bulunamadı",
|
||||
"ALL_SOURCES": "Tüm kaynaklar",
|
||||
"HINT_SELECT": "seç",
|
||||
"HINT_OPEN": "aç",
|
||||
"HINT_CLOSE": "kapat"
|
||||
}
|
||||
},
|
||||
"LOADING": "Yükleniyor",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "已过期",
|
||||
"EDIT": "编辑…",
|
||||
"COPY_URL": "复制 URL",
|
||||
"OPEN": "打开"
|
||||
"OPEN": "打开",
|
||||
"CHANNELS_ONE": "1 个频道"
|
||||
},
|
||||
"STATUS": "状态",
|
||||
"STATUS_ANY": "全部",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "重置筛选",
|
||||
"REMOVED": "已删除“{{name}}”",
|
||||
"REMOVED_SWITCHED": "已删除“{{name}}”,已切换到“{{next}}”",
|
||||
"REMOVE_FAILED": "无法删除“{{name}}”"
|
||||
"REMOVE_FAILED": "无法删除“{{name}}”",
|
||||
"ADD_SOURCE": "添加来源"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "分类",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "添加播放列表后,您的观看历史会显示在这里。",
|
||||
"NO_ITEMS_TITLE": "还没有观看记录",
|
||||
"NO_ITEMS_BODY": "开始观看媒体库中的任意内容后,它会显示在这里。"
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "查找播放列表…",
|
||||
"RECENT": "最近",
|
||||
"NO_MATCHES": "未找到",
|
||||
"ALL_SOURCES": "所有来源",
|
||||
"HINT_SELECT": "选择",
|
||||
"HINT_OPEN": "打开",
|
||||
"HINT_CLOSE": "关闭"
|
||||
}
|
||||
},
|
||||
"LOADING": "加载中",
|
||||
|
||||
@@ -1917,7 +1917,8 @@
|
||||
"EXPIRED": "已過期",
|
||||
"EDIT": "編輯…",
|
||||
"COPY_URL": "複製 URL",
|
||||
"OPEN": "開啟"
|
||||
"OPEN": "開啟",
|
||||
"CHANNELS_ONE": "1 個頻道"
|
||||
},
|
||||
"STATUS": "狀態",
|
||||
"STATUS_ANY": "全部",
|
||||
@@ -1927,7 +1928,8 @@
|
||||
"RESET_FILTERS": "重設篩選",
|
||||
"REMOVED": "已移除「{{name}}」",
|
||||
"REMOVED_SWITCHED": "已移除「{{name}}」,已切換到「{{next}}」",
|
||||
"REMOVE_FAILED": "無法移除「{{name}}」"
|
||||
"REMOVE_FAILED": "無法移除「{{name}}」",
|
||||
"ADD_SOURCE": "新增來源"
|
||||
},
|
||||
"CONTEXT": {
|
||||
"CATEGORIES": "類別",
|
||||
@@ -2020,6 +2022,15 @@
|
||||
"NO_PLAYLISTS_BODY": "新增播放清單後,您的觀看歷史會顯示在這裡。",
|
||||
"NO_ITEMS_TITLE": "還沒有觀看記錄",
|
||||
"NO_ITEMS_BODY": "開始觀看媒體庫中的任意內容後,它會顯示在這裡。"
|
||||
},
|
||||
"SWITCHER": {
|
||||
"SEARCH": "尋找播放清單…",
|
||||
"RECENT": "最近",
|
||||
"NO_MATCHES": "找不到",
|
||||
"ALL_SOURCES": "所有來源",
|
||||
"HINT_SELECT": "選擇",
|
||||
"HINT_OPEN": "開啟",
|
||||
"HINT_CLOSE": "關閉"
|
||||
}
|
||||
},
|
||||
"LOADING": "載入中",
|
||||
|
||||
Reference in new issue
Block a user