forked from Archives/Athou_commafeed
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fe1c2a3c0 | ||
|
|
c2e453027c | ||
|
|
f16bac9b59 | ||
|
|
8cca826e70 | ||
|
|
b0165bb26a | ||
|
|
366294ab46 | ||
|
|
2988938440 | ||
|
|
e865769e30 | ||
|
|
f87be2fc03 | ||
|
|
466846d268 | ||
|
|
61b6be4090 | ||
|
|
cb779ec494 | ||
|
|
da6f2050f9 | ||
|
|
4304f84a55 | ||
|
|
8a175d8221 | ||
|
|
f1896d34e2 | ||
|
|
45d0e0ec98 | ||
|
|
38c5beec2f | ||
|
|
c4715dc3f7 | ||
|
|
6ce6b5ef0e | ||
|
|
1af3dd452c | ||
|
|
1f4ec41222 | ||
|
|
512c4cc507 | ||
|
|
d391c8f1c9 | ||
|
|
46d3e67aec | ||
|
|
d9505c4d87 | ||
|
|
42491f5778 | ||
|
|
9c897c9fb2 | ||
|
|
21b500a96e | ||
|
|
04c74b5daa | ||
|
|
3edb8a3ee2 | ||
|
|
922346bef6 |
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@@ -7,6 +7,7 @@ exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- enhancement
|
||||
- bug
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: wontfix
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## [3.9.0]
|
||||
|
||||
- improve performance by disabling the loader when nothing is loading (most noticeable on mobile)
|
||||
- added a setting to disable the 'mark all as read' confirmation
|
||||
- added a setting to disable the custom context menu
|
||||
- if the custom context is enabled, it can still be disabled by pressing the shift key
|
||||
- the announcement feature is now working again and supports html ('announcement' configuration element in config.yml)
|
||||
- add support for MariaDB 11+
|
||||
- fix entry header shortly rendered as mobile on desktop, causing a small visual glitch
|
||||
- fix an issue that could cause a feed to not refresh correctly if the url was very long
|
||||
- database cleanup batch size is now configurable
|
||||
- css parsing errors are no longer logged to the standard output
|
||||
- fix small errors in the api documentation
|
||||
|
||||
## [3.8.1]
|
||||
|
||||
- in expanded mode, don't scroll when clicking on the body of the current entry
|
||||
- improve content cleanup task performance for instances with a very large number of feeds
|
||||
|
||||
## [3.8.0]
|
||||
|
||||
- add previous and next buttons in the toolbar
|
||||
@@ -90,10 +109,9 @@
|
||||
## [3.0.1]
|
||||
|
||||
- allow env variable substitution in config.yml
|
||||
- e.g. having a custom config.yml file with `app.session.path=${SOME_ENV_VAR}` will substitute `SOME_ENV_VAR` with
|
||||
its value
|
||||
- e.g. having a custom config.yml file with `app.session.path=${SOME_ENV_VAR}` will substitute `SOME_ENV_VAR` with its value
|
||||
- allow env variable prefixed with `CF_` to override config.yml properties
|
||||
- e.g. setting `CF_APP_ALLOWREGISTRATIONS=true` will set `app.allowRegistrations` to `true`
|
||||
- e.g. setting `CF_APP_ALLOWREGISTRATIONS=true` will set `app.allowRegistrations` to `true`
|
||||
|
||||
## [3.0.0]
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
</parent>
|
||||
<artifactId>commafeed-client</artifactId>
|
||||
<name>CommaFeed Client</name>
|
||||
|
||||
@@ -78,6 +78,7 @@ describe("entries", () => {
|
||||
sourceWebsiteUrl: "",
|
||||
entries: [{ id: "3" } as Entry],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
scrollingToEntry: false,
|
||||
},
|
||||
},
|
||||
@@ -102,6 +103,7 @@ describe("entries", () => {
|
||||
sourceWebsiteUrl: "",
|
||||
entries: [{ id: "3", read: false } as Entry, { id: "4", read: false } as Entry],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
scrollingToEntry: false,
|
||||
},
|
||||
},
|
||||
@@ -128,6 +130,7 @@ describe("entries", () => {
|
||||
sourceWebsiteUrl: "",
|
||||
entries: [{ id: "3", read: false } as Entry, { id: "4", read: false } as Entry],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
scrollingToEntry: false,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -27,6 +27,7 @@ interface EntriesState {
|
||||
timestamp?: number
|
||||
selectedEntryId?: string
|
||||
hasMore: boolean
|
||||
loading: boolean
|
||||
search?: string
|
||||
scrollingToEntry: boolean
|
||||
}
|
||||
@@ -40,6 +41,7 @@ const initialState: EntriesState = {
|
||||
sourceWebsiteUrl: "",
|
||||
entries: [],
|
||||
hasMore: true,
|
||||
loading: false,
|
||||
scrollingToEntry: false,
|
||||
}
|
||||
|
||||
@@ -329,6 +331,10 @@ export const entriesSlice = createSlice({
|
||||
state.sourceWebsiteUrl = ""
|
||||
state.hasMore = true
|
||||
state.selectedEntryId = undefined
|
||||
state.loading = true
|
||||
})
|
||||
builder.addCase(loadMoreEntries.pending, state => {
|
||||
state.loading = true
|
||||
})
|
||||
builder.addCase(loadEntries.fulfilled, (state, action) => {
|
||||
state.entries = action.payload.entries
|
||||
@@ -336,12 +342,14 @@ export const entriesSlice = createSlice({
|
||||
state.sourceLabel = action.payload.name
|
||||
state.sourceWebsiteUrl = action.payload.feedLink
|
||||
state.hasMore = action.payload.hasMore
|
||||
state.loading = false
|
||||
})
|
||||
builder.addCase(loadMoreEntries.fulfilled, (state, action) => {
|
||||
// remove already existing entries
|
||||
const entriesToAdd = action.payload.entries.filter(e => !state.entries.some(e2 => e.id === e2.id))
|
||||
state.entries = [...state.entries, ...entriesToAdd]
|
||||
state.hasMore = action.payload.hasMore
|
||||
state.loading = false
|
||||
})
|
||||
builder.addCase(tagEntry.pending, (state, action) => {
|
||||
state.entries
|
||||
|
||||
@@ -91,6 +91,28 @@ export const changeAlwaysScrollToEntry = createAsyncThunk<
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, alwaysScrollToEntry })
|
||||
})
|
||||
export const changeMarkAllAsReadConfirmation = createAsyncThunk<
|
||||
void,
|
||||
boolean,
|
||||
{
|
||||
state: RootState
|
||||
}
|
||||
>("settings/markAllAsReadConfirmation", (markAllAsReadConfirmation, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, markAllAsReadConfirmation })
|
||||
})
|
||||
export const changeCustomContextMenu = createAsyncThunk<
|
||||
void,
|
||||
boolean,
|
||||
{
|
||||
state: RootState
|
||||
}
|
||||
>("settings/customContextMenu", (customContextMenu, thunkApi) => {
|
||||
const { settings } = thunkApi.getState().user
|
||||
if (!settings) return
|
||||
client.user.saveSettings({ ...settings, customContextMenu })
|
||||
})
|
||||
export const changeSharingSetting = createAsyncThunk<
|
||||
void,
|
||||
{ site: keyof SharingSettings; value: boolean },
|
||||
@@ -151,6 +173,14 @@ export const userSlice = createSlice({
|
||||
if (!state.settings) return
|
||||
state.settings.alwaysScrollToEntry = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeMarkAllAsReadConfirmation.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.markAllAsReadConfirmation = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeCustomContextMenu.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.customContextMenu = action.meta.arg
|
||||
})
|
||||
builder.addCase(changeSharingSetting.pending, (state, action) => {
|
||||
if (!state.settings) return
|
||||
state.settings.sharingSettings[action.meta.arg.site] = action.meta.arg.value
|
||||
@@ -162,6 +192,8 @@ export const userSlice = createSlice({
|
||||
changeShowRead.fulfilled,
|
||||
changeScrollMarks.fulfilled,
|
||||
changeAlwaysScrollToEntry.fulfilled,
|
||||
changeMarkAllAsReadConfirmation.fulfilled,
|
||||
changeCustomContextMenu.fulfilled,
|
||||
changeSharingSetting.fulfilled
|
||||
),
|
||||
() => {
|
||||
|
||||
@@ -3,38 +3,6 @@ export interface AddCategoryRequest {
|
||||
parentId?: string
|
||||
}
|
||||
|
||||
export interface ApplicationSettings {
|
||||
publicUrl: string
|
||||
allowRegistrations: boolean
|
||||
createDemoAccount: boolean
|
||||
googleAnalyticsTrackingCode?: string
|
||||
googleAuthKey?: string
|
||||
backgroundThreads: number
|
||||
databaseUpdateThreads: number
|
||||
smtpHost?: string
|
||||
smtpPort?: number
|
||||
smtpTls?: boolean
|
||||
smtpUserName?: string
|
||||
smtpPassword?: string
|
||||
smtpFromAddress?: string
|
||||
graphiteEnabled?: boolean
|
||||
graphitePrefix?: string
|
||||
graphiteHost?: string
|
||||
graphitePort?: number
|
||||
graphiteInterval?: number
|
||||
heavyLoad: boolean
|
||||
pubsubhubbub: boolean
|
||||
imageProxyEnabled: boolean
|
||||
queryTimeout: number
|
||||
keepStatusDays: number
|
||||
maxFeedCapacity: number
|
||||
refreshIntervalMinutes: number
|
||||
cache: ApplicationSettingsCache
|
||||
announcement?: string
|
||||
userAgent?: string
|
||||
unreadThreshold?: Date
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
id: string
|
||||
parentId?: string
|
||||
@@ -234,6 +202,8 @@ export interface Settings {
|
||||
customJs?: string
|
||||
scrollSpeed: number
|
||||
alwaysScrollToEntry: boolean
|
||||
markAllAsReadConfirmation: boolean
|
||||
customContextMenu: boolean
|
||||
sharingSettings: SharingSettings
|
||||
}
|
||||
|
||||
@@ -300,8 +270,6 @@ export interface UserModel {
|
||||
admin: boolean
|
||||
}
|
||||
|
||||
export type ApplicationSettingsCache = "NOOP" | "REDIS"
|
||||
|
||||
export type ReadingMode = "all" | "unread"
|
||||
|
||||
export type ReadingOrder = "asc" | "desc"
|
||||
|
||||
36
commafeed-client/src/components/AnnouncementDialog.tsx
Normal file
36
commafeed-client/src/components/AnnouncementDialog.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Trans } from "@lingui/macro"
|
||||
import { Box, Dialog, Text } from "@mantine/core"
|
||||
import { useAppSelector } from "app/store"
|
||||
import { Content } from "components/content/Content"
|
||||
import { useAsync } from "react-async-hook"
|
||||
import useLocalStorage from "use-local-storage"
|
||||
|
||||
const sha256Hex = async (input: string | undefined) => {
|
||||
const data = new TextEncoder().encode(input)
|
||||
const buffer = await crypto.subtle.digest("SHA-256", data)
|
||||
const array = Array.from(new Uint8Array(buffer))
|
||||
return array.map(b => b.toString(16).padStart(2, "0")).join("")
|
||||
}
|
||||
|
||||
export function AnnouncementDialog() {
|
||||
const announcement = useAppSelector(state => state.server.serverInfos?.announcement)
|
||||
const announcementHash = useAsync(sha256Hex, [announcement]).result
|
||||
const [localStorageHash, setLocalStorageHash] = useLocalStorage("announcement-hash", "no-hash")
|
||||
|
||||
const opened = !!announcementHash && announcementHash !== localStorageHash
|
||||
const onClosed = () => setLocalStorageHash(announcementHash)
|
||||
|
||||
if (!announcement) return null
|
||||
return (
|
||||
<Dialog opened={opened} withCloseButton onClose={onClosed} size="xl" radius="md">
|
||||
<Box>
|
||||
<Text weight="bold">
|
||||
<Trans>Announcement</Trans>
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Content content={announcement} />
|
||||
</Box>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -161,6 +161,20 @@ export function KeyboardShortcutsHelp() {
|
||||
</Kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Trans>Show native menu (desktop)</Trans>
|
||||
</td>
|
||||
<td>
|
||||
<Kbd>
|
||||
<Trans>Shift</Trans>
|
||||
</Kbd>
|
||||
<span> + </span>
|
||||
<Kbd>
|
||||
<Trans>Right click</Trans>
|
||||
</Kbd>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Trans>Show entry menu (mobile)</Trans>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Trans } from "@lingui/macro"
|
||||
import { Box } from "@mantine/core"
|
||||
import { openModal } from "@mantine/modals"
|
||||
import { Constants } from "app/constants"
|
||||
import {
|
||||
@@ -31,9 +32,11 @@ export function FeedEntries() {
|
||||
const entriesTimestamp = useAppSelector(state => state.entries.timestamp)
|
||||
const selectedEntryId = useAppSelector(state => state.entries.selectedEntryId)
|
||||
const hasMore = useAppSelector(state => state.entries.hasMore)
|
||||
const loading = useAppSelector(state => state.entries.loading)
|
||||
const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks)
|
||||
const scrollingToEntry = useAppSelector(state => state.entries.scrollingToEntry)
|
||||
const sidebarVisible = useAppSelector(state => state.tree.sidebarVisible)
|
||||
const customContextMenu = useAppSelector(state => state.user.settings?.customContextMenu)
|
||||
const { viewMode } = useViewMode()
|
||||
const dispatch = useAppDispatch()
|
||||
const { openLinkInBackgroundTab } = useBrowserExtension()
|
||||
@@ -62,6 +65,8 @@ export function FeedEntries() {
|
||||
|
||||
const contextMenu = useContextMenu()
|
||||
const headerRightClicked = (entry: ExpendableEntry, event: React.MouseEvent) => {
|
||||
if (event.shiftKey || !customContextMenu) return
|
||||
|
||||
event.preventDefault()
|
||||
contextMenu.show({
|
||||
id: Constants.dom.entryContextMenuId(entry),
|
||||
@@ -71,6 +76,10 @@ export function FeedEntries() {
|
||||
|
||||
const bodyClicked = (entry: ExpendableEntry) => {
|
||||
if (viewMode !== "expanded") return
|
||||
|
||||
// entry is already selected
|
||||
if (entry.id === selectedEntryId) return
|
||||
|
||||
dispatch(
|
||||
selectEntry({
|
||||
entry,
|
||||
@@ -276,9 +285,9 @@ export function FeedEntries() {
|
||||
<InfiniteScroll
|
||||
id="entries"
|
||||
initialLoad={false}
|
||||
loadMore={() => dispatch(loadMoreEntries())}
|
||||
loadMore={() => !loading && dispatch(loadMoreEntries())}
|
||||
hasMore={hasMore}
|
||||
loader={<Loader key={0} />}
|
||||
loader={<Box key={0}>{loading && <Loader />}</Box>}
|
||||
>
|
||||
{entries.map(entry => (
|
||||
<div
|
||||
|
||||
@@ -13,8 +13,27 @@ export function MarkAllAsReadButton(props: { iconSize: number }) {
|
||||
const source = useAppSelector(state => state.entries.source)
|
||||
const sourceLabel = useAppSelector(state => state.entries.sourceLabel)
|
||||
const entriesTimestamp = useAppSelector(state => state.entries.timestamp) ?? Date.now()
|
||||
const markAllAsReadConfirmation = useAppSelector(state => state.user.settings?.markAllAsReadConfirmation)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
const buttonClicked = () => {
|
||||
if (markAllAsReadConfirmation) {
|
||||
setThreshold(0)
|
||||
setOpened(true)
|
||||
} else {
|
||||
dispatch(
|
||||
markAllEntries({
|
||||
sourceType: source.type,
|
||||
req: {
|
||||
id: source.id,
|
||||
read: true,
|
||||
olderThan: entriesTimestamp,
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={opened} onClose={() => setOpened(false)} title={<Trans>Mark all entries as read</Trans>}>
|
||||
@@ -70,14 +89,7 @@ export function MarkAllAsReadButton(props: { iconSize: number }) {
|
||||
</Group>
|
||||
</Stack>
|
||||
</Modal>
|
||||
<ActionButton
|
||||
icon={<TbChecks size={props.iconSize} />}
|
||||
label={<Trans>Mark all as read</Trans>}
|
||||
onClick={() => {
|
||||
setThreshold(0)
|
||||
setOpened(true)
|
||||
}}
|
||||
/>
|
||||
<ActionButton icon={<TbChecks size={props.iconSize} />} label={<Trans>Mark all as read</Trans>} onClick={buttonClicked} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ import { Divider, Select, SimpleGrid, Stack, Switch } from "@mantine/core"
|
||||
import { Constants } from "app/constants"
|
||||
import {
|
||||
changeAlwaysScrollToEntry,
|
||||
changeCustomContextMenu,
|
||||
changeLanguage,
|
||||
changeMarkAllAsReadConfirmation,
|
||||
changeScrollMarks,
|
||||
changeScrollSpeed,
|
||||
changeSharingSetting,
|
||||
@@ -19,6 +21,8 @@ export function DisplaySettings() {
|
||||
const showRead = useAppSelector(state => state.user.settings?.showRead)
|
||||
const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks)
|
||||
const alwaysScrollToEntry = useAppSelector(state => state.user.settings?.alwaysScrollToEntry)
|
||||
const markAllAsReadConfirmation = useAppSelector(state => state.user.settings?.markAllAsReadConfirmation)
|
||||
const customContextMenu = useAppSelector(state => state.user.settings?.customContextMenu)
|
||||
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
|
||||
const dispatch = useAppDispatch()
|
||||
|
||||
@@ -58,6 +62,18 @@ export function DisplaySettings() {
|
||||
onChange={e => dispatch(changeScrollMarks(e.currentTarget.checked))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show confirmation when marking all entries as read</Trans>}
|
||||
checked={markAllAsReadConfirmation}
|
||||
onChange={e => dispatch(changeMarkAllAsReadConfirmation(e.currentTarget.checked))}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
label={<Trans>Show CommaFeed's own context menu on right click</Trans>}
|
||||
checked={customContextMenu}
|
||||
onChange={e => dispatch(changeCustomContextMenu(e.currentTarget.checked))}
|
||||
/>
|
||||
|
||||
<Divider label={<Trans>Sharing sites</Trans>} labelPosition="center" />
|
||||
|
||||
<SimpleGrid cols={2}>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { useMediaQuery } from "@mantine/hooks"
|
||||
import { Constants } from "app/constants"
|
||||
|
||||
export const useMobile = (breakpoint: string = Constants.layout.mobileBreakpoint) => !useMediaQuery(`(min-width: ${breakpoint})`)
|
||||
export const useMobile = (breakpoint: string = Constants.layout.mobileBreakpoint) =>
|
||||
!useMediaQuery(`(min-width: ${breakpoint})`, undefined, {
|
||||
getInitialValueInEffect: false,
|
||||
})
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "ملف opml هو ملف XML يحتوي على عناوين URL للتغ
|
||||
msgid "Analyze feed"
|
||||
msgstr "تحليل التغذية"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "مفتاح API"
|
||||
@@ -665,6 +669,7 @@ msgstr "تم إغلاق التسجيلات في مثيل CommaFeed هذا"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "مشاركة"
|
||||
msgid "Sharing sites"
|
||||
msgstr "مشاركة المواقع"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "الحلقة"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "إظهار موجز ويب والفئات التي لا تحتوي عل
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "إظهار تعليمات اختصار لوحة المفاتيح"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Un fitxer opml és un fitxer XML que conté URL i categories de canals.
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analitzar el feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "clau API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Els registres estan tancats en aquesta instància de CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Comparteix"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartir llocs"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "canvi"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Mostra feeds i categories sense entrades no llegides"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Mostra l'ajuda de la drecera del teclat"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Soubor opml je soubor XML obsahující adresy URL a kategorie zdrojů. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyzujte krmivo"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Klíč API"
|
||||
@@ -665,6 +669,7 @@ msgstr "V této instanci CommaFeed jsou registrace uzavřeny"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Sdílejte"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Stránky pro sdílení"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Směna"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Zobrazit kanály a kategorie bez nepřečtených položek"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Zobrazit nápovědu ke klávesovým zkratkám"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Mae ffeil opml yn ffeil XML sy'n cynnwys URLs porthiant a chategorïau.
|
||||
msgid "Analyze feed"
|
||||
msgstr "Dadansoddi porthiant"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Allwedd API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Mae cofrestriadau ar gau ar yr achos CommaFeed hwn"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Rhannu"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Rhannu gwefannau"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "shifft"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Dangos ffrydiau a chategorïau heb unrhyw gofnodion heb eu darllen"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Dangos cymorth llwybr byr bysellfwrdd"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "En opml-fil er en XML-fil, der indeholder feed-URL'er og kategorier. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyser foder"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-nøgle"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registreringer er lukket på denne CommaFeed-instans"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Vis feeds og kategorier uden ulæste poster"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Vis hjælp til tastaturgenveje"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Eine opml-Datei ist eine XML-Datei, die Feed-URLs und Kategorien enthäl
|
||||
msgid "Analyze feed"
|
||||
msgstr "Feed analysieren"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-Schlüssel"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registrierungen sind für diese CommaFeed-Instanz geschlossen"
|
||||
msgid "REST API"
|
||||
msgstr "REST-API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Teilen"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Seiten teilen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Verschiebung"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Feeds und Kategorien ohne ungelesene Einträge anzeigen"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Tastenkürzel-Hilfe anzeigen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "An opml file is an XML file containing feed URLs and categories. You can
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyze feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr "Announcement"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API key"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registrations are closed on this CommaFeed instance"
|
||||
msgid "REST API"
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Right click"
|
||||
@@ -716,11 +721,20 @@ msgstr "Share"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sharing sites"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Shift"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr "Show CommaFeed's own context menu on right click"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr "Show confirmation when marking all entries as read"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr "Show entry menu (desktop)"
|
||||
@@ -737,6 +751,10 @@ msgstr "Show feeds and categories with no unread entries"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Show keyboard shortcut help"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr "Show native menu (desktop)"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Un archivo opml es un archivo XML que contiene categorías y direcciones
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analizar alimentación"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "clave API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Los registros están cerrados en esta instancia de CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Compartir"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartir sitios"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Cambio"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Mostrar feeds y categorías sin entradas no leídas"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Mostrar ayuda de atajo de teclado"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "یک فایل opml یک فایل XML است که حاوی آدرسه
|
||||
msgid "Analyze feed"
|
||||
msgstr "خوراک را تجزیه و تحلیل کنید"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "کلید API"
|
||||
@@ -665,6 +669,7 @@ msgstr "ثبت نام در این نمونه CommaFeed بسته شده است"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "به اشتراک بگذارید"
|
||||
msgid "Sharing sites"
|
||||
msgstr "اشتراک گذاری سایت ها"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "شیفت"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "فیدها و دسته ها را بدون ورودی خوانده نشد
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "نمایش راهنمایی میانبر صفحه کلید"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Opml-tiedosto on XML-tiedosto, joka sisältää syötteen URL-osoitteet
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analysoi syöte"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-avain"
|
||||
@@ -665,6 +669,7 @@ msgstr "Tämän CommaFeed-esiintymän rekisteröinnit on suljettu"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Jaa"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sivustojen jakaminen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Vaihto"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Näytä syötteet ja luokat ilman lukemattomia merkintöjä"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Näytä pikanäppäimen ohje"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Un fichier OPML est un fichier XML contenant des URL de flux et des cat
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyser le flux"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr "Annonces"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Clé API"
|
||||
@@ -264,7 +268,7 @@ msgstr "Affichage"
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
#: src/pages/app/DonatePage.tsx
|
||||
msgid "Donate"
|
||||
msgstr "Faites un don"
|
||||
msgstr "Faire un don"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Download"
|
||||
@@ -665,6 +669,7 @@ msgstr "Les inscriptions sont fermées sur cette instance de CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr "Clic droit"
|
||||
@@ -716,11 +721,20 @@ msgstr "Partager"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sites de partage"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Maj"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr "Demander une confirmation avant de tout marquer comme lu"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr "Afficher les options de l'entrée (ordinateur)"
|
||||
@@ -737,6 +751,10 @@ msgstr "Afficher les flux et les catégories pour lesquels tout est déjà lu"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Montrer les raccourcis clavier"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr "Afficher les options du navigateur (ordinateur)"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Un ficheiro opml é un ficheiro XML que contén URL e categorías de fon
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analizar feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "chave API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Os rexistros están pechados nesta instancia de CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Compartir"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartir sitios"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "quendas"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Mostrar fontes e categorías sen entradas sen ler"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Mostrar axuda do atallo do teclado"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Az opml-fájl olyan XML-fájl, amely feed URL-címeket és kategóriáka
|
||||
msgid "Analyze feed"
|
||||
msgstr "Hírcsatorna elemzése"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API kulcs"
|
||||
@@ -665,6 +669,7 @@ msgstr "A regisztrációk le vannak zárva ezen a CommaFeed példányon"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Oszd meg"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Webhelyek megosztása"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Hírcsatornák és kategóriák megjelenítése olvasatlan bejegyzések
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "A billentyűparancsok súgójának megjelenítése"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "File opml adalah file XML yang berisi URL dan kategori feed. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analisis umpan"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "kunci API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Pendaftaran ditutup pada instans CommaFeed ini"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Bagikan"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Berbagi situs"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Pergeseran"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Tampilkan umpan dan kategori tanpa entri yang belum dibaca"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Tampilkan bantuan pintasan keyboard"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Un file opml è un file XML contenente URL e categorie di feed. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analizza feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Chiave API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Le registrazioni sono chiuse su questa istanza CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Condividi"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Condivisione di siti"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Cambio"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Mostra feed e categorie senza voci non lette"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Mostra la guida alle scorciatoie da tastiera"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "opml ファイルは、フィードの URL とカテゴリを含む XML
|
||||
msgid "Analyze feed"
|
||||
msgstr "フィードを分析する"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "APIキー"
|
||||
@@ -665,6 +669,7 @@ msgstr "この CommaFeed インスタンスの登録は終了しています"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "シェア"
|
||||
msgid "Sharing sites"
|
||||
msgstr "共有サイト"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "シフト"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "未読エントリのないフィードとカテゴリを表示する"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "キーボード ショートカットのヘルプを表示"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "opml 파일은 피드 URL과 카테고리를 포함하는 XML 파일입
|
||||
msgid "Analyze feed"
|
||||
msgstr "피드 분석"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API 키"
|
||||
@@ -665,6 +669,7 @@ msgstr "이 CommaFeed 인스턴스에 대한 등록이 마감되었습니다."
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "공유"
|
||||
msgid "Sharing sites"
|
||||
msgstr "사이트 공유"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "시프트"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "읽지 않은 항목이 없는 피드 및 카테고리 표시"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "키보드 단축키 도움말 표시"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Fail opml ialah fail XML yang mengandungi URL suapan dan kategori. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Menganalisis suapan"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Kunci API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Pendaftaran ditutup pada contoh CommaFeed ini"
|
||||
msgid "REST API"
|
||||
msgstr "REHAT API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Kongsi"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Berkongsi tapak"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Anjakan"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Tunjukkan suapan dan kategori tanpa entri yang belum dibaca"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Tunjukkan bantuan pintasan papan kekunci"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "En opml-fil er en XML-fil som inneholder feed-URLer og kategorier. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyser feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-nøkkel"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registreringer er stengt på denne CommaFeed-forekomsten"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Vis feeder og kategorier uten uleste oppføringer"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Vis hurtigtasthjelp"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Een opml-bestand is een XML-bestand met feed-URL's en categorieën. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyseer feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-sleutel"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registraties zijn gesloten op deze CommaFeed-instantie"
|
||||
msgid "REST API"
|
||||
msgstr "REST-API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Delen"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Sites delen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Toon feeds en categorieën zonder ongelezen items"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Toon hulp bij sneltoetsen"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "En opml-fil er en XML-fil som inneholder feed-URLer og kategorier. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyser feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-nøkkel"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registreringer er stengt på denne CommaFeed-forekomsten"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Del"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delingssider"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Vis feeder og kategorier uten uleste oppføringer"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Vis hurtigtasthjelp"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Plik opml to plik XML zawierający adresy URL i kategorie kanałów. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analizuj kanał"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "klucz API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Rejestracje są zamknięte w tej instancji CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Udostępnij"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Udostępnianie witryn"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "zmiana"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Pokaż kanały i kategorie bez nieprzeczytanych wpisów"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Pokaż pomoc dotyczącą skrótów klawiaturowych"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Um arquivo opml é um arquivo XML contendo URLs e categorias de feed. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analisar feed"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "chave de API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Os registros estão fechados nesta instância do CommaFeed"
|
||||
msgid "REST API"
|
||||
msgstr "API REST"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Compartilhar"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Compartilhando sites"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Mudar"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Mostrar feeds e categorias sem entradas não lidas"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Mostrar ajuda de atalho de teclado"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "OPML-файл — это XML-файл, содержащий URL-адре
|
||||
msgid "Analyze feed"
|
||||
msgstr "Анализ канала"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "ключ API"
|
||||
@@ -665,6 +669,7 @@ msgstr "Регистрация закрыта для этого экземпля
|
||||
msgid "REST API"
|
||||
msgstr "ОТДЫХА API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Поделиться"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Обмен сайтами"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Сдвиг"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Показать каналы и категории без непроч
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Показать справку по сочетаниям клавиш."
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "Súbor opml je súbor XML obsahujúci adresy URL kanálov a kategórie.
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analyzujte krmivo"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "Kľúč API"
|
||||
@@ -665,6 +669,7 @@ msgstr "V tejto inštancii CommaFeed sú registrácie uzavreté"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Zdieľať"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Zdieľanie stránok"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Smena"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Zobraziť kanály a kategórie bez neprečítaných záznamov"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Zobraziť pomoc s klávesovými skratkami"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "En opml-fil är en XML-fil som innehåller feed-URL:er och kategorier. "
|
||||
msgid "Analyze feed"
|
||||
msgstr "Analysera foder"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API-nyckel"
|
||||
@@ -665,6 +669,7 @@ msgstr "Registreringar är stängda på denna CommaFeed-instans"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "Dela"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Delningssajter"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Skift"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "Visa flöden och kategorier utan olästa poster"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Visa kortkommandohjälp"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -15,15 +15,15 @@ msgstr ""
|
||||
|
||||
#: src/components/content/add/CategorySelect.tsx
|
||||
msgid "{0} (in {1})"
|
||||
msgstr ""
|
||||
msgstr "{0} ({1} içinde)"
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "<0>CommaFeed is an open-source project. Sources are hosted on </0><1>GitHub</1>."
|
||||
msgstr ""
|
||||
msgstr "<0>CommaFeed açık kaynak kodlu bir proje. Kaynak kodları </0><1>GitHub</1>'da."
|
||||
|
||||
#: src/pages/app/FeedDetailsPage.tsx
|
||||
msgid "<0>Complete syntax is available </0><1>here</1>."
|
||||
msgstr ""
|
||||
msgstr "<0>Tüm sözdizimi </0><1>burada</1>."
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
msgid "<0>Have an account?</0><1>Log in!</1>"
|
||||
@@ -31,7 +31,7 @@ msgstr "<0>Hesabınız var mı?</0><1>Giriş yapın!</1>"
|
||||
|
||||
#: src/pages/app/DonatePage.tsx
|
||||
msgid "<0>Hey,</0><1>I'm Jérémie from Belgium and I've been working on CommaFeed in my free time for over 10 years now. Thanks for taking an interest in helping me continue supporting CommaFeed.</1>"
|
||||
msgstr ""
|
||||
msgstr "<0>Merhaba,</0><1>Ben Belçika'dan Jérémie ve 10 yıldır boş zamanlarımda CommaFeed üzerinde çalışıyorum. CommaFeed'i desteklememe ilgi gösterdiğiniz için teşekkürler.</1>"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "<0>Need an account?</0><1>Sign up!</1>"
|
||||
@@ -73,7 +73,7 @@ msgstr "Tümü"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Always scroll selected entry to the top of the page, even if it fits entirely on screen"
|
||||
msgstr ""
|
||||
msgstr "Seçilen girişi her zaman sayfanın üstüne kaydır, ekrana tamamen sığsa bile"
|
||||
|
||||
#: src/pages/auth/PasswordRecoveryPage.tsx
|
||||
msgid "An email has been sent if this address was registered. Check your inbox."
|
||||
@@ -87,6 +87,10 @@ msgstr "Bir opml dosyası, besleme URL'lerini ve kategorilerini içeren bir XML
|
||||
msgid "Analyze feed"
|
||||
msgstr "Feed'i analiz et"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr "Duyuru"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API anahtarı"
|
||||
@@ -137,7 +141,7 @@ msgstr ""
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "Browser extention"
|
||||
msgstr ""
|
||||
msgstr "Tarayıcı eklentisi"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/components/content/add/AddCategory.tsx
|
||||
@@ -173,7 +177,7 @@ msgstr "Feed'in çalışıp çalışmadığını kontrol edin"
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "CommaFeed browser extension version {browserExtensionVersion}."
|
||||
msgstr ""
|
||||
msgstr "CommaFeed tarayıcı eklentisi sürüm {browserExtensionVersion}."
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "CommaFeed next unread item"
|
||||
@@ -181,7 +185,7 @@ msgstr "CommaFeed sonraki okunmamış öğe"
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "CommaFeed version {version} ({revision})."
|
||||
msgstr ""
|
||||
msgstr "CommaFeed sürüm {version} ({revision})."
|
||||
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
msgid "Compact"
|
||||
@@ -209,7 +213,7 @@ msgstr "Etiket oluştur: {query}"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Ctrl"
|
||||
msgstr ""
|
||||
msgstr "Ctrl"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "Current password"
|
||||
@@ -217,15 +221,15 @@ msgstr "Geçerli şifre"
|
||||
|
||||
#: src/pages/app/SettingsPage.tsx
|
||||
msgid "Custom code"
|
||||
msgstr ""
|
||||
msgstr "Özel kod"
|
||||
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
msgid "Custom CSS rules that will be applied"
|
||||
msgstr ""
|
||||
msgstr "Uygulanacak özel CSS kuralları"
|
||||
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
msgid "Custom JS code that will be executed on page load"
|
||||
msgstr ""
|
||||
msgstr "Sayfa yüklendiğinde çalıştırılacak özel JS kodu"
|
||||
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
msgid "Date created"
|
||||
@@ -323,7 +327,7 @@ msgstr "Aboneliklerinizi ve kategorilerinizi diğer besleme okuma hizmetlerinde
|
||||
#: src/components/header/Header.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Extension options"
|
||||
msgstr ""
|
||||
msgstr "Eklenti ayarları"
|
||||
|
||||
#: src/components/content/add/Subscribe.tsx
|
||||
msgid "Feed name"
|
||||
@@ -337,7 +341,7 @@ msgstr "Feed URL'si"
|
||||
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
msgid "Fetch all my feeds now"
|
||||
msgstr ""
|
||||
msgstr "Tüm feed'lerimi şimdi çek"
|
||||
|
||||
#: src/components/content/add/ImportOpml.tsx
|
||||
msgid "file is required"
|
||||
@@ -369,7 +373,7 @@ msgstr "Oluşturulan besleme url'si"
|
||||
|
||||
#: src/components/content/FeedEntryContextMenu.tsx
|
||||
msgid "Go to {0}"
|
||||
msgstr ""
|
||||
msgstr "{0}'a git"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Go to the All view"
|
||||
@@ -463,7 +467,7 @@ msgstr "Çıkış"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Long press"
|
||||
msgstr ""
|
||||
msgstr "Uzun bas"
|
||||
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
#: src/pages/admin/AdminUsersPage.tsx
|
||||
@@ -495,7 +499,7 @@ msgstr "Metrikler"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Middle click"
|
||||
msgstr ""
|
||||
msgstr "Orta tuş ile tıkla"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Move the page down"
|
||||
@@ -560,7 +564,7 @@ msgstr "Hata!"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
msgid "Open CommaFeed"
|
||||
msgstr ""
|
||||
msgstr "CommaFeed'i aç"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Open current entry in a new tab"
|
||||
@@ -576,11 +580,11 @@ msgstr "Bağlantıyı aç"
|
||||
|
||||
#: src/components/content/FeedEntryContextMenu.tsx
|
||||
msgid "Open link in new background tab"
|
||||
msgstr ""
|
||||
msgstr "Bağlantıyı arkaplanda yeni sekmede aç"
|
||||
|
||||
#: src/components/content/FeedEntryContextMenu.tsx
|
||||
msgid "Open link in new tab"
|
||||
msgstr ""
|
||||
msgstr "Bağlantıyı yeni sekmede aç"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Open next entry"
|
||||
@@ -596,7 +600,7 @@ msgstr "Geçerli girişi aç/kapat"
|
||||
|
||||
#: src/pages/app/AddPage.tsx
|
||||
msgid "OPML"
|
||||
msgstr ""
|
||||
msgstr "OPML"
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "OPML export"
|
||||
@@ -642,7 +646,7 @@ msgstr "Konum"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
msgid "Previous"
|
||||
msgstr ""
|
||||
msgstr "Önceki"
|
||||
|
||||
#: src/pages/app/SettingsPage.tsx
|
||||
msgid "Profile"
|
||||
@@ -663,11 +667,12 @@ msgstr "Bu CommaFeed örneğinde kayıtlar kapalı"
|
||||
|
||||
#: src/pages/app/AboutPage.tsx
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
msgstr "REST API"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
msgstr "Sağ tık"
|
||||
|
||||
#: src/components/admin/UserEdit.tsx
|
||||
#: src/components/settings/CustomCodeSettings.tsx
|
||||
@@ -716,18 +721,27 @@ msgstr "Paylaş"
|
||||
msgid "Sharing sites"
|
||||
msgstr "Siteleri paylaşma"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "Vardiya"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr "Sağ tıkta CommaFeed'in kendi menüsünü göster"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr "Tüm girişleri okundu işaretlerken onay iste"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
msgstr "Giriş menüsünü göster (masaüstü)"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (mobile)"
|
||||
msgstr ""
|
||||
msgstr "Giriş menüsünü göster (mobil)"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show feeds and categories with no unread entries"
|
||||
@@ -737,6 +751,10 @@ msgstr "Okunmamış girişi olmayan beslemeleri ve kategorileri göster"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "Klavye kısayolu yardımını göster"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr "Orijinal tarayıcı menüsünü göster (masaüstü)"
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
@@ -782,7 +800,7 @@ msgstr "Başarı"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Swipe header to the right"
|
||||
msgstr ""
|
||||
msgstr "Başlığı sağa kaydır"
|
||||
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
@@ -792,7 +810,7 @@ msgstr "Karanlık temaya geç"
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Switch to light theme"
|
||||
msgstr "Açık temaya geç"
|
||||
msgstr "Aydınlık temaya geç"
|
||||
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
msgid "Tags"
|
||||
@@ -812,7 +830,7 @@ msgstr "Geçerli girişin okuma durumunu değiştir"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
msgstr "Kenar çubuğunu göster/gizle"
|
||||
|
||||
#: src/pages/auth/LoginPage.tsx
|
||||
msgid "Try out CommaFeed with the demo account: demo/demo"
|
||||
@@ -820,11 +838,11 @@ msgstr "CommaFeed'i demo hesabıyla deneyin: demo/demo"
|
||||
|
||||
#: src/pages/WelcomePage.tsx
|
||||
msgid "Try the demo!"
|
||||
msgstr ""
|
||||
msgstr "Demo'yu deneyin!"
|
||||
|
||||
#: src/components/header/Header.tsx
|
||||
msgid "Unread"
|
||||
msgstr "Okunmadı"
|
||||
msgstr "Okunmamış"
|
||||
|
||||
#: src/components/content/FeedEntryContextMenu.tsx
|
||||
#: src/components/content/FeedEntryFooter.tsx
|
||||
@@ -855,8 +873,8 @@ msgstr "Web sitesi"
|
||||
|
||||
#: src/pages/app/FeedEntriesPage.tsx
|
||||
msgid "You don't have any subscriptions yet. Why not try adding one by clicking on the + sign at the top of the page?"
|
||||
msgstr "Henüz aboneliğiniz yok. "
|
||||
msgstr "Henüz aboneliğiniz yok. Sayfanın üstündeki + işaretiyle feed ekleyebilirsiniz."
|
||||
|
||||
#: src/components/header/ProfileMenu.tsx
|
||||
msgid "Your feeds have been queued for refresh."
|
||||
msgstr ""
|
||||
msgstr "Feed'leriniz yenileme için sıraya alındı."
|
||||
|
||||
@@ -87,6 +87,10 @@ msgstr "opml 文件是包含提要 URL 和类别的 XML 文件。"
|
||||
msgid "Analyze feed"
|
||||
msgstr "分析饲料"
|
||||
|
||||
#: src/components/AnnouncementDialog.tsx
|
||||
msgid "Announcement"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/ProfileSettings.tsx
|
||||
msgid "API key"
|
||||
msgstr "API 密钥"
|
||||
@@ -665,6 +669,7 @@ msgstr "此 CommaFeed 实例上的注册已关闭"
|
||||
msgid "REST API"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Right click"
|
||||
msgstr ""
|
||||
@@ -716,11 +721,20 @@ msgstr "分享"
|
||||
msgid "Sharing sites"
|
||||
msgstr "共享站点"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Shift"
|
||||
msgstr "换档"
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show CommaFeed's own context menu on right click"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/settings/DisplaySettings.tsx
|
||||
msgid "Show confirmation when marking all entries as read"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show entry menu (desktop)"
|
||||
msgstr ""
|
||||
@@ -737,6 +751,10 @@ msgstr "显示没有未读条目的提要和类别"
|
||||
msgid "Show keyboard shortcut help"
|
||||
msgstr "显示键盘快捷键帮助"
|
||||
|
||||
#: src/components/KeyboardShortcutsHelp.tsx
|
||||
msgid "Show native menu (desktop)"
|
||||
msgstr ""
|
||||
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/auth/RegistrationPage.tsx
|
||||
#: src/pages/WelcomePage.tsx
|
||||
|
||||
@@ -18,6 +18,7 @@ import { redirectToAdd, redirectToRootCategory } from "app/slices/redirect"
|
||||
import { reloadTree, setMobileMenuOpen, setSidebarWidth } from "app/slices/tree"
|
||||
import { reloadProfile, reloadSettings, reloadTags } from "app/slices/user"
|
||||
import { useAppDispatch, useAppSelector } from "app/store"
|
||||
import { AnnouncementDialog } from "components/AnnouncementDialog"
|
||||
import { Loader } from "components/Loader"
|
||||
import { Logo } from "components/Logo"
|
||||
import { OnDesktop } from "components/responsive/OnDesktop"
|
||||
@@ -197,6 +198,7 @@ export default function Layout(props: LayoutProps) {
|
||||
>
|
||||
<Box id="content" className={classes.mainContent}>
|
||||
<Suspense fallback={<Loader />}>
|
||||
<AnnouncementDialog />
|
||||
<Outlet />
|
||||
</Suspense>
|
||||
</Box>
|
||||
|
||||
@@ -27,7 +27,10 @@ app:
|
||||
|
||||
# number of database updating threads
|
||||
databaseUpdateThreads: 1
|
||||
|
||||
|
||||
# rows to delete per query while cleaning up old entries
|
||||
databaseCleanupBatchSize: 100
|
||||
|
||||
# settings for sending emails (password recovery)
|
||||
smtpHost: localhost
|
||||
smtpPort: 25
|
||||
@@ -81,8 +84,12 @@ app:
|
||||
|
||||
# Database connection
|
||||
# -------------------
|
||||
# for MariaDB
|
||||
# driverClass is org.mariadb.jdbc.Driver
|
||||
# url is jdbc:mariadb://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for MySQL
|
||||
# driverClass is com.mysql.jdbc.Driver
|
||||
# driverClass is com.mysql.cj.jdbc.Driver
|
||||
# url is jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for PostgreSQL
|
||||
|
||||
@@ -6,28 +6,31 @@ app:
|
||||
|
||||
# whether to expose a robots.txt file that disallows web crawlers and search engine indexers
|
||||
hideFromWebCrawlers: true
|
||||
|
||||
|
||||
# whether to allow user registrations
|
||||
allowRegistrations: false
|
||||
|
||||
# whether to enable strict password validation (1 uppercase char, 1 lowercase char, 1 digit, 1 special char)
|
||||
strictPasswordPolicy: true
|
||||
|
||||
|
||||
# create a demo account the first time the app starts
|
||||
createDemoAccount: false
|
||||
|
||||
|
||||
# put your google analytics tracking code here
|
||||
googleAnalyticsTrackingCode:
|
||||
|
||||
|
||||
# put your google server key (used for youtube favicon fetching)
|
||||
googleAuthKey:
|
||||
|
||||
|
||||
# number of http threads
|
||||
backgroundThreads: 3
|
||||
|
||||
|
||||
# number of database updating threads
|
||||
databaseUpdateThreads: 1
|
||||
|
||||
|
||||
# rows to delete per query while cleaning up old entries
|
||||
databaseCleanupBatchSize: 100
|
||||
|
||||
# settings for sending emails (password recovery)
|
||||
smtpHost:
|
||||
smtpPort:
|
||||
@@ -43,28 +46,28 @@ app:
|
||||
graphiteHost: "localhost"
|
||||
graphitePort: 2003
|
||||
graphiteInterval: 60
|
||||
|
||||
|
||||
# whether this commafeed instance has a lot of feeds to refresh
|
||||
# leave this to false in almost all cases
|
||||
heavyLoad: false
|
||||
|
||||
|
||||
# minimum amount of time commafeed will wait before refreshing the same feed
|
||||
refreshIntervalMinutes: 5
|
||||
|
||||
|
||||
# whether to enable pubsub
|
||||
# probably not needed if refreshIntervalMinutes is low
|
||||
pubsubhubbub: false
|
||||
|
||||
|
||||
# if enabled, images in feed entries will be proxied through the server instead of accessed directly by the browser
|
||||
# useful if commafeed is usually accessed through a restricting proxy
|
||||
# useful if commafeed is usually accessed through a restricting proxy
|
||||
imageProxyEnabled: false
|
||||
|
||||
|
||||
# database query timeout (in milliseconds), 0 to disable
|
||||
queryTimeout: 0
|
||||
|
||||
|
||||
# time to keep unread statuses (in days), 0 to disable
|
||||
keepStatusDays: 0
|
||||
|
||||
|
||||
# entries to keep per feed, old entries will be deleted, 0 to disable
|
||||
maxFeedCapacity: 500
|
||||
|
||||
@@ -73,17 +76,21 @@ app:
|
||||
|
||||
# cache service to use, possible values are 'noop' and 'redis'
|
||||
cache: noop
|
||||
|
||||
|
||||
# announcement string displayed on the main page
|
||||
announcement:
|
||||
|
||||
|
||||
# user-agent string that will be used by the http client, leave empty for the default one
|
||||
userAgent:
|
||||
|
||||
|
||||
# Database connection
|
||||
# -------------------
|
||||
# -------------------
|
||||
# for MariaDB
|
||||
# driverClass is org.mariadb.jdbc.Driver
|
||||
# url is jdbc:mariadb://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for MySQL
|
||||
# driverClass is com.mysql.jdbc.Driver
|
||||
# driverClass is com.mysql.cj.jdbc.Driver
|
||||
# url is jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for PostgreSQL
|
||||
@@ -105,7 +112,7 @@ database:
|
||||
minSize: 1
|
||||
maxSize: 50
|
||||
maxConnectionAge: 30m
|
||||
|
||||
|
||||
server:
|
||||
applicationConnectors:
|
||||
- type: http
|
||||
@@ -115,7 +122,7 @@ server:
|
||||
port: 8084
|
||||
requestLog:
|
||||
appenders: [ ]
|
||||
|
||||
|
||||
logging:
|
||||
level: ERROR
|
||||
loggers:
|
||||
@@ -131,7 +138,7 @@ logging:
|
||||
archivedLogFilenamePattern: log/commafeed-%d.log
|
||||
archivedFileCount: 5
|
||||
timeZone: UTC
|
||||
|
||||
|
||||
# Redis pool configuration
|
||||
# (only used if app.cache is 'redis')
|
||||
# -----------------------------------
|
||||
@@ -140,8 +147,7 @@ redis:
|
||||
port: 6379
|
||||
# username is only required when using ACLs
|
||||
username:
|
||||
password:
|
||||
password:
|
||||
timeout: 2000
|
||||
database: 0
|
||||
maxTotal: 500
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
</parent>
|
||||
<artifactId>commafeed-server</artifactId>
|
||||
<name>CommaFeed Server</name>
|
||||
@@ -142,6 +142,12 @@
|
||||
<title>CommaFeed</title>
|
||||
<version>${project.version}</version>
|
||||
</info>
|
||||
<securityDefinitions>
|
||||
<securityDefinition>
|
||||
<name>basicAuth</name>
|
||||
<type>basic</type>
|
||||
</securityDefinition>
|
||||
</securityDefinitions>
|
||||
<typesToSkip>
|
||||
<typeToSkip>com.commafeed.backend.model.User</typeToSkip>
|
||||
</typesToSkip>
|
||||
@@ -226,7 +232,7 @@
|
||||
<dependency>
|
||||
<groupId>com.commafeed</groupId>
|
||||
<artifactId>commafeed-client</artifactId>
|
||||
<version>3.8.0</version>
|
||||
<version>3.9.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -444,6 +450,11 @@
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>8.0.33</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>3.1.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
@@ -494,4 +505,4 @@
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -7,6 +7,7 @@ import javax.validation.Valid;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Positive;
|
||||
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
||||
@@ -95,6 +96,11 @@ public class CommaFeedConfiguration extends Configuration {
|
||||
@Valid
|
||||
private Integer databaseUpdateThreads;
|
||||
|
||||
@NotNull
|
||||
@Positive
|
||||
@Valid
|
||||
private Integer databaseCleanupBatchSize = 100;
|
||||
|
||||
private String smtpHost;
|
||||
private int smtpPort;
|
||||
private boolean smtpTls;
|
||||
|
||||
@@ -28,13 +28,10 @@ public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||
return query().select(content).from(content).where(content.contentHash.eq(contentHash), content.titleHash.eq(titleHash)).fetch();
|
||||
}
|
||||
|
||||
public int deleteWithoutEntries(int max) {
|
||||
|
||||
public long deleteWithoutEntries(int max) {
|
||||
JPQLQuery<Integer> subQuery = JPAExpressions.selectOne().from(entry).where(entry.content.id.eq(content.id));
|
||||
List<FeedEntryContent> list = query().selectFrom(content).where(subQuery.notExists()).limit(max).fetch();
|
||||
List<Long> ids = query().select(content.id).from(content).where(subQuery.notExists()).limit(max).fetch();
|
||||
|
||||
int deleted = list.size();
|
||||
delete(list);
|
||||
return deleted;
|
||||
return deleteQuery(content).where(content.id.in(ids)).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
}
|
||||
|
||||
public int delete(Long feedId, long max) {
|
||||
|
||||
List<FeedEntry> list = query().selectFrom(entry).where(entry.feed.id.eq(feedId)).limit(max).fetch();
|
||||
return delete(list);
|
||||
}
|
||||
|
||||
@@ -270,8 +270,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getOldStatuses(Date olderThan, int limit) {
|
||||
return query().selectFrom(status).where(status.entryInserted.lt(olderThan), status.starred.isFalse()).limit(limit).fetch();
|
||||
public long deleteOldStatuses(Date olderThan, int limit) {
|
||||
List<Long> ids = query().select(status.id)
|
||||
.from(status)
|
||||
.where(status.entryInserted.lt(olderThan), status.starred.isFalse())
|
||||
.limit(limit)
|
||||
.fetch();
|
||||
return deleteQuery(status).where(status.id.in(ids)).execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.hibernate.annotations.QueryHints;
|
||||
|
||||
import com.commafeed.backend.model.AbstractModel;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.jpa.impl.JPADeleteClause;
|
||||
import com.querydsl.jpa.impl.JPAQuery;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import com.querydsl.jpa.impl.JPAUpdateClause;
|
||||
@@ -30,6 +31,10 @@ public abstract class GenericDAO<T extends AbstractModel> extends AbstractDAO<T>
|
||||
return new JPAUpdateClause(currentSession(), entityPath);
|
||||
}
|
||||
|
||||
protected JPADeleteClause deleteQuery(EntityPath<T> entityPath) {
|
||||
return new JPADeleteClause(currentSession(), entityPath);
|
||||
}
|
||||
|
||||
public void saveOrUpdate(T model) {
|
||||
persist(model);
|
||||
}
|
||||
|
||||
@@ -94,11 +94,10 @@ public class FeedRefreshWorker {
|
||||
|
||||
return new FeedRefreshWorkerResult(feed, Collections.emptyList());
|
||||
} catch (Exception e) {
|
||||
String message = "Unable to refresh feed " + feed.getUrl() + " : " + e.getMessage();
|
||||
log.debug(e.getClass().getName() + " " + message, e);
|
||||
log.debug("unable to refresh feed {}", feed.getUrl(), e);
|
||||
|
||||
feed.setErrorCount(feed.getErrorCount() + 1);
|
||||
feed.setMessage(message);
|
||||
feed.setMessage("Unable to refresh feed : " + e.getMessage());
|
||||
feed.setDisabledUntil(refreshIntervalCalculator.onFetchError(feed));
|
||||
|
||||
return new FeedRefreshWorkerResult(feed, Collections.emptyList());
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.commafeed.backend.feed;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@@ -22,16 +19,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Document.OutputSettings;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Entities.EscapeMode;
|
||||
import org.jsoup.safety.Cleaner;
|
||||
import org.jsoup.safety.Safelist;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.netpreserve.urlcanon.Canonicalizer;
|
||||
import org.netpreserve.urlcanon.ParsedUrl;
|
||||
import org.w3c.css.sac.InputSource;
|
||||
import org.w3c.dom.css.CSSStyleDeclaration;
|
||||
|
||||
import com.commafeed.backend.feed.FeedEntryKeyword.Mode;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
@@ -41,7 +32,6 @@ import com.google.gwt.i18n.client.HasDirection.Direction;
|
||||
import com.google.gwt.i18n.shared.BidiUtils;
|
||||
import com.ibm.icu.text.CharsetDetector;
|
||||
import com.ibm.icu.text.CharsetMatch;
|
||||
import com.steadystate.css.parser.CSSOMParser;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -54,12 +44,6 @@ public class FeedUtils {
|
||||
|
||||
private static final String ESCAPED_QUESTION_MARK = Pattern.quote("?");
|
||||
|
||||
private static final List<String> ALLOWED_IFRAME_CSS_RULES = Arrays.asList("height", "width", "border");
|
||||
private static final List<String> ALLOWED_IMG_CSS_RULES = Arrays.asList("display", "width", "height");
|
||||
private static final char[] FORBIDDEN_CSS_RULE_CHARACTERS = new char[] { '(', ')' };
|
||||
|
||||
private static final Safelist WHITELIST = buildWhiteList();
|
||||
|
||||
public static String truncate(String string, int length) {
|
||||
if (string != null) {
|
||||
string = string.substring(0, Math.min(length, string.length()));
|
||||
@@ -67,40 +51,6 @@ public class FeedUtils {
|
||||
return string;
|
||||
}
|
||||
|
||||
private static synchronized Safelist buildWhiteList() {
|
||||
Safelist whitelist = new Safelist();
|
||||
whitelist.addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "dl", "dt", "em", "h1",
|
||||
"h2", "h3", "h4", "h5", "h6", "i", "iframe", "img", "li", "ol", "p", "pre", "q", "small", "strike", "strong", "sub", "sup",
|
||||
"table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul");
|
||||
|
||||
whitelist.addAttributes("div", "dir");
|
||||
whitelist.addAttributes("pre", "dir");
|
||||
whitelist.addAttributes("code", "dir");
|
||||
whitelist.addAttributes("table", "dir");
|
||||
whitelist.addAttributes("p", "dir");
|
||||
whitelist.addAttributes("a", "href", "title");
|
||||
whitelist.addAttributes("blockquote", "cite");
|
||||
whitelist.addAttributes("col", "span", "width");
|
||||
whitelist.addAttributes("colgroup", "span", "width");
|
||||
whitelist.addAttributes("iframe", "src", "height", "width", "allowfullscreen", "frameborder", "style");
|
||||
whitelist.addAttributes("img", "align", "alt", "height", "src", "title", "width", "style");
|
||||
whitelist.addAttributes("ol", "start", "type");
|
||||
whitelist.addAttributes("q", "cite");
|
||||
whitelist.addAttributes("table", "border", "bordercolor", "summary", "width");
|
||||
whitelist.addAttributes("td", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "width");
|
||||
whitelist.addAttributes("th", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "scope", "width");
|
||||
whitelist.addAttributes("ul", "type");
|
||||
|
||||
whitelist.addProtocols("a", "href", "ftp", "http", "https", "magnet", "mailto");
|
||||
whitelist.addProtocols("blockquote", "cite", "http", "https");
|
||||
whitelist.addProtocols("img", "src", "http", "https");
|
||||
whitelist.addProtocols("q", "cite", "http", "https");
|
||||
|
||||
whitelist.addEnforcedAttribute("a", "target", "_blank");
|
||||
whitelist.addEnforcedAttribute("a", "rel", "noreferrer");
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect feed encoding by using the declared encoding in the xml processing instruction and by detecting the characters used in the
|
||||
* feed
|
||||
@@ -233,87 +183,6 @@ public class FeedUtils {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public static String handleContent(String content, String baseUri, boolean keepTextOnly) {
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
baseUri = StringUtils.trimToEmpty(baseUri);
|
||||
|
||||
Document dirty = Jsoup.parseBodyFragment(content, baseUri);
|
||||
Cleaner cleaner = new Cleaner(WHITELIST);
|
||||
Document clean = cleaner.clean(dirty);
|
||||
|
||||
for (Element e : clean.select("iframe[style]")) {
|
||||
String style = e.attr("style");
|
||||
String escaped = escapeIFrameCss(style);
|
||||
e.attr("style", escaped);
|
||||
}
|
||||
|
||||
for (Element e : clean.select("img[style]")) {
|
||||
String style = e.attr("style");
|
||||
String escaped = escapeImgCss(style);
|
||||
e.attr("style", escaped);
|
||||
}
|
||||
|
||||
clean.outputSettings(new OutputSettings().escapeMode(EscapeMode.base).prettyPrint(false));
|
||||
Element body = clean.body();
|
||||
if (keepTextOnly) {
|
||||
content = body.text();
|
||||
} else {
|
||||
content = body.html();
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
public static String escapeIFrameCss(String orig) {
|
||||
String rule = "";
|
||||
CSSOMParser parser = new CSSOMParser();
|
||||
try {
|
||||
List<String> rules = new ArrayList<>();
|
||||
CSSStyleDeclaration decl = parser.parseStyleDeclaration(new InputSource(new StringReader(orig)));
|
||||
|
||||
for (int i = 0; i < decl.getLength(); i++) {
|
||||
String property = decl.item(i);
|
||||
String value = decl.getPropertyValue(property);
|
||||
if (StringUtils.isBlank(property) || StringUtils.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_IFRAME_CSS_RULES.contains(property) && StringUtils.containsNone(value, FORBIDDEN_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property) + ";");
|
||||
}
|
||||
}
|
||||
rule = StringUtils.join(rules, "");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
public static String escapeImgCss(String orig) {
|
||||
String rule = "";
|
||||
CSSOMParser parser = new CSSOMParser();
|
||||
try {
|
||||
List<String> rules = new ArrayList<>();
|
||||
CSSStyleDeclaration decl = parser.parseStyleDeclaration(new InputSource(new StringReader(orig)));
|
||||
|
||||
for (int i = 0; i < decl.getLength(); i++) {
|
||||
String property = decl.item(i);
|
||||
String value = decl.getPropertyValue(property);
|
||||
if (StringUtils.isBlank(property) || StringUtils.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_IMG_CSS_RULES.contains(property) && StringUtils.containsNone(value, FORBIDDEN_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property) + ";");
|
||||
}
|
||||
}
|
||||
rule = StringUtils.join(rules, "");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
public static boolean isRTL(FeedEntry entry) {
|
||||
String text = entry.getContent().getContent();
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ public class UserSettings extends AbstractModel {
|
||||
private int scrollSpeed;
|
||||
|
||||
private boolean alwaysScrollToEntry;
|
||||
private boolean markAllAsReadConfirmation;
|
||||
private boolean customContextMenu;
|
||||
|
||||
private boolean email;
|
||||
private boolean gmail;
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryContentDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
@@ -14,7 +15,6 @@ import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.UnitOfWork;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
@@ -22,11 +22,10 @@ import lombok.extern.slf4j.Slf4j;
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
@Singleton
|
||||
public class DatabaseCleaningService {
|
||||
|
||||
private static final int BATCH_SIZE = 100;
|
||||
private final int batchSize;
|
||||
|
||||
private final UnitOfWork unitOfWork;
|
||||
private final FeedDAO feedDAO;
|
||||
@@ -34,17 +33,28 @@ public class DatabaseCleaningService {
|
||||
private final FeedEntryContentDAO feedEntryContentDAO;
|
||||
private final FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
|
||||
public long cleanFeedsWithoutSubscriptions() {
|
||||
@Inject
|
||||
public DatabaseCleaningService(CommaFeedConfiguration config, UnitOfWork unitOfWork, FeedDAO feedDAO, FeedEntryDAO feedEntryDAO,
|
||||
FeedEntryContentDAO feedEntryContentDAO, FeedEntryStatusDAO feedEntryStatusDAO) {
|
||||
this.unitOfWork = unitOfWork;
|
||||
this.feedDAO = feedDAO;
|
||||
this.feedEntryDAO = feedEntryDAO;
|
||||
this.feedEntryContentDAO = feedEntryContentDAO;
|
||||
this.feedEntryStatusDAO = feedEntryStatusDAO;
|
||||
this.batchSize = config.getApplicationSettings().getDatabaseCleanupBatchSize();
|
||||
}
|
||||
|
||||
public void cleanFeedsWithoutSubscriptions() {
|
||||
log.info("cleaning feeds without subscriptions");
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
int deleted;
|
||||
long entriesTotal = 0;
|
||||
do {
|
||||
List<Feed> feeds = unitOfWork.call(() -> feedDAO.findWithoutSubscriptions(1));
|
||||
for (Feed feed : feeds) {
|
||||
int entriesDeleted = 0;
|
||||
long entriesDeleted;
|
||||
do {
|
||||
entriesDeleted = unitOfWork.call(() -> feedEntryDAO.delete(feed.getId(), BATCH_SIZE));
|
||||
entriesDeleted = unitOfWork.call(() -> feedEntryDAO.delete(feed.getId(), batchSize));
|
||||
entriesTotal += entriesDeleted;
|
||||
log.info("removed {} entries for feeds without subscriptions", entriesTotal);
|
||||
} while (entriesDeleted > 0);
|
||||
@@ -54,26 +64,24 @@ public class DatabaseCleaningService {
|
||||
log.info("removed {} feeds without subscriptions", total);
|
||||
} while (deleted != 0);
|
||||
log.info("cleanup done: {} feeds without subscriptions deleted", total);
|
||||
return total;
|
||||
}
|
||||
|
||||
public long cleanContentsWithoutEntries() {
|
||||
public void cleanContentsWithoutEntries() {
|
||||
log.info("cleaning contents without entries");
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
long deleted;
|
||||
do {
|
||||
deleted = unitOfWork.call(() -> feedEntryContentDAO.deleteWithoutEntries(BATCH_SIZE));
|
||||
deleted = unitOfWork.call(() -> feedEntryContentDAO.deleteWithoutEntries(batchSize));
|
||||
total += deleted;
|
||||
log.info("removed {} contents without entries", total);
|
||||
} while (deleted != 0);
|
||||
log.info("cleanup done: {} contents without entries deleted", total);
|
||||
return total;
|
||||
}
|
||||
|
||||
public long cleanEntriesForFeedsExceedingCapacity(final int maxFeedCapacity) {
|
||||
public void cleanEntriesForFeedsExceedingCapacity(final int maxFeedCapacity) {
|
||||
long total = 0;
|
||||
while (true) {
|
||||
List<FeedCapacity> feeds = unitOfWork.call(() -> feedEntryDAO.findFeedsExceedingCapacity(maxFeedCapacity, BATCH_SIZE));
|
||||
List<FeedCapacity> feeds = unitOfWork.call(() -> feedEntryDAO.findFeedsExceedingCapacity(maxFeedCapacity, batchSize));
|
||||
if (feeds.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
@@ -82,7 +90,7 @@ public class DatabaseCleaningService {
|
||||
long remaining = feed.getCapacity() - maxFeedCapacity;
|
||||
do {
|
||||
final long rem = remaining;
|
||||
int deleted = unitOfWork.call(() -> feedEntryDAO.deleteOldEntries(feed.getId(), Math.min(BATCH_SIZE, rem)));
|
||||
int deleted = unitOfWork.call(() -> feedEntryDAO.deleteOldEntries(feed.getId(), Math.min(batchSize, rem)));
|
||||
total += deleted;
|
||||
remaining -= deleted;
|
||||
log.info("removed {} entries for feeds exceeding capacity", total);
|
||||
@@ -90,19 +98,17 @@ public class DatabaseCleaningService {
|
||||
}
|
||||
}
|
||||
log.info("cleanup done: {} entries for feeds exceeding capacity deleted", total);
|
||||
return total;
|
||||
}
|
||||
|
||||
public long cleanStatusesOlderThan(final Date olderThan) {
|
||||
public void cleanStatusesOlderThan(final Date olderThan) {
|
||||
log.info("cleaning old read statuses");
|
||||
long total = 0;
|
||||
int deleted = 0;
|
||||
long deleted;
|
||||
do {
|
||||
deleted = unitOfWork.call(() -> feedEntryStatusDAO.delete(feedEntryStatusDAO.getOldStatuses(olderThan, BATCH_SIZE)));
|
||||
deleted = unitOfWork.call(() -> feedEntryStatusDAO.deleteOldStatuses(olderThan, batchSize));
|
||||
total += deleted;
|
||||
log.info("removed {} old read statuses", total);
|
||||
} while (deleted != 0);
|
||||
log.info("cleanup done: {} old read statuses deleted", total);
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.commafeed.backend.service;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -8,27 +11,47 @@ import javax.inject.Singleton;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Document;
|
||||
import org.jsoup.nodes.Document.OutputSettings;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.nodes.Entities.EscapeMode;
|
||||
import org.jsoup.safety.Cleaner;
|
||||
import org.jsoup.safety.Safelist;
|
||||
import org.w3c.css.sac.CSSException;
|
||||
import org.w3c.css.sac.CSSParseException;
|
||||
import org.w3c.css.sac.ErrorHandler;
|
||||
import org.w3c.css.sac.InputSource;
|
||||
import org.w3c.dom.css.CSSStyleDeclaration;
|
||||
|
||||
import com.commafeed.backend.dao.FeedEntryContentDAO;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.steadystate.css.parser.CSSOMParser;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class FeedEntryContentService {
|
||||
|
||||
private static final Safelist HTML_WHITELIST = buildWhiteList();
|
||||
private static final List<String> ALLOWED_IFRAME_CSS_RULES = Arrays.asList("height", "width", "border");
|
||||
private static final List<String> ALLOWED_IMG_CSS_RULES = Arrays.asList("display", "width", "height");
|
||||
private static final char[] FORBIDDEN_CSS_RULE_CHARACTERS = new char[] { '(', ')' };
|
||||
|
||||
private final FeedEntryContentDAO feedEntryContentDAO;
|
||||
|
||||
/**
|
||||
* this is NOT thread-safe
|
||||
*/
|
||||
public FeedEntryContent findOrCreate(FeedEntryContent content, String baseUrl) {
|
||||
content.setAuthor(FeedUtils.truncate(FeedUtils.handleContent(content.getAuthor(), baseUrl, true), 128));
|
||||
content.setTitle(FeedUtils.truncate(FeedUtils.handleContent(content.getTitle(), baseUrl, true), 2048));
|
||||
content.setContent(FeedUtils.handleContent(content.getContent(), baseUrl, false));
|
||||
content.setMediaDescription(FeedUtils.handleContent(content.getMediaDescription(), baseUrl, false));
|
||||
content.setAuthor(FeedUtils.truncate(handleContent(content.getAuthor(), baseUrl, true), 128));
|
||||
content.setTitle(FeedUtils.truncate(handleContent(content.getTitle(), baseUrl, true), 2048));
|
||||
content.setContent(handleContent(content.getContent(), baseUrl, false));
|
||||
content.setMediaDescription(handleContent(content.getMediaDescription(), baseUrl, false));
|
||||
|
||||
String contentHash = DigestUtils.sha1Hex(StringUtils.trimToEmpty(content.getContent()));
|
||||
content.setContentHash(contentHash);
|
||||
@@ -37,7 +60,7 @@ public class FeedEntryContentService {
|
||||
content.setTitleHash(titleHash);
|
||||
|
||||
List<FeedEntryContent> existing = feedEntryContentDAO.findExisting(contentHash, titleHash);
|
||||
Optional<FeedEntryContent> equivalentContent = existing.stream().filter(c -> content.equivalentTo(c)).findFirst();
|
||||
Optional<FeedEntryContent> equivalentContent = existing.stream().filter(content::equivalentTo).findFirst();
|
||||
if (equivalentContent.isPresent()) {
|
||||
return equivalentContent.get();
|
||||
}
|
||||
@@ -45,4 +68,140 @@ public class FeedEntryContentService {
|
||||
feedEntryContentDAO.saveOrUpdate(content);
|
||||
return content;
|
||||
}
|
||||
|
||||
private static Safelist buildWhiteList() {
|
||||
Safelist whitelist = new Safelist();
|
||||
whitelist.addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "dl", "dt", "em", "h1",
|
||||
"h2", "h3", "h4", "h5", "h6", "i", "iframe", "img", "li", "ol", "p", "pre", "q", "small", "strike", "strong", "sub", "sup",
|
||||
"table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul");
|
||||
|
||||
whitelist.addAttributes("div", "dir");
|
||||
whitelist.addAttributes("pre", "dir");
|
||||
whitelist.addAttributes("code", "dir");
|
||||
whitelist.addAttributes("table", "dir");
|
||||
whitelist.addAttributes("p", "dir");
|
||||
whitelist.addAttributes("a", "href", "title");
|
||||
whitelist.addAttributes("blockquote", "cite");
|
||||
whitelist.addAttributes("col", "span", "width");
|
||||
whitelist.addAttributes("colgroup", "span", "width");
|
||||
whitelist.addAttributes("iframe", "src", "height", "width", "allowfullscreen", "frameborder", "style");
|
||||
whitelist.addAttributes("img", "align", "alt", "height", "src", "title", "width", "style");
|
||||
whitelist.addAttributes("ol", "start", "type");
|
||||
whitelist.addAttributes("q", "cite");
|
||||
whitelist.addAttributes("table", "border", "bordercolor", "summary", "width");
|
||||
whitelist.addAttributes("td", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "width");
|
||||
whitelist.addAttributes("th", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "scope", "width");
|
||||
whitelist.addAttributes("ul", "type");
|
||||
|
||||
whitelist.addProtocols("a", "href", "ftp", "http", "https", "magnet", "mailto");
|
||||
whitelist.addProtocols("blockquote", "cite", "http", "https");
|
||||
whitelist.addProtocols("img", "src", "http", "https");
|
||||
whitelist.addProtocols("q", "cite", "http", "https");
|
||||
|
||||
whitelist.addEnforcedAttribute("a", "target", "_blank");
|
||||
whitelist.addEnforcedAttribute("a", "rel", "noreferrer");
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
private String handleContent(String content, String baseUri, boolean keepTextOnly) {
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
baseUri = StringUtils.trimToEmpty(baseUri);
|
||||
|
||||
Document dirty = Jsoup.parseBodyFragment(content, baseUri);
|
||||
Cleaner cleaner = new Cleaner(HTML_WHITELIST);
|
||||
Document clean = cleaner.clean(dirty);
|
||||
|
||||
for (Element e : clean.select("iframe[style]")) {
|
||||
String style = e.attr("style");
|
||||
String escaped = escapeIFrameCss(style);
|
||||
e.attr("style", escaped);
|
||||
}
|
||||
|
||||
for (Element e : clean.select("img[style]")) {
|
||||
String style = e.attr("style");
|
||||
String escaped = escapeImgCss(style);
|
||||
e.attr("style", escaped);
|
||||
}
|
||||
|
||||
clean.outputSettings(new OutputSettings().escapeMode(EscapeMode.base).prettyPrint(false));
|
||||
Element body = clean.body();
|
||||
if (keepTextOnly) {
|
||||
content = body.text();
|
||||
} else {
|
||||
content = body.html();
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private String escapeIFrameCss(String orig) {
|
||||
String rule = "";
|
||||
try {
|
||||
List<String> rules = new ArrayList<>();
|
||||
CSSStyleDeclaration decl = buildCssParser().parseStyleDeclaration(new InputSource(new StringReader(orig)));
|
||||
|
||||
for (int i = 0; i < decl.getLength(); i++) {
|
||||
String property = decl.item(i);
|
||||
String value = decl.getPropertyValue(property);
|
||||
if (StringUtils.isBlank(property) || StringUtils.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_IFRAME_CSS_RULES.contains(property) && StringUtils.containsNone(value, FORBIDDEN_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property) + ";");
|
||||
}
|
||||
}
|
||||
rule = StringUtils.join(rules, "");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
private String escapeImgCss(String orig) {
|
||||
String rule = "";
|
||||
try {
|
||||
List<String> rules = new ArrayList<>();
|
||||
CSSStyleDeclaration decl = buildCssParser().parseStyleDeclaration(new InputSource(new StringReader(orig)));
|
||||
|
||||
for (int i = 0; i < decl.getLength(); i++) {
|
||||
String property = decl.item(i);
|
||||
String value = decl.getPropertyValue(property);
|
||||
if (StringUtils.isBlank(property) || StringUtils.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_IMG_CSS_RULES.contains(property) && StringUtils.containsNone(value, FORBIDDEN_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property) + ";");
|
||||
}
|
||||
}
|
||||
rule = StringUtils.join(rules, "");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
|
||||
private CSSOMParser buildCssParser() {
|
||||
CSSOMParser parser = new CSSOMParser();
|
||||
|
||||
parser.setErrorHandler(new ErrorHandler() {
|
||||
@Override
|
||||
public void warning(CSSParseException exception) throws CSSException {
|
||||
log.debug("warning while parsing css: {}", exception.getMessage(), exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(CSSParseException exception) throws CSSException {
|
||||
log.debug("error while parsing css: {}", exception.getMessage(), exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(CSSParseException exception) throws CSSException {
|
||||
log.debug("fatal error while parsing css: {}", exception.getMessage(), exception);
|
||||
}
|
||||
});
|
||||
|
||||
return parser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ public class Settings implements Serializable {
|
||||
@ApiModelProperty(value = "always scroll selected entry to the top of the page, even if it fits entirely on screen", required = true)
|
||||
private boolean alwaysScrollToEntry;
|
||||
|
||||
@ApiModelProperty(value = "ask for confirmation when marking all entries as read", required = true)
|
||||
private boolean markAllAsReadConfirmation;
|
||||
|
||||
@ApiModelProperty(value = "show commafeed's own context menu on right click", required = true)
|
||||
private boolean customContextMenu;
|
||||
|
||||
@ApiModelProperty(value = "sharing settings", required = true)
|
||||
private SharingSettings sharingSettings = new SharingSettings();
|
||||
|
||||
|
||||
@@ -23,19 +23,16 @@ public class Subscription implements Serializable {
|
||||
@ApiModelProperty(value = "subscription name", required = true)
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "error message while fetching the feed", required = true)
|
||||
@ApiModelProperty(value = "error message while fetching the feed")
|
||||
private String message;
|
||||
|
||||
@ApiModelProperty(value = "error count", required = true)
|
||||
private int errorCount;
|
||||
|
||||
@ApiModelProperty(value = "last time the feed was refreshed", dataType = "number", required = true)
|
||||
@ApiModelProperty(value = "last time the feed was refreshed", dataType = "number")
|
||||
private Date lastRefresh;
|
||||
|
||||
@ApiModelProperty(
|
||||
value = "next time the feed refresh is planned, null if refresh is already queued",
|
||||
dataType = "number",
|
||||
required = true)
|
||||
@ApiModelProperty(value = "next time the feed refresh is planned, null if refresh is already queued", dataType = "number")
|
||||
private Date nextRefresh;
|
||||
|
||||
@ApiModelProperty(value = "this subscription's feed url", required = true)
|
||||
|
||||
@@ -30,7 +30,7 @@ public class UserModel implements Serializable {
|
||||
@ApiModelProperty(value = "account status", required = true)
|
||||
private boolean enabled;
|
||||
|
||||
@ApiModelProperty(value = "account creation date", dataType = "number", required = true)
|
||||
@ApiModelProperty(value = "account creation date", dataType = "number")
|
||||
private Date created;
|
||||
|
||||
@ApiModelProperty(value = "last login date", dataType = "number")
|
||||
|
||||
@@ -104,6 +104,8 @@ public class UserREST {
|
||||
s.setLanguage(settings.getLanguage());
|
||||
s.setScrollSpeed(settings.getScrollSpeed());
|
||||
s.setAlwaysScrollToEntry(settings.isAlwaysScrollToEntry());
|
||||
s.setMarkAllAsReadConfirmation(settings.isMarkAllAsReadConfirmation());
|
||||
s.setCustomContextMenu(settings.isCustomContextMenu());
|
||||
} else {
|
||||
s.setReadingMode(ReadingMode.unread.name());
|
||||
s.setReadingOrder(ReadingOrder.desc.name());
|
||||
@@ -122,6 +124,8 @@ public class UserREST {
|
||||
s.setLanguage("en");
|
||||
s.setScrollSpeed(400);
|
||||
s.setAlwaysScrollToEntry(false);
|
||||
s.setMarkAllAsReadConfirmation(true);
|
||||
s.setCustomContextMenu(true);
|
||||
}
|
||||
return Response.ok(s).build();
|
||||
}
|
||||
@@ -148,6 +152,8 @@ public class UserREST {
|
||||
s.setLanguage(settings.getLanguage());
|
||||
s.setScrollSpeed(settings.getScrollSpeed());
|
||||
s.setAlwaysScrollToEntry(settings.isAlwaysScrollToEntry());
|
||||
s.setMarkAllAsReadConfirmation(settings.isMarkAllAsReadConfirmation());
|
||||
s.setCustomContextMenu(settings.isCustomContextMenu());
|
||||
|
||||
s.setEmail(settings.getSharingSettings().isEmail());
|
||||
s.setGmail(settings.getSharingSettings().isGmail());
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
|
||||
<changeSet id="mark-all-as-read-confirmation" author="athou">
|
||||
<addColumn tableName="USERSETTINGS">
|
||||
<column name="markAllAsReadConfirmation" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="custom-context-menu" author="athou">
|
||||
<addColumn tableName="USERSETTINGS">
|
||||
<column name="customContextMenu" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -21,5 +21,6 @@
|
||||
<include file="changelogs/db.changelog-3.5.xml" />
|
||||
<include file="changelogs/db.changelog-3.6.xml" />
|
||||
<include file="changelogs/db.changelog-3.8.xml" />
|
||||
<include file="changelogs/db.changelog-3.9.xml" />
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -28,6 +28,9 @@ app:
|
||||
# number of database updating threads
|
||||
databaseUpdateThreads: 1
|
||||
|
||||
# rows to delete per query while cleaning up old entries
|
||||
databaseCleanupBatchSize: 100
|
||||
|
||||
# settings for sending emails (password recovery)
|
||||
smtpHost: localhost
|
||||
smtpPort: 25
|
||||
@@ -80,9 +83,13 @@ app:
|
||||
userAgent:
|
||||
|
||||
# Database connection
|
||||
# -------------------
|
||||
# -------------------
|
||||
# for MariaDB
|
||||
# driverClass is org.mariadb.jdbc.Driver
|
||||
# url is jdbc:mariadb://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for MySQL
|
||||
# driverClass is com.mysql.jdbc.Driver
|
||||
# driverClass is com.mysql.cj.jdbc.Driver
|
||||
# url is jdbc:mysql://localhost/commafeed?autoReconnect=true&failOverReadOnly=false&maxReconnects=20&rewriteBatchedStatements=true
|
||||
#
|
||||
# for PostgreSQL
|
||||
|
||||
Reference in New Issue
Block a user