Compare commits

..

93 Commits

Author SHA1 Message Date
Athou
9f421ec3b0 add context menu to navigate to feed if a category is displayed 2023-02-27 19:56:32 +01:00
Athou
69fb11eee0 add context menu item to open link in new tab 2023-02-27 07:41:13 +01:00
Athou
ffbb85df43 add context menu on entry headers 2023-02-24 15:18:04 +01:00
Athou
a4e78c4e0d throttle event 2023-02-24 14:53:30 +01:00
Athou
6d4b0cbdef bump all dependencies 2023-02-04 08:34:23 +01:00
Athou
ea4b120a85 prevent full feed fetching next time we fetch it if caching header values changed but content did not (#1037) 2023-01-27 08:49:59 +01:00
Athou
5c2454c331 bring back "refresh all my feeds" (#1036) 2023-01-19 07:29:19 +01:00
Athou
4ff46965c4 add websocket support to immediately refresh tree when new entries are available 2023-01-18 20:58:45 +01:00
Athou
33e3f7ea3c feeds added manually to the queue now refresh immediately instead of waiting up to 15s (#1036) 2023-01-18 18:53:38 +01:00
Athou
347fc4f2c8 allow to force refresh feed anytime (#1036) 2023-01-18 18:53:38 +01:00
Athou
2b4ff4a8a5 on fetch error and not under heavy load, don't increase refresh interval exponentially 2023-01-18 18:53:38 +01:00
Jorengarenar
f7d34983e0 Allow API key for count of unread 2023-01-10 00:34:25 +01:00
Athou
3271d69fcb allow session configuration (#1028) 2023-01-04 11:32:08 +01:00
Jérémie Panzer
7ea24b21f8 Merge pull request #1023 from Jorengarenar/develop
Enable environment variables in config.yml
2023-01-04 07:26:23 +01:00
Jorengarenar
b2b608e8c3 Enable environment variables in config.yml 2023-01-03 19:46:01 +01:00
Athou
e44ea5bc96 re-add dropwizard-migrations to be able to use liquibase from command line 2022-11-15 10:48:55 +01:00
Athou
fa58b1e53f reload entries after marking everything as read, as commafeed 2.x does 2022-11-15 08:24:18 +01:00
Athou
9466bc544c show placeholder when favicon is loading 2022-11-08 11:57:59 +01:00
Athou
9e65f5726c require src and alt for images 2022-11-08 11:52:47 +01:00
Athou
fc2c3740a0 dependencies update 2022-11-08 11:52:47 +01:00
Athou
2095a6512b make compact mode more compact 2022-11-05 14:13:19 +01:00
Athou
a461a72224 enable maven cache to speed up build 2022-11-04 09:08:21 +01:00
Athou
f9e7653901 restore swipe-to-right to toggle read/unread status (#1019) 2022-11-04 08:57:33 +01:00
Athou
a11e528b8d restore title ellipsis when overflowing 2022-10-29 17:55:21 +02:00
Athou
c0937aa473 reduce sharing icon background size 2022-10-29 08:38:31 +02:00
Athou
fecd6451d5 reduce spacing between buttons to fix toolbar not fitting on a single line on mobile 2022-10-29 08:32:41 +02:00
Athou
fb96631351 add locales that were supported by commafeed 2.x 2022-10-28 17:02:43 +02:00
Athou
a16450be5d add missing keyboard shortcut in help 2022-10-28 13:33:43 +02:00
Athou
02628b5886 add clear button for search 2022-10-28 13:33:43 +02:00
Athou
60e37deae8 bump all dependencies 2022-10-28 10:25:43 +02:00
Athou
21922265e4 changelog update 2022-10-28 10:25:34 +02:00
Athou
42c740eaff readme update 2022-10-28 10:24:33 +02:00
Athou
d187c23a77 add search support 2022-10-27 21:38:28 +02:00
Athou
9252042c99 fix loadMoreEntries for tags 2022-10-27 15:19:45 +02:00
Athou
66c5a471e3 add missing translations 2022-10-27 14:55:53 +02:00
Athou
91c48bedd3 separate theme from layout in profile menu 2022-10-27 14:55:53 +02:00
Athou
c882ad5399 use ActionButton to reduce space used on mobile 2022-10-27 14:55:50 +02:00
Athou
b3700dc09e scrolling on mobile triggers a click outside 2022-10-27 14:55:30 +02:00
Athou
b06187ddf7 add indicator when there are tags 2022-10-27 14:32:23 +02:00
Athou
cf69bb2013 autofocus tag input 2022-10-25 18:05:46 +02:00
Athou
81b284ad94 readme update 2022-10-25 13:40:39 +02:00
Athou
f838f877fa add support for tags 2022-10-25 12:21:07 +02:00
Athou
d7c6f8eb52 select and mark entry as read when scrolling in expanded view 2022-10-13 13:20:14 +02:00
Athou
6f49f1fe01 use preferred color scheme as initial value 2022-10-12 12:26:02 +02:00
Athou
e75c4554a5 use darker orange in light theme 2022-10-12 12:23:07 +02:00
Athou
58852502dc remove some clutter by removing shadow in light theme 2022-10-12 12:21:45 +02:00
Athou
a151646850 update all dependencies 2022-10-12 08:34:52 +02:00
Athou
97d290de9d add support for "n" and "p" keyboard shortcuts 2022-10-12 08:08:16 +02:00
Athou
438b255708 give responsibility of marking as read and expanding to caller 2022-10-11 15:11:13 +02:00
Athou
90d2ad6b19 fix scrolling for "j" and "k" keyboard shortcuts 2022-09-13 18:10:30 +02:00
Athou
21fcae52b2 remove unnecessary html 2022-09-13 17:01:29 +02:00
Athou
d72c9ba247 add compact headers 2022-09-05 14:54:14 +02:00
Athou
27f80148cb add missing alt attributes 2022-08-26 08:43:24 +02:00
Athou
1daf57a4bd show placeholder while favicon is loading 2022-08-26 08:23:28 +02:00
Athou
3999532e77 initial RTL support 2022-08-26 08:13:36 +02:00
Athou
126a5e3bbc add "mark as read up to here" 2022-08-24 09:11:52 +02:00
Athou
a1fb5871d1 add initial support for expanded mode 2022-08-24 08:36:13 +02:00
Athou
4c18ebf61a load swagger-ui css lazily 2022-08-22 14:49:24 +02:00
Athou
8bc6a2adcc remove StrictMode, it doesn't really help and causes all components to be rendered twice in dev 2022-08-22 13:43:14 +02:00
Athou
475c0673a0 add "show feeds and categories with no unread entries" option 2022-08-22 13:24:52 +02:00
Athou
f81491fb32 show placeholders for loading img tags, this allows the entry to have its final height immediately 2022-08-22 10:45:19 +02:00
Athou
1f2a265c54 mvnw update 2022-08-21 09:05:00 +02:00
Athou
fbfe16e784 return relative urls to rely less on publicUrl where possible (#1016) 2022-08-20 11:37:30 +02:00
Athou
c6439fe020 prevent caching of index.html so that the webapp is always up to date 2022-08-19 16:17:10 +02:00
Athou
7e605e5cda add sharing buttons 2022-08-19 16:17:10 +02:00
Athou
973fe56cc8 add support for starring entries 2022-08-19 14:58:47 +02:00
Athou
91bc7fa4b0 various dependency updates 2022-08-19 14:58:47 +02:00
Athou
051fa37949 scroll only if the entry doesn't entirely fit on screen (same as commafeed v1) 2022-08-19 14:58:47 +02:00
Athou
243aaac3da vite eslint plugin 1.8.1 fixes the issue that required us to override the default exclude filter 2022-08-17 16:01:04 +02:00
Athou
a8db632c4a support for marking entries older than a threshold 2022-08-15 21:30:07 +02:00
Athou
11f5b22cb4 reorganize about page a little 2022-08-15 18:32:18 +02:00
Athou
5967706daa git-commit-id-plugin can now retrieve commit information during github action 2022-08-15 18:27:12 +02:00
Athou
9c02eba0dc add api documentation page 2022-08-15 16:38:29 +02:00
Athou
e2340c2e98 add about page 2022-08-15 15:19:11 +02:00
Athou
a8e818f97f extract page title to its own component 2022-08-15 10:08:08 +02:00
Athou
6f26c54b62 add details page for "All" to be be able to get the generated feed url 2022-08-15 10:08:08 +02:00
Athou
448feedace style entries content with mantine styles 2022-08-15 10:08:08 +02:00
Athou
eefc1ee0d7 add metrics page 2022-08-15 10:08:08 +02:00
Athou
d2eac62273 add error page 2022-08-15 10:08:08 +02:00
Athou
ee89b34ab8 dependencies update 2022-08-14 13:31:17 +02:00
Athou
2d8584b72d store build result 2022-08-14 13:14:23 +02:00
Athou
e803ce13eb trigger reload manually instead of relying on effects 2022-08-13 22:05:19 +02:00
Athou
4e5fd18eea redirect to new feed after subscribe now works even for existing feeds 2022-08-13 19:00:58 +02:00
Athou
9ec62bc1de display error when importing invalid OPML file 2022-08-13 18:46:08 +02:00
Athou
906acb217a react-async-hook library provides useAsyncCallback that does the same thing as useMutation 2022-08-13 18:38:11 +02:00
Athou
6c6cc8d85b return smaller error when trying to subscribe to an invalid feed 2022-08-13 18:05:24 +02:00
Athou
5cb09bc4c6 show information about demo account if enabled 2022-08-13 18:00:07 +02:00
Athou
198d9fb17e no need to send a redirect after importing an opml file anymore 2022-08-13 17:45:19 +02:00
Athou
33b87312f4 redirect to new feed after subscribe 2022-08-13 17:41:41 +02:00
Athou
ece9b993e0 add playwright tests 2022-08-13 17:41:41 +02:00
Athou
04894f118b replace old client with new client from commafeed-ui repository 2022-08-13 17:41:41 +02:00
Athou
ac7b6eeb21 split client and server into maven modules 2022-08-13 10:48:09 +02:00
Athou
4c4868a2b6 cleanup demo account every 24h (#1014) 2022-08-08 16:53:43 +02:00
414 changed files with 49412 additions and 13710 deletions

View File

@@ -1,3 +0,0 @@
{
"directory": "src/main/app/lib"
}

View File

@@ -3,18 +3,26 @@ name: Java CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: ["8", "11", "17"]
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: ["8", "11", "17"]
steps:
- uses: actions/checkout@v3
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: "temurin"
- name: Build with Maven
run: mvn --batch-mode --update-snapshots verify
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Java
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: "temurin"
cache: "maven"
- name: Build with Maven
run: mvn --batch-mode --update-snapshots verify
- uses: actions/upload-artifact@v3
if: ${{ matrix.java == '8' }}
with:
name: commafeed.jar
path: commafeed-server/target/commafeed.jar

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

18
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar

View File

@@ -1,3 +1,8 @@
v 3.0.0
- complete overhaul of the UI
- backend and frontend are now in separate maven modules
- no changes to the api or the database
v 2.6.0
- add support for media content as a backup for missing content (useful for youtube feeds)
- correctly follow http error code 308 redirects

View File

@@ -1,4 +1,4 @@
# CommaFeed [![Build Status](https://travis-ci.org/Athou/commafeed.svg?branch=master)](https://travis-ci.org/Athou/commafeed)
# CommaFeed
Sources for [CommaFeed.com](http://www.commafeed.com/).
@@ -7,17 +7,20 @@ CommaFeed is now considered feature-complete and is in maintenance mode.
## Related open-source projects
Android apps: [News+ extension](https://github.com/Athou/commafeed-newsplus)
Browser extensions:
Browser extensions: [Chrome](https://github.com/Athou/commafeed-chrome) - [Firefox](https://github.com/Athou/commafeed-firefox) - [Opera](https://github.com/Athou/commafeed-opera) - [Safari](https://github.com/Athou/commafeed-safari)
- [Chrome](https://github.com/Athou/commafeed-chrome)
- [Firefox](https://github.com/Athou/commafeed-firefox)
- [Opera](https://github.com/Athou/commafeed-opera)
- [Safari](https://github.com/Athou/commafeed-safari)
## Deployment on your own server
### The very short version (download precompiled package)
mkdir commafeed && cd commafeed
wget https://github.com/Athou/commafeed/releases/download/2.6.0/commafeed.jar
wget https://raw.githubusercontent.com/Athou/commafeed/2.6.0/config.yml.example -O config.yml
wget https://github.com/Athou/commafeed/releases/download/3.0.0/commafeed.jar
wget https://raw.githubusercontent.com/Athou/commafeed/3.0.0/commafeed-server/config.yml.example -O config.yml
vi config.yml
java -Djava.net.preferIPv4Stack=true -jar commafeed.jar server config.yml
@@ -26,9 +29,9 @@ Browser extensions: [Chrome](https://github.com/Athou/commafeed-chrome) - [Firef
git clone https://github.com/Athou/commafeed.git
cd commafeed
./mvnw clean package
cp config.yml.example config.yml
cp commafeed-server/config.yml.example config.yml
vi config.yml
java -Djava.net.preferIPv4Stack=true -jar target/commafeed.jar server config.yml
java -Djava.net.preferIPv4Stack=true -jar commafeed-server/target/commafeed.jar server config.yml
### The long version (same as the short version, but more detailed)
@@ -39,6 +42,9 @@ You also need the Java 1.8+ JDK in order to build the application.
To install the required packages to build CommaFeed on Ubuntu, issue the following commands
# if this commands works and returns a version >= 1.8.0 you're good to go and you can skip JDK installation
javac -version
# if openjdk-8-jdk is not available on your ubuntu version (14.04 LTS), add the following repo first
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
@@ -58,56 +64,48 @@ Now build the application
./mvnw clean package
Copy `config.yml.example` to `config.yml` then edit the file to your liking.
Copy `commafeed-server/config.yml.example` to `./config.yml` then edit the file to your liking.
Issue the following command to run the app, the server will listen by default on `http://localhost:8082`. The default user is `admin` and the default password is `admin`.
java -Djava.net.preferIPv4Stack=true -jar target/commafeed.jar server config.yml
java -Djava.net.preferIPv4Stack=true -jar commafeed-server/target/commafeed.jar server config.yml
You can use a proxy http server such as nginx or apache.
## Translate CommaFeed into your language
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/src/main/app/i18n).
Files for internationalization are located [here](https://github.com/Athou/commafeed/tree/master/commafeed-client/src/locales).
To add a new language, create a new file in that directory.
The name of the file should be the two-letters [ISO-639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
The language has to be referenced in the `src/main/app/js/i18n.js` file to be picked up.
To add a new language:
## Themes
- edit `commafeed-client/src/i18n.ts`
- add the new locale to the `locales` array.
- import the dayjs locale
- edit `commafeed-client/.linguirc` and add the new locale to the `locales` array.
- run `npm run i18n` and add translations to the newly created `commafeed-client/src/locales/[locale]/messages.po` file
To create a theme, create a new file `src/main/app/sass/themes/_<theme>.scss`. Your styles should be wrapped in a `#theme-<theme>` element and use the [SCSS format](http://sass-lang.com/) which is a superset of CSS.
Don't forget to reference your theme in `src/main/app/sass/app.scss` and in `src/main/app/js/controllers.js` (look for `$scope.themes`).
See [\_test.scss](https://github.com/Athou/commafeed/blob/master/src/main/app/sass/themes/_test.scss) for an example.
The name of the locale should be the two-letters [ISO-639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
## Local development
Steps to configuring a development environment for CommaFeed may include, but may not be limited to:
- `git clone https://github.com/Athou/CommaFeed`
1. `git clone https://github.com/Athou/CommaFeed` into some folder to get the project files.
2. Install Eclipse Luna (or latest) from http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/lunasr1 or your repo if available.
3. In Eclipse, Window → Preferences → Maven → Annotation Processing. Check "Automatically configure JDT APT"
- You may have to install the m2e-apt connector to have "Annotation Processing" as an option. Do so from Window → Preferences → Maven → Discovery → Open Catalog → type "m2e-apt" in the search box
- If you have installed Eclipse EE instead of Luna, you may have trouble installing m2e-apt
4. Install Lombok into Eclipse from http://projectlombok.org/download.html
- You may have to run `java -jar lombok.jar` as an administrator if your eclipse installation is not in your home folder
5. In Eclipse, File → Import → Maven → Existing Maven Projects. Navigate to where you cloned the CommaFeed files into, and select that as the root directory. Click Finish.
- You may notice some errors along the lines of "Plugin execution not covered by lifecycle configuration". These are inconsequential.
6. Find the file "CommaFeedApplication.java" under the navigation pane.
7. Right click it to bring up the context menu → Debug as... → Debug Configurations
8. Type `server config.dev.yml` under "Program arguments" in the "Arguments" tab for the Java Application setting "CommaFeedApplication"
9. Apply and hit "Debug"
10. The debugger is now working. To connect to it, open a terminal (or command prompt) and navigate to the directory where you cloned the CommaFeed files.
11. Issue the command `gulp dev` on Unix based systems or `gulp.cmd dev` in Windows.
12. The development server is now running at http://localhost:8082 and is proxying REST requests to dropwizard on port 8083.
13. Connect to the server from your browser; you should have functional breakpoints and watches on assets.
14. When you're done developing, create a fork at the top of https://github.com/Athou/CommaFeed page and commit your changes to it.
15. If you'd like to contribute to CommaFeed, create a pull request from your repository to https://github.com/Athou/CommaFeed when your changes are ready. There's a button to do so at the top of https://github.com/Athou/CommaFeed.
### Backend
- Open `commafeed-server` in your preferred Java IDE.
- CommaFeed uses Lombok, you need the Lombok plugin for your IDE.
- If using Eclipse, Go to Window → Preferences → Maven → Annotation Processing and check "Automatically configure JDT APT"
- Start `CommaFeedApplication.java` in debug mode with `server config.dev.yml` as arguments
### Frontend
- Open `commafeed-client` in your preferred JavaScript IDE.
- run `npm install`
- run `npm run dev`
- the frontend server is now running at http://localhost:8082 and is proxying REST requests to the backend running on port 8083
## Copyright and license
Copyright 2013-2016 CommaFeed.
Copyright 2013-2022 CommaFeed.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this work except in compliance with the License.

View File

@@ -1,37 +0,0 @@
{
"name": "commafeed",
"version": "2.0.0",
"dependencies": {
"jquery": "2.1.3",
"jquery-ui": "1.10.3",
"jquery-mousewheel": "3.1.12",
"lodash": "3.4.0",
"bootstrap": "3.3.2",
"font-awesome": "3.2.1",
"angular": "1.3.14",
"angular-resource": "1.3.14",
"angular-route": "1.3.14",
"angular-sanitize": "1.3.14",
"angular-touch": "1.3.14",
"angular-animate": "1.3.14",
"angular-ui-router": "0.2.13",
"angular-ui-utils": "0.1.0",
"angular-ui-select2": "0.0.5",
"angular-bootstrap": "0.2.0",
"angular-loading-bar": "0.6.0",
"angular-translate": "2.6.1",
"angular-translate-loader-static-files": "2.6.1",
"ngInfiniteScroll": "1.0.0",
"ng-grid": "2.0.6",
"mousetrap": "1.4.6",
"momentjs": "2.9.0",
"devicejs": "0.2.4",
"zocial-less": "1.0.0",
"swagger-ui": "2.1.0",
"tinycon": "0.6.5"
},
"resolutions": {
"angular": "1.3.14",
"angular-translate": "2.6.1"
}
}

View File

@@ -0,0 +1,6 @@
dist
node_modules
vite.config.ts
src/locales/**/*.ts

View File

@@ -0,0 +1,85 @@
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"react-app",
"airbnb",
"airbnb-typescript",
"prettier"
],
"plugins": ["@typescript-eslint", "prettier", "hooks"],
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
// make eslint check prettier rules
"prettier/prettier": "error",
// enforce consistent curly braces usage
"curly": ["error", "multi-line", "consistent"],
// set "props" to false because it cases false positives with immer
"no-param-reassign": ["error", { "props": false }],
"prefer-destructuring": [
"error",
{
"array": false,
"object": true
},
{
"enforceForRenamedProperties": false
}
],
// causes issues in thunks when we want to dispatch an action that is defined in the reducer
"@typescript-eslint/no-use-before-define": "off",
// make sure the key prop is filled when required
"react/jsx-key": ["error", { "checkFragmentShorthand": true }],
// configure additional hooks
"react-hooks/exhaustive-deps": [
"warn",
{
"additionalHooks": "(^useAsync$|useDidUpdate)"
}
],
// trigger even if props is used only in createStyles()
"react/no-unused-prop-types": "off",
// no longer required with modern react versions
"react/react-in-jsx-scope": "off",
// not required with typescript
"react/prop-types": "off",
"react/require-default-props": "off",
// matter of taste
"react/destructuring-assignment": "off",
"react/jsx-props-no-spreading": "off",
"react/no-unescaped-entities": "off",
"import/prefer-default-export": "off",
// enforce hook call order
"hooks/sort": [
2,
{
"groups": [
"useLocation",
"useParams",
"useState",
"useAppSelector",
"useAppDispatch",
"useAsync",
"useForm",
"useAsyncCallback",
"useCallback",
"useEffect"
]
}
]
}
}

33
commafeed-client/.gitignore vendored Normal file
View File

@@ -0,0 +1,33 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# rollup-plugin-visualizer
/stats.html
# vite
vite.config.ts.timestamp-*.mjs
# compiled locales
src/locales/**/*.ts

View File

@@ -0,0 +1,57 @@
{
"locales": [
"ar",
"ca",
"cs",
"cy",
"da",
"de",
"en",
"es",
"fa",
"fi",
"fr",
"gl",
"hu",
"id",
"it",
"ja",
"ko",
"ms",
"nb",
"nl",
"nn",
"pl",
"pt",
"ru",
"sk",
"sv",
"tr",
"zh"
],
"catalogs": [
{
"path": "src/locales/{locale}/messages",
"include": [
"src"
],
"exclude": [
"src/locales/**"
]
}
],
"format": "po",
"formatOptions": {
"origins": true,
"lineNumbers": false
},
"sourceLocale": "en",
"fallbackLocales": {
"default": "en"
},
"extractBabelOptions": {
"presets": [
"@babel/preset-typescript"
]
}
}

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="manifest" href="manifest.json" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>CommaFeed</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

18760
commafeed-client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
{
"name": "commafeed-client",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "npm run i18n:compile && tsc && vite build",
"preview": "vite preview",
"test": "vitest",
"test:ci": "vitest run",
"eslint": "eslint --ext=.js,.jsx,.ts,.tsx src",
"i18n": "npm run i18n:extract && npm run i18n:compile",
"i18n:extract": "lingui extract --clean",
"i18n:compile": "lingui compile --typescript",
"postinstall": "npm run i18n:compile"
},
"dependencies": {
"@emotion/react": "^11.10.5",
"@fontsource/open-sans": "^4.5.14",
"@lingui/core": "^3.17.0",
"@lingui/macro": "^3.17.0",
"@lingui/react": "^3.17.0",
"@mantine/core": "^5.10.3",
"@mantine/form": "^5.10.3",
"@mantine/hooks": "^5.10.3",
"@mantine/modals": "^5.10.3",
"@mantine/notifications": "^5.10.3",
"@mantine/spotlight": "^5.10.3",
"@reduxjs/toolkit": "^1.9.2",
"axios": "^1.3.2",
"dayjs": "^1.11.7",
"interweave": "^13.0.0",
"lodash": "^4.17.21",
"make-plural": "^7.2.0",
"mousetrap": "^1.6.5",
"react": "^18.2.0",
"react-async-hook": "^4.0.0",
"react-contexify": "^6.0.0",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-infinite-scroller": "^1.2.6",
"react-redux": "^8.0.5",
"react-router-dom": "^6.8.0",
"react-swipeable": "^7.0.0",
"swagger-ui-react": "^4.15.5",
"tinycon": "^0.6.8",
"websocket-heartbeat-js": "^1.1.1"
},
"devDependencies": {
"@lingui/cli": "^3.17.0",
"@types/eslint": "^8.21.0",
"@types/lodash": "^4.14.191",
"@types/mousetrap": "^1.6.11",
"@types/react": "^18.0.27",
"@types/react-dom": "^18.0.10",
"@types/react-infinite-scroller": "^1.2.3",
"@types/swagger-ui-react": "^4.11.0",
"@types/tinycon": "^0.6.3",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"@vitejs/plugin-react": "^3.1.0",
"eslint": "^8.33.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "^8.6.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-hooks": "^0.4.3",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.3",
"rollup-plugin-visualizer": "^5.9.0",
"typescript": "^4.9.5",
"vite": "^4.1.1",
"vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^4.0.5",
"vitest": "^0.28.4",
"vitest-mock-extended": "^1.0.9"
}
}

98
commafeed-client/pom.xml Normal file
View File

@@ -0,0 +1,98 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.commafeed</groupId>
<artifactId>commafeed</artifactId>
<version>3.0.0</version>
</parent>
<artifactId>commafeed-client</artifactId>
<name>CommaFeed Client</name>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.12.1</version>
<?m2e ignore?>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<nodeVersion>v16.16.0</nodeVersion>
<npmVersion>8.15.0</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>ci</arguments>
</configuration>
</execution>
<execution>
<id>npm run eslint</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run eslint</arguments>
</configuration>
</execution>
<execution>
<id>npm run test</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run test:ci</arguments>
</configuration>
</execution>
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<phase>compile</phase>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy web interface to resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/classes/assets</outputDirectory>
<resources>
<resource>
<directory>dist</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,5 +1,10 @@
{
"$schema": "https://json.schemastore.org/web-manifest-combined.json",
"name": "CommaFeed",
"scope": ".",
"start_url": "./",
"display": "standalone",
"theme_color": "#f88a14",
"icons": [
{
"src": "app-icon-72.png",
@@ -25,8 +30,5 @@
"type": "image/png",
"density": "4.0"
}
],
"scope": ".",
"start_url": "./",
"display": "standalone"
]
}

View File

@@ -0,0 +1,147 @@
import { i18n } from "@lingui/core"
import { I18nProvider } from "@lingui/react"
import { ColorScheme, ColorSchemeProvider, MantineProvider } from "@mantine/core"
import { useColorScheme, useLocalStorage } from "@mantine/hooks"
import { ModalsProvider } from "@mantine/modals"
import { NotificationsProvider } from "@mantine/notifications"
import { Constants } from "app/constants"
import { redirectTo } from "app/slices/redirect"
import { reloadServerInfos } from "app/slices/server"
import { useAppDispatch, useAppSelector } from "app/store"
import { categoryUnreadCount } from "app/utils"
import { ErrorBoundary } from "components/ErrorBoundary"
import { Header } from "components/header/Header"
import { Tree } from "components/sidebar/Tree"
import { useI18n } from "i18n"
import { AdminUsersPage } from "pages/admin/AdminUsersPage"
import { MetricsPage } from "pages/admin/MetricsPage"
import { AboutPage } from "pages/app/AboutPage"
import { AddPage } from "pages/app/AddPage"
import { CategoryDetailsPage } from "pages/app/CategoryDetailsPage"
import { FeedDetailsPage } from "pages/app/FeedDetailsPage"
import { FeedEntriesPage } from "pages/app/FeedEntriesPage"
import Layout from "pages/app/Layout"
import { SettingsPage } from "pages/app/SettingsPage"
import { TagDetailsPage } from "pages/app/TagDetailsPage"
import { LoginPage } from "pages/auth/LoginPage"
import { PasswordRecoveryPage } from "pages/auth/PasswordRecoveryPage"
import { RegistrationPage } from "pages/auth/RegistrationPage"
import React, { useEffect } from "react"
import { HashRouter, Navigate, Route, Routes, useNavigate } from "react-router-dom"
import Tinycon from "tinycon"
function Providers(props: { children: React.ReactNode }) {
const preferredColorScheme = useColorScheme()
const [colorScheme, setColorScheme] = useLocalStorage<ColorScheme>({
key: "color-scheme",
defaultValue: preferredColorScheme,
getInitialValueInEffect: true,
})
const toggleColorScheme = (value?: ColorScheme) => setColorScheme(value || (colorScheme === "dark" ? "light" : "dark"))
return (
<I18nProvider i18n={i18n}>
<ColorSchemeProvider colorScheme={colorScheme} toggleColorScheme={toggleColorScheme}>
<MantineProvider
withGlobalStyles
withNormalizeCSS
theme={{
primaryColor: "orange",
colorScheme,
fontFamily: "Open Sans",
}}
>
<ModalsProvider>
<NotificationsProvider position="top-center" zIndex={9999}>
<ErrorBoundary>{props.children}</ErrorBoundary>
</NotificationsProvider>
</ModalsProvider>
</MantineProvider>
</ColorSchemeProvider>
</I18nProvider>
)
}
// swagger-ui is very large, load only on-demand
const ApiDocumentationPage = React.lazy(() => import("pages/app/ApiDocumentationPage"))
function AppRoutes() {
return (
<Routes>
<Route path="/" element={<Navigate to={`/app/category/${Constants.categories.all.id}`} replace />} />
<Route path="login" element={<LoginPage />} />
<Route path="register" element={<RegistrationPage />} />
<Route path="passwordRecovery" element={<PasswordRecoveryPage />} />
<Route path="app" element={<Layout header={<Header />} sidebar={<Tree />} />}>
<Route path="category">
<Route path=":id" element={<FeedEntriesPage sourceType="category" />} />
<Route path=":id/details" element={<CategoryDetailsPage />} />
</Route>
<Route path="feed">
<Route path=":id" element={<FeedEntriesPage sourceType="feed" />} />
<Route path=":id/details" element={<FeedDetailsPage />} />
</Route>
<Route path="tag">
<Route path=":id" element={<FeedEntriesPage sourceType="tag" />} />
<Route path=":id/details" element={<TagDetailsPage />} />
</Route>
<Route path="add" element={<AddPage />} />
<Route path="settings" element={<SettingsPage />} />
<Route path="admin">
<Route path="users" element={<AdminUsersPage />} />
<Route path="metrics" element={<MetricsPage />} />
</Route>
<Route path="about" element={<AboutPage />} />
<Route path="api" element={<ApiDocumentationPage />} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
)
}
function RedirectHandler() {
const target = useAppSelector(state => state.redirect.to)
const dispatch = useAppDispatch()
const navigate = useNavigate()
useEffect(() => {
if (target) {
// pages can subscribe to state.timestamp in order to refresh when navigating to an url matching the current page
navigate(target, { state: { timestamp: new Date() } })
dispatch(redirectTo(undefined))
}
}, [target, dispatch, navigate])
return null
}
function FaviconHandler() {
const root = useAppSelector(state => state.tree.rootCategory)
useEffect(() => {
const unreadCount = categoryUnreadCount(root)
if (unreadCount === 0) Tinycon.reset()
else Tinycon.setBubble(unreadCount)
}, [root])
return null
}
export function App() {
useI18n()
const dispatch = useAppDispatch()
useEffect(() => {
dispatch(reloadServerInfos())
}, [dispatch])
return (
<Providers>
<>
<FaviconHandler />
<HashRouter>
<RedirectHandler />
<AppRoutes />
</HashRouter>
</>
</Providers>
)
}

View File

@@ -0,0 +1,113 @@
import axios from "axios"
import {
AddCategoryRequest,
Category,
CategoryModificationRequest,
CollapseRequest,
Entries,
FeedInfo,
FeedInfoRequest,
FeedModificationRequest,
GetEntriesPaginatedRequest,
IDRequest,
LoginRequest,
MarkRequest,
Metrics,
MultipleMarkRequest,
PasswordResetRequest,
ProfileModificationRequest,
RegistrationRequest,
ServerInfo,
Settings,
StarRequest,
SubscribeRequest,
Subscription,
TagRequest,
UserModel,
} from "./types"
const axiosInstance = axios.create({ baseURL: "./rest", withCredentials: true })
axiosInstance.interceptors.response.use(
response => response,
error => {
if (error.response.status === 401) window.location.hash = "/login"
throw error
}
)
export const client = {
category: {
getRoot: () => axiosInstance.get<Category>("category/get"),
modify: (req: CategoryModificationRequest) => axiosInstance.post("category/modify", req),
collapse: (req: CollapseRequest) => axiosInstance.post("category/collapse", req),
getEntries: (req: GetEntriesPaginatedRequest) => axiosInstance.get<Entries>("category/entries", { params: req }),
markEntries: (req: MarkRequest) => axiosInstance.post("category/mark", req),
add: (req: AddCategoryRequest) => axiosInstance.post("category/add", req),
delete: (req: IDRequest) => axiosInstance.post("category/delete", req),
},
entry: {
mark: (req: MarkRequest) => axiosInstance.post("entry/mark", req),
markMultiple: (req: MultipleMarkRequest) => axiosInstance.post("entry/markMultiple", req),
star: (req: StarRequest) => axiosInstance.post("entry/star", req),
getTags: () => axiosInstance.get<string[]>("entry/tags"),
tag: (req: TagRequest) => axiosInstance.post("entry/tag", req),
},
feed: {
get: (id: string) => axiosInstance.get<Subscription>(`feed/get/${id}`),
modify: (req: FeedModificationRequest) => axiosInstance.post("feed/modify", req),
getEntries: (req: GetEntriesPaginatedRequest) => axiosInstance.get<Entries>("feed/entries", { params: req }),
markEntries: (req: MarkRequest) => axiosInstance.post("feed/mark", req),
fetchFeed: (req: FeedInfoRequest) => axiosInstance.post<FeedInfo>("feed/fetch", req),
refreshAll: () => axiosInstance.get("feed/refreshAll"),
subscribe: (req: SubscribeRequest) => axiosInstance.post<number>("feed/subscribe", req),
unsubscribe: (req: IDRequest) => axiosInstance.post("feed/unsubscribe", req),
importOpml: (req: File) => {
const formData = new FormData()
formData.append("file", req)
return axiosInstance.post("feed/import", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
},
},
user: {
login: (req: LoginRequest) => axiosInstance.post("user/login", req),
register: (req: RegistrationRequest) => axiosInstance.post("user/register", req),
passwordReset: (req: PasswordResetRequest) => axiosInstance.post("user/passwordReset", req),
getSettings: () => axiosInstance.get<Settings>("user/settings"),
saveSettings: (settings: Settings) => axiosInstance.post("user/settings", settings),
getProfile: () => axiosInstance.get<UserModel>("user/profile"),
saveProfile: (req: ProfileModificationRequest) => axiosInstance.post("user/profile", req),
deleteProfile: () => axiosInstance.post("user/profile/deleteAccount"),
},
server: {
getServerInfos: () => axiosInstance.get<ServerInfo>("server/get"),
},
admin: {
getAllUsers: () => axiosInstance.get<UserModel[]>("admin/user/getAll"),
saveUser: (req: UserModel) => axiosInstance.post("admin/user/save", req),
deleteUser: (req: IDRequest) => axiosInstance.post("admin/user/delete", req),
getMetrics: () => axiosInstance.get<Metrics>("admin/metrics"),
},
}
/**
* transform an error object to an array of strings that can be displayed to the user
* @param err an error object (e.g. from axios)
* @returns an array of messages to show the user
*/
export const errorToStrings = (err: unknown) => {
let strings: string[] = []
if (axios.isAxiosError(err)) {
if (err.response) {
const { data } = err.response
if (typeof data === "string") strings.push(data)
if (typeof data === "object" && data.message) strings.push(data.message)
if (typeof data === "object" && data.errors) strings = [...strings, ...data.errors]
}
}
return strings
}

View File

@@ -0,0 +1,100 @@
import { t } from "@lingui/macro"
import { DEFAULT_THEME } from "@mantine/core"
import { IconType } from "react-icons"
import { FaAt } from "react-icons/fa"
import { SiBuffer, SiFacebook, SiGmail, SiInstapaper, SiPocket, SiTumblr, SiTwitter } from "react-icons/si"
import { Category, Entry, SharingSettings } from "./types"
const categories: { [key: string]: Category } = {
all: {
id: "all",
name: t`All`,
expanded: false,
children: [],
feeds: [],
position: 0,
},
starred: {
id: "starred",
name: t`Starred`,
expanded: false,
children: [],
feeds: [],
position: 1,
},
}
const sharing: {
[key in keyof SharingSettings]: {
label: string
icon: IconType
color: `#${string}`
url: (url: string, description: string) => string
}
} = {
email: {
label: "Email",
icon: FaAt,
color: "#000000",
url: (url, desc) => `mailto:?subject=${desc}&body=${url}`,
},
gmail: {
label: "Gmail",
icon: SiGmail,
color: "#EA4335",
url: (url, desc) => `https://mail.google.com/mail/?view=cm&fs=1&tf=1&source=mailto&su=${desc}&body=${url}`,
},
facebook: {
label: "Facebook",
icon: SiFacebook,
color: "#1B74E4",
url: url => `https://www.facebook.com/sharer/sharer.php?u=${url}`,
},
twitter: {
label: "Twitter",
icon: SiTwitter,
color: "#1D9BF0",
url: (url, desc) => `http://twitter.com/share?text=${desc}&url=${url}`,
},
tumblr: {
label: "Tumblr",
icon: SiTumblr,
color: "#375672",
url: (url, desc) => `http://www.tumblr.com/share/link?url=${url}&name=${desc}`,
},
pocket: {
label: "Pocket",
icon: SiPocket,
color: "#EF4154",
url: (url, desc) => `https://getpocket.com/save?url=${url}&title=${desc}`,
},
instapaper: {
label: "Instapaper",
icon: SiInstapaper,
color: "#010101",
url: (url, desc) => `https://www.instapaper.com/hello2?url=${url}&title=${desc}`,
},
buffer: {
label: "Buffer",
icon: SiBuffer,
color: "#000000",
url: (url, desc) => `https://bufferapp.com/add?url=${url}&text=${desc}`,
},
}
export const Constants = {
categories,
sharing,
layout: {
mobileBreakpoint: DEFAULT_THEME.breakpoints.md,
headerHeight: 60,
sidebarWidth: 350,
entryMaxWidth: 650,
isTopVisible: (div: HTMLElement) => div.getBoundingClientRect().top >= Constants.layout.headerHeight,
isBottomVisible: (div: HTMLElement) => div.getBoundingClientRect().bottom <= window.innerHeight,
},
dom: {
mainScrollAreaId: "main-scroll-area-id",
entryId: (entry: Entry) => `entry-id-${entry.id}`,
},
}

View File

@@ -0,0 +1,142 @@
/* eslint-disable import/first */
import { beforeEach, describe, expect, it, vi } from "vitest"
import { DeepMockProxy, mockDeep, mockReset } from "vitest-mock-extended"
vi.doMock("app/client", () => ({ client: mockDeep() }))
import { configureStore } from "@reduxjs/toolkit"
import { client } from "app/client"
import { reducers } from "app/store"
import { Entries, Entry } from "app/types"
import { AxiosResponse } from "axios"
import { loadEntries, loadMoreEntries, markAllEntries, markEntry } from "./entries"
describe("entries", () => {
const mockClient = client as DeepMockProxy<typeof client>
beforeEach(() => {
mockReset(mockClient)
})
it("loads entries", async () => {
mockClient.feed.getEntries.mockResolvedValue({
data: {
entries: [{ id: "3" } as Entry],
hasMore: false,
name: "my-feed",
errorCount: 3,
feedLink: "https://mysite.com/feed",
timestamp: 123,
ignoredReadStatus: false,
},
} as AxiosResponse<Entries>)
const store = configureStore({ reducer: reducers })
const promise = store.dispatch(loadEntries({ source: { type: "feed", id: "feed-id" }, clearSearch: true }))
expect(store.getState().entries.source.type).toBe("feed")
expect(store.getState().entries.source.id).toBe("feed-id")
expect(store.getState().entries.entries).toStrictEqual([])
expect(store.getState().entries.hasMore).toBe(true)
expect(store.getState().entries.sourceLabel).toBe("")
expect(store.getState().entries.sourceWebsiteUrl).toBe("")
expect(store.getState().entries.timestamp).toBeUndefined()
await promise
expect(store.getState().entries.source.type).toBe("feed")
expect(store.getState().entries.source.id).toBe("feed-id")
expect(store.getState().entries.entries).toStrictEqual([{ id: "3" }])
expect(store.getState().entries.hasMore).toBe(false)
expect(store.getState().entries.sourceLabel).toBe("my-feed")
expect(store.getState().entries.sourceWebsiteUrl).toBe("https://mysite.com/feed")
expect(store.getState().entries.timestamp).toBe(123)
})
it("loads more entries", async () => {
mockClient.category.getEntries.mockResolvedValue({
data: {
entries: [{ id: "4" } as Entry],
hasMore: false,
name: "my-feed",
errorCount: 3,
feedLink: "https://mysite.com/feed",
timestamp: 123,
ignoredReadStatus: false,
},
} as AxiosResponse<Entries>)
const store = configureStore({
reducer: reducers,
preloadedState: {
entries: {
source: {
type: "category",
id: "category-id",
},
sourceLabel: "",
sourceWebsiteUrl: "",
entries: [{ id: "3" } as Entry],
hasMore: true,
scrollingToEntry: false,
},
},
})
const promise = store.dispatch(loadMoreEntries())
await promise
expect(store.getState().entries.entries).toStrictEqual([{ id: "3" }, { id: "4" }])
expect(store.getState().entries.hasMore).toBe(false)
})
it("marks an entry as read", async () => {
const store = configureStore({
reducer: reducers,
preloadedState: {
entries: {
source: {
type: "category",
id: "category-id",
},
sourceLabel: "",
sourceWebsiteUrl: "",
entries: [{ id: "3", read: false } as Entry, { id: "4", read: false } as Entry],
hasMore: true,
scrollingToEntry: false,
},
},
})
store.dispatch(markEntry({ entry: { id: "3" } as Entry, read: true }))
expect(store.getState().entries.entries).toStrictEqual([
{ id: "3", read: true },
{ id: "4", read: false },
])
expect(mockClient.entry.mark).toHaveBeenCalledWith({ id: "3", read: true })
})
it("marks all entries as read", async () => {
const store = configureStore({
reducer: reducers,
preloadedState: {
entries: {
source: {
type: "category",
id: "category-id",
},
sourceLabel: "",
sourceWebsiteUrl: "",
entries: [{ id: "3", read: false } as Entry, { id: "4", read: false } as Entry],
hasMore: true,
scrollingToEntry: false,
},
},
})
store.dispatch(markAllEntries({ sourceType: "category", req: { id: "all", read: true } }))
expect(store.getState().entries.entries).toStrictEqual([
{ id: "3", read: true },
{ id: "4", read: true },
])
expect(mockClient.category.markEntries).toHaveBeenCalledWith({ id: "all", read: true })
})
})

View File

@@ -0,0 +1,339 @@
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"
import { client } from "app/client"
import { Constants } from "app/constants"
import { RootState } from "app/store"
import { Entries, Entry, MarkRequest, TagRequest } from "app/types"
import { scrollToWithCallback } from "app/utils"
import { flushSync } from "react-dom"
// eslint-disable-next-line import/no-cycle
import { reloadTree } from "./tree"
// eslint-disable-next-line import/no-cycle
import { reloadTags } from "./user"
export type EntrySourceType = "category" | "feed" | "tag"
export type EntrySource = { type: EntrySourceType; id: string }
export type ExpendableEntry = Entry & { expanded?: boolean }
interface EntriesState {
/** selected source */
source: EntrySource
sourceLabel: string
sourceWebsiteUrl: string
entries: ExpendableEntry[]
/** stores when the first batch of entries were retrieved
*
* this is used when marking all entries of a feed/category to only mark entries up to that timestamp as newer entries were potentially never shown
*/
timestamp?: number
selectedEntryId?: string
hasMore: boolean
search?: string
scrollingToEntry: boolean
}
const initialState: EntriesState = {
source: {
type: "category",
id: Constants.categories.all.id,
},
sourceLabel: "",
sourceWebsiteUrl: "",
entries: [],
hasMore: true,
scrollingToEntry: false,
}
const getEndpoint = (sourceType: EntrySourceType) =>
sourceType === "category" || sourceType === "tag" ? client.category.getEntries : client.feed.getEntries
export const loadEntries = createAsyncThunk<Entries, { source: EntrySource; clearSearch: boolean }, { state: RootState }>(
"entries/load",
async (arg, thunkApi) => {
if (arg.clearSearch) thunkApi.dispatch(setSearch(""))
const state = thunkApi.getState()
const endpoint = getEndpoint(arg.source.type)
const result = await endpoint(buildGetEntriesPaginatedRequest(state, arg.source, 0))
return result.data
}
)
export const loadMoreEntries = createAsyncThunk<Entries, void, { state: RootState }>("entries/loadMore", async (_, thunkApi) => {
const state = thunkApi.getState()
const { source } = state.entries
const offset =
state.user.settings?.readingMode === "all" ? state.entries.entries.length : state.entries.entries.filter(e => !e.read).length
const endpoint = getEndpoint(state.entries.source.type)
const result = await endpoint(buildGetEntriesPaginatedRequest(state, source, offset))
return result.data
})
const buildGetEntriesPaginatedRequest = (state: RootState, source: EntrySource, offset: number) => ({
id: source.type === "tag" ? Constants.categories.all.id : source.id,
order: state.user.settings?.readingOrder,
readType: state.user.settings?.readingMode,
offset,
limit: 50,
tag: source.type === "tag" ? source.id : undefined,
keywords: state.entries.search,
})
export const reloadEntries = createAsyncThunk<void, void, { state: RootState }>("entries/reload", async (arg, thunkApi) => {
const state = thunkApi.getState()
thunkApi.dispatch(loadEntries({ source: state.entries.source, clearSearch: false }))
})
export const search = createAsyncThunk<void, string, { state: RootState }>("entries/search", async (arg, thunkApi) => {
const state = thunkApi.getState()
thunkApi.dispatch(setSearch(arg))
thunkApi.dispatch(loadEntries({ source: state.entries.source, clearSearch: false }))
})
export const markEntry = createAsyncThunk(
"entries/entry/mark",
(arg: { entry: Entry; read: boolean }) => {
client.entry.mark({
id: arg.entry.id,
read: arg.read,
})
},
{
condition: arg => arg.entry.read !== arg.read,
}
)
export const markMultipleEntries = createAsyncThunk(
"entries/entry/markMultiple",
async (arg: { entries: Entry[]; read: boolean }, thunkApi) => {
const requests: MarkRequest[] = arg.entries.map(e => ({
id: e.id,
read: arg.read,
}))
await client.entry.markMultiple({ requests })
thunkApi.dispatch(reloadTree())
}
)
export const markEntriesUpToEntry = createAsyncThunk<void, Entry, { state: RootState }>(
"entries/entry/upToEntry",
async (arg, thunkApi) => {
const state = thunkApi.getState()
const { entries } = state.entries
const index = entries.findIndex(e => e.id === arg.id)
if (index === -1) return
thunkApi.dispatch(
markMultipleEntries({
entries: entries.slice(0, index + 1),
read: true,
})
)
}
)
export const markAllEntries = createAsyncThunk<void, { sourceType: EntrySourceType; req: MarkRequest }, { state: RootState }>(
"entries/entry/markAll",
async (arg, thunkApi) => {
const endpoint = arg.sourceType === "category" ? client.category.markEntries : client.feed.markEntries
await endpoint(arg.req)
thunkApi.dispatch(reloadEntries())
thunkApi.dispatch(reloadTree())
}
)
export const starEntry = createAsyncThunk("entries/entry/star", (arg: { entry: Entry; starred: boolean }) => {
client.entry.star({
id: arg.entry.id,
feedId: +arg.entry.feedId,
starred: arg.starred,
})
})
export const selectEntry = createAsyncThunk<
void,
{
entry: Entry
expand: boolean
markAsRead: boolean
scrollToEntry: boolean
},
{ state: RootState }
>("entries/entry/select", (arg, thunkApi) => {
const state = thunkApi.getState()
const entry = state.entries.entries.find(e => e.id === arg.entry.id)
if (!entry) return
// flushSync is required because we need the newly selected entry to be expanded
// and the previously selected entry to be collapsed to be able to scroll to the right position
flushSync(() => {
// mark as read if requested
if (arg.markAsRead) {
thunkApi.dispatch(markEntry({ entry, read: true }))
}
// set entry as selected
thunkApi.dispatch(entriesSlice.actions.setSelectedEntry(entry))
// expand if requested
const previouslySelectedEntry = state.entries.entries.find(e => e.id === state.entries.selectedEntryId)
if (previouslySelectedEntry) {
thunkApi.dispatch(entriesSlice.actions.setEntryExpanded({ entry: previouslySelectedEntry, expanded: false }))
}
thunkApi.dispatch(entriesSlice.actions.setEntryExpanded({ entry, expanded: arg.expand }))
})
if (arg.scrollToEntry) {
const entryElement = document.getElementById(Constants.dom.entryId(entry))
if (entryElement) {
const scrollSpeed = state.user.settings?.scrollSpeed
thunkApi.dispatch(entriesSlice.actions.setScrollingToEntry(true))
scrollToEntry(entryElement, scrollSpeed, () => thunkApi.dispatch(entriesSlice.actions.setScrollingToEntry(false)))
}
}
})
const scrollToEntry = (entryElement: HTMLElement, scrollSpeed: number | undefined, onScrollEnded: () => void) => {
// the entry is entirely visible, no need to scroll
if (Constants.layout.isTopVisible(entryElement) && Constants.layout.isBottomVisible(entryElement)) {
onScrollEnded()
return
}
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
if (scrollArea) {
scrollToWithCallback({
element: scrollArea,
options: {
// add a small gap between the top of the content and the top of the page
top: entryElement.offsetTop - 3,
behavior: scrollSpeed && scrollSpeed > 0 ? "smooth" : "auto",
},
onScrollEnded,
})
}
}
export const selectPreviousEntry = createAsyncThunk<
void,
{
expand: boolean
markAsRead: boolean
scrollToEntry: boolean
},
{ state: RootState }
>("entries/entry/selectPrevious", (arg, thunkApi) => {
const state = thunkApi.getState()
const { entries } = state.entries
const previousIndex = entries.findIndex(e => e.id === state.entries.selectedEntryId) - 1
if (previousIndex >= 0) {
thunkApi.dispatch(
selectEntry({
entry: entries[previousIndex],
expand: arg.expand,
markAsRead: arg.markAsRead,
scrollToEntry: arg.scrollToEntry,
})
)
}
})
export const selectNextEntry = createAsyncThunk<
void,
{
expand: boolean
markAsRead: boolean
scrollToEntry: boolean
},
{ state: RootState }
>("entries/entry/selectNext", (arg, thunkApi) => {
const state = thunkApi.getState()
const { entries } = state.entries
const nextIndex = entries.findIndex(e => e.id === state.entries.selectedEntryId) + 1
if (nextIndex < entries.length) {
thunkApi.dispatch(
selectEntry({
entry: entries[nextIndex],
expand: arg.expand,
markAsRead: arg.markAsRead,
scrollToEntry: arg.scrollToEntry,
})
)
}
})
export const tagEntry = createAsyncThunk<void, TagRequest, { state: RootState }>("entries/entry/tag", async (arg, thunkApi) => {
await client.entry.tag(arg)
thunkApi.dispatch(reloadTags())
})
export const entriesSlice = createSlice({
name: "entries",
initialState,
reducers: {
setSelectedEntry: (state, action: PayloadAction<Entry>) => {
state.selectedEntryId = action.payload.id
},
setEntryExpanded: (state, action: PayloadAction<{ entry: Entry; expanded: boolean }>) => {
state.entries
.filter(e => e.id === action.payload.entry.id)
.forEach(e => {
e.expanded = action.payload.expanded
})
},
setScrollingToEntry: (state, action: PayloadAction<boolean>) => {
state.scrollingToEntry = action.payload
},
setSearch: (state, action: PayloadAction<string>) => {
state.search = action.payload
},
},
extraReducers: builder => {
builder.addCase(markEntry.pending, (state, action) => {
state.entries
.filter(e => e.id === action.meta.arg.entry.id)
.forEach(e => {
e.read = action.meta.arg.read
})
})
builder.addCase(markMultipleEntries.pending, (state, action) => {
state.entries
.filter(e => action.meta.arg.entries.some(e2 => e2.id === e.id))
.forEach(e => {
e.read = action.meta.arg.read
})
})
builder.addCase(markAllEntries.pending, (state, action) => {
state.entries
.filter(e => (action.meta.arg.req.olderThan ? e.date < action.meta.arg.req.olderThan : true))
.forEach(e => {
e.read = true
})
})
builder.addCase(starEntry.pending, (state, action) => {
state.entries
.filter(e => action.meta.arg.entry.id === e.id && action.meta.arg.entry.feedId === e.feedId)
.forEach(e => {
e.starred = action.meta.arg.starred
})
})
builder.addCase(loadEntries.pending, (state, action) => {
state.source = action.meta.arg.source
state.entries = []
state.timestamp = undefined
state.sourceLabel = ""
state.sourceWebsiteUrl = ""
state.hasMore = true
state.selectedEntryId = undefined
})
builder.addCase(loadEntries.fulfilled, (state, action) => {
state.entries = action.payload.entries
state.timestamp = action.payload.timestamp
state.sourceLabel = action.payload.name
state.sourceWebsiteUrl = action.payload.feedLink
state.hasMore = action.payload.hasMore
})
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
})
builder.addCase(tagEntry.pending, (state, action) => {
state.entries
.filter(e => +e.id === action.meta.arg.entryId)
.forEach(e => {
e.tags = action.meta.arg.tags
})
})
},
})
export const { setSearch } = entriesSlice.actions
export default entriesSlice.reducer

View File

@@ -0,0 +1,10 @@
import { store } from "app/store"
import { describe, expect, it } from "vitest"
import { redirectToCategory } from "./redirect"
describe("redirects", () => {
it("redirects to category", async () => {
await store.dispatch(redirectToCategory("1"))
expect(store.getState().redirect.to).toBe("/app/category/1")
})
})

View File

@@ -0,0 +1,61 @@
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"
import { Constants } from "app/constants"
import { RootState } from "app/store"
interface RedirectState {
to?: string
}
const initialState: RedirectState = {}
export const redirectToLogin = createAsyncThunk("redirect/login", (_, thunkApi) => thunkApi.dispatch(redirectTo("/login")))
export const redirectToRegistration = createAsyncThunk("redirect/register", (_, thunkApi) => thunkApi.dispatch(redirectTo("/register")))
export const redirectToPasswordRecovery = createAsyncThunk("redirect/passwordRecovery", (_, thunkApi) =>
thunkApi.dispatch(redirectTo("/passwordRecovery"))
)
export const redirectToSelectedSource = createAsyncThunk<void, void, { state: RootState }>("redirect/selectedSource", (_, thunkApi) => {
const { source } = thunkApi.getState().entries
thunkApi.dispatch(redirectTo(`/app/${source.type}/${source.id}`))
})
export const redirectToCategory = createAsyncThunk("redirect/category", (id: string, thunkApi) =>
thunkApi.dispatch(redirectTo(`/app/category/${id}`))
)
export const redirectToRootCategory = createAsyncThunk("redirect/category/root", (_, thunkApi) =>
thunkApi.dispatch(redirectToCategory(Constants.categories.all.id))
)
export const redirectToCategoryDetails = createAsyncThunk("redirect/category/details", (id: string, thunkApi) =>
thunkApi.dispatch(redirectTo(`/app/category/${id}/details`))
)
export const redirectToFeed = createAsyncThunk("redirect/feed", (id: string | number, thunkApi) =>
thunkApi.dispatch(redirectTo(`/app/feed/${id}`))
)
export const redirectToFeedDetails = createAsyncThunk("redirect/feed/details", (id: string, thunkApi) =>
thunkApi.dispatch(redirectTo(`/app/feed/${id}/details`))
)
export const redirectToTag = createAsyncThunk("redirect/tag", (id: string, thunkApi) => thunkApi.dispatch(redirectTo(`/app/tag/${id}`)))
export const redirectToTagDetails = createAsyncThunk("redirect/tag/details", (id: string, thunkApi) =>
thunkApi.dispatch(redirectTo(`/app/tag/${id}/details`))
)
export const redirectToAdd = createAsyncThunk("redirect/add", (_, thunkApi) => thunkApi.dispatch(redirectTo("/app/add")))
export const redirectToSettings = createAsyncThunk("redirect/settings", (_, thunkApi) => thunkApi.dispatch(redirectTo("/app/settings")))
export const redirectToAdminUsers = createAsyncThunk("redirect/admin/users", (_, thunkApi) =>
thunkApi.dispatch(redirectTo("/app/admin/users"))
)
export const redirectToMetrics = createAsyncThunk("redirect/admin/metrics", (_, thunkApi) =>
thunkApi.dispatch(redirectTo("/app/admin/metrics"))
)
export const redirectToAbout = createAsyncThunk("redirect/about", (_, thunkApi) => thunkApi.dispatch(redirectTo("/app/about")))
export const redirectToApiDocumentation = createAsyncThunk("redirect/api", (_, thunkApi) => thunkApi.dispatch(redirectTo("/app/api")))
export const redirectSlice = createSlice({
name: "redirect",
initialState,
reducers: {
redirectTo: (state, action: PayloadAction<string | undefined>) => {
state.to = action.payload
},
},
})
export const { redirectTo } = redirectSlice.actions
export default redirectSlice.reducer

View File

@@ -0,0 +1,23 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"
import { client } from "app/client"
import { ServerInfo } from "app/types"
interface ServerState {
serverInfos?: ServerInfo
}
const initialState: ServerState = {}
export const reloadServerInfos = createAsyncThunk("server/infos", () => client.server.getServerInfos().then(r => r.data))
export const serverSlice = createSlice({
name: "server",
initialState,
reducers: {},
extraReducers: builder => {
builder.addCase(reloadServerInfos.fulfilled, (state, action) => {
state.serverInfos = action.payload
})
},
})
export default serverSlice.reducer

View File

@@ -0,0 +1,58 @@
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit"
import { client } from "app/client"
import { Category, CollapseRequest } from "app/types"
import { visitCategoryTree } from "app/utils"
// eslint-disable-next-line import/no-cycle
import { markEntry } from "./entries"
import { redirectTo } from "./redirect"
interface TreeState {
rootCategory?: Category
mobileMenuOpen: boolean
}
const initialState: TreeState = {
mobileMenuOpen: false,
}
export const reloadTree = createAsyncThunk("tree/reload", () => client.category.getRoot().then(r => r.data))
export const collapseTreeCategory = createAsyncThunk("tree/category/collapse", async (req: CollapseRequest) =>
client.category.collapse(req)
)
export const treeSlice = createSlice({
name: "tree",
initialState,
reducers: {
setMobileMenuOpen: (state, action: PayloadAction<boolean>) => {
state.mobileMenuOpen = action.payload
},
},
extraReducers: builder => {
builder.addCase(reloadTree.fulfilled, (state, action) => {
state.rootCategory = action.payload
})
builder.addCase(collapseTreeCategory.pending, (state, action) => {
if (!state.rootCategory) return
visitCategoryTree(state.rootCategory, c => {
if (+c.id === action.meta.arg.id) c.expanded = !action.meta.arg.collapse
})
})
builder.addCase(markEntry.pending, (state, action) => {
if (!state.rootCategory) return
visitCategoryTree(state.rootCategory, c =>
c.feeds
.filter(f => f.id === +action.meta.arg.entry.feedId)
.forEach(f => {
f.unread = action.meta.arg.read ? f.unread - 1 : f.unread + 1
})
)
})
builder.addCase(redirectTo, state => {
state.mobileMenuOpen = false
})
},
})
export const { setMobileMenuOpen } = treeSlice.actions
export default treeSlice.reducer

View File

@@ -0,0 +1,144 @@
import { t } from "@lingui/macro"
import { showNotification } from "@mantine/notifications"
import { createAsyncThunk, createSlice, isAnyOf } from "@reduxjs/toolkit"
import { client } from "app/client"
import { RootState } from "app/store"
import { ReadingMode, ReadingOrder, Settings, SharingSettings, UserModel, ViewMode } from "app/types"
// eslint-disable-next-line import/no-cycle
import { reloadEntries } from "./entries"
interface UserState {
settings?: Settings
profile?: UserModel
tags?: string[]
}
const initialState: UserState = {}
export const reloadSettings = createAsyncThunk("settings/reload", () => client.user.getSettings().then(r => r.data))
export const reloadProfile = createAsyncThunk("profile/reload", () => client.user.getProfile().then(r => r.data))
export const reloadTags = createAsyncThunk("entries/tags", () => client.entry.getTags().then(r => r.data))
export const changeReadingMode = createAsyncThunk<void, ReadingMode, { state: RootState }>(
"settings/readingMode",
(readingMode, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, readingMode })
thunkApi.dispatch(reloadEntries())
}
)
export const changeReadingOrder = createAsyncThunk<void, ReadingOrder, { state: RootState }>(
"settings/readingOrder",
(readingOrder, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, readingOrder })
thunkApi.dispatch(reloadEntries())
}
)
export const changeViewMode = createAsyncThunk<void, ViewMode, { state: RootState }>("settings/viewMode", (viewMode, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, viewMode })
thunkApi.dispatch(reloadEntries())
})
export const changeLanguage = createAsyncThunk<void, string, { state: RootState }>("settings/language", (language, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, language })
})
export const changeScrollSpeed = createAsyncThunk<void, boolean, { state: RootState }>("settings/scrollSpeed", (speed, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, scrollSpeed: speed ? 400 : 0 })
})
export const changeShowRead = createAsyncThunk<void, boolean, { state: RootState }>("settings/showRead", (showRead, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, showRead })
})
export const changeScrollMarks = createAsyncThunk<void, boolean, { state: RootState }>("settings/scrollMarks", (scrollMarks, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({ ...settings, scrollMarks })
})
export const changeSharingSetting = createAsyncThunk<void, { site: keyof SharingSettings; value: boolean }, { state: RootState }>(
"settings/sharingSetting",
(sharingSetting, thunkApi) => {
const { settings } = thunkApi.getState().user
if (!settings) return
client.user.saveSettings({
...settings,
sharingSettings: {
...settings.sharingSettings,
[sharingSetting.site]: sharingSetting.value,
},
})
}
)
export const userSlice = createSlice({
name: "user",
initialState,
reducers: {},
extraReducers: builder => {
builder.addCase(reloadSettings.fulfilled, (state, action) => {
state.settings = action.payload
})
builder.addCase(reloadProfile.fulfilled, (state, action) => {
state.profile = action.payload
})
builder.addCase(reloadTags.fulfilled, (state, action) => {
state.tags = action.payload
})
builder.addCase(changeReadingMode.pending, (state, action) => {
if (!state.settings) return
state.settings.readingMode = action.meta.arg
})
builder.addCase(changeReadingOrder.pending, (state, action) => {
if (!state.settings) return
state.settings.readingOrder = action.meta.arg
})
builder.addCase(changeViewMode.pending, (state, action) => {
if (!state.settings) return
state.settings.viewMode = action.meta.arg
})
builder.addCase(changeLanguage.pending, (state, action) => {
if (!state.settings) return
state.settings.language = action.meta.arg
})
builder.addCase(changeScrollSpeed.pending, (state, action) => {
if (!state.settings) return
state.settings.scrollSpeed = action.meta.arg ? 400 : 0
})
builder.addCase(changeShowRead.pending, (state, action) => {
if (!state.settings) return
state.settings.showRead = action.meta.arg
})
builder.addCase(changeScrollMarks.pending, (state, action) => {
if (!state.settings) return
state.settings.scrollMarks = action.meta.arg
})
builder.addCase(changeSharingSetting.pending, (state, action) => {
if (!state.settings) return
state.settings.sharingSettings[action.meta.arg.site] = action.meta.arg.value
})
builder.addMatcher(
isAnyOf(
changeLanguage.fulfilled,
changeScrollSpeed.fulfilled,
changeShowRead.fulfilled,
changeScrollMarks.fulfilled,
changeSharingSetting.fulfilled
),
() => {
showNotification({
message: t`Settings saved.`,
color: "green",
})
}
)
},
})
export default userSlice.reducer

View File

@@ -0,0 +1,26 @@
import { configureStore } from "@reduxjs/toolkit"
import { setupListeners } from "@reduxjs/toolkit/query"
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"
import entriesReducer from "./slices/entries"
import redirectReducer from "./slices/redirect"
import serverReducer from "./slices/server"
import treeReducer from "./slices/tree"
import userReducer from "./slices/user"
export const reducers = {
entries: entriesReducer,
redirect: redirectReducer,
tree: treeReducer,
server: serverReducer,
user: userReducer,
}
export const store = configureStore({ reducer: reducers })
setupListeners(store.dispatch)
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

View File

@@ -0,0 +1,308 @@
export interface AddCategoryRequest {
name: string
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
name: string
children: Category[]
feeds: Subscription[]
expanded: boolean
position: number
}
export interface CategoryModificationRequest {
id: number
name?: string
parentId?: string
position?: number
}
export interface CollapseRequest {
id: number
collapse: boolean
}
export interface Entries {
name: string
message?: string
errorCount: number
feedLink: string
timestamp: number
hasMore: boolean
offset?: number
limit?: number
entries: Entry[]
ignoredReadStatus: boolean
}
export interface Entry {
id: string
guid: string
title: string
content: string
categories?: string
rtl: boolean
author?: string
enclosureUrl?: string
enclosureType?: string
mediaDescription?: string
mediaThumbnailUrl?: string
mediaThumbnailWidth?: number
mediaThumbnailHeight?: number
date: number
insertedDate: number
feedId: string
feedName: string
feedUrl: string
feedLink: string
iconUrl: string
url: string
read: boolean
starred: boolean
markable: boolean
tags: string[]
}
export interface FeedInfo {
url: string
title: string
}
export interface FeedInfoRequest {
url: string
}
export interface FeedModificationRequest {
id: number
name?: string
categoryId?: string
position?: number
filter?: string
}
export interface GetEntriesRequest {
id: string
readType?: ReadingMode
newerThan?: number
order?: ReadingOrder
keywords?: string
onlyIds?: boolean
excludedSubscriptionIds?: string
tag?: string
}
export interface GetEntriesPaginatedRequest extends GetEntriesRequest {
offset: number
limit: number
}
export interface IDRequest {
id: number
}
export interface LoginRequest {
name: string
password: string
}
export interface MarkRequest {
id: string
read: boolean
olderThan?: number
keywords?: string
excludedSubscriptions?: number[]
}
export interface MetricCounter {
count: number
}
export interface MetricGauge {
value: number
}
export interface MetricMeter {
count: number
m15_rate: number
m1_rate: number
m5_rate: number
mean_rate: number
units: string
}
export type MetricTimer = {
count: number
max: number
mean: number
min: number
p50: number
p75: number
p95: number
p98: number
p99: number
p999: number
stddev: number
m15_rate: number
m1_rate: number
m5_rate: number
mean_rate: number
duration_units: string
rate_units: string
}
export interface Metrics {
counters: { [key: string]: MetricCounter }
gauges: { [key: string]: MetricGauge }
meters: { [key: string]: MetricMeter }
timers: { [key: string]: MetricTimer }
}
export interface MultipleMarkRequest {
requests: MarkRequest[]
}
export interface PasswordResetRequest {
email: string
}
export interface ProfileModificationRequest {
currentPassword: string
email: string
newPassword?: string
newApiKey?: boolean
}
export interface RegistrationRequest {
name: string
password: string
email: string
}
export interface ServerInfo {
announcement?: string
version: string
gitCommit: string
allowRegistrations: boolean
googleAnalyticsCode?: string
smtpEnabled: boolean
demoAccountEnabled: boolean
}
export interface Settings {
language: string
readingMode: ReadingMode
readingOrder: ReadingOrder
viewMode: ViewMode
showRead: boolean
scrollMarks: boolean
theme?: string
customCss?: string
scrollSpeed: number
sharingSettings: SharingSettings
}
export interface SharingSettings {
email: boolean
gmail: boolean
facebook: boolean
twitter: boolean
tumblr: boolean
pocket: boolean
instapaper: boolean
buffer: boolean
}
export interface StarRequest {
id: string
feedId: number
starred: boolean
}
export interface SubscribeRequest {
url: string
title: string
categoryId?: string
}
export interface Subscription {
id: number
name: string
message?: string
errorCount: number
lastRefresh?: number
nextRefresh?: number
feedUrl: string
feedLink: string
iconUrl: string
unread: number
categoryId?: string
position?: number
newestItemTime?: number
filter?: string
}
export interface TagRequest {
entryId: number
tags: string[]
}
export interface UnreadCount {
feedId?: number
unreadCount?: number
newestItemTime?: number
}
export interface UserModel {
id: number
name: string
email?: string
apiKey?: string
password?: string
enabled: boolean
created: number
lastLogin?: number
admin: boolean
}
export type ApplicationSettingsCache = "NOOP" | "REDIS"
export type ReadingMode = "all" | "unread"
export type ReadingOrder = "asc" | "desc"
export type ViewMode = "title" | "cozy" | "expanded"

View File

@@ -0,0 +1,66 @@
import { Category } from "./types"
export function visitCategoryTree(category: Category, visitor: (category: Category) => void): void {
visitor(category)
category.children.forEach(child => visitCategoryTree(child, visitor))
}
export function flattenCategoryTree(category: Category): Category[] {
const categories: Category[] = []
visitCategoryTree(category, c => categories.push(c))
return categories
}
export function categoryUnreadCount(category?: Category): number {
if (!category) return 0
return flattenCategoryTree(category)
.flatMap(c => c.feeds)
.map(f => f.unread)
.reduce((total, current) => total + current, 0)
}
export const calculatePlaceholderSize = ({ width, height, maxWidth }: { width?: number; height?: number; maxWidth: number }) => {
const placeholderWidth = width && Math.min(width, maxWidth)
const placeholderHeight = height && width && width > maxWidth ? height * (maxWidth / width) : height
return { width: placeholderWidth, height: placeholderHeight }
}
export const scrollToWithCallback = ({
element,
options,
onScrollEnded,
}: {
element: HTMLElement
options: ScrollToOptions
onScrollEnded: () => void
}) => {
const offset = (options.top ?? 0).toFixed()
const onScroll = () => {
if (element.offsetTop.toFixed() === offset) {
element.removeEventListener("scroll", onScroll)
onScrollEnded()
}
}
element.addEventListener("scroll", onScroll)
// scrollTo does not trigger if there's nothing to do, trigger it manually
onScroll()
element.scrollTo(options)
}
export const openLinkInBackgroundTab = (url: string) => {
// simulate ctrl+click to open tab in background
const a = document.createElement("a")
a.href = url
a.rel = "noreferrer"
a.dispatchEvent(
new MouseEvent("click", {
ctrlKey: true,
metaKey: true,
})
)
}

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,28 @@
import { ActionIcon, Button, useMantineTheme } from "@mantine/core"
import { useMediaQuery } from "@mantine/hooks"
import { forwardRef } from "react"
interface ActionButtonProps {
className?: string
icon?: React.ReactNode
label?: string
onClick?: React.MouseEventHandler
}
/**
* Switches between Button with label (desktop) and ActionIcon (mobile)
*/
export const ActionButton = forwardRef<HTMLButtonElement, ActionButtonProps>((props: ActionButtonProps, ref) => {
const theme = useMantineTheme()
const mobile = !useMediaQuery(`(min-width: ${theme.breakpoints.lg}px)`)
return mobile ? (
<ActionIcon ref={ref} color={theme.primaryColor} variant="subtle" className={props.className} onClick={props.onClick}>
{props.icon}
</ActionIcon>
) : (
<Button ref={ref} variant="subtle" size="xs" className={props.className} leftIcon={props.icon} onClick={props.onClick}>
{props.label}
</Button>
)
})
ActionButton.displayName = "HeaderButton"

View File

@@ -0,0 +1,48 @@
import { t } from "@lingui/macro"
import { Alert as MantineAlert, Box } from "@mantine/core"
import { Fragment } from "react"
import { TbAlertCircle, TbAlertTriangle, TbCircleCheck } from "react-icons/tb"
type Level = "error" | "warning" | "success"
export interface ErrorsAlertProps {
level?: Level
messages: string[]
}
export function Alert(props: ErrorsAlertProps) {
let title: string
let color: string
let icon: React.ReactNode
const level = props.level ?? "error"
switch (level) {
case "error":
title = t`Error`
color = "red"
icon = <TbAlertCircle />
break
case "warning":
title = t`Warning`
color = "orange"
icon = <TbAlertTriangle />
break
case "success":
title = t`Success`
color = "green"
icon = <TbCircleCheck />
break
default:
throw Error(`unsupported level: ${level}`)
}
return (
<MantineAlert title={title} color={color} icon={icon}>
{props.messages.map((m, i) => (
<Fragment key={m}>
<Box>{m}</Box>
{i !== props.messages.length - 1 && <br />}
</Fragment>
))}
</MantineAlert>
)
}

View File

@@ -0,0 +1,5 @@
import { Group } from "@mantine/core"
export function ButtonToolbar(props: { children: React.ReactNode }) {
return <Group spacing={14}>{props.children}</Group>
}

View File

@@ -0,0 +1,26 @@
import { ErrorPage } from "pages/ErrorPage"
import React, { ReactNode } from "react"
interface ErrorBoundaryProps {
children?: ReactNode
}
interface ErrorBoundaryState {
error?: Error
}
export class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) {
super(props)
this.state = {}
}
componentDidCatch(error: Error) {
this.setState({ error })
}
render() {
if (this.state.error) return <ErrorPage error={this.state.error} />
return this.props.children
}
}

View File

@@ -0,0 +1,54 @@
import { Box, Center, createStyles } from "@mantine/core"
import { useState } from "react"
import { TbPhoto } from "react-icons/tb"
interface ImageWithPlaceholderWhileLoadingProps {
src: string
alt: string
title?: string
width?: number
height?: number | "auto"
placeholderWidth?: number
placeholderHeight?: number
placeholderBackgroundColor?: string
placeholderIconSize?: number
placeholderIconColor?: string
}
const useStyles = createStyles((theme, props: ImageWithPlaceholderWhileLoadingProps) => ({
placeholder: {
width: props.placeholderWidth ?? 400,
height: props.placeholderHeight ?? 600,
maxWidth: "100%",
color: props.placeholderIconColor ?? theme.fn.variant({ color: theme.primaryColor, variant: "subtle" }).color,
backgroundColor: props.placeholderBackgroundColor ?? (theme.colorScheme === "dark" ? theme.colors.dark[5] : theme.colors.gray[1]),
},
}))
export function ImageWithPlaceholderWhileLoading(props: ImageWithPlaceholderWhileLoadingProps) {
const { classes } = useStyles(props)
const [loading, setLoading] = useState(true)
return (
<>
{loading && (
<Box>
<Center className={classes.placeholder}>
<div>
<TbPhoto size={props.placeholderIconSize ?? 48} />
</div>
</Center>
</Box>
)}
<img
src={props.src}
alt={props.alt}
title={props.title}
width={props.width}
height={props.height}
onLoad={() => setLoading(false)}
style={{ display: loading ? "none" : "block" }}
/>
</>
)
}

View File

@@ -0,0 +1,183 @@
import { Trans } from "@lingui/macro"
import { Kbd, Table } from "@mantine/core"
export function KeyboardShortcutsHelp() {
return (
<Table striped highlightOnHover>
<tbody>
<tr>
<td>
<Trans>Refresh</Trans>
</td>
<td>
<Kbd>R</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Open next entry</Trans>
</td>
<td>
<Kbd>J</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Open previous entry</Trans>
</td>
<td>
<Kbd>K</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Set focus on next entry without opening it</Trans>
</td>
<td>
<Kbd>N</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Set focus on previous entry without opening it</Trans>
</td>
<td>
<Kbd>P</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Move the page down</Trans>
</td>
<td>
<Kbd>
<Trans>Space</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Move the page up</Trans>
</td>
<td>
<Kbd>
<Trans>Shift</Trans>
</Kbd>
<span> + </span>
<Kbd>
<Trans>Space</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Open/close current entry</Trans>
</td>
<td>
<Kbd>O</Kbd>
<span>, </span>
<Kbd>
<Trans>Enter</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Open current entry in a new tab</Trans>
</td>
<td>
<Kbd>V</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Open current entry in a new tab in the background</Trans>
</td>
<td>
<Kbd>B</Kbd>
<span>, </span>
<Kbd>
<Trans>Middle click</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Toggle read status of current entry</Trans>
</td>
<td>
<Kbd>M</Kbd>
<span>, </span>
<Trans>Swipe header to the right</Trans>
</td>
</tr>
<tr>
<td>
<Trans>Mark all entries as read</Trans>
</td>
<td>
<Kbd>
<Trans>Shift</Trans>
</Kbd>
<span> + </span>
<Kbd>A</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Go to the All view</Trans>
</td>
<td>
<Kbd>G</Kbd>
<span> </span>
<Kbd>A</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Navigate to a subscription by entering its name</Trans>
</td>
<td>
<Kbd>
<Trans>Ctrl</Trans>
</Kbd>
<span> + </span>
<Kbd>K</Kbd>
<span>, </span>
<Kbd>G</Kbd>
<span> </span>
<Kbd>U</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Show entry menu (desktop)</Trans>
</td>
<td>
<Kbd>
<Trans>Right click</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Show entry menu (mobile)</Trans>
</td>
<td>
<Kbd>
<Trans>Long press</Trans>
</Kbd>
</td>
</tr>
<tr>
<td>
<Trans>Show keyboard shortcut help</Trans>
</td>
<td>
<Kbd>?</Kbd>
</td>
</tr>
</tbody>
</Table>
)
}

View File

@@ -0,0 +1,9 @@
import { Center, Loader as MantineLoader } from "@mantine/core"
export function Loader() {
return (
<Center>
<MantineLoader size="xl" variant="bars" />
</Center>
)
}

View File

@@ -0,0 +1,10 @@
import { Image } from "@mantine/core"
import logo from "assets/logo.svg"
export interface LogoProps {
size: number
}
export function Logo(props: LogoProps) {
return <Image src={logo} width={props.size} />
}

View File

@@ -0,0 +1,14 @@
import { Trans } from "@lingui/macro"
import dayjs from "dayjs"
import { useEffect, useState } from "react"
export function RelativeDate(props: { date: Date | number | undefined }) {
const [now, setNow] = useState(new Date())
useEffect(() => {
const interval = setInterval(() => setNow(new Date()), 60 * 1000)
return () => clearInterval(interval)
}, [])
if (!props.date) return <Trans>N/A</Trans>
return <>{dayjs(props.date).from(dayjs(now))}</>
}

View File

@@ -0,0 +1,50 @@
import { t, Trans } from "@lingui/macro"
import { Box, Button, Checkbox, Group, PasswordInput, Stack, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { client, errorToStrings } from "app/client"
import { UserModel } from "app/types"
import { Alert } from "components/Alert"
import { useAsyncCallback } from "react-async-hook"
import { TbDeviceFloppy } from "react-icons/tb"
interface UserEditProps {
user?: UserModel
onCancel: () => void
onSave: () => void
}
export function UserEdit(props: UserEditProps) {
const form = useForm<UserModel>({
initialValues: props.user ?? ({ enabled: true } as UserModel),
})
const saveUser = useAsyncCallback(client.admin.saveUser, { onSuccess: props.onSave })
return (
<>
{saveUser.error && (
<Box mb="md">
<Alert messages={errorToStrings(saveUser.error)} />
</Box>
)}
<form onSubmit={form.onSubmit(saveUser.execute)}>
<Stack>
<TextInput label={t`Name`} {...form.getInputProps("name")} required />
<PasswordInput label={t`Password`} {...form.getInputProps("password")} required={!props.user} />
<TextInput type="email" label={t`E-mail`} {...form.getInputProps("email")} />
<Checkbox label={t`Admin`} {...form.getInputProps("admin", { type: "checkbox" })} />
<Checkbox label={t`Enabled`} {...form.getInputProps("enabled", { type: "checkbox" })} />
<Group>
<Button variant="default" onClick={props.onCancel}>
<Trans>Cancel</Trans>
</Button>
<Button type="submit" leftIcon={<TbDeviceFloppy size={16} />} loading={saveUser.loading}>
<Trans>Save</Trans>
</Button>
</Group>
</Stack>
</form>
</>
)
}

View File

@@ -0,0 +1,97 @@
import { Box, createStyles, Mark, TypographyStylesProvider } from "@mantine/core"
import { Constants } from "app/constants"
import { useAppSelector } from "app/store"
import { calculatePlaceholderSize } from "app/utils"
import { ImageWithPlaceholderWhileLoading } from "components/ImageWithPlaceholderWhileLoading"
import { ChildrenNode, Interweave, Matcher, MatchResponse, Node, TransformCallback } from "interweave"
export interface ContentProps {
content: string
}
const useStyles = createStyles(theme => ({
content: {
// break long links or long words
overflowWrap: "anywhere",
"& a": {
color: theme.fn.variant({ color: theme.primaryColor, variant: "subtle" }).color,
},
"& iframe": {
maxWidth: "100%",
},
"& pre, & code": {
whiteSpace: "pre-wrap",
},
},
}))
const transform: TransformCallback = node => {
if (node.tagName === "IMG") {
// show placeholders for loading img tags, this allows the entry to have its final height immediately
const src = node.getAttribute("src") ?? undefined
if (!src) return undefined
const alt = node.getAttribute("alt") ?? "image"
const title = node.getAttribute("title") ?? undefined
const nodeWidth = node.getAttribute("width")
const nodeHeight = node.getAttribute("height")
const width = nodeWidth ? parseInt(nodeWidth, 10) : undefined
const height = nodeHeight ? parseInt(nodeHeight, 10) : undefined
const placeholderSize = calculatePlaceholderSize({
width,
height,
maxWidth: Constants.layout.entryMaxWidth,
})
return (
<ImageWithPlaceholderWhileLoading
src={src}
alt={alt}
title={title}
width={width}
height="auto"
placeholderWidth={placeholderSize.width}
placeholderHeight={placeholderSize.height}
/>
)
}
return undefined
}
class HighlightMatcher extends Matcher {
private search: string
constructor(search: string) {
super("highlight")
this.search = search
}
match(string: string): MatchResponse<unknown> | null {
const pattern = this.search.split(" ").join("|")
return this.doMatch(string, new RegExp(pattern, "i"), () => ({}))
}
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars
replaceWith(children: ChildrenNode, props: unknown): Node {
return <Mark>{children}</Mark>
}
// eslint-disable-next-line class-methods-use-this
asTag(): string {
return "span"
}
}
export function Content(props: ContentProps) {
const { classes } = useStyles()
const search = useAppSelector(state => state.entries.search)
const matchers = search ? [new HighlightMatcher(search)] : []
return (
<TypographyStylesProvider>
<Box className={classes.content}>
<Interweave content={props.content} transform={transform} matchers={matchers} />
</Box>
</TypographyStylesProvider>
)
}

View File

@@ -0,0 +1,26 @@
import { TypographyStylesProvider } from "@mantine/core"
import { ImageWithPlaceholderWhileLoading } from "components/ImageWithPlaceholderWhileLoading"
export function Enclosure(props: { enclosureType: string; enclosureUrl: string }) {
const hasVideo = props.enclosureType && props.enclosureType.indexOf("video") === 0
const hasAudio = props.enclosureType && props.enclosureType.indexOf("audio") === 0
const hasImage = props.enclosureType && props.enclosureType.indexOf("image") === 0
return (
<TypographyStylesProvider>
{hasVideo && (
// eslint-disable-next-line jsx-a11y/media-has-caption
<video controls>
<source src={props.enclosureUrl} type={props.enclosureType} />
</video>
)}
{hasAudio && (
// eslint-disable-next-line jsx-a11y/media-has-caption
<audio controls>
<source src={props.enclosureUrl} type={props.enclosureType} />
</audio>
)}
{hasImage && <ImageWithPlaceholderWhileLoading src={props.enclosureUrl} alt="enclosure" />}
</TypographyStylesProvider>
)
}

View File

@@ -0,0 +1,265 @@
import { t } from "@lingui/macro"
import { openModal } from "@mantine/modals"
import { Constants } from "app/constants"
import {
ExpendableEntry,
loadMoreEntries,
markAllEntries,
markEntry,
reloadEntries,
selectEntry,
selectNextEntry,
selectPreviousEntry,
} from "app/slices/entries"
import { redirectToRootCategory } from "app/slices/redirect"
import { useAppDispatch, useAppSelector } from "app/store"
import { openLinkInBackgroundTab } from "app/utils"
import { KeyboardShortcutsHelp } from "components/KeyboardShortcutsHelp"
import { Loader } from "components/Loader"
import { useMousetrap } from "hooks/useMousetrap"
import throttle from "lodash/throttle"
import { useEffect } from "react"
import InfiniteScroll from "react-infinite-scroller"
import { FeedEntry } from "./FeedEntry"
export function FeedEntries() {
const source = useAppSelector(state => state.entries.source)
const entries = useAppSelector(state => state.entries.entries)
const entriesTimestamp = useAppSelector(state => state.entries.timestamp)
const selectedEntryId = useAppSelector(state => state.entries.selectedEntryId)
const hasMore = useAppSelector(state => state.entries.hasMore)
const viewMode = useAppSelector(state => state.user.settings?.viewMode)
const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks)
const scrollingToEntry = useAppSelector(state => state.entries.scrollingToEntry)
const dispatch = useAppDispatch()
const selectedEntry = entries.find(e => e.id === selectedEntryId)
const headerClicked = (entry: ExpendableEntry, event: React.MouseEvent) => {
if (event.button === 1 || event.ctrlKey || event.metaKey) {
// middle click
dispatch(markEntry({ entry, read: true }))
} else if (event.button === 0) {
// main click
// don't trigger the link
event.preventDefault()
dispatch(
selectEntry({
entry,
expand: !entry.expanded,
markAsRead: !entry.expanded,
scrollToEntry: true,
})
)
}
}
useEffect(() => {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => {
if (viewMode !== "expanded") return
if (scrollingToEntry) return
const currentEntry = entries
// use slice to get a copy of the array because reverse mutates the array in-place
.slice()
.reverse()
.find(e => {
const el = document.getElementById(Constants.dom.entryId(e))
return el && !Constants.layout.isTopVisible(el)
})
if (currentEntry) {
dispatch(
selectEntry({
entry: currentEntry,
expand: false,
markAsRead: !!scrollMarks,
scrollToEntry: false,
})
)
}
}
const throttledListener = throttle(listener, 100)
scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener)
}, [dispatch, entries, viewMode, scrollMarks, scrollingToEntry])
useMousetrap("r", () => dispatch(reloadEntries()))
useMousetrap("j", () =>
dispatch(
selectNextEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
)
useMousetrap("n", () =>
dispatch(
selectNextEntry({
expand: false,
markAsRead: false,
scrollToEntry: true,
})
)
)
useMousetrap("k", () =>
dispatch(
selectPreviousEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
)
useMousetrap("p", () =>
dispatch(
selectPreviousEntry({
expand: false,
markAsRead: false,
scrollToEntry: true,
})
)
)
useMousetrap("space", () => {
if (selectedEntry) {
if (selectedEntry.expanded) {
const entryElement = document.getElementById(Constants.dom.entryId(selectedEntry))
if (entryElement && Constants.layout.isBottomVisible(entryElement)) {
dispatch(
selectNextEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
} else {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
scrollArea?.scrollTo({
top: scrollArea.scrollTop + scrollArea.clientHeight * 0.8,
behavior: "smooth",
})
}
} else {
dispatch(
selectEntry({
entry: selectedEntry,
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
}
} else {
dispatch(
selectNextEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
}
})
useMousetrap("shift+space", () => {
if (selectedEntry) {
if (selectedEntry.expanded) {
const entryElement = document.getElementById(Constants.dom.entryId(selectedEntry))
if (entryElement && Constants.layout.isTopVisible(entryElement)) {
dispatch(
selectPreviousEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
} else {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
scrollArea?.scrollTo({
top: scrollArea.scrollTop - scrollArea.clientHeight * 0.8,
behavior: "smooth",
})
}
} else {
dispatch(
selectPreviousEntry({
expand: true,
markAsRead: true,
scrollToEntry: true,
})
)
}
}
})
useMousetrap(["o", "enter"], () => {
// toggle expanded status
if (!selectedEntry) return
dispatch(
selectEntry({
entry: selectedEntry,
expand: !selectedEntry.expanded,
markAsRead: !selectedEntry.expanded,
scrollToEntry: true,
})
)
})
useMousetrap("v", () => {
// open tab in foreground
if (!selectedEntry) return
window.open(selectedEntry.url, "_blank", "noreferrer")
})
useMousetrap("b", () => {
// simulate ctrl+click to open tab in background
if (!selectedEntry) return
openLinkInBackgroundTab(selectedEntry.url)
})
useMousetrap("m", () => {
// toggle read status
if (!selectedEntry) return
dispatch(markEntry({ entry: selectedEntry, read: !selectedEntry.read }))
})
useMousetrap("shift+a", () => {
// mark all entries as read
dispatch(
markAllEntries({
sourceType: source.type,
req: {
id: source.id,
read: true,
olderThan: entriesTimestamp,
},
})
)
})
useMousetrap("g a", () => dispatch(redirectToRootCategory()))
useMousetrap("?", () => openModal({ title: t`Keyboard shortcuts`, size: "xl", children: <KeyboardShortcutsHelp /> }))
if (!entries) return <Loader />
return (
<InfiniteScroll
initialLoad={false}
loadMore={() => dispatch(loadMoreEntries())}
hasMore={hasMore}
loader={<Loader key={0} />}
useWindow={false}
getScrollParent={() => document.getElementById(Constants.dom.mainScrollAreaId)}
>
{entries.map(entry => (
<div
key={entry.id}
ref={el => {
if (el) el.id = Constants.dom.entryId(entry)
}}
>
<FeedEntry
entry={entry}
expanded={!!entry.expanded || viewMode === "expanded"}
showSelectionIndicator={entry.id === selectedEntryId && (!entry.expanded || viewMode === "expanded")}
onHeaderClick={event => headerClicked(entry, event)}
/>
</div>
))}
</InfiniteScroll>
)
}

View File

@@ -0,0 +1,101 @@
import { Anchor, Box, createStyles, Divider, Paper } from "@mantine/core"
import { Constants } from "app/constants"
import { markEntry } from "app/slices/entries"
import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types"
import React from "react"
import { useSwipeable } from "react-swipeable"
import { FeedEntryBody } from "./FeedEntryBody"
import { FeedEntryCompactHeader } from "./FeedEntryCompactHeader"
import { FeedEntryContextMenu, useFeedEntryContextMenu } from "./FeedEntryContextMenu"
import { FeedEntryFooter } from "./FeedEntryFooter"
import { FeedEntryHeader } from "./FeedEntryHeader"
interface FeedEntryProps {
entry: Entry
expanded: boolean
showSelectionIndicator: boolean
onHeaderClick: (e: React.MouseEvent) => void
}
const useStyles = createStyles((theme, props: FeedEntryProps & { compact: boolean }) => {
let backgroundColor
if (theme.colorScheme === "dark") backgroundColor = props.entry.read ? "inherit" : theme.colors.dark[5]
else backgroundColor = props.entry.read && !props.expanded ? theme.colors.gray[0] : "inherit"
let marginY = theme.spacing.xs
if (props.compact) marginY = 6
let mobileMarginY = 6
if (props.compact) mobileMarginY = 4
const styles = {
paper: {
backgroundColor,
marginTop: marginY,
marginBottom: marginY,
[theme.fn.smallerThan(Constants.layout.mobileBreakpoint)]: {
marginTop: mobileMarginY,
marginBottom: mobileMarginY,
},
},
body: {
maxWidth: Constants.layout.entryMaxWidth,
},
}
if (props.showSelectionIndicator) {
styles.paper.borderLeftColor = theme.colorScheme === "dark" ? theme.colors.orange[4] : theme.colors.orange[6]
}
return styles
})
export function FeedEntry(props: FeedEntryProps) {
const viewMode = useAppSelector(state => state.user.settings?.viewMode)
const compact = viewMode === "title"
const compactHeader = compact && !props.expanded
const { classes } = useStyles({ ...props, compact })
const dispatch = useAppDispatch()
const swipeHandlers = useSwipeable({
onSwipedRight: () => dispatch(markEntry({ entry: props.entry, read: !props.entry.read })),
})
const { onContextMenu } = useFeedEntryContextMenu(props.entry)
const spacing = compact ? 8 : "xs"
const borderRadius = compact ? "xs" : "sm"
return (
<Paper withBorder radius={borderRadius} className={classes.paper}>
<Anchor
variant="text"
href={props.entry.url}
target="_blank"
rel="noreferrer"
onClick={props.onHeaderClick}
onAuxClick={props.onHeaderClick}
onContextMenu={onContextMenu}
>
<Box p={spacing} {...swipeHandlers}>
{compactHeader && <FeedEntryCompactHeader entry={props.entry} />}
{!compactHeader && <FeedEntryHeader entry={props.entry} expanded={props.expanded} />}
</Box>
</Anchor>
{props.expanded && (
<Box px={spacing} pb={spacing}>
<Box className={classes.body} sx={{ direction: props.entry.rtl ? "rtl" : "ltr" }}>
<FeedEntryBody entry={props.entry} />
</Box>
<Divider variant="dashed" my={spacing} />
<FeedEntryFooter entry={props.entry} />
</Box>
)}
<FeedEntryContextMenu entry={props.entry} />
</Paper>
)
}

View File

@@ -0,0 +1,35 @@
import { Box } from "@mantine/core"
import { Entry } from "app/types"
import { Content } from "./Content"
import { Enclosure } from "./Enclosure"
import { Media } from "./Media"
export interface FeedEntryBodyProps {
entry: Entry
}
export function FeedEntryBody(props: FeedEntryBodyProps) {
return (
<Box>
<Box>
<Content content={props.entry.content} />
</Box>
{props.entry.enclosureType && props.entry.enclosureUrl && (
<Box pt="md">
<Enclosure enclosureType={props.entry.enclosureType} enclosureUrl={props.entry.enclosureUrl} />
</Box>
)}
{/* show media only if we don't have content to avoid duplicate content */}
{!props.entry.content && props.entry.mediaThumbnailUrl && (
<Box pt="md">
<Media
thumbnailUrl={props.entry.mediaThumbnailUrl}
thumbnailWidth={props.entry.mediaThumbnailWidth}
thumbnailHeight={props.entry.mediaThumbnailHeight}
description={props.entry.mediaDescription}
/>
</Box>
)}
</Box>
)
}

View File

@@ -0,0 +1,58 @@
import { Box, createStyles, Text } from "@mantine/core"
import { Entry } from "app/types"
import { RelativeDate } from "components/RelativeDate"
import { OnDesktop } from "components/responsive/OnDesktop"
import { FeedEntryTitle } from "./FeedEntryTitle"
import { FeedFavicon } from "./FeedFavicon"
export interface FeedEntryHeaderProps {
entry: Entry
}
const useStyles = createStyles((theme, props: FeedEntryHeaderProps) => ({
wrapper: {
display: "flex",
alignItems: "center",
columnGap: "10px",
},
title: {
flexGrow: 1,
fontWeight: theme.colorScheme === "light" && !props.entry.read ? "bold" : "inherit",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
feedName: {
width: "145px",
minWidth: "145px",
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
date: {
whiteSpace: "nowrap",
},
}))
export function FeedEntryCompactHeader(props: FeedEntryHeaderProps) {
const { classes } = useStyles(props)
return (
<Box className={classes.wrapper}>
<Box>
<FeedFavicon url={props.entry.iconUrl} />
</Box>
<OnDesktop>
<Text color="dimmed" className={classes.feedName}>
{props.entry.feedName}
</Text>
</OnDesktop>
<Box className={classes.title}>
<FeedEntryTitle entry={props.entry} />
</Box>
<OnDesktop>
<Text color="dimmed" className={classes.date}>
<RelativeDate date={props.entry.date} />
</Text>
</OnDesktop>
</Box>
)
}

View File

@@ -0,0 +1,127 @@
import { t, Trans } from "@lingui/macro"
import { createStyles, Group } from "@mantine/core"
import { Constants } from "app/constants"
import { markEntriesUpToEntry, markEntry, starEntry } from "app/slices/entries"
import { redirectToFeed } from "app/slices/redirect"
import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types"
import { openLinkInBackgroundTab } from "app/utils"
import { throttle, truncate } from "lodash"
import { useEffect } from "react"
import { Item, Menu, Separator, useContextMenu } from "react-contexify"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbRss, TbStar, TbStarOff } from "react-icons/tb"
interface FeedEntryContextMenuProps {
entry: Entry
}
const iconSize = 16
const useStyles = createStyles(theme => ({
menu: {
// apply mantine theme from MenuItem.styles.ts
fontSize: theme.fontSizes.sm,
"--contexify-item-color": `${theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black} !important`,
"--contexify-activeItem-color": `${theme.colorScheme === "dark" ? theme.colors.dark[0] : theme.black} !important`,
"--contexify-activeItem-bgColor": `${
theme.colorScheme === "dark" ? theme.fn.rgba(theme.colors.dark[3], 0.35) : theme.colors.gray[1]
} !important`,
},
}))
const menuId = (entry: Entry) => entry.id
export function FeedEntryContextMenu(props: FeedEntryContextMenuProps) {
const { classes, theme } = useStyles()
const sourceType = useAppSelector(state => state.entries.source.type)
const dispatch = useAppDispatch()
return (
<Menu id={menuId(props.entry)} theme={theme.colorScheme} animation={false} className={classes.menu}>
<Item
onClick={() => {
window.open(props.entry.url, "_blank", "noreferrer")
dispatch(markEntry({ entry: props.entry, read: true }))
}}
>
<Group>
<TbExternalLink size={iconSize} />
<Trans>Open link in new tab</Trans>
</Group>
</Item>
<Item
onClick={() => {
openLinkInBackgroundTab(props.entry.url)
dispatch(markEntry({ entry: props.entry, read: true }))
}}
>
<Group>
<TbExternalLink size={iconSize} />
<Trans>Open link in new background tab</Trans>
</Group>
</Item>
<Separator />
<Item onClick={() => dispatch(starEntry({ entry: props.entry, starred: !props.entry.starred }))}>
<Group>
{props.entry.starred ? <TbStarOff size={iconSize} /> : <TbStar size={iconSize} />}
{props.entry.starred ? t`Unstar` : t`Star`}
</Group>
</Item>
<Item onClick={() => dispatch(markEntry({ entry: props.entry, read: !props.entry.read }))}>
<Group>
{props.entry.read ? <TbEyeOff size={iconSize} /> : <TbEyeCheck size={iconSize} />}
{props.entry.read ? t`Keep unread` : t`Mark as read`}
</Group>
</Item>
<Item onClick={() => dispatch(markEntriesUpToEntry(props.entry))}>
<Group>
<TbArrowBarToDown size={iconSize} />
<Trans>Mark as read up to here</Trans>
</Group>
</Item>
{sourceType === "category" && (
<>
<Separator />
<Item
onClick={() => {
dispatch(redirectToFeed(props.entry.feedId))
}}
>
<Group>
<TbRss size={iconSize} />
<Trans>Go to {truncate(props.entry.feedName)}</Trans>
</Group>
</Item>
</>
)}
</Menu>
)
}
export function useFeedEntryContextMenu(entry: Entry) {
const contextMenu = useContextMenu({
id: menuId(entry),
})
const onContextMenu = (event: React.MouseEvent) => {
event.preventDefault()
contextMenu.show({
event,
})
}
// close context menu on scroll
useEffect(() => {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => contextMenu.hideAll()
const throttledListener = throttle(listener, 100)
scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener)
}, [contextMenu])
return { onContextMenu }
}

View File

@@ -0,0 +1,108 @@
import { t } from "@lingui/macro"
import { Group, Indicator, MultiSelect, Popover } from "@mantine/core"
import { useMediaQuery } from "@mantine/hooks"
import { Constants } from "app/constants"
import { markEntriesUpToEntry, markEntry, starEntry, tagEntry } from "app/slices/entries"
import { useAppDispatch, useAppSelector } from "app/store"
import { Entry } from "app/types"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
import { throttle } from "lodash"
import { useEffect, useState } from "react"
import { TbArrowBarToDown, TbExternalLink, TbEyeCheck, TbEyeOff, TbShare, TbStar, TbStarOff, TbTag } from "react-icons/tb"
import { ShareButtons } from "./ShareButtons"
interface FeedEntryFooterProps {
entry: Entry
}
export function FeedEntryFooter(props: FeedEntryFooterProps) {
const [scrollPosition, setScrollPosition] = useState(0)
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
const tags = useAppSelector(state => state.user.tags)
const mobile = !useMediaQuery(`(min-width: ${Constants.layout.mobileBreakpoint}px)`)
const dispatch = useAppDispatch()
const showSharingButtons = sharingSettings && Object.values(sharingSettings).some(v => v)
const readStatusButtonClicked = () => dispatch(markEntry({ entry: props.entry, read: !props.entry.read }))
const onTagsChange = (values: string[]) =>
dispatch(
tagEntry({
entryId: +props.entry.id,
tags: values,
})
)
useEffect(() => {
const scrollArea = document.getElementById(Constants.dom.mainScrollAreaId)
const listener = () => setScrollPosition(scrollArea ? scrollArea.scrollTop : 0)
const throttledListener = throttle(listener, 100)
scrollArea?.addEventListener("scroll", throttledListener)
return () => scrollArea?.removeEventListener("scroll", throttledListener)
}, [])
return (
<Group position="apart">
<ButtonToolbar>
{props.entry.markable && (
<ActionButton
icon={props.entry.read ? <TbEyeOff size={18} /> : <TbEyeCheck size={18} />}
label={props.entry.read ? t`Keep unread` : t`Mark as read`}
onClick={readStatusButtonClicked}
/>
)}
<ActionButton
icon={props.entry.starred ? <TbStarOff size={18} /> : <TbStar size={18} />}
label={props.entry.starred ? t`Unstar` : t`Star`}
onClick={() => dispatch(starEntry({ entry: props.entry, starred: !props.entry.starred }))}
/>
{showSharingButtons && (
<Popover withArrow withinPortal shadow="md" positionDependencies={[scrollPosition]} closeOnClickOutside={!mobile}>
<Popover.Target>
<ActionButton icon={<TbShare size={18} />} label={t`Share`} />
</Popover.Target>
<Popover.Dropdown>
<ShareButtons url={props.entry.url} description={props.entry.title} />
</Popover.Dropdown>
</Popover>
)}
{tags && (
<Popover withArrow withinPortal shadow="md" positionDependencies={[scrollPosition]} closeOnClickOutside={!mobile}>
<Popover.Target>
<Indicator label={props.entry.tags.length} showZero={false} dot={false} inline size={16}>
<ActionButton icon={<TbTag size={18} />} label={t`Tags`} />
</Indicator>
</Popover.Target>
<Popover.Dropdown>
<MultiSelect
data={tags}
placeholder="Tags"
searchable
creatable
autoFocus
getCreateLabel={query => t`Create tag: ${query}`}
value={props.entry.tags}
onChange={onTagsChange}
/>
</Popover.Dropdown>
</Popover>
)}
<a href={props.entry.url} target="_blank" rel="noreferrer">
<ActionButton icon={<TbExternalLink size={18} />} label={t`Open link`} />
</a>
</ButtonToolbar>
<ActionButton
icon={<TbArrowBarToDown size={18} />}
label={t`Mark as read up to here`}
onClick={() => dispatch(markEntriesUpToEntry(props.entry))}
/>
</Group>
)
}

View File

@@ -0,0 +1,60 @@
import { Box, createStyles, Text } from "@mantine/core"
import { Entry } from "app/types"
import { RelativeDate } from "components/RelativeDate"
import { FeedEntryTitle } from "./FeedEntryTitle"
import { FeedFavicon } from "./FeedFavicon"
export interface FeedEntryHeaderProps {
entry: Entry
expanded: boolean
}
const useStyles = createStyles((theme, props: FeedEntryHeaderProps) => ({
headerText: {
fontWeight: theme.colorScheme === "light" && !props.entry.read ? "bold" : "inherit",
whiteSpace: props.expanded ? "inherit" : "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
headerSubtext: {
display: "flex",
alignItems: "center",
fontSize: "90%",
whiteSpace: props.expanded ? "inherit" : "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
}))
export function FeedEntryHeader(props: FeedEntryHeaderProps) {
const { classes } = useStyles(props)
return (
<Box>
<Box className={classes.headerText}>
<FeedEntryTitle entry={props.entry} />
</Box>
<Box className={classes.headerSubtext}>
<Box mr={6}>
<FeedFavicon url={props.entry.iconUrl} />
</Box>
<Box>
<Text color="dimmed">{props.entry.feedName}</Text>
</Box>
<Box>
<Text color="dimmed">
<span>&nbsp;·&nbsp;</span>
<RelativeDate date={props.entry.date} />
</Text>
</Box>
</Box>
{props.expanded && (
<Box className={classes.headerSubtext}>
<Text color="dimmed">
{props.entry.author && <span>by {props.entry.author}</span>}
{props.entry.author && props.entry.categories && <span>&nbsp;·&nbsp;</span>}
{props.entry.categories && <span>{props.entry.categories}</span>}
</Text>
</Box>
)}
</Box>
)
}

View File

@@ -0,0 +1,21 @@
import { Highlight } from "@mantine/core"
import { useAppSelector } from "app/store"
import { Entry } from "app/types"
export interface FeedEntryTitleProps {
entry: Entry
}
export function FeedEntryTitle(props: FeedEntryTitleProps) {
const search = useAppSelector(state => state.entries.search)
const keywords = search?.split(" ")
return (
<Highlight
highlight={keywords ?? ""}
// make sure ellipsis is shown when title is too long
span
>
{props.entry.title}
</Highlight>
)
}

View File

@@ -0,0 +1,22 @@
import { ImageWithPlaceholderWhileLoading } from "components/ImageWithPlaceholderWhileLoading"
export interface FeedFaviconProps {
url: string
size?: number
}
export function FeedFavicon({ url, size = 18 }: FeedFaviconProps) {
return (
<ImageWithPlaceholderWhileLoading
src={url}
alt="feed favicon"
width={size}
height={size}
placeholderWidth={size}
placeholderHeight={size}
placeholderBackgroundColor="inherit"
placeholderIconSize={size}
placeholderIconColor="inherit"
/>
)
}

View File

@@ -0,0 +1,39 @@
import { Box, TypographyStylesProvider } from "@mantine/core"
import { Constants } from "app/constants"
import { calculatePlaceholderSize } from "app/utils"
import { ImageWithPlaceholderWhileLoading } from "components/ImageWithPlaceholderWhileLoading"
import { Content } from "./Content"
export interface MediaProps {
thumbnailUrl: string
thumbnailWidth?: number
thumbnailHeight?: number
description?: string
}
export function Media(props: MediaProps) {
const width = props.thumbnailWidth
const height = props.thumbnailHeight
const placeholderSize = calculatePlaceholderSize({
width,
height,
maxWidth: Constants.layout.entryMaxWidth,
})
return (
<TypographyStylesProvider>
<ImageWithPlaceholderWhileLoading
src={props.thumbnailUrl}
alt="media thumbnail"
width={props.thumbnailWidth}
height={props.thumbnailHeight}
placeholderWidth={placeholderSize.width}
placeholderHeight={placeholderSize.height}
/>
{props.description && (
<Box pt="md">
<Content content={props.description} />
</Box>
)}
</TypographyStylesProvider>
)
}

View File

@@ -0,0 +1,55 @@
import { ActionIcon, Box, createStyles, SimpleGrid } from "@mantine/core"
import { Constants } from "app/constants"
import { useAppSelector } from "app/store"
import { SharingSettings } from "app/types"
import { IconType } from "react-icons"
type Color = `#${string}`
const useStyles = createStyles((theme, props: { color: Color }) => ({
socialIcon: {
color: props.color,
backgroundColor: theme.colorScheme === "dark" ? theme.colors.gray[2] : "white",
borderRadius: "50%",
},
}))
function ShareButton({ url, icon, color }: { url: string; icon: IconType; color: Color }) {
const { classes } = useStyles({ color })
const onClick = (e: React.MouseEvent) => {
e.preventDefault()
window.open(url, "", "menubar=no,toolbar=no,resizable=yes,scrollbars=yes,width=800,height=600")
}
return (
<ActionIcon>
<a href={url} target="_blank" rel="noreferrer" onClick={onClick}>
<Box p={6} className={classes.socialIcon}>
{icon({ size: 18 })}
</Box>
</a>
</ActionIcon>
)
}
export function ShareButtons(props: { url: string; description: string }) {
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
const url = encodeURIComponent(props.url)
const desc = encodeURIComponent(props.description)
return (
<SimpleGrid cols={4}>
{(Object.keys(Constants.sharing) as Array<keyof SharingSettings>)
.filter(site => sharingSettings && sharingSettings[site])
.map(site => (
<ShareButton
key={site}
icon={Constants.sharing[site].icon}
color={Constants.sharing[site].color}
url={Constants.sharing[site].url(url, desc)}
/>
))}
</SimpleGrid>
)
}

View File

@@ -0,0 +1,50 @@
import { t, Trans } from "@lingui/macro"
import { Box, Button, Group, Stack, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { client, errorToStrings } from "app/client"
import { redirectToSelectedSource } from "app/slices/redirect"
import { reloadTree } from "app/slices/tree"
import { useAppDispatch } from "app/store"
import { AddCategoryRequest } from "app/types"
import { Alert } from "components/Alert"
import { useAsyncCallback } from "react-async-hook"
import { TbFolderPlus } from "react-icons/tb"
import { CategorySelect } from "./CategorySelect"
export function AddCategory() {
const dispatch = useAppDispatch()
const form = useForm<AddCategoryRequest>()
const addCategory = useAsyncCallback(client.category.add, {
onSuccess: () => {
dispatch(reloadTree())
dispatch(redirectToSelectedSource())
},
})
return (
<>
{addCategory.error && (
<Box mb="md">
<Alert messages={errorToStrings(addCategory.error)} />
</Box>
)}
<form onSubmit={form.onSubmit(addCategory.execute)}>
<Stack>
<TextInput label={t`Category`} placeholder={t`Category`} {...form.getInputProps("name")} required />
<CategorySelect label={t`Parent`} {...form.getInputProps("parentId")} clearable />
<Group position="center">
<Button variant="default" onClick={() => dispatch(redirectToSelectedSource())}>
<Trans>Cancel</Trans>
</Button>
<Button type="submit" leftIcon={<TbFolderPlus size={16} />} loading={addCategory.loading}>
<Trans>Add</Trans>
</Button>
</Group>
</Stack>
</form>
</>
)
}

View File

@@ -0,0 +1,27 @@
import { t } from "@lingui/macro"
import { Select, SelectItem, SelectProps } from "@mantine/core"
import { Constants } from "app/constants"
import { useAppSelector } from "app/store"
import { flattenCategoryTree } from "app/utils"
type CategorySelectProps = Partial<SelectProps> & { withAll?: boolean }
export function CategorySelect(props: CategorySelectProps) {
const rootCategory = useAppSelector(state => state.tree.rootCategory)
const categories = rootCategory && flattenCategoryTree(rootCategory)
const selectData: SelectItem[] | undefined = categories
?.filter(c => c.id !== Constants.categories.all.id)
.sort((c1, c2) => c1.name.localeCompare(c2.name))
.map(c => ({
label: c.name,
value: c.id,
}))
if (props.withAll) {
selectData?.unshift({
label: t`All`,
value: Constants.categories.all.id,
})
}
return <Select {...props} data={selectData ?? []} disabled={!selectData} />
}

View File

@@ -0,0 +1,58 @@
import { t, Trans } from "@lingui/macro"
import { Box, Button, FileInput, Group, Stack } from "@mantine/core"
import { useForm } from "@mantine/form"
import { client, errorToStrings } from "app/client"
import { redirectToSelectedSource } from "app/slices/redirect"
import { reloadTree } from "app/slices/tree"
import { useAppDispatch } from "app/store"
import { Alert } from "components/Alert"
import { useAsyncCallback } from "react-async-hook"
import { TbFileImport } from "react-icons/tb"
export function ImportOpml() {
const dispatch = useAppDispatch()
const form = useForm<{ file: File }>({
validate: {
file: v => (v ? null : t`file is required`),
},
})
const importOpml = useAsyncCallback(client.feed.importOpml, {
onSuccess: () => {
dispatch(reloadTree())
dispatch(redirectToSelectedSource())
},
})
return (
<>
{importOpml.error && (
<Box mb="md">
<Alert messages={errorToStrings(importOpml.error)} />
</Box>
)}
<form onSubmit={form.onSubmit(v => importOpml.execute(v.file))}>
<Stack>
<FileInput
label={t`OPML file`}
placeholder={t`OPML file`}
description={t`An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services.`}
{...form.getInputProps("file")}
required
accept="application/xml"
/>
<Group position="center">
<Button variant="default" onClick={() => dispatch(redirectToSelectedSource())}>
<Trans>Cancel</Trans>
</Button>
<Button type="submit" leftIcon={<TbFileImport size={16} />} loading={importOpml.loading}>
<Trans>Import</Trans>
</Button>
</Group>
</Stack>
</form>
</>
)
}

View File

@@ -0,0 +1,117 @@
import { t, Trans } from "@lingui/macro"
import { Box, Button, Group, Stack, Stepper, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { client, errorToStrings } from "app/client"
import { Constants } from "app/constants"
import { redirectToFeed, redirectToSelectedSource } from "app/slices/redirect"
import { reloadTree } from "app/slices/tree"
import { useAppDispatch } from "app/store"
import { FeedInfoRequest, SubscribeRequest } from "app/types"
import { Alert } from "components/Alert"
import { useState } from "react"
import { useAsyncCallback } from "react-async-hook"
import { TbRss } from "react-icons/tb"
import { CategorySelect } from "./CategorySelect"
export function Subscribe() {
const [activeStep, setActiveStep] = useState(0)
const dispatch = useAppDispatch()
const step0Form = useForm<FeedInfoRequest>({
initialValues: {
url: "",
},
})
const step1Form = useForm<SubscribeRequest>({
initialValues: {
url: "",
title: "",
categoryId: Constants.categories.all.id,
},
})
const fetchFeed = useAsyncCallback(client.feed.fetchFeed, {
onSuccess: ({ data }) => {
step1Form.setFieldValue("url", data.url)
step1Form.setFieldValue("title", data.title)
setActiveStep(step => step + 1)
},
})
const subscribe = useAsyncCallback(client.feed.subscribe, {
onSuccess: sub => {
dispatch(reloadTree())
dispatch(redirectToFeed(sub.data))
},
})
const previousStep = () => {
if (activeStep === 0) dispatch(redirectToSelectedSource())
else setActiveStep(activeStep - 1)
}
const nextStep = (e: React.FormEvent<HTMLFormElement>) => {
if (activeStep === 0) {
step0Form.onSubmit(fetchFeed.execute)(e)
} else if (activeStep === 1) {
step1Form.onSubmit(subscribe.execute)(e)
}
}
return (
<>
{fetchFeed.error && (
<Box mb="md">
<Alert messages={errorToStrings(fetchFeed.error)} />
</Box>
)}
{subscribe.error && (
<Box mb="md">
<Alert messages={errorToStrings(subscribe.error)} />
</Box>
)}
<form onSubmit={nextStep}>
<Stepper active={activeStep} onStepClick={setActiveStep}>
<Stepper.Step
label={t`Analyze feed`}
description={t`Check that the feed is working`}
allowStepSelect={activeStep === 1}
>
<TextInput
label={t`Feed URL`}
placeholder="http://www.mysite.com/rss"
description={t`The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page.`}
required
autoFocus
{...step0Form.getInputProps("url")}
/>
</Stepper.Step>
<Stepper.Step label={t`Subscribe`} description={t`Subscribe to the feed`} allowStepSelect={false}>
<Stack>
<TextInput label={t`Feed URL`} {...step1Form.getInputProps("url")} disabled />
<TextInput label={t`Feed name`} {...step1Form.getInputProps("title")} required autoFocus />
<CategorySelect label={t`Category`} {...step1Form.getInputProps("categoryId")} clearable />
</Stack>
</Stepper.Step>
</Stepper>
<Group position="center" mt="xl">
<Button variant="default" onClick={previousStep}>
<Trans>Back</Trans>
</Button>
{activeStep === 0 && (
<Button type="submit" loading={fetchFeed.loading}>
<Trans>Next</Trans>
</Button>
)}
{activeStep === 1 && (
<Button type="submit" leftIcon={<TbRss size={16} />} loading={fetchFeed.loading || subscribe.loading}>
<Trans>Subscribe</Trans>
</Button>
)}
</Group>
</form>
</>
)
}

View File

@@ -0,0 +1,89 @@
import { t } from "@lingui/macro"
import { ActionIcon, Center, Divider, Indicator, Popover, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { search } from "app/slices/entries"
import { changeReadingMode, changeReadingOrder } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { ActionButton } from "components/ActionButtton"
import { ButtonToolbar } from "components/ButtonToolbar"
import { Loader } from "components/Loader"
import { useEffect } from "react"
import { TbArrowDown, TbArrowUp, TbEye, TbEyeOff, TbRefresh, TbSearch, TbUser, TbX } from "react-icons/tb"
import { MarkAllAsReadButton } from "./MarkAllAsReadButton"
import { ProfileMenu } from "./ProfileMenu"
import { RefreshMenu } from "./RefreshMenu"
function HeaderDivider() {
return <Divider orientation="vertical" />
}
const iconSize = 18
export function Header() {
const settings = useAppSelector(state => state.user.settings)
const profile = useAppSelector(state => state.user.profile)
const searchFromStore = useAppSelector(state => state.entries.search)
const dispatch = useAppDispatch()
const searchForm = useForm<{ search: string }>({
validate: {
search: value => (value.length > 0 && value.length < 3 ? t`Search requires at least 3 characters` : null),
},
})
const { setValues } = searchForm
useEffect(() => {
setValues({
search: searchFromStore,
})
}, [setValues, searchFromStore])
if (!settings) return <Loader />
return (
<Center>
<ButtonToolbar>
<RefreshMenu control={<ActionButton icon={<TbRefresh size={iconSize} />} label={t`Refresh`} />} />
<MarkAllAsReadButton iconSize={iconSize} />
<HeaderDivider />
<ActionButton
icon={settings.readingMode === "all" ? <TbEye size={iconSize} /> : <TbEyeOff size={iconSize} />}
label={settings.readingMode === "all" ? t`All` : t`Unread`}
onClick={() => dispatch(changeReadingMode(settings.readingMode === "all" ? "unread" : "all"))}
/>
<ActionButton
icon={settings.readingOrder === "asc" ? <TbArrowUp size={iconSize} /> : <TbArrowDown size={iconSize} />}
label={settings.readingOrder === "asc" ? t`Asc` : t`Desc`}
onClick={() => dispatch(changeReadingOrder(settings.readingOrder === "asc" ? "desc" : "asc"))}
/>
<Popover>
<Popover.Target>
<Indicator disabled={!searchFromStore}>
<ActionButton icon={<TbSearch size={iconSize} />} label={t`Search`} />
</Indicator>
</Popover.Target>
<Popover.Dropdown>
<form onSubmit={searchForm.onSubmit(values => dispatch(search(values.search)))}>
<TextInput
placeholder={t`Search`}
{...searchForm.getInputProps("search")}
icon={<TbSearch size={iconSize} />}
rightSection={
<ActionIcon onClick={() => searchFromStore && dispatch(search(""))}>
<TbX />
</ActionIcon>
}
autoFocus
/>
</form>
</Popover.Dropdown>
</Popover>
<HeaderDivider />
<ProfileMenu control={<ActionButton icon={<TbUser size={iconSize} />} label={profile?.name} />} />
</ButtonToolbar>
</Center>
)
}

View File

@@ -0,0 +1,83 @@
import { t, Trans } from "@lingui/macro"
import { Button, Code, Group, Modal, Slider, Stack, Text } from "@mantine/core"
import { markAllEntries } from "app/slices/entries"
import { useAppDispatch, useAppSelector } from "app/store"
import { ActionButton } from "components/ActionButtton"
import { useState } from "react"
import { TbChecks } from "react-icons/tb"
export function MarkAllAsReadButton(props: { iconSize: number }) {
const [opened, setOpened] = useState(false)
const [threshold, setThreshold] = useState(0)
const source = useAppSelector(state => state.entries.source)
const sourceLabel = useAppSelector(state => state.entries.sourceLabel)
const entriesTimestamp = useAppSelector(state => state.entries.timestamp) ?? Date.now()
const dispatch = useAppDispatch()
return (
<>
<Modal opened={opened} onClose={() => setOpened(false)} title={t`Mark all entries as read`}>
<Stack>
<Text size="sm">
{threshold === 0 && (
<Trans>
Are you sure you want to mark all entries of <Code>{sourceLabel}</Code> as read?
</Trans>
)}
{threshold > 0 && (
<Trans>
Are you sure you want to mark entries older than {threshold} days of <Code>{sourceLabel}</Code> as read?
</Trans>
)}
</Text>
<Slider
py="xl"
min={0}
max={28}
marks={[
{ value: 0, label: "0" },
{ value: 7, label: "7" },
{ value: 14, label: "14" },
{ value: 21, label: "21" },
{ value: 28, label: "28" },
]}
value={threshold}
onChange={setThreshold}
/>
<Group position="right">
<Button variant="default" onClick={() => setOpened(false)}>
<Trans>Cancel</Trans>
</Button>
<Button
color="red"
onClick={() => {
setOpened(false)
dispatch(
markAllEntries({
sourceType: source.type,
req: {
id: source.id,
read: true,
olderThan: entriesTimestamp - threshold * 24 * 60 * 60 * 1000,
},
})
)
}}
>
<Trans>Confirm</Trans>
</Button>
</Group>
</Stack>
</Modal>
<ActionButton
icon={<TbChecks size={props.iconSize} />}
label={t`Mark all as read`}
onClick={() => {
setThreshold(0)
setOpened(true)
}}
/>
</>
)
}

View File

@@ -0,0 +1,146 @@
import { Trans } from "@lingui/macro"
import { Box, Divider, Group, Menu, SegmentedControl, SegmentedControlItem, useMantineColorScheme } from "@mantine/core"
import { redirectToAbout, redirectToAdminUsers, redirectToMetrics, redirectToSettings } from "app/slices/redirect"
import { changeViewMode } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { ViewMode } from "app/types"
import { useState } from "react"
import { TbChartLine, TbHelp, TbLayoutList, TbList, TbMoon, TbNotes, TbPower, TbSettings, TbSun, TbUsers } from "react-icons/tb"
interface ProfileMenuProps {
control: React.ReactElement
}
interface ViewModeControlItem extends SegmentedControlItem {
value: ViewMode
}
const iconSize = 16
const viewModeData: ViewModeControlItem[] = [
{
value: "title",
label: (
<Group>
<TbList size={iconSize} />
<Box ml={6}>
<Trans>Compact</Trans>
</Box>
</Group>
),
},
{
value: "cozy",
label: (
<Group>
<TbLayoutList size={iconSize} />
<Box ml={6}>
<Trans>Cozy</Trans>
</Box>
</Group>
),
},
{
value: "expanded",
label: (
<Group>
<TbNotes size={iconSize} />
<Box ml={6}>
<Trans>Expanded</Trans>
</Box>
</Group>
),
},
]
export function ProfileMenu(props: ProfileMenuProps) {
const [opened, setOpened] = useState(false)
const viewMode = useAppSelector(state => state.user.settings?.viewMode)
const admin = useAppSelector(state => state.user.profile?.admin)
const dispatch = useAppDispatch()
const { colorScheme, toggleColorScheme } = useMantineColorScheme()
const dark = colorScheme === "dark"
const logout = () => {
window.location.href = "logout"
}
return (
<Menu position="bottom-end" closeOnItemClick={false} opened={opened} onChange={setOpened}>
<Menu.Target>{props.control}</Menu.Target>
<Menu.Dropdown>
<Menu.Item
icon={<TbSettings size={iconSize} />}
onClick={() => {
dispatch(redirectToSettings())
setOpened(false)
}}
>
<Trans>Settings</Trans>
</Menu.Item>
<Divider />
<Menu.Label>
<Trans>Theme</Trans>
</Menu.Label>
<Menu.Item icon={dark ? <TbSun size={iconSize} /> : <TbMoon size={iconSize} />} onClick={() => toggleColorScheme()}>
{dark ? <Trans>Switch to light theme</Trans> : <Trans>Switch to dark theme</Trans>}
</Menu.Item>
<Divider />
<Menu.Label>
<Trans>Display</Trans>
</Menu.Label>
<SegmentedControl
fullWidth
orientation="vertical"
data={viewModeData}
value={viewMode}
onChange={e => dispatch(changeViewMode(e as ViewMode))}
mb="xs"
/>
{admin && (
<>
<Divider />
<Menu.Label>
<Trans>Admin</Trans>
</Menu.Label>
<Menu.Item
icon={<TbUsers size={iconSize} />}
onClick={() => {
dispatch(redirectToAdminUsers())
setOpened(false)
}}
>
<Trans>Manage users</Trans>
</Menu.Item>
<Menu.Item
icon={<TbChartLine size={iconSize} />}
onClick={() => {
dispatch(redirectToMetrics())
setOpened(false)
}}
>
<Trans>Metrics</Trans>
</Menu.Item>
</>
)}
<Divider />
<Menu.Item
icon={<TbHelp size={iconSize} />}
onClick={() => {
dispatch(redirectToAbout())
setOpened(false)
}}
>
<Trans>About</Trans>
</Menu.Item>
<Menu.Item icon={<TbPower size={iconSize} />} onClick={logout}>
<Trans>Logout</Trans>
</Menu.Item>
</Menu.Dropdown>
</Menu>
)
}

View File

@@ -0,0 +1,41 @@
import { t, Trans } from "@lingui/macro"
import { Menu } from "@mantine/core"
import { showNotification } from "@mantine/notifications"
import { client } from "app/client"
import { reloadEntries } from "app/slices/entries"
import { useAppDispatch } from "app/store"
import { TbRotateClockwise, TbWorldDownload } from "react-icons/tb"
interface RefreshMenuProps {
control: React.ReactElement
}
const iconSize = 16
export function RefreshMenu(props: RefreshMenuProps) {
const dispatch = useAppDispatch()
return (
<Menu>
<Menu.Target>{props.control}</Menu.Target>
<Menu.Dropdown>
<Menu.Item icon={<TbRotateClockwise size={iconSize} />} onClick={() => dispatch(reloadEntries())}>
<Trans>Reload</Trans>
</Menu.Item>
<Menu.Item
icon={<TbWorldDownload size={iconSize} />}
onClick={() =>
client.feed.refreshAll().then(() =>
showNotification({
message: t`Your feeds have been queued for refresh.`,
color: "green",
})
)
}
>
<Trans>Fetch all my feeds now</Trans>
</Menu.Item>
</Menu.Dropdown>
</Menu>
)
}

View File

@@ -0,0 +1,9 @@
import { MetricGauge } from "app/types"
interface MeterProps {
gauge: MetricGauge
}
export function Gauge(props: MeterProps) {
return <span>{props.gauge.value}</span>
}

View File

@@ -0,0 +1,19 @@
import { Box } from "@mantine/core"
import { MetricMeter } from "app/types"
interface MeterProps {
meter: MetricMeter
}
export function Meter(props: MeterProps) {
return (
<Box>
<Box>Mean: {props.meter.mean_rate.toFixed(2)}</Box>
<Box>Last minute: {props.meter.m1_rate.toFixed(2)}</Box>
<Box>Last 5 minutes: {props.meter.m5_rate.toFixed(2)}</Box>
<Box>Last 15 minutes: {props.meter.m15_rate.toFixed(2)}</Box>
<Box>Units: {props.meter.units}</Box>
<Box>Total: {props.meter.count}</Box>
</Box>
)
}

View File

@@ -0,0 +1,22 @@
import { Accordion, Box, Group } from "@mantine/core"
interface MetricAccordionItemProps {
metricKey: string
name: string
headerValue: number
children: React.ReactNode
}
export function MetricAccordionItem({ metricKey, name, headerValue, children }: MetricAccordionItemProps) {
return (
<Accordion.Item value={metricKey} key={metricKey}>
<Accordion.Control>
<Group position="apart">
<Box>{name}</Box>
<Box>{headerValue}</Box>
</Group>
</Accordion.Control>
<Accordion.Panel>{children}</Accordion.Panel>
</Accordion.Item>
)
}

View File

@@ -0,0 +1,19 @@
import { Box } from "@mantine/core"
import { MetricTimer } from "app/types"
interface MetricTimerProps {
timer: MetricTimer
}
export function Timer(props: MetricTimerProps) {
return (
<Box>
<Box>Mean: {props.timer.mean_rate.toFixed(2)}</Box>
<Box>Last minute: {props.timer.m1_rate.toFixed(2)}</Box>
<Box>Last 5 minutes: {props.timer.m5_rate.toFixed(2)}</Box>
<Box>Last 15 minutes: {props.timer.m15_rate.toFixed(2)}</Box>
<Box>Units: {props.timer.rate_units}</Box>
<Box>Total: {props.timer.count}</Box>
</Box>
)
}

View File

@@ -0,0 +1,11 @@
import { Box, MediaQuery } from "@mantine/core"
import { Constants } from "app/constants"
import React from "react"
export function OnDesktop(props: { children: React.ReactNode }) {
return (
<MediaQuery smallerThan={Constants.layout.mobileBreakpoint} styles={{ display: "none" }}>
<Box>{props.children}</Box>
</MediaQuery>
)
}

View File

@@ -0,0 +1,11 @@
import { Box, MediaQuery } from "@mantine/core"
import { Constants } from "app/constants"
import React from "react"
export function OnMobile(props: { children: React.ReactNode }) {
return (
<MediaQuery largerThan={Constants.layout.mobileBreakpoint} styles={{ display: "none" }}>
<Box>{props.children}</Box>
</MediaQuery>
)
}

View File

@@ -0,0 +1,61 @@
import { t } from "@lingui/macro"
import { Divider, Select, SimpleGrid, Stack, Switch } from "@mantine/core"
import { Constants } from "app/constants"
import { changeLanguage, changeScrollMarks, changeScrollSpeed, changeSharingSetting, changeShowRead } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { SharingSettings } from "app/types"
import { locales } from "i18n"
export function DisplaySettings() {
const language = useAppSelector(state => state.user.settings?.language)
const scrollSpeed = useAppSelector(state => state.user.settings?.scrollSpeed)
const showRead = useAppSelector(state => state.user.settings?.showRead)
const scrollMarks = useAppSelector(state => state.user.settings?.scrollMarks)
const sharingSettings = useAppSelector(state => state.user.settings?.sharingSettings)
const dispatch = useAppDispatch()
return (
<Stack>
<Select
description={t`Language`}
value={language}
data={locales.map(l => ({
value: l.key,
label: l.label,
}))}
onChange={s => s && dispatch(changeLanguage(s))}
/>
<Switch
label={t`Scroll smoothly when navigating between entries`}
checked={scrollSpeed ? scrollSpeed > 0 : false}
onChange={e => dispatch(changeScrollSpeed(e.currentTarget.checked))}
/>
<Switch
label={t`Show feeds and categories with no unread entries`}
checked={showRead}
onChange={e => dispatch(changeShowRead(e.currentTarget.checked))}
/>
<Switch
label={t`In expanded view, scrolling through entries mark them as read`}
checked={scrollMarks}
onChange={e => dispatch(changeScrollMarks(e.currentTarget.checked))}
/>
<Divider label={t`Sharing sites`} labelPosition="center" />
<SimpleGrid cols={2}>
{(Object.keys(Constants.sharing) as Array<keyof SharingSettings>).map(site => (
<Switch
key={site}
label={Constants.sharing[site].label}
checked={sharingSettings && sharingSettings[site]}
onChange={e => dispatch(changeSharingSetting({ site, value: e.currentTarget.checked }))}
/>
))}
</SimpleGrid>
</Stack>
)
}

View File

@@ -0,0 +1,130 @@
import { t, Trans } from "@lingui/macro"
import { Anchor, Box, Button, Checkbox, Divider, Group, Input, PasswordInput, Stack, Text, TextInput } from "@mantine/core"
import { useForm } from "@mantine/form"
import { openConfirmModal } from "@mantine/modals"
import { client, errorToStrings } from "app/client"
import { redirectToLogin, redirectToSelectedSource } from "app/slices/redirect"
import { reloadProfile } from "app/slices/user"
import { useAppDispatch, useAppSelector } from "app/store"
import { ProfileModificationRequest } from "app/types"
import { Alert } from "components/Alert"
import { useEffect } from "react"
import { useAsyncCallback } from "react-async-hook"
import { TbDeviceFloppy, TbTrash } from "react-icons/tb"
interface FormData extends ProfileModificationRequest {
newPasswordConfirmation?: string
}
export function ProfileSettings() {
const profile = useAppSelector(state => state.user.profile)
const dispatch = useAppDispatch()
const form = useForm<FormData>({
validate: {
newPasswordConfirmation: (value, values) => (value !== values.newPassword ? t`Passwords do not match` : null),
},
})
const { setValues } = form
const saveProfile = useAsyncCallback(client.user.saveProfile, {
onSuccess: () => {
dispatch(reloadProfile())
dispatch(redirectToSelectedSource())
},
})
const deleteProfile = useAsyncCallback(client.user.deleteProfile, {
onSuccess: () => {
dispatch(redirectToLogin())
},
})
const openDeleteProfileModal = () =>
openConfirmModal({
title: t`Delete account`,
children: (
<Text size="sm">
<Trans>Are you sure you want to delete your account? There's no turning back!</Trans>
</Text>
),
labels: { confirm: t`Confirm`, cancel: t`Cancel` },
confirmProps: { color: "red" },
onConfirm: () => deleteProfile.execute(),
})
useEffect(() => {
if (!profile) return
setValues({
currentPassword: "",
email: profile.email ?? "",
newApiKey: false,
})
}, [setValues, profile])
return (
<>
{saveProfile.error && (
<Box mb="md">
<Alert messages={errorToStrings(saveProfile.error)} />
</Box>
)}
{deleteProfile.error && (
<Box mb="md">
<Alert messages={errorToStrings(deleteProfile.error)} />
</Box>
)}
<form onSubmit={form.onSubmit(saveProfile.execute)}>
<Stack>
<Input.Wrapper label={t`User name`}>
<Box>{profile?.name}</Box>
</Input.Wrapper>
<Input.Wrapper
label={t`OPML export`}
description={t`Export your subscriptions and categories as an OPML file that can be imported in other feed reading services`}
>
<Box>
<Anchor href="rest/feed/export" download="commafeed_opml.xml">
<Trans>Download</Trans>
</Anchor>
</Box>
</Input.Wrapper>
<PasswordInput
label={t`Current password`}
description={t`Enter your current password to change profile settings`}
required
{...form.getInputProps("currentPassword")}
/>
<TextInput type="email" label={t`E-mail`} {...form.getInputProps("email")} required />
<PasswordInput
label={t`New password`}
description={t`Changing password will generate a new API key`}
{...form.getInputProps("newPassword")}
/>
<PasswordInput label={t`Confirm password`} {...form.getInputProps("newPasswordConfirmation")} />
<TextInput label={t`API key`} readOnly value={profile?.apiKey} />
<Checkbox label={t`Generate new API key`} {...form.getInputProps("newApiKey", { type: "checkbox" })} />
<Group>
<Button variant="default" onClick={() => dispatch(redirectToSelectedSource())}>
<Trans>Cancel</Trans>
</Button>
<Button type="submit" leftIcon={<TbDeviceFloppy size={16} />} loading={saveProfile.loading}>
<Trans>Save</Trans>
</Button>
<Divider orientation="vertical" />
<Button
color="red"
leftIcon={<TbTrash size={16} />}
onClick={() => openDeleteProfileModal()}
loading={deleteProfile.loading}
>
<Trans>Delete account</Trans>
</Button>
</Group>
</Stack>
</form>
</>
)
}

View File

@@ -0,0 +1,168 @@
import { t } from "@lingui/macro"
import { Box, Stack } from "@mantine/core"
import { Constants } from "app/constants"
import {
redirectToCategory,
redirectToCategoryDetails,
redirectToFeed,
redirectToFeedDetails,
redirectToTag,
redirectToTagDetails,
} from "app/slices/redirect"
import { collapseTreeCategory } from "app/slices/tree"
import { useAppDispatch, useAppSelector } from "app/store"
import { Category, Subscription } from "app/types"
import { categoryUnreadCount, flattenCategoryTree } from "app/utils"
import { Loader } from "components/Loader"
import { OnDesktop } from "components/responsive/OnDesktop"
import React from "react"
import { TbChevronDown, TbChevronRight, TbInbox, TbStar, TbTag } from "react-icons/tb"
import { TreeNode } from "./TreeNode"
import { TreeSearch } from "./TreeSearch"
const allIcon = <TbInbox size={16} />
const starredIcon = <TbStar size={16} />
const tagIcon = <TbTag size={16} />
const expandedIcon = <TbChevronDown size={16} />
const collapsedIcon = <TbChevronRight size={16} />
const errorThreshold = 9
export function Tree() {
const root = useAppSelector(state => state.tree.rootCategory)
const source = useAppSelector(state => state.entries.source)
const tags = useAppSelector(state => state.user.tags)
const showRead = useAppSelector(state => state.user.settings?.showRead)
const dispatch = useAppDispatch()
const feedClicked = (e: React.MouseEvent, id: string) => {
if (e.detail === 2) dispatch(redirectToFeedDetails(id))
else dispatch(redirectToFeed(id))
}
const categoryClicked = (e: React.MouseEvent, id: string) => {
if (e.detail === 2) {
dispatch(redirectToCategoryDetails(id))
} else {
dispatch(redirectToCategory(id))
}
}
const categoryIconClicked = (e: React.MouseEvent, category: Category) => {
e.stopPropagation()
dispatch(
collapseTreeCategory({
id: +category.id,
collapse: category.expanded,
})
)
}
const tagClicked = (e: React.MouseEvent, id: string) => {
if (e.detail === 2) dispatch(redirectToTagDetails(id))
else dispatch(redirectToTag(id))
}
const allCategoryNode = () => (
<TreeNode
id={Constants.categories.all.id}
name={t`All`}
icon={allIcon}
unread={categoryUnreadCount(root)}
selected={source.type === "category" && source.id === Constants.categories.all.id}
expanded={false}
level={0}
hasError={false}
onClick={categoryClicked}
/>
)
const starredCategoryNode = () => (
<TreeNode
id={Constants.categories.starred.id}
name={t`Starred`}
icon={starredIcon}
unread={0}
selected={source.type === "category" && source.id === Constants.categories.starred.id}
expanded={false}
level={0}
hasError={false}
onClick={categoryClicked}
/>
)
const categoryNode = (category: Category, level = 0) => {
const unreadCount = categoryUnreadCount(category)
if (unreadCount === 0 && !showRead) return null
const hasError = !category.expanded && flattenCategoryTree(category).some(c => c.feeds.some(f => f.errorCount > errorThreshold))
return (
<TreeNode
id={category.id}
name={category.name}
icon={category.expanded ? expandedIcon : collapsedIcon}
unread={unreadCount}
selected={source.type === "category" && source.id === category.id}
expanded={category.expanded}
level={level}
hasError={hasError}
onClick={categoryClicked}
onIconClick={e => categoryIconClicked(e, category)}
key={category.id}
/>
)
}
const feedNode = (feed: Subscription, level = 0) => {
if (feed.unread === 0 && !showRead) return null
return (
<TreeNode
id={String(feed.id)}
name={feed.name}
icon={feed.iconUrl}
unread={feed.unread}
selected={source.type === "feed" && source.id === String(feed.id)}
level={level}
hasError={feed.errorCount > errorThreshold}
onClick={feedClicked}
key={feed.id}
/>
)
}
const tagNode = (tag: string) => (
<TreeNode
id={tag}
name={tag}
icon={tagIcon}
unread={0}
selected={source.type === "tag" && source.id === tag}
level={0}
hasError={false}
onClick={tagClicked}
key={tag}
/>
)
const recursiveCategoryNode = (category: Category, level = 0) => (
<React.Fragment key={`recursiveCategoryNode-${category.id}`}>
{categoryNode(category, level)}
{category.expanded && category.children.map(c => recursiveCategoryNode(c, level + 1))}
{category.expanded && category.feeds.map(f => feedNode(f, level + 1))}
</React.Fragment>
)
if (!root) return <Loader />
const feeds = flattenCategoryTree(root).flatMap(c => c.feeds)
return (
<Stack>
<OnDesktop>
<TreeSearch feeds={feeds} />
</OnDesktop>
<Box>
{allCategoryNode()}
{starredCategoryNode()}
{root.children.map(c => recursiveCategoryNode(c))}
{root.feeds.map(f => feedNode(f))}
{tags?.map(tag => tagNode(tag))}
</Box>
</Stack>
)
}

View File

@@ -0,0 +1,63 @@
import { Box, createStyles } from "@mantine/core"
import { FeedFavicon } from "components/content/FeedFavicon"
import React, { ReactNode } from "react"
import { UnreadCount } from "./UnreadCount"
interface TreeNodeProps {
id: string
name: string
icon: ReactNode | string
unread: number
selected: boolean
expanded?: boolean
level: number
hasError: boolean
onClick: (e: React.MouseEvent, id: string) => void
onIconClick?: (e: React.MouseEvent, id: string) => void
}
const useStyles = createStyles((theme, props: TreeNodeProps) => {
let backgroundColor = "inherit"
if (props.selected) backgroundColor = theme.colorScheme === "dark" ? theme.colors.dark[4] : theme.colors.gray[3]
let color
if (props.hasError) color = theme.colors.red[6]
else if (theme.colorScheme === "dark") color = props.unread > 0 ? theme.colors.dark[0] : theme.colors.dark[3]
else color = props.unread > 0 ? theme.black : theme.colors.gray[6]
return {
node: {
display: "flex",
alignItems: "center",
cursor: "pointer",
color,
backgroundColor,
"&:hover": {
backgroundColor: theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.colors.gray[0],
},
},
nodeText: {
flexGrow: 1,
whiteSpace: "nowrap",
overflow: "hidden",
textOverflow: "ellipsis",
},
}
})
export function TreeNode(props: TreeNodeProps) {
const { classes } = useStyles(props)
return (
<Box py={1} pl={props.level * 20} className={classes.node} onClick={(e: React.MouseEvent) => props.onClick(e, props.id)}>
<Box mr={6} onClick={(e: React.MouseEvent) => props.onIconClick && props.onIconClick(e, props.id)}>
{typeof props.icon === "string" ? <FeedFavicon url={props.icon} /> : props.icon}
</Box>
<Box className={classes.nodeText}>{props.name}</Box>
{!props.expanded && (
<Box>
<UnreadCount unreadCount={props.unread} />
</Box>
)}
</Box>
)
}

View File

@@ -0,0 +1,61 @@
import { t } from "@lingui/macro"
import { Box, Center, Kbd, TextInput } from "@mantine/core"
import { openSpotlight, SpotlightAction, SpotlightProvider } from "@mantine/spotlight"
import { redirectToFeed } from "app/slices/redirect"
import { useAppDispatch } from "app/store"
import { Subscription } from "app/types"
import { FeedFavicon } from "components/content/FeedFavicon"
import { useMousetrap } from "hooks/useMousetrap"
import { TbSearch } from "react-icons/tb"
export interface TreeSearchProps {
feeds: Subscription[]
}
export function TreeSearch(props: TreeSearchProps) {
const dispatch = useAppDispatch()
const actions: SpotlightAction[] = props.feeds
.sort((f1, f2) => f1.name.localeCompare(f2.name))
.map(f => ({
title: f.name,
icon: <FeedFavicon url={f.iconUrl} />,
onTrigger: () => dispatch(redirectToFeed(f.id)),
}))
const searchIcon = <TbSearch size={18} />
const rightSection = (
<Center>
<Kbd>Ctrl</Kbd>
<Box mx={5}>+</Box>
<Kbd>K</Kbd>
</Center>
)
// additional keyboard shortcut used by commafeed v1
useMousetrap("g u", () => openSpotlight())
return (
<SpotlightProvider
actions={actions}
searchIcon={searchIcon}
searchPlaceholder={t`Search`}
shortcut="ctrl+k"
nothingFoundMessage={t`Nothing found`}
>
<TextInput
placeholder={t`Search`}
icon={searchIcon}
rightSectionWidth={100}
rightSection={rightSection}
styles={{
input: { cursor: "pointer" },
rightSection: { pointerEvents: "none" },
}}
onClick={() => openSpotlight()}
// prevent focus
onFocus={e => e.target.blur()}
readOnly
/>
</SpotlightProvider>
)
}

View File

@@ -0,0 +1,18 @@
import { Badge, createStyles } from "@mantine/core"
const useStyles = createStyles(() => ({
badge: {
width: "3.2rem",
// for some reason, mantine Badge has "cursor: 'default'"
cursor: "pointer",
},
}))
export function UnreadCount(props: { unreadCount: number }) {
const { classes } = useStyles()
if (props.unreadCount <= 0) return null
const count = props.unreadCount >= 1000 ? "999+" : props.unreadCount
return <Badge className={classes.badge}>{count}</Badge>
}

View File

@@ -0,0 +1,39 @@
import { t } from "@lingui/macro"
import { useAppSelector } from "app/store"
interface Step {
label: string
done: boolean
}
export const useAppLoading = () => {
const profile = useAppSelector(state => state.user.profile)
const settings = useAppSelector(state => state.user.settings)
const rootCategory = useAppSelector(state => state.tree.rootCategory)
const tags = useAppSelector(state => state.user.tags)
const steps: Step[] = [
{
label: t`Loading settings...`,
done: !!settings,
},
{
label: t`Loading profile...`,
done: !!profile,
},
{
label: t`Loading subscriptions...`,
done: !!rootCategory,
},
{
label: t`Loading tags...`,
done: !!tags,
},
]
const loading = steps.some(s => !s.done)
const loadingPercentage = Math.round((100.0 * steps.filter(s => s.done).length) / steps.length)
const loadingStepLabel = steps.find(s => !s.done)?.label
return { steps, loading, loadingPercentage, loadingStepLabel }
}

View File

@@ -0,0 +1,22 @@
import mousetrap, { ExtendedKeyboardEvent } from "mousetrap"
import { useEffect, useRef } from "react"
type Callback = (e: ExtendedKeyboardEvent, combo: string) => void
export const useMousetrap = (key: string | string[], callback: Callback) => {
// use a ref to avoid unbinding/rebinding every time the callback changes
const callbackRef = useRef(callback)
callbackRef.current = callback
useEffect(() => {
mousetrap.bind(key, (event, combo) => {
callbackRef.current(event, combo)
// prevent default behavior
return false
})
return () => {
mousetrap.unbind(key)
}
}, [key])
}

View File

@@ -0,0 +1,24 @@
import { reloadTree } from "app/slices/tree"
import { useAppDispatch } from "app/store"
import { useEffect } from "react"
import WebsocketHeartbeatJs from "websocket-heartbeat-js"
export const useWebSocket = () => {
const dispatch = useAppDispatch()
useEffect(() => {
const currentUrl = new URL(window.location.href)
const wsProtocol = currentUrl.protocol === "http:" ? "ws" : "wss"
const wsUrl = `${wsProtocol}://${currentUrl.hostname}:${currentUrl.port}/ws`
const ws = new WebsocketHeartbeatJs({ url: wsUrl, pingMsg: "ping" })
ws.onmessage = event => {
const { data } = event
if (typeof data === "string") {
if (data.startsWith("new-feed-entries:")) dispatch(reloadTree())
}
}
return () => ws.close()
}, [dispatch])
}

View File

@@ -0,0 +1,154 @@
import { i18n, Messages } from "@lingui/core"
import { useAppSelector } from "app/store"
import dayjs from "dayjs"
import "dayjs/locale/ar"
import "dayjs/locale/ca"
import "dayjs/locale/cs"
import "dayjs/locale/cy"
import "dayjs/locale/da"
import "dayjs/locale/de"
import "dayjs/locale/en"
import "dayjs/locale/es"
import "dayjs/locale/fa"
import "dayjs/locale/fi"
import "dayjs/locale/fr"
import "dayjs/locale/gl"
import "dayjs/locale/hu"
import "dayjs/locale/id"
import "dayjs/locale/it"
import "dayjs/locale/ja"
import "dayjs/locale/ko"
import "dayjs/locale/ms"
import "dayjs/locale/nb"
import "dayjs/locale/nl"
import "dayjs/locale/nn"
import "dayjs/locale/pl"
import "dayjs/locale/pt"
import "dayjs/locale/ru"
import "dayjs/locale/sk"
import "dayjs/locale/sv"
import "dayjs/locale/tr"
import "dayjs/locale/zh"
import {
ar,
ca,
cs,
cy,
da,
de,
en,
es,
fa,
fi,
fr,
gl,
hu,
id,
it,
ja,
ko,
ms,
nb,
nl,
nn,
pl,
PluralCategory,
pt,
ru,
sk,
sv,
tr,
zh,
} from "make-plural"
import { useEffect } from "react"
import { messages as arMessages } from "./locales/ar/messages"
import { messages as caMessages } from "./locales/ca/messages"
import { messages as csMessages } from "./locales/cs/messages"
import { messages as cyMessages } from "./locales/cy/messages"
import { messages as daMessages } from "./locales/da/messages"
import { messages as deMessages } from "./locales/de/messages"
import { messages as enMessages } from "./locales/en/messages"
import { messages as esMessages } from "./locales/es/messages"
import { messages as faMessages } from "./locales/fa/messages"
import { messages as fiMessages } from "./locales/fi/messages"
import { messages as frMessages } from "./locales/fr/messages"
import { messages as glMessages } from "./locales/gl/messages"
import { messages as huMessages } from "./locales/hu/messages"
import { messages as idMessages } from "./locales/id/messages"
import { messages as itMessages } from "./locales/it/messages"
import { messages as jaMessages } from "./locales/ja/messages"
import { messages as koMessages } from "./locales/ko/messages"
import { messages as msMessages } from "./locales/ms/messages"
import { messages as nbMessages } from "./locales/nb/messages"
import { messages as nlMessages } from "./locales/nl/messages"
import { messages as nnMessages } from "./locales/nn/messages"
import { messages as plMessages } from "./locales/pl/messages"
import { messages as ptMessages } from "./locales/pt/messages"
import { messages as ruMessages } from "./locales/ru/messages"
import { messages as skMessages } from "./locales/sk/messages"
import { messages as svMessages } from "./locales/sv/messages"
import { messages as trMessages } from "./locales/tr/messages"
import { messages as zhMessages } from "./locales/zh/messages"
interface Locale {
key: string
label: string
messages: Messages
plurals?: (n: number | string, ord?: boolean) => PluralCategory
}
// add an object to the array to add a new locale
// don't forget to also add it to the 'locales' array in .linguirc
export const locales: Locale[] = [
{ key: "ar", messages: arMessages, plurals: ar, label: "العربية" },
{ key: "ca", messages: caMessages, plurals: ca, label: "Català" },
{ key: "cs", messages: csMessages, plurals: cs, label: "Čeština" },
{ key: "cy", messages: cyMessages, plurals: cy, label: "Cymraeg" },
{ key: "da", messages: daMessages, plurals: da, label: "Danish" },
{ key: "de", messages: deMessages, plurals: de, label: "Deutsch" },
{ key: "en", messages: enMessages, plurals: en, label: "English" },
{ key: "es", messages: esMessages, plurals: es, label: "Español" },
{ key: "fa", messages: faMessages, plurals: fa, label: "فارسی" },
{ key: "fi", messages: fiMessages, plurals: fi, label: "Suomi" },
{ key: "fr", messages: frMessages, plurals: fr, label: "Français" },
{ key: "gl", messages: glMessages, plurals: gl, label: "Galician" },
{ key: "hu", messages: huMessages, plurals: hu, label: "Magyar" },
{ key: "id", messages: idMessages, plurals: id, label: "Indonesian" },
{ key: "it", messages: itMessages, plurals: it, label: "Italiano" },
{ key: "ja", messages: jaMessages, plurals: ja, label: "日本語" },
{ key: "ko", messages: koMessages, plurals: ko, label: "한국어" },
{ key: "ms", messages: msMessages, plurals: ms, label: "Bahasa Malaysian" },
{ key: "nb", messages: nbMessages, plurals: nb, label: "Norsk (bokmål)" },
{ key: "nl", messages: nlMessages, plurals: nl, label: "Nederlands" },
{ key: "nn", messages: nnMessages, plurals: nn, label: "Norsk (nynorsk)" },
{ key: "pl", messages: plMessages, plurals: pl, label: "Polski" },
{ key: "pt", messages: ptMessages, plurals: pt, label: "Português" },
{ key: "ru", messages: ruMessages, plurals: ru, label: "Русский" },
{ key: "sk", messages: skMessages, plurals: sk, label: "Slovenčina" },
{ key: "sv", messages: svMessages, plurals: sv, label: "Svenska" },
{ key: "tr", messages: trMessages, plurals: tr, label: "Türkçe" },
{ key: "zh", messages: zhMessages, plurals: zh, label: "简体中文" },
]
locales.forEach(l => {
i18n.loadLocaleData({
[l.key]: {
plurals: l.plurals,
},
})
i18n.load({
[l.key]: l.messages,
})
})
function activateLocale(locale: string) {
i18n.activate(locale)
dayjs.locale(locale)
}
export const useI18n = () => {
const locale = useAppSelector(state => state.user.settings?.language)
useEffect(() => {
activateLocale(locale ?? "en")
}, [locale])
}

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ar\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0> هل لديك حساب؟ </0> <1> تسجيل الدخول! </ 1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0> هل تحتاج إلى حساب؟ </0> <1> اشترك! </ 1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "مفتاح API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "حول"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "الإجراءات"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "إضافة"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "إضافة فئة"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "إضافة مستخدم"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "إداري"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "الكل"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "تم إرسال بريد إلكتروني إذا تم تسجيل هذا العنوان. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "ملف opml هو ملف XML يحتوي على عناوين URL للتغذية والفئات. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "تحليل التغذية"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "هل أنت متأكد أنك تريد حذف الفئة <0> {categoryName} </0>؟"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "هل أنت متأكد أنك تريد حذف المستخدم <0> {userName} </0>؟"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "هل أنت متأكد أنك تريد حذف حسابك؟ "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "هل أنت متأكد أنك تريد تعليم كافة إدخالات <0> {sourceLabel} </0> كمقروءة؟"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "هل أنت متأكد أنك تريد وضع علامة على الإدخالات الأقدم من {عتبة} يوم من <0> {sourceLabel} </0> كمقروءة؟"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "هل أنت متأكد أنك تريد إلغاء الاشتراك من <0> {feedName} </0>؟"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "تصاعدي"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "المتغيرات المتاحة هي \"العنوان\" و \"المحتوى\" و \"url\" و \"المؤلف\" و \"الفئات\" ويتم تحويل محتواها إلى أحرف صغيرة لتسهيل مقارنة السلسلة."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "العودة"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "العودة لتسجيل الدخول"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "ملحقات المستعرض"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "إلغاء"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "الفئة"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "سيؤدي تغيير كلمة المرور إلى إنشاء مفتاح API جديد"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "تأكد من عمل الخلاصة"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed هو مشروع مفتوح المصدر. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed التالي العنصر غير المقروء"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "إصدار CommaFeed {الإصدار} ({مراجعة})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "مضغوط"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "تأكيد"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "تأكيد كلمة المرور"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "دافئ"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "إنشاء علامة: {استعلام}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "السيطرة"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "كلمة المرور الحالية"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "تاريخ الإنشاء"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "حذف"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "حذف الفئة"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "حذف الحساب"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "حذف المستخدم"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "تنازلي"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "عرض"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "تنزيل"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "اسحب الرابط إلى شريط الإشارات"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "البريد الإلكتروني"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "عنوان البريد الإلكتروني"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "تحرير المستخدم"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "ممكن"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "دخول"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "أدخل كلمة المرور الحالية لتغيير إعدادات ملف التعريف"
#: src/components/Alert.tsx
msgid "Error"
msgstr "خطأ"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "مثال: {مثال}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "موسع"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "قم بتصدير اشتراكاتك وفئاتك كملف OPML يمكن استيراده في خدمات قراءة الأعلاف الأخرى"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "موجز URL"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "اسم الخلاصة"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "تصفية التعبير"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "هل نسيت كلمة المرور؟"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "قم بإنشاء مفتاح API في ملف التعريف الخاص بك أولاً."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "إنشاء مفتاح API جديد"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "رابط الخلاصة المولدة"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "انتقل إلى وثائق API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "اذهب إلى طريقة العرض \"الكل\""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "الأشياء الجيدة"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "المرجع نفسه"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "إذا لم يكن فارغًا ، فسيتم تقييم التعبير إلى \"صواب\" أو \"خطأ\". "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "إذا واجهت مشكلة ، فالرجاء الإبلاغ عنها على صفحة مشكلات مشروع GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "إذا أعجبك هذا المشروع ، فيرجى التفكير في التبرع لدعم المطور والمساعدة في تغطية تكاليف إبقاء هذا الموقع على الإنترنت."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "استيراد"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "في العرض الموسع ، التمرير عبر الإدخالات وضع علامة عليها كمقروءة"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "إبقاء غير مقروءة"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "اختصارات لوحة المفاتيح"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "لغة"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "تاريخ آخر تسجيل دخول"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "التحديث الأخير"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "آخر رسالة تحديث"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "رابط"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "تحميل ملف التعريف ..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "تحميل الإعدادات ..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "تحميل الاشتراكات ..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "تحميل العلامات ..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "تسجيل الدخول"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "تسجيل الخروج"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "إدارة المستخدمين"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "تعليم الكل كمقروء"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "تعليم كافة الإدخالات كمقروءة"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "وضع علامة كمقروء"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "وضع علامة كمقروءة حتى هنا"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "المقاييس"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "تحريك الصفحة لأسفل"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "تحريك الصفحة لأعلى"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "لا"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "الاسم"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "انتقل إلى اشتراك بإدخال اسمه"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "كلمة مرور جديدة"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "الأحدث أولاً"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "التالي"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "التحديث التالي"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "اختصار العنصر غير المقروء التالي"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "لا مزيد من الإدخالات"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "لم يتم العثور على شيء"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "تصدير OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "ملف OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "الأقدم أولا"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "اوووه!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "فتح الإدخال الحالي في علامة تبويب جديدة"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "فتح الإدخال الحالي في علامة تبويب جديدة في الخلفية"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "افتح الرابط"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "فتح الإدخال التالي"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "فتح الإدخال السابق"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "فتح / إغلاق الإدخال الحالي"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "طلب"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "والد"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "الفئة الأصل"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "كلمة المرور"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "استعادة كلمة المرور"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "كلمات المرور غير متطابقة"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "المنـصب"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "الملف الشخصي"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "استعادة كلمة السر"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "تحديث"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "تم إغلاق التسجيلات في مثيل CommaFeed هذا"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "حفظ"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "قم بالتمرير بسلاسة عند التنقل بين الإدخالات"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "بحث"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "يتطلب البحث 3 أحرف على الأقل"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "ضع التركيز على الإدخال التالي دون فتحه"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "ضع التركيز على الإدخال السابق دون فتحه"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "إعدادات"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "تم حفظ الإعدادات."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "مشاركة"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "مشاركة المواقع"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "الحلقة"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "إظهار موجز ويب والفئات التي لا تحتوي على إدخالات غير مقروءة"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "إظهار تعليمات اختصار لوحة المفاتيح"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "قم بالتسجيل"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "شيء سيء حدث للتو ..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "فضاء"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "النجم"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "مميز بنجمة"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "اشتراك"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "عنوان URL للاشتراك"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "الاشتراك في موجز ويب"
#: src/components/Alert.tsx
msgid "Success"
msgstr "النجاح"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "التبديل إلى النسق الداكن"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "قم بالتبديل إلى النسق الفاتح"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "الكلمات"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "عنوان URL للتغذية التي تريد الاشتراك فيها. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "الموضوع"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "تبديل قراءة حالة الإدخال الحالي"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "جرب CommaFeed باستخدام الحساب التجريبي: تجريبي / تجريبي"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "غير مقروءة"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "إلغاء النجم"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "إلغاء الاشتراك"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "اسم المستخدم أو البريد الإلكتروني"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "اسم المستخدم"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "تحذير"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "موقع الكتروني"
#: 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 "ليس لديك أي اشتراكات حتى الآن. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "الملف مطلوب"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ca\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Teniu un compte?</0><1>Inicieu la sessió!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Necessites un compte?</0><1>Registreu-vos!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "clau API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Sobre"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Accions"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Afegir"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Afegeix categoria"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Afegeix usuari"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Administrador"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Tot"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "S'ha enviat un correu electrònic si aquesta adreça estava registrada. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Un fitxer opml és un fitxer XML que conté URL i categories de canals. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analitzar el feed"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Estàs segur que vols suprimir la categoria <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Esteu segur que voleu suprimir l'usuari <0>{userName}</0>?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Esteu segur que voleu suprimir el vostre compte? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Esteu segur que voleu marcar totes les entrades de <0>{sourceLabel}</0> com a llegides?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Esteu segur que voleu marcar les entrades més antigues de {threshold} dies de <0>{sourceLabel}</0> com a llegides?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Estàs segur que vols cancel·lar la subscripció a <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Les variables disponibles són \"títol\", \"contingut\", \"url\" \"autor\" i \"categories\" i el seu contingut es converteix en minúscules per facilitar la comparació de cadenes."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Enrere"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Tornar a iniciar sessió"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Extensions del navegador"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Cancel·la"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Categoria"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Canviar la contrasenya generarà una nova clau d'API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Comproveu que el canal funciona"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed és un projecte de codi obert. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed següent element no llegit"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "Versió CommaFeed {versió} ({revisió})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compacte"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Confirmar"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Confirmeu la contrasenya"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Acollidor"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Crea una etiqueta: {consulta}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Contrasenya actual"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Data de creació"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Eliminar"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Suprimeix la categoria"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Suprimeix el compte"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Suprimeix l'usuari"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Mostra"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Descarrega"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Arrossegueu l'enllaç a la barra d'adreces d'interès"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "Correu electrònic"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Adreça de correu electrònic"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Edita l'usuari"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "activat"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Entra"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "introduïu la vostra contrasenya actual per canviar la configuració del perfil"
#: src/components/Alert.tsx
msgid "Error"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Exemple: {exemple}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Ampliat"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "exporteu les vostres subscripcions i categories com a fitxer OPML que es pot importar a altres serveis de lectura de feeds"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL del canal"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nom del canal"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Expressió de filtratge"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Heu oblidat la contrasenya?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "primer genereu una clau API al vostre perfil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Genera una nova clau d'API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "URL del feed generat"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Vés a la documentació de l'API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Vés a la vista Tot"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Bones"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Si no està buida, una expressió que s'avalua com a \"vertader\" o \"fals\". "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Si trobeu un problema, informeu-lo a la pàgina de problemes del projecte GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Si t'agrada aquest projecte, considera una donació per donar suport al desenvolupador i ajudar a cobrir els costos de mantenir aquest lloc web en línia."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importació"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "a la vista ampliada, desplaçant-se per les entrades les marqueu com a llegides"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Mantenir sense llegir"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Dreceres de teclat"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Llengua"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Data de l'últim inici de sessió"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Última actualització"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "últim missatge d'actualització"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Enllaç"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Carregant el perfil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "S'està carregant la configuració..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "S'estan carregant les subscripcions..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Carregant les etiquetes..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Inicia sessió"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Tanca sessió"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Gestionar usuaris"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Marca-ho tot com a llegit"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marqueu totes les entrades com a llegides"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Marca com a llegit"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Marca com a llegit fins aquí"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "mètriques"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Mou la pàgina cap avall"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Mou la pàgina cap amunt"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nom"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navegueu a una subscripció introduint-ne el nom"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Contrasenya nova"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "El més nou primer"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Següent"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Propera actualització"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Següent marcador d'elements no llegit"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "No hi ha més entrades"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "No s'ha trobat res"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Exportació OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "Fitxer OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "el més vell primer"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Vaja!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Obre l'entrada actual en una pestanya nova"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Obre l'entrada actual en una pestanya nova al fons"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Enllaç obert"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Obre la següent entrada"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Obre l'entrada anterior"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Obrir/tancar l'entrada actual"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Ordre"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "pares"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Categoria pare"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Contrasenya"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Recuperació de contrasenya"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Les contrasenyes no coincideixen"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Posició"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "API REST"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Recuperar la contrasenya"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Actualitzar"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Els registres estan tancats en aquesta instància de CommaFeed"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Desa"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Desplaceu-vos suaument quan navegueu entre entrades"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Cerca"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "la cerca requereix almenys 3 caràcters"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "posa el focus a la següent entrada sense obrir-la"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Estableix el focus en l'entrada anterior sense obrir-la"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Configuració"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Configuració desada."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Comparteix"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Compartir llocs"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "canvi"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Mostra feeds i categories sense entrades no llegides"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Mostra l'ajuda de la drecera del teclat"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Inscriu-te"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Acaba de passar una cosa dolenta..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Espai"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Estrella"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Estrellat"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Subscriu-te"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL de subscripció"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Subscriu-te al canal"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Éxit"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Canvia al tema fosc"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Canvia al tema clar"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Etiquetes"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "l'URL del canal al qual us voleu subscriure. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Canvia l'estat de lectura de l'entrada actual"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Proveu CommaFeed amb el compte de demostració: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Sense llegir"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Desestrellar"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Donar-se de baixa"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nom d'usuari o correu electrònic"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nom d'usuari"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Avís"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Lloc web"
#: 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 "Encara no teniu cap subscripció. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "el fitxer és necessari"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: cs\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Máte účet?</0><1>Přihlaste se!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Potřebujete účet?</0><1>Zaregistrujte se!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "Klíč API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Asi"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Akce"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Přidej"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Přidat kategorii"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Přidat uživatele"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Správce"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Všechny"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Pokud byla tato adresa zaregistrována, byl odeslán e-mail. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Soubor opml je soubor XML obsahující adresy URL a kategorie zdrojů. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analyzujte krmivo"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Opravdu chcete smazat kategorii <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Opravdu chcete smazat uživatele <0>{userName}</0>?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Opravdu chcete smazat svůj účet? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Opravdu chcete označit všechny položky <0>{sourceLabel}</0> jako přečtené?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Opravdu chcete označit záznamy starší než {threshold} dnů <0>{sourceLabel}</0> jako přečtené?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Opravdu se chcete odhlásit z odběru <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Dostupné proměnné jsou 'název', 'obsah', 'url', 'autor' a 'kategorie' a jejich obsah je převeden na malá písmena, aby se usnadnilo porovnávání řetězců."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Zpět"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Zpět k přihlášení"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Rozšíření prohlížeče"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Zrušit"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Kategorie"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Změna hesla vygeneruje nový klíč API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Zkontrolujte, zda zdroj funguje"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed je projekt s otevřeným zdrojovým kódem. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed další nepřečtená položka"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed verze {version} ({revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Kompaktní"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Potvrdit"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Potvrďte heslo"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Útulný"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Vytvořit značku: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Aktuální heslo"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Datum vytvoření"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Smazat"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Odstranit kategorii"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Smazat účet"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Smazat uživatele"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Displej"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Stáhnout"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Přetáhněte odkaz na lištu záložek"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "E-mailová adresa"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Upravit uživatele"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Povoleno"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Vstupte"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Zadejte své aktuální heslo pro změnu nastavení profilu"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Chyba"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Příklad: {příklad}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Rozbaleno"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exportujte svá předplatná a kategorie jako soubor OPML, který lze importovat do jiných služeb čtení kanálů"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL zdroje"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Název zdroje"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Filtrování výrazu"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Zapomněli jste heslo?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Nejprve ve svém profilu vygenerujte klíč API."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Vygenerujte nový klíč API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Generovaná adresa URL zdroje"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Přejděte na dokumentaci API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Přejděte do zobrazení Vše"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Dobroty"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Pokud není prázdný, výraz vyhodnocený jako 'true' nebo 'false'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Pokud narazíte na problém, nahlaste jej prosím na stránce problémů projektu GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Pokud se vám tento projekt líbí, zvažte prosím dar na podporu vývojáře a pomozte pokrýt náklady na udržování tohoto webu online."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "V rozšířeném zobrazení je procházením označíte jako přečtené"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Ponechat nepřečtené"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Klávesové zkratky"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Jazyk"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Datum posledního přihlášení"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Poslední aktualizace"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Poslední obnovovací zpráva"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Odkaz"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Načítání profilu..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Načítání nastavení..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Načítání odběrů..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Načítání značek..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Přihlaste se"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Odhlášení"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Spravujte uživatele"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Označit vše jako přečtené"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Označte všechny položky jako přečtené"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Označit jako přečtené"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Označit jako přečtené až sem"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Metriky"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Přesuňte stránku dolů"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Přesuňte stránku nahoru"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Jméno"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Přejděte na předplatné zadáním jeho názvu"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Nové heslo"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Nejnovější jako první"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Další"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Další obnovení"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Další nepřečtená položka bookmarklet"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Žádné další záznamy"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Nic nebylo nalezeno"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Export OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "soubor OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Nejdříve nejstarší"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Jejda!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Otevřete aktuální položku na nové kartě"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Otevřít aktuální položku na nové kartě na pozadí"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Otevřít odkaz"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Otevřete další položku"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Otevřít předchozí záznam"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Otevřít/zavřít aktuální položku"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Objednávka"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Rodič"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Rodičovská kategorie"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Heslo"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Obnovení hesla"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Hesla se neshodují"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Pozice"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Obnovte heslo"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Obnovit"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "V této instanci CommaFeed jsou registrace uzavřeny"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Uložit"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Posouvejte plynule při navigaci mezi položkami"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Hledej"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Hledání vyžaduje alespoň 3 znaky"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Zaměřte se na další položku, aniž byste ji otevřeli"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Nastavit fokus na předchozí záznam bez jeho otevření"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Nastavení"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Nastavení uloženo."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Sdílejte"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Stránky pro sdílení"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Směna"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Zobrazit kanály a kategorie bez nepřečtených položek"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Zobrazit nápovědu ke klávesovým zkratkám"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Zaregistrujte se"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Právě se stalo něco špatného..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Vesmír"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Hvězda"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "S hvězdičkou"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Přihlaste se"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL pro přihlášení"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Přihlaste se k odběru kanálu"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Úspěch"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Přepněte na tmavý motiv"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Přepněte na světlé téma"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Značky"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Adresa URL kanálu, k jehož odběru se chcete přihlásit. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Téma"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Přepne stav čtení aktuálního záznamu"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Vyzkoušejte CommaFeed s demo účtem: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Nepřečteno"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Odstranit hvězdu"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Odhlásit odběr"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Uživatelské jméno nebo e-mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Uživatelské jméno"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Varování"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Webové stránky"
#: 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 "Zatím nemáte žádné předplatné. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr ""

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: cy\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>A oes gennych gyfrif?</0><1>Mewngofnodi!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Angen cyfrif?</0><1>Ymunwch!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "Allwedd API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Ynghylch"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Camau gweithredu"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Ychwanegu"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Ychwanegu categori"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Ychwanegu defnyddiwr"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Gweinyddol"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Pawb"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Mae e-bost wedi'i anfon os oedd y cyfeiriad hwn wedi'i gofrestru. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Mae ffeil opml yn ffeil XML sy'n cynnwys URLs porthiant a chategorïau. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Dadansoddi porthiant"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Ydych chi'n siŵr eich bod am ddileu categori <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Ydych chi'n siŵr eich bod am ddileu defnyddiwr <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Ydych chi'n siŵr eich bod am ddileu eich cyfrif? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Ydych chi'n siŵr eich bod am farcio bod pob cofnod o <0>{sourceLabel}</0> wedi'i ddarllen?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Ydych chi'n siŵr eich bod am farcio cofnodion sy'n hŷn na {trothwy} diwrnod o <0>{sourceLabel}</0> fel rhai sydd wedi'u darllen?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Ydych chi'n siŵr eich bod am ddad-danysgrifio o <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Y newidynnau sydd ar gael yw 'teitl', 'cynnwys', 'url' 'awdur' a 'chategorïau' ac mae eu cynnwys yn cael ei drosi i lythrennau bach er mwyn hwyluso cymhariaeth llinynnol."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Yn ôl"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Yn ôl i fewngofnodi"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Estyniadau porwr"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Diddymu"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "categori"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Bydd newid cyfrinair yn cynhyrchu allwedd API newydd"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Gwiriwch fod y porthiant yn gweithio"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "Mae ComaFeed yn brosiect ffynhonnell agored. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed eitem nesaf heb ei darllen"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "Fersiwn ComaFeed {fersiwn} ({ adolygu})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "cryno"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Cadarnhau"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Cadarnhau'r cyfrinair"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "clyd"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Creu tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Cyfrinair presennol"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Dyddiad creu"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Dileu"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Dileu Categori"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Dileu cyfrif"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Dileu defnyddiwr"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "Rhag"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Arddangos"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Lawrlwytho"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Llusgwch y ddolen i'r bar nod tudalen"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "E-bost"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "cyfeiriad e-bost"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Golygu defnyddiwr"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Wedi'i alluogi"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Ewch i mewn"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Rhowch eich cyfrinair presennol i newid gosodiadau proffil"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Gwall"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "enghraifft: {example}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Ehangu"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Allforio eich tanysgrifiadau a'ch categorïau fel ffeil OPML y gellir ei mewnforio i wasanaethau darllen porthiant eraill"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL porthiant"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Enw porthiant"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Hidlo mynegiant"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Wedi anghofio cyfrinair?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Cynhyrchu allwedd API yn eich proffil yn gyntaf."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Cynhyrchu allwedd API newydd"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "url porthiant a gynhyrchir"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Ewch i'r ddogfennaeth API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Ewch i'r golwg Pawb"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "nwyddau"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Os nad yw'n wag, mynegiad sy'n gwerthuso i 'gwir' neu 'anghywir'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Os byddwch yn dod ar draws mater, rhowch wybod amdano ar dudalen materion y prosiect GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Os ydych chi'n hoffi'r prosiect hwn, ystyriwch rodd i gefnogi'r datblygwr a helpu i dalu costau cadw'r wefan hon ar-lein."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Mewnforio"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Mewn gwedd estynedig, mae sgrolio trwy gofnodion yn nodi eu bod wedi'u darllen"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Cadwch heb ei ddarllen"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "llwybrau byr bysellfwrdd"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Iaith"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Dyddiad mewngofnodi diwethaf"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "adnewyddu diwethaf"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Neges adnewyddu ddiwethaf"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Cyswllt"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Wrthi'n llwytho proffil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Wrthi'n llwytho gosodiadau..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Yn llwytho tanysgrifiadau..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Wrthi'n llwytho tagiau..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Mewngofnodi"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Allgofnodi"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Rheoli defnyddwyr"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Marciwch y cyfan wedi'i ddarllen"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marciwch bob cofnod wedi'i ddarllen"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Marciwch ei fod wedi'i ddarllen"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Marciwch fel y darllenwyd hyd yma"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "metrigau"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Symudwch y dudalen i lawr"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Symudwch y dudalen i fyny"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "Amh"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Enw"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Llywiwch i danysgrifiad trwy nodi ei enw"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Cyfrinair newydd"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Y diweddaraf yn gyntaf"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Nesaf"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Adnewyddu nesaf"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Llyfrnod yr eitem nesaf heb ei darllen"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Dim mwy o gofnodion"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Dim wedi'i ddarganfod"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "allforio OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "ffeil OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Hynaf yn gyntaf"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Wps!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Agorwch y cofnod cyfredol mewn tab newydd"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Agorwch y cofnod cyfredol mewn tab newydd yn y cefndir"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Dolen agored"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Agor y cofnod nesaf"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Agor cofnod blaenorol"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Agor / cau'r cofnod cyfredol"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "gorchymyn"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "rhiant"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Categori Rhiant"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "cyfrinair"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Adfer Cyfrinair"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Nid yw cyfrineiriau yn cyfateb"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Swydd"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Proffil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Adfer cyfrinair"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Adnewyddu"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Mae cofrestriadau ar gau ar yr achos CommaFeed hwn"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Arbed"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Sgroliwch yn esmwyth wrth lywio rhwng cofnodion"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Chwilio"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Mae angen o leiaf 3 nod ar gyfer chwilio"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Gosodwch ffocws ar y cofnod nesaf heb ei agor"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Gosod ffocws ar gofnod blaenorol heb ei agor"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Gosodiadau"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Gosodiadau wedi'u cadw."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Rhannu"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Rhannu gwefannau"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "shifft"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Dangos ffrydiau a chategorïau heb unrhyw gofnodion heb eu darllen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Dangos cymorth llwybr byr bysellfwrdd"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Cofrestrwch"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Mae rhywbeth drwg newydd ddigwydd ..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Gofod"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "seren"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "serennog"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Tanysgrifio"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "Tanysgrifio URL"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Tanysgrifio i'r porthiant"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Llwyddiant"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Newid i thema dywyll"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Newid i thema golau"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Tagiau"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Y URL ar gyfer y porthwr rydych chi am danysgrifio iddo. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Thema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Toglo statws darllen y cofnod cyfredol"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Rhowch gynnig ar CommaFeed gyda'r cyfrif demo: demo / demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Heb ei ddarllen"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "dad-seren"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Dad-danysgrifio"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Enw Defnyddiwr neu E-bost"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Enw defnyddiwr"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Rhybudd"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Gwefan"
#: 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 "Nid oes gennych unrhyw danysgrifiadau eto. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "mae angen y ffeil"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: da\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Har du en konto?</0><1>Log ind!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Har du brug for en konto?</0><1>Tilmeld dig!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API-nøgle"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Omkring"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Handlinger"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Tilføj"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Tilføj kategori"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Tilføj bruger"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr ""
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Alle"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Der er sendt en e-mail, hvis denne adresse var registreret. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "En opml-fil er en XML-fil, der indeholder feed-URL'er og kategorier. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analyser foder"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Er du sikker på, at du vil slette kategori <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Er du sikker på, at du vil slette bruger <0>{brugernavn}</0>?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Er du sikker på, at du vil slette din konto? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Er du sikker på, at du vil markere alle poster i <0>{sourceLabel}</0> som læst?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Er du sikker på, at du vil markere poster, der er ældre end {threshold} dage af <0>{sourceLabel}</0> som læst?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Er du sikker på, at du vil afmelde <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Tilgængelige variabler er 'title', 'content', 'url' 'author' og 'category', og deres indhold konverteres til små bogstaver for at lette strengsammenligning."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Tilbage"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Tilbage for at logge ind"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Browserudvidelser"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Annuller"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Kategori"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Ændring af adgangskode vil generere en ny API-nøgle"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Tjek, at foderet virker"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed er et open source-projekt. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed næste ulæste element"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Kompakt"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Bekræft"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Bekræft adgangskode"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Hyggeligt"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Opret tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Nuværende adgangskode"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Dato oprettet"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Slet"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Slet kategori"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Slet konto"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Slet bruger"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Skærm"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Træk linket til bogmærkelinjen"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "E-mailadresse"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Rediger bruger"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Aktiveret"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Indtast din nuværende adgangskode for at ændre profilindstillinger"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Fejl"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Eksempel: {eksempel}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Udvidet"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Eksporter dine abonnementer og kategorier som en OPML-fil, der kan importeres i andre feed-læsningstjenester"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Feednavn"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Filtrerende udtryk"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Glemt adgangskode?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Generer først en API-nøgle i din profil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Generer ny API-nøgle"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Genereret feed-url"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Gå til API-dokumentationen."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Gå til visningen Alle"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Godbidder"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Hvis det ikke er tomt, et udtryk, der vurderes til 'sand' eller 'falsk'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Hvis du støder på et problem, bedes du rapportere det på problemsiden for GitHub-projektet."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Hvis du kan lide dette projekt, bedes du overveje en donation for at støtte udvikleren og hjælpe med at dække omkostningerne ved at holde denne hjemmeside online."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "I udvidet visning markerer du dem som læst, når du ruller gennem poster"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Forbehold ulæst"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Tastaturgenveje"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Sprog"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Sidste login dato"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Sidste opdatering"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Sidste opdateringsmeddelelse"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr ""
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Indlæser profil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Indlæser indstillinger..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Indlæser abonnementer..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Indlæser tags..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Log ind"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Log ud"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Administrer brugere"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Marker alle som læst"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marker alle poster som læst"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Markér som læst"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Markér som læst indtil her"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Flyt siden ned"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Flyt siden op"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Navn"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Naviger til et abonnement ved at indtaste dets navn"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Ny adgangskode"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Nyeste først"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Næste"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Næste opdatering"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Næste ulæste emne bogmærke"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Ingen flere poster"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Intet fundet"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML eksport"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML fil"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Ældst først"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Hovsa!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Åbn den aktuelle post i en ny fane"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Åbn den aktuelle post i en ny fane i baggrunden"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Åbent link"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Åbn næste post"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Åbn forrige post"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Åbn/luk aktuel indgang"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Bestilling"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Forælder"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Forældrekategori"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Adgangskode"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Gendannelse af adgangskode"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Adgangskoder stemmer ikke overens"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr ""
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Gendan adgangskode"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Opdater"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Registreringer er lukket på denne CommaFeed-instans"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Gem"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Rul jævnt, når du navigerer mellem poster"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Søg"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Søgning kræver mindst 3 tegn"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Sæt fokus på næste post uden at åbne den"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Sæt fokus på forrige indtastning uden at åbne den"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Indstillinger"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Indstillinger gemt."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Del"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Delingssider"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Skift"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Vis feeds og kategorier uden ulæste poster"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Vis hjælp til tastaturgenveje"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Tilmeld dig"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Der er lige sket noget slemt..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Rum"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Stjerne"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Medvirkende"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Tilmeld"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Abonner på feedet"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Succes"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Skift til mørkt tema"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Skift til lystema"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL'en til det feed, du vil abonnere på. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Skift læsestatus for den aktuelle post"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Prøv CommaFeed med demokontoen: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Ulæst"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Afmeld"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Brugernavn eller e-mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Brugernavn"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Advarsel"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Hjemmeside"
#: 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 "Du har ingen abonnementer endnu. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "fil er påkrævet"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: de\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Haben Sie ein Konto?</0><1>Melden Sie sich an!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Benötigen Sie ein Konto?</0><1>Melden Sie sich an!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API-Schlüssel"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Ungefähr"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Aktionen"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Hinzufügen"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Kategorie hinzufügen"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Benutzer hinzufügen"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Verwaltung"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Alle"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Eine E-Mail wurde gesendet, wenn diese Adresse registriert wurde. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Eine opml-Datei ist eine XML-Datei, die Feed-URLs und Kategorien enthält. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Feed analysieren"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Sind Sie sicher, dass Sie die Kategorie <0>{categoryName}</0> löschen möchten?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Sind Sie sicher, dass Sie Benutzer <0>{userName}</0> löschen möchten?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Sind Sie sicher, dass Sie Ihr Konto löschen möchten? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Sind Sie sicher, dass Sie alle Einträge von <0>{sourceLabel}</0> als gelesen markieren möchten?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Sind Sie sicher, dass Sie Einträge, die älter als {threshold} Tage von <0>{sourceLabel}</0> sind, als gelesen markieren möchten?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Sind Sie sicher, dass Sie <0>{feedName}</0> abbestellen möchten?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "Asz"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Verfügbare Variablen sind „Titel“, „Inhalt“, „URL“, „Autor“ und „Kategorien“, und ihr Inhalt wird in Kleinbuchstaben umgewandelt, um den String-Vergleich zu erleichtern."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Zurück"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Zurück zum Anmelden"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Browsererweiterungen"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Abbrechen"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Kategorie"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Das Ändern des Passworts generiert einen neuen API-Schlüssel"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Überprüfen Sie, ob der Feed funktioniert"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed ist ein Open-Source-Projekt. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed nächstes ungelesenes Element"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed-Version {Version} ({Revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Kompakt"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Bestätigen"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Passwort bestätigen"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Gemütlich"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Tag erstellen: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "Strg"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Aktuelles Passwort"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Erstellungsdatum"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Löschen"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Kategorie löschen"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Konto löschen"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Benutzer löschen"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "Beschr"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Anzeige"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Herunterladen"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Link in Lesezeichenleiste ziehen"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "E-Mail"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "E-Mail-Adresse"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Benutzer bearbeiten"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Aktiviert"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Eintreten"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Geben Sie Ihr aktuelles Passwort ein, um die Profileinstellungen zu ändern"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Fehler"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Beispiel: {Beispiel}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Erweitert"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exportieren Sie Ihre Abonnements und Kategorien als OPML-Datei, die in andere Feed-Lesedienste importiert werden kann"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "Feed-URL"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Feedname"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Filterausdruck"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Passwort vergessen?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Generieren Sie zuerst einen API-Schlüssel in Ihrem Profil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Neuen API-Schlüssel generieren"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Generierte Feed-URL"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Gehen Sie zur API-Dokumentation."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Zur Ansicht Alle wechseln"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Gutes"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Wenn nicht leer, ein Ausdruck, der als „wahr“ oder „falsch“ ausgewertet wird. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Wenn Sie auf ein Problem stoßen, melden Sie es bitte auf der Problemseite des GitHub-Projekts."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Wenn Ihnen dieses Projekt gefällt, denken Sie bitte über eine Spende nach, um den Entwickler zu unterstützen und die Kosten für die Onlinehaltung dieser Website zu decken."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importieren"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "In der erweiterten Ansicht werden Einträge beim Scrollen als gelesen markiert"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Ungelesen lassen"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Tastenkürzel"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Sprache"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Letztes Anmeldedatum"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Letzte Aktualisierung"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Letzte Aktualisierungsmeldung"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Verbindung"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Lade Profil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Lade Einstellungen..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Abonnements werden geladen..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Tags werden geladen..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Einloggen"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Abmelden"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Benutzer verwalten"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Alle als gelesen markieren"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Alle Einträge als gelesen markieren"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Als gelesen markieren"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Bis hierhin als gelesen markieren"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Metriken"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Seite nach unten verschieben"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Bewege die Seite nach oben"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "n. z"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navigieren Sie zu einem Abonnement, indem Sie seinen Namen eingeben"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Neues Passwort"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Neueste zuerst"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Weiter"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Nächste Aktualisierung"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Lesezeichen für das nächste ungelesene Element"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Keine weiteren Einträge"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Nichts gefunden"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML-Export"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML-Datei"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Älteste zuerst"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Ups!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Aktuellen Eintrag in neuem Tab öffnen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Aktuellen Eintrag in neuem Tab im Hintergrund öffnen"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Link öffnen"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Nächsten Eintrag öffnen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Vorherigen Eintrag öffnen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Aktuellen Eintrag öffnen/schließen"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Bestellung"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Elternteil"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Elternkategorie"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Passwort"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Passwortwiederherstellung"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Passwörter stimmen nicht überein"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Stellung"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "REST-API"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Kennwort wiederherstellen"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Aktualisieren"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Registrierungen sind für diese CommaFeed-Instanz geschlossen"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Speichern"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Geschwindes Scrollen beim Navigieren zwischen Einträgen"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Suche"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Suche erfordert mindestens 3 Zeichen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Fokus auf den nächsten Eintrag setzen, ohne ihn zu öffnen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Fokus auf vorherigen Eintrag setzen, ohne ihn zu öffnen"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Einstellungen"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Einstellungen gespeichert."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Teilen"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Seiten teilen"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Verschiebung"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Feeds und Kategorien ohne ungelesene Einträge anzeigen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Tastenkürzel-Hilfe anzeigen"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Melden Sie sich an"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Etwas Schlimmes ist gerade passiert..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Raum"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Stern"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Markiert"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Abonnieren"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL abonnieren"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Feed abonnieren"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Erfolg"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Zum dunklen Design wechseln"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Wechseln Sie zum Lichtdesign"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Die URL für den Feed, den Sie abonnieren möchten. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Thema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Lesestatus des aktuellen Eintrags umschalten"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Testen Sie CommaFeed mit dem Demokonto: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Ungelesen"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Stern entfernen"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Abbestellen"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Benutzername oder E-Mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Benutzername"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Warnung"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Webseite"
#: 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 "Sie haben noch keine Abonnements. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "Datei ist erforderlich"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-08-04 18:51+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: en\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr "<0>Complete syntax is available </0><1>here</1>."
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Have an account?</0><1>Log in!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Need an account?</0><1>Sign up!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API key"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "About"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Actions"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Add"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Add category"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Add user"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Admin"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "All"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "An email has been sent if this address was registered. Check your inbox."
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analyze feed"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Are you sure you want to delete category <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Are you sure you want to delete user <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Are you sure you want to delete your account? There's no turning back!"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "Asc"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Back"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Back to log in"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Browser extentions"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Cancel"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Category"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Changing password will generate a new API key"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Check that the feed is working"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed next unread item"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed version {version} ({revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compact"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Confirm"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Confirm password"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Cozy"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Create tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "Ctrl"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Current password"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Date created"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Delete"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Delete Category"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Delete account"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Delete user"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "Desc"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Display"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Download"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Drag link to bookmark bar"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "E-mail"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "E-mail address"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Edit user"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Enabled"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Enter"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Enter your current password to change profile settings"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Error"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Example: {example}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Expanded"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "Feed URL"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Feed name"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr "Fetch all my feeds now"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Filtering expression"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Forgot password?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Generate an API key in your profile first."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Generate new API key"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Generated feed url"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Go to the API documentation."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Go to the All view"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr "Go to {0}"
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Goodies"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "Id"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "If you encounter an issue, please report it on the issues page of the GitHub project."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Import"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "In expanded view, scrolling through entries mark them as read"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Keep unread"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Keyboard shortcuts"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Language"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Last login date"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Last refresh"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Last refresh message"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Link"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Loading profile..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Loading settings..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Loading subscriptions..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Loading tags..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Log in"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Logout"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr "Long press"
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Manage users"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Mark all as read"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Mark all entries as read"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Mark as read"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Mark as read up to here"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Metrics"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr "Middle click"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Move the page down"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Move the page up"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "N/A"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Name"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navigate to a subscription by entering its name"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "New password"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Newest first"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Next"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Next refresh"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Next unread item bookmarklet"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "No more entries"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Nothing found"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr "OPML"
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML export"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML file"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Oldest first"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Oops!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Open current entry in a new tab"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Open current entry in a new tab in the background"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Open link"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr "Open link in new background tab"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr "Open link in new tab"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Open next entry"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Open previous entry"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Open/close current entry"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Order"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Parent"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Parent Category"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Password"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Password Recovery"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Passwords do not match"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Position"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profile"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "REST API"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Recover password"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Refresh"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Registrations are closed on this CommaFeed instance"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr "Reload"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr "Right click"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Save"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Scroll smoothly when navigating between entries"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Search"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Search requires at least 3 characters"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Set focus on next entry without opening it"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Set focus on previous entry without opening it"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Settings"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Settings saved."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Share"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Sharing sites"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Shift"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr "Show entry menu (desktop)"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr "Show entry menu (mobile)"
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Show feeds and categories with no unread entries"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Show keyboard shortcut help"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Sign up"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Something bad just happened..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Space"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Star"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Starred"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Subscribe"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "Subscribe URL"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Subscribe to the feed"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Success"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr "Swipe header to the right"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Switch to dark theme"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Switch to light theme"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Tags"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Theme"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Toggle read status of current entry"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Try out CommaFeed with the demo account: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Unread"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Unstar"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Unsubscribe"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "User Name or E-mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "User name"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Warning"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Website"
#: 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 "You don't have any subscriptions yet. Why not try adding one by clicking on the + sign at the top of the page?"
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr "Your feeds have been queued for refresh."
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "file is required"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: es\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>¿Tienes una cuenta?</0><1>¡Inicia sesión!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>¿Necesitas una cuenta?</0><1>¡Regístrate!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "clave API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Sobre"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Acciones"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Agregar"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Añadir categoría"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Añadir usuario"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Administrador"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Todo"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Se ha enviado un correo electrónico si se registró esta dirección. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Un archivo opml es un archivo XML que contiene categorías y direcciones URL de fuentes. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analizar alimentación"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "¿Está seguro de que desea eliminar la categoría <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "¿Está seguro de que desea eliminar el usuario <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "¿Está seguro de que desea eliminar su cuenta? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "¿Está seguro de que desea marcar todas las entradas de <0>{sourceLabel}</0> como leídas?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "¿Está seguro de que desea marcar las entradas anteriores a {threshold} días de <0>{sourceLabel}</0> como leídas?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "¿Está seguro de que desea darse de baja de <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "ASC"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Las variables disponibles son 'título', 'contenido', 'url', 'autor' y 'categorías' y su contenido se convierte a minúsculas para facilitar la comparación de cadenas."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Atrás"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Volver a iniciar sesión"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Extensiones del navegador"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Cancelar"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Categoría"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Cambiar la contraseña generará una nueva clave API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Compruebe que el feed funciona"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed es un proyecto de código abierto. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed siguiente elemento no leído"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "versión de CommaFeed {versión} ({revisión})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compacto"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Confirmar"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Confirmar contraseña"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Acogedor"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Crear etiqueta: {consulta}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Contraseña actual"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Fecha de creación"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Borrar"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Borrar categoría"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Borrar cuenta"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Borrar usuario"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Pantalla"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "descargar"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Arrastra el enlace a la barra de marcadores"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "Correo electrónico"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "dirección de correo electrónico"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Editar usuario"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Habilitado"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Entrar"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Ingrese su contraseña actual para cambiar la configuración del perfil"
#: src/components/Alert.tsx
msgid "Error"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Ejemplo: {ejemplo}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Expandido"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exporte sus suscripciones y categorías como un archivo OPML que se puede importar en otros servicios de lectura de feeds"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL de fuente"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nombre de alimentación"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Expresión de filtrado"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "¿Olvidaste la contraseña?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Primero genere una clave API en su perfil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Generar nueva clave API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "URL del feed generado"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Ir a la documentación de la API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Ir a la vista Todo"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "golosinas"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "Identificación"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Si no está vacío, una expresión que se evalúa como 'verdadero' o 'falso'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Si encuentra un problema, infórmelo en la página de problemas del proyecto GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Si le gusta este proyecto, considere una donación para apoyar al desarrollador y ayudar a cubrir los costos de mantener este sitio web en línea."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importar"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "En la vista ampliada, al desplazarse por las entradas, márquelas como leídas"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Mantener sin leer"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "atajos de teclado"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Idioma"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "fecha del último inicio de sesión"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Última actualización"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Último mensaje de actualización"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Enlace"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Cargando perfil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Cargando ajustes..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Cargando suscripciones..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Cargando etiquetas..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Iniciar sesión"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Salir"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Administrar usuarios"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Marcar todo como leído"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marcar todas las entradas como leídas"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Marcar como leído"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Marcar como leído hasta aquí"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Métricas"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Mover la página hacia abajo"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Mover la página hacia arriba"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "N/D"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nombre"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navegar a una suscripción ingresando su nombre"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Nueva contraseña"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "más reciente primero"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Siguiente"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Próxima actualización"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Bookmarklet del siguiente elemento no leído"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "No más entradas"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Nada encontrado"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Exportación OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "archivo OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "más antigua primero"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "¡Ups!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Abrir la entrada actual en una nueva pestaña"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Abrir la entrada actual en una nueva pestaña en segundo plano"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Abrir enlace"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Abrir siguiente entrada"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Abrir entrada anterior"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Abrir/cerrar entrada actual"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Orden"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Padre"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Categoría principal"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Contraseña"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Recuperación de contraseña"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Las contraseñas no coinciden"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Posición"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "API REST"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Recuperar contraseña"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Actualizar"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Los registros están cerrados en esta instancia de CommaFeed"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Guardar"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Desplazarse suavemente al navegar entre entradas"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Buscar"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "La búsqueda requiere al menos 3 caracteres"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Establezca el foco en la siguiente entrada sin abrirla"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Poner el foco en la entrada anterior sin abrirla"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Configuraciones"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Ajustes guardados."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Compartir"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Compartir sitios"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Cambio"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Mostrar feeds y categorías sin entradas no leídas"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Mostrar ayuda de atajo de teclado"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Registrarse"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Algo malo acaba de pasar..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Espacio"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "estrella"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Destacado"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Suscribirse"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL de suscripción"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Suscríbete a la fuente"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Éxito"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Cambiar a tema oscuro"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Cambiar a tema claro"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Etiquetas"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "La URL de la fuente a la que desea suscribirse. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Alternar estado de lectura de la entrada actual"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Pruebe CommaFeed con la cuenta demo: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "No leído"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Desmarcar"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Cancelar suscripción"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nombre de usuario o correo electrónico"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nombre de usuario"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Advertencia"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Sitio web"
#: 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 "Todavía no tienes ninguna suscripción. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "archivo requerido"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fa\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>حساب دارید؟</0><1>وارد سیستم شوید!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>به یک حساب نیاز دارید؟</0><1>ثبت نام کنید!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "کلید API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "در مورد"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "اعمال"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "اضافه کنید"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "اضافه کردن دسته"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "افزودن کاربر"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "مدیر"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "همه"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "اگر این آدرس ثبت شده باشد ایمیل ارسال شده است. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "یک فایل opml یک فایل XML است که حاوی آدرس‌ها و دسته‌های فید است. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "خوراک را تجزیه و تحلیل کنید"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "آیا مطمئن هستید که می خواهید دسته <0>{categoryName}</0> را حذف کنید؟"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "آیا مطمئن هستید که می خواهید کاربر <0>{userName}</0> را حذف کنید؟"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "آیا مطمئن هستید که می خواهید حساب خود را حذف کنید؟ "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "آیا مطمئن هستید که می خواهید همه ورودی های <0>{sourceLabel}</0> را به عنوان خوانده شده علامت گذاری کنید؟"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "آیا مطمئن هستید که می خواهید ورودی های قدیمی تر از {threshold} روز <0>{sourceLabel}</0> را به عنوان خوانده شده علامت گذاری کنید؟"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "آیا مطمئن هستید که می خواهید اشتراک <0>{feedName}</0> را لغو کنید؟"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "صعودی"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "متغیرهای موجود عبارتند از «عنوان»، «محتوا»، «url» «نویسنده» و «دسته‌ها» و محتوای آن‌ها برای سهولت مقایسه رشته‌ها به حروف کوچک تبدیل می‌شود."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "برگشت"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "بازگشت برای ورود به سیستم"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "گسترش مرورگر"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "لغو"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "مقوله"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "تغییر رمز عبور یک کلید API جدید ایجاد می کند"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "بررسی کنید که خوراک کار می کند"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed یک پروژه منبع باز است. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "مورد خوانده نشده بعدی CommaFeed"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "نسخه {نسخه} CommaFeed ({نسخه})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "فشرده"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "تأیید کنید"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "رمز عبور را تأیید کنید"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "دنج"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "ایجاد برچسب: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "رمز عبور فعلی"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "تاریخ ایجاد"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "حذف کنید"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "حذف دسته"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "حذف حساب"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "حذف کاربر"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "توصیف"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "نمایش"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "دانلود"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "پیوند را به نوار نشانک بکشید"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "ایمیل"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "آدرس ایمیل"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "ویرایش کاربر"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "فعال"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "وارد شوید"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "رمز عبور فعلی خود را برای تغییر تنظیمات نمایه وارد کنید"
#: src/components/Alert.tsx
msgid "Error"
msgstr "خطا"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "مثال: {مثال}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "گسترش یافت"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "اشتراک ها و دسته های خود را به عنوان یک فایل OPML صادر کنید که می تواند در سایر خدمات خواندن فید وارد شود"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL فید"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "نام فید"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "بیان فیلتر"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "رمز عبور را فراموش کرده اید؟"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "ابتدا یک کلید API در نمایه خود ایجاد کنید."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "کلید API جدید ایجاد کنید"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "آدرس اینترنتی فید تولید شده"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "به مستندات API بروید."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "به نمای All بروید"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "خوبی ها"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "شناسه"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "اگر خالی نباشد، عبارتی به \"درست\" یا \"نادرست\" ارزیابی می شود. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "اگر با مشکلی مواجه شدید، لطفاً آن را در صفحه مشکلات پروژه GitHub گزارش دهید."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "اگر این پروژه را دوست دارید، لطفاً کمک مالی برای حمایت از توسعه دهنده و کمک به پوشش هزینه های آنلاین نگه داشتن این وب سایت در نظر بگیرید."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "واردات"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "در نمای بازشده، پیمایش در ورودی‌ها، آنها را به عنوان خوانده شده علامت‌گذاری می‌کند"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "خوانده نشده نگه دارید"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "میانبرهای صفحه کلید"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "زبان"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "آخرین تاریخ ورود"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "آخرین به روز رسانی"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "آخرین پیام تازه کردن"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "پیوند"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "بارگیری نمایه..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "بارگیری تنظیمات..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "بارگیری اشتراک ها..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "بارگیری برچسب ها..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "وارد شوید"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "خروج"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "کاربران را مدیریت کنید"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "همه را به عنوان خوانده شده علامت گذاری کنید"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "همه ورودی ها را به عنوان خوانده شده علامت گذاری کنید"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "علامت گذاری به عنوان خوانده شده"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "تا اینجا به عنوان خوانده شده علامت بزنید"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "متریک"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "صفحه را به پایین ببرید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "صفحه را به بالا ببرید"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "نام"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "با وارد کردن نام اشتراک، به آن بروید"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "رمز عبور جدید"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "ابتدا جدیدترین"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "بعد"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "رفرش بعدی"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "بوکمارک مورد خوانده نشده بعدی"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "ورودی دیگری وجود ندارد"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "چیزی پیدا نشد"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "صادرات OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "فایل OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "قدیمی ترین اول"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "اوه!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "ورودی فعلی را در یک برگه جدید باز کنید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "ورودی فعلی را در یک برگه جدید در پس زمینه باز کنید"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "پیوند را باز کنید"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "ورودی بعدی را باز کنید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "ورودی قبلی را باز کنید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "باز کردن/بستن ورودی فعلی"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "سفارش"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "پدر و مادر"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "دسته والد"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "رمز عبور"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "بازیابی رمز عبور"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "گذرواژه ها مطابقت ندارند"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "موقعیت"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "نمایه"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "بازیابی رمز عبور"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "تازه کردن"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "ثبت نام در این نمونه CommaFeed بسته شده است"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "ذخیره کنید"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "هنگام پیمایش بین ورودی‌ها به آرامی حرکت کنید"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "جستجو"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "جستجو به حداقل 3 کاراکتر نیاز دارد"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "فوکوس را روی ورودی بعدی بدون باز کردن آن تنظیم کنید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "فوکوس را روی ورودی قبلی بدون باز کردن آن تنظیم کنید"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "تنظیمات"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "تنظیمات ذخیره شد."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "به اشتراک بگذارید"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "اشتراک گذاری سایت ها"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "شیفت"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "فیدها و دسته ها را بدون ورودی خوانده نشده نشان دهید"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "نمایش راهنمایی میانبر صفحه کلید"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "ثبت نام کنید"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "اتفاق بدی افتاد..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "فضا"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "ستاره"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "ستاره دار"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "مشترک شوید"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL اشتراک"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "در فید مشترک شوید"
#: src/components/Alert.tsx
msgid "Success"
msgstr "موفقیت"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "تغییر به تم تیره"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "روی زمینه روشن"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "برچسب ها"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL فیدی که می خواهید در آن مشترک شوید. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "تم"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "وضعیت خواندن ورودی فعلی را تغییر دهید"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "CommaFeed را با حساب آزمایشی امتحان کنید: دمو/دمو"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "خوانده نشده"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "لغو اشتراک"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "نام کاربری یا ایمیل"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "نام کاربری"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "هشدار"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "وب سایت"
#: 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 "شما هنوز هیچ اشتراکی ندارید. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "فایل مورد نیاز است"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fi\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Onko sinulla tili?</0><1>Kirjaudu sisään!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Tarvitsetko tilin?</0><1>Rekisteröidy!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API-avain"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Noin"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Toimet"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Lisää"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Lisää luokka"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Lisää käyttäjä"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Järjestelmänvalvoja"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Kaikki"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Sähköposti on lähetetty, jos tämä osoite on rekisteröity. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Opml-tiedosto on XML-tiedosto, joka sisältää syötteen URL-osoitteet ja luokat. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analysoi syöte"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Haluatko varmasti poistaa luokan <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Haluatko varmasti poistaa käyttäjän <0>{userName}</0>?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Haluatko varmasti poistaa tilisi? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Haluatko varmasti merkitä kaikki kohteen <0>{sourceLabel}</0> merkinnät luetuiksi?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Haluatko varmasti merkitä <0>{sourceLabel}</0>:n {threshold} päivää vanhemmat merkinnät luetuiksi?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Haluatko varmasti peruuttaa kohteen <0>{feedName}</0> tilauksen?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Käytettävissä olevat muuttujat ovat 'title', 'content', 'url' 'author' ja 'categories', ja niiden sisältö muunnetaan pienillä kirjaimilla merkkijonojen vertailun helpottamiseksi."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Takaisin"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Takaisin sisäänkirjautumiseen"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Selaimen laajennukset"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Peruuta"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Luokka"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Salasanan vaihtaminen luo uuden API-avaimen"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Tarkista, että syöttö toimii"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed on avoimen lähdekoodin projekti. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed seuraava lukematon kohde"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed-versio {version} ({versio})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Kompakti"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Vahvista"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Vahvista salasana"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Viihtyisä"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Luo tunniste: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Nykyinen salasana"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Luontipäivämäärä"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Poista"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Poista luokka"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Poista tili"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Poista käyttäjä"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Näyttö"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Lataa"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Vedä linkki kirjanmerkkipalkkiin"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "Sähköposti"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Sähköpostiosoite"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Muokkaa käyttäjää"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Käytössä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Anna nykyinen salasanasi muuttaaksesi profiiliasetuksia"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Virhe"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Esimerkki: {example}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Laajennettu"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Vie tilauksesi ja luokat OPML-tiedostona, joka voidaan tuoda muihin syötteiden lukupalveluihin"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "Syötteen URL-osoite"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Syötteen nimi"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Suodattava lauseke"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Unohditko salasanan?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Luo ensin API-avain profiiliisi."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Luo uusi API-avain"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Luotu syötteen URL-osoite"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Siirry API-dokumentaatioon."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Siirry Kaikki-näkymään"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Hyvää"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Jos ei tyhjä, lauseke, jonka arvo on \"tosi\" tai \"epätosi\". "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Jos kohtaat ongelman, ilmoita siitä GitHub-projektin ongelmasivulla."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Jos pidät tästä projektista, harkitse lahjoitusta tukeaksesi kehittäjää ja autat kattamaan tämän verkkosivuston verkossa pitämisestä aiheutuvat kulut."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Tuo"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Merkitse ne luetuiksi laajennetussa näkymässä vierittämällä merkintöjä"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Pidä lukematta"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Pikanäppäimet"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Kieli"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Viimeinen kirjautumispäivä"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Viimeinen päivitys"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Viimeinen päivitysviesti"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Linkki"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Ladataan profiilia..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Ladataan asetuksia..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Ladataan tilauksia..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Ladataan tunnisteita..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Kirjaudu sisään"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Uloskirjautuminen"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Hallitse käyttäjiä"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Merkitse kaikki luetuiksi"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Merkitse kaikki merkinnät luetuiksi"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Merkitse luetuksi"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Merkitse luetuksi tähän asti"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Siirrä sivua alaspäin"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Siirrä sivua ylöspäin"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nimi"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Siirry tilaukseen kirjoittamalla sen nimi"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Uusi salasana"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Uusin ensin"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Seuraava"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Seuraava päivitys"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Seuraavan lukemattoman kohteen kirjanmerkki"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Ei enää merkintöjä"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Mitään ei löytynyt"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML-vienti"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML-tiedosto"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Vanhin ensin"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Hups!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Avaa nykyinen merkintä uudessa välilehdessä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Avaa nykyinen merkintä uudella välilehdellä taustalla"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Avaa linkki"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Avaa seuraava merkintä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Avaa edellinen merkintä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Avaa/sulje nykyinen merkintä"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Tilaus"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Vanhempi"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Pääluokka"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Salasana"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Salasanan palautus"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Salasanat eivät täsmää"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Sijainti"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profiili"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Palauta salasana"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Päivitä"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Tämän CommaFeed-esiintymän rekisteröinnit on suljettu"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Tallenna"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Selaa sujuvasti navigoidessasi merkintöjen välillä"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Etsi"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Haku vaatii vähintään 3 merkkiä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Keskitä seuraavaan merkintään avaamatta sitä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Aseta kohdistus edelliseen merkintään avaamatta sitä"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Asetukset"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Asetukset tallennettu."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Jaa"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Sivustojen jakaminen"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Vaihto"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Näytä syötteet ja luokat ilman lukemattomia merkintöjä"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Näytä pikanäppäimen ohje"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Rekisteröidy"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Jotain pahaa tapahtui juuri..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Avaruus"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Tähti"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Tähdellä merkitty"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Tilaa"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "Tilaa URL-osoite"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Tilaa syöte"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Onnistui"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Vaihda tummaan teemaan"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Vaihda vaaleaan teemaan"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Sen syötteen URL-osoite, jonka haluat tilata. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Teema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Vaihda nykyisen merkinnän lukutila"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Kokeile CommaFeediä demotilillä: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Lukematon"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Poista tähti"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Peruuta tilaus"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Käyttäjänimi tai sähköpostiosoite"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Käyttäjänimi"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Varoitus"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Verkkosivusto"
#: 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 "Sinulla ei ole vielä tilauksia. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "tiedosto vaaditaan"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-08-04 18:51+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: fr\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr "<0>La syntaxe complète est disponible </0><1>ici</1>."
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Déjà un compte ?</0><1>Connectez-vous !</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Besoin d'un compte ?</0><1>Enregistrez-vous !</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "Clé API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "A propos"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Actions"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Ajouter"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Ajouter une catégorie"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Ajouter un utilisateur"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Administrateur"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Tout"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Un e-mail a été envoyé si cette adresse est enregistrée. Vérifiez votre boîte de réception."
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Un fichier OPML est un fichier XML contenant des URL de flux et des catégories. Vous pouvez obtenir un fichier OPML en exportant vos données à partir d'autres services de lecture de flux."
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analyser le flux"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Etes-vous sûr de vouloir supprimer la catégorie <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Etes-vous sûr de vouloir supprimer l'utilisateur <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Êtes-vous sûr de vouloir supprimer définitivement votre compte ?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Etes-vous sûr de vouloir marquer toutes les entrées de <0>{sourceLabel}</0> comme lues?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Etes-vous sûr de vouloir marquer les entrées de <0>{sourceLabel}</0> plus anciennes que {threshold} jours comme lues?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Etes-vous sûr de vouloir vous désabonner de <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "Ascendant"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Les variables disponibles sont 'title', 'content', 'url' 'author' et 'categories' et leur contenu est converti en minuscules pour faciliter la comparaison de chaînes."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Retour"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Retour à la connexion"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Extensions pour navigateurs"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Annuler"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Catégorie"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Changer de mot de passe générera une nouvelle clé API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Vérifie que le flux fonctionne"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed est un projet open-source. Les sources sont hébergées sur <0>GitHub</0>."
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed prochain article non lu"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed version {version} ({revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compact"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Confirmer"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Confirmer le mot de passe"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Cozy"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Créer le tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "Ctrl"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Mot de passe actuel"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Date de création"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Effacer"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Effacer la catégorie"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Effacer le compte"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Effacer l'utilisateur"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "Descendant"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Affichage"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Télécharger"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Déplacez le lien vers la barre de favoris"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "E-mail"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Adresse e-mail"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Modifier un utilisateur"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Actif"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Entrer"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Entrez votre mot de passe actuel pour changer les paramètres du profil"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Erreur"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Exemple : {example}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Vue étendue"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exporter vos abonnements et catégories en tant que fichier OPML qui peut être importé dans d'autres services de lecture de flux"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL du flux"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nom du flux"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Expression de filtrage"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Mot de passe oublié ?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Générez d'abord une clé API dans votre profil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Générer une nouvelle clé API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "URL du flux généré"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Aller à la documentation de l'API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Aller à la catégorie Tout"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Extensions"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "Identifiant"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Si non vide, une expression évaluant à 'vrai' ou 'faux'. Si faux, les nouvelles entrées de ce flux seront marquées comme lues automatiquement."
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Si vous rencontrez un problème, merci de le signaler sur la page du projet GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Si vous aimez ce projet, n'hésitez pas à faire un don pour encourager le développeur et aider à couvrir les coûts d'hébergement de la plate-forme."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importer"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "En mode de lecture étendu, marquer les éléments comme lus lorsque la fenêtre descend."
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Garder non lu"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Raccourcis clavier"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Langue"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Dernière connexion"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Dernière mise à jour"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Dernier message de mise à jour"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Lien"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Chargement du profil ..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Chargement des paramètres ..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Chargement des abonnements ..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Chargement des tags ..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Connexion"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Déconnexion"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Gestion des utilisateurs"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Tout marquer comme lu"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marquer toutes les entrées comme lues"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Marquer comme lu"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Marquer comme lu jusqu'ici"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Métriques"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Faites défiler la page vers le bas"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Faites défiler la page vers le haut"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "N/A"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nom"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Naviguer vers un abonnement en entrant son nom"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Nouveau mot de passe"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Plus récent en premier"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Suivant"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Prochaine mise à jour"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Bookmarklet vers le prochain article non lu"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Plus d'entrées"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Aucun résultat"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr "OPML"
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Export du fichier OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "Fichier OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Du plus ancien au plus récent"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Oups !"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Ouvrir l'entrée actuelle dans un nouvel onglet"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Ouvrir l'entrée actuelle dans un nouvel onglet en arrière-plan"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Ouvrir le lien"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Ouvrir l'entrée suivante"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Ouvrir l'entrée précédente"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Ouvrir/fermer l'entrée actuelle"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Ordre"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Parent"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Catégorie parente"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Mot de passe"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Récupération de mot de passe"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Les mots de passe ne correspondent pas"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Position"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "API REST"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Récupérer le mot de passe"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Rafraîchir"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Les inscriptions sont fermées sur cette instance de CommaFeed"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Enregistrer"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Défilement animé lors de la navigation entre les entrées"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Rechercher"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "La recherche requiert au moins 3 caractères"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Sélectionner l'article suivant sans l'ouvrir"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Sélectionner l'article précédent sans l'ouvrir"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Réglages"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Réglages enregistrés."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Partager"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Sites de partage"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Maj"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Afficher les flux et les catégories pour lesquels tout est déjà lu"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Montrer les raccourcis clavier"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Créer un compte"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Quelque chose s'est mal passé..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Espace"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Ajouter aux favoris"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Favoris"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "S'abonner"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL pour s'abonner"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "S'abonner au flux"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Succès"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr "Faire glisser le titre vers la droite"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Activer le mode sombre"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Activer le mode clair"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Tags"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "L'URL du flux auquel vous souhaitez vous abonner. Vous pouvez aussi utiliser l'URL du site directement et CommaFeed va essayer de trouver le flux dans la page."
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Thème"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Marquer l'entrée actuelle comme lue/non lue"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Essayez CommaFeed avec le compte de démonstration : demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Non lu"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Retirer des favoris"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Se désabonner"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nom d'utilisateur ou e-mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nom"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Attention"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Site web"
#: 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 "Vous n'avez pas encore d'abonnements. Pourquoi ne pas essayer d'en ajouter un en cliquant sur le signe + en haut de la page ?"
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "fichier requis"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: gl\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Tes unha conta?</0><1>Iniciar sesión!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Necesitas unha conta?</0><1>Rexístrate!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "chave API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Sobre"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Accións"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Engadir"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Engadir categoría"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Engadir usuario"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Administración"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Todos"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Enviouse un correo electrónico se este enderezo estaba rexistrado. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Un ficheiro opml é un ficheiro XML que contén URL e categorías de fontes. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analizar feed"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Estás seguro de que queres eliminar a categoría <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Estás seguro de que queres eliminar o usuario <0>{userName}</0>?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Estás seguro de que queres eliminar a túa conta? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Estás seguro de que queres marcar todas as entradas de <0>{sourceLabel}</0> como lidas?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Estás seguro de que queres marcar as entradas anteriores a {threshold} días de <0>{sourceLabel}</0> como lidas?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Estás seguro de que queres cancelar a subscrición a <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "As variables dispoñibles son 'título', 'contido', 'url' 'autor' e 'categorías' e o seu contido convértese a minúsculas para facilitar a comparación de cadeas."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Atrás"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Volver para iniciar sesión"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Extensións do navegador"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Cancelar"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Categoría"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "O cambio de contrasinal xerará unha nova clave de API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Comproba que a fonte funciona"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed é un proxecto de código aberto. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed seguinte elemento non lido"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "Versión de CommaFeed {versión} ({revisión})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compacto"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Confirmar"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Confirmar contrasinal"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "acolledor"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Crear etiqueta: {consulta}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Contrasinal actual"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Data de creación"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Eliminar"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Eliminar categoría"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Eliminar conta"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Eliminar usuario"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Exhibición"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Descargar"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Arrastra a ligazón á barra de marcadores"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "Correo electrónico"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Enderezo de correo electrónico"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Editar usuario"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Activado"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Entra"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Introduce o teu contrasinal actual para cambiar a configuración do perfil"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Erro"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Exemplo: {exemplo}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Ampliado"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exporta as túas subscricións e categorías como ficheiro OPML que se pode importar noutros servizos de lectura de feeds"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL da fonte"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nome do feed"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Expresión de filtrado"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Esqueceches o contrasinal?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Xera primeiro unha clave API no teu perfil."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Xerar nova clave de API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "URL da fonte xerada"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Ir á documentación da API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Ir á vista Todos"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "agasallos"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Se non está baleira, unha expresión que se avalía como \"verdadeiro\" ou \"falso\". "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Se atopas algún problema, infórmao na páxina de problemas do proxecto GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Se che gusta este proxecto, considera unha doazón para apoiar o programador e axudar a cubrir os custos de manter este sitio web en liña."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importación"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Na vista ampliada, ao desprazarse polas entradas márcaas como lidas"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Manter sen ler"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "atallos de teclado"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Lingua"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "última data de inicio de sesión"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Última actualización"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Última mensaxe de actualización"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Ligazón"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Cargando perfil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Cargando configuración..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Cargando subscricións..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Cargando etiquetas..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Iniciar sesión"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Pechar sesión"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Xestionar usuarios"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Marcar todo como lido"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Marcar todas as entradas como lidas"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Marcar como lido"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Marcar como lido ata aquí"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Métricas"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Move a páxina cara abaixo"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Move a páxina cara arriba"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nome"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navega a unha subscrición introducindo o seu nome"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "novo contrasinal"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "o máis novo primeiro"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Seguinte"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Próxima actualización"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Seguinte marcador de elementos non lidos"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Non hai máis entradas"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Non se atopou nada"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Exportación OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "ficheiro OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "O máis vello primeiro"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Vaia!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Abrir a entrada actual nunha nova pestana"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Abre a entrada actual nunha nova pestana en segundo plano"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "ligazón aberta"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Abrir a seguinte entrada"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Abrir entrada anterior"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Abrir/pechar entrada actual"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Orde"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Pai"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Categoría de pais"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Contrasinal"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Recuperación de contrasinal"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Os contrasinais non coinciden"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Posición"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Perfil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "API REST"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Recuperar o contrasinal"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Actualizar"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Os rexistros están pechados nesta instancia de CommaFeed"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Gardar"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Desprácese suavemente ao navegar entre as entradas"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Busca"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "A busca require polo menos 3 caracteres"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Establece o foco na seguinte entrada sen abrila"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Establecer o foco na entrada anterior sen abrila"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Configuración"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "axustes gardados."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Compartir"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Compartir sitios"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "quendas"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Mostrar fontes e categorías sen entradas sen ler"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Mostrar axuda do atallo do teclado"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Rexístrese"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Algo malo pasou..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Espazo"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "estrela"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "estrela"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Subscríbete"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL de subscrición"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Subscríbete ao feed"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Éxito"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Cambiar ao tema escuro"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Cambiar ao tema claro"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Etiquetas"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "O URL do feed ao que quere subscribirse. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "alternar o estado de lectura da entrada actual"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Proba CommaFeed coa conta de demostración: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Sen ler"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Desestrela"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Cancelar a subscrición"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nome de usuario ou correo electrónico"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nome de usuario"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Aviso"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Páxina web"
#: 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 "Aínda non tes ningunha subscrición. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "é necesario o ficheiro"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: hu\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Van fiókja?</0><1>Jelentkezzen be!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Fiókra van szüksége?</0><1>Regisztráljon!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API kulcs"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Kb"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Műveletek"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr ""
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Kategória hozzáadása"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Felhasználó hozzáadása"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr ""
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Mind"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "E-mailt küldtünk, ha ez a cím regisztrálva volt. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Az opml-fájl olyan XML-fájl, amely feed URL-címeket és kategóriákat tartalmaz. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Hírcsatorna elemzése"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Biztosan törölni szeretné a(z) <0>{categoryName}</0> kategóriát?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Biztosan törölni szeretné a(z) <0>{userName}</0> felhasználót?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Biztosan törli a fiókját? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Biztosan olvasottként szeretné megjelölni a(z) <0>{sourceLabel}</0> összes bejegyzését?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Biztosan olvasottként szeretné megjelölni a(z) <0>{sourceLabel}</0> {threshold} napjánál régebbi bejegyzéseket?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Biztosan le szeretne iratkozni a következőről: <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "A rendelkezésre álló változók a következők: 'cím', 'tartalom', 'url' 'szerző' és 'kategóriák', és tartalmukat a rendszer kisbetűssé alakítja a karakterlánc-összehasonlítás megkönnyítése érdekében."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Vissza"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Vissza a bejelentkezéshez"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Böngészőbővítések"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Mégse"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Kategória"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "A jelszó megváltoztatása új API-kulcsot generál"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Ellenőrizze, hogy a feed működik-e"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed következő olvasatlan elem"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed verzió {version} ({revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Kompakt"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Erősítse meg"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Erősítse meg a jelszót"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Hangulatos"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Címke létrehozása: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Jelenlegi jelszó"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Létrehozás dátuma"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Törlés"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Kategória törlése"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Fiók törlése"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Felhasználó törlése"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Kijelző"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Letöltés"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Húzza a hivatkozást a könyvjelzősávra"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "E-mail cím"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Felhasználó szerkesztése"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Engedélyezve"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Adja meg jelenlegi jelszavát a profilbeállítások módosításához"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Hiba"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Példa: {example}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Kiterjesztve"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Exportálja előfizetéseit és kategóriáit OPML-fájlként, amely importálható más feedolvasó szolgáltatásokba"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr ""
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Hírcsatorna neve"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Szűrő kifejezés"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Elfelejtette a jelszavát?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Először generáljon API-kulcsot a profiljában."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Új API-kulcs létrehozása"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Hírcsatorna generált URL-je"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Nyissa meg az API dokumentációját."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Lépjen az Összes nézetre"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Jók"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Ha nem üres, akkor 'igaz' vagy 'hamis' értékre kiértékelő kifejezés. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Ha problémát tapasztal, kérjük, jelentse azt a GitHub projekt problémák oldalán."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Ha tetszik ez a projekt, kérjük, fontolja meg adományozását a fejlesztő támogatására és a webhely online tartásának költségeinek fedezésére."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importálás"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Kibontott nézetben a bejegyzések görgetése olvasottként jelöli meg őket"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Olvasatlan marad"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Billentyűparancsok"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Nyelv"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Utolsó bejelentkezés dátuma"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Utolsó frissítés"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Utolsó frissítési üzenet"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr ""
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Profil betöltése..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Beállítások betöltése..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Előfizetések betöltése..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Címkék betöltése..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Jelentkezzen be"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Kijelentkezés"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Felhasználók kezelése"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Minden megjelölése olvasottként"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Minden bejegyzés megjelölése olvasottként"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Megjelölés olvasottként"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Megjelölés idáig olvasottként"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Mozgassa le az oldalt"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Mozgassa felfelé az oldalt"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Név"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navigáljon egy előfizetéshez a nevének megadásával"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Új jelszó"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "A legújabbak először"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Következő"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Következő frissítés"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Következő olvasatlan elem könyvjelző"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Nincs több bejegyzés"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Semmi sem található"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr ""
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML fájl"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "A legidősebb első"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Hoppá!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Az aktuális bejegyzés megnyitása új lapon"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Az aktuális bejegyzés megnyitása egy új lapon a háttérben"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Link megnyitása"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Következő bejegyzés megnyitása"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Nyissa meg az előző bejegyzést"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Aktuális bejegyzés megnyitása/zárása"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Rendelés"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Szülő"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Szülő kategória"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Jelszó"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Jelszó helyreállítás"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "A jelszavak nem egyeznek"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Pozíció"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Jelszó helyreállítása"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Frissítés"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "A regisztrációk le vannak zárva ezen a CommaFeed példányon"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Mentés"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Sima görgetés, amikor a bejegyzések között navigál"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Keresés"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "A kereséshez legalább 3 karakter szükséges"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Állítsa a fókuszt a következő bejegyzésre anélkül, hogy megnyitná azt"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Állítsa a fókuszt az előző bejegyzésre anélkül, hogy megnyitná azt"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Beállítások"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Beállítások mentve."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Oszd meg"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Webhelyek megosztása"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Hírcsatornák és kategóriák megjelenítése olvasatlan bejegyzések nélkül"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "A billentyűparancsok súgójának megjelenítése"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Regisztráljon"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Valami rossz történt..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Csillag"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Csillaggal megjelölve"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Feliratkozás"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "Feliratkozási URL"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Feliratkozás a hírfolyamra"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Siker"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Váltás sötét témára"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Váltás világos témára"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Címkék"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "Az előfizetni kívánt hírcsatorna URL-je. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Téma"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Az aktuális bejegyzés olvasási állapotának váltása"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Próbálja ki a CommaFeed-et a demo fiókkal: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Olvasatlan"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Leiratkozás"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Felhasználói név vagy e-mail cím"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Felhasználónév"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Figyelem"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Webhely"
#: 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 "Még nincs előfizetése. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "fájl szükséges"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: id\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Punya akun?</0><1>Masuk!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Butuh akun?</0><1>Daftar!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "kunci API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Tentang"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Tindakan"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Tambahkan"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Tambahkan kategori"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Tambahkan pengguna"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr ""
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Semua"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "Email telah dikirim jika alamat ini terdaftar. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "File opml adalah file XML yang berisi URL dan kategori feed. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analisis umpan"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Anda yakin ingin menghapus kategori <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Apakah Anda yakin ingin menghapus pengguna <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Apakah Anda yakin ingin menghapus akun Anda? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Apakah Anda yakin ingin menandai semua entri <0>{sourceLabel}</0> sebagai telah dibaca?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Apakah Anda yakin ingin menandai entri yang lebih lama dari {threshold} hari <0>{sourceLabel}</0> sebagai telah dibaca?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Yakin ingin berhenti berlangganan <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Variabel yang tersedia adalah 'judul', 'konten', 'url' 'penulis' dan 'kategori' dan kontennya diubah menjadi huruf kecil untuk memudahkan perbandingan string."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Kembali"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Kembali untuk masuk"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Ekstensi peramban"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Batal"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Kategori"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "Mengubah kata sandi akan menghasilkan kunci API baru"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Periksa apakah umpannya berfungsi"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed adalah proyek sumber terbuka. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed item yang belum dibaca berikutnya"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "CommaFeed versi {versi} ({revisi})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Ringkas"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Konfirmasi"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Konfirmasi kata sandi"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Nyaman"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Buat tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Kata sandi saat ini"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Tanggal dibuat"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Hapus"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Hapus Kategori"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Hapus akun"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Hapus pengguna"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Tampilan"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Unduh"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Seret tautan ke bilah bookmark"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "Email"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Alamat email"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Edit pengguna"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Diaktifkan"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Masuk"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Masukkan kata sandi Anda saat ini untuk mengubah pengaturan profil"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Kesalahan"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Contoh: {contoh}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Diperluas"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Ekspor langganan dan kategori Anda sebagai file OPML yang dapat diimpor ke layanan membaca feed lainnya"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL Umpan"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nama umpan"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Memfilter ekspresi"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Lupa kata sandi?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Buat kunci API di profil Anda terlebih dahulu."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Buat kunci API baru"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "Url umpan yang dihasilkan"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Buka dokumentasi API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Pergi ke tampilan Semua"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Pernak-pernik"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Jika tidak kosong, ekspresi mengevaluasi ke 'benar' atau 'salah'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Jika Anda mengalami masalah, harap laporkan di halaman masalah proyek GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Jika Anda menyukai proyek ini, mohon pertimbangkan sumbangan untuk mendukung pengembang dan membantu menutupi biaya menjaga situs web ini tetap online."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Impor"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Dalam tampilan yang diperluas, menggulir entri menandainya sebagai telah dibaca"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Tetap belum dibaca"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Pintasan keyboard"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Bahasa"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Tanggal masuk terakhir"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Penyegaran terakhir"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Pesan penyegaran terakhir"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Tautan"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Memuat profil..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Memuat pengaturan..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Memuat langganan..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Memuat tag..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Masuk"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Keluar"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Kelola pengguna"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Tandai semua sebagai telah dibaca"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Tandai semua entri sebagai telah dibaca"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Tandai sebagai telah dibaca"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Tandai sebagai telah dibaca sampai di sini"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Metrik"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Pindahkan halaman ke bawah"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Pindahkan halaman ke atas"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "T/A"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nama"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navigasikan ke langganan dengan memasukkan namanya"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Kata sandi baru"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Terbaru dulu"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Selanjutnya"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Penyegaran berikutnya"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Bookmarklet item yang belum dibaca berikutnya"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Tidak ada entri lagi"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Tidak ada yang ditemukan"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "ekspor OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "file OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Tertua dulu"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Ups!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Buka entri saat ini di tab baru"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Buka entri saat ini di tab baru di latar belakang"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Buka tautan"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Buka entri berikutnya"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Buka entri sebelumnya"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Buka/tutup entri saat ini"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Pesan"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Orang tua"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Kategori Induk"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "Kata Sandi"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Pemulihan Kata Sandi"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Kata sandi tidak cocok"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Posisi"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profil"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Pulihkan kata sandi"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Segarkan"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Pendaftaran ditutup pada instans CommaFeed ini"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Simpan"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Gulir dengan lancar saat menavigasi antar entri"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Pencarian"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "Pencarian membutuhkan setidaknya 3 karakter"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Tetapkan fokus pada entri berikutnya tanpa membukanya"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Tetapkan fokus pada entri sebelumnya tanpa membukanya"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Pengaturan"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Pengaturan disimpan."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Bagikan"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Berbagi situs"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Pergeseran"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Tampilkan umpan dan kategori tanpa entri yang belum dibaca"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Tampilkan bantuan pintasan keyboard"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Daftar"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "Sesuatu yang buruk baru saja terjadi..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Luar Angkasa"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Bintang"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Berbintang"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Berlangganan"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL Berlangganan"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Berlangganan umpan"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Sukses"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Beralih ke tema gelap"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Beralih ke tema terang"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Tag"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "URL untuk umpan yang ingin Anda langgani. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Beralih status baca entri saat ini"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Cobalah CommaFeed dengan akun demo: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Belum Dibaca"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Hapus bintang"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Berhenti berlangganan"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nama Pengguna atau Email"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nama pengguna"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Peringatan"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Situs Web"
#: 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 "Anda belum memiliki langganan. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "file diperlukan"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: it\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>Hai un account?</0><1>Accedi!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>Hai bisogno di un account?</0><1>Registrati!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "Chiave API"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "Circa"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "Azioni"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "Aggiungi"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "Aggiungi categoria"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "Aggiungi utente"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "Ammin"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "Tutto"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "È stata inviata un'e-mail se questo indirizzo è stato registrato. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "Un file opml è un file XML contenente URL e categorie di feed. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "Analizza feed"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "Sei sicuro di voler eliminare la categoria <0>{categoryName}</0>?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "Sei sicuro di voler eliminare l'utente <0>{userName}</0> ?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "Sei sicuro di voler eliminare il tuo account? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "Sei sicuro di voler contrassegnare tutte le voci di <0>{sourceLabel}</0> come lette?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "Sei sicuro di voler contrassegnare le voci più vecchie di {threshold} giorni di <0>{sourceLabel}</0> come lette?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "Sei sicuro di voler annullare l'iscrizione a <0>{feedName}</0>?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "Le variabili disponibili sono 'titolo', 'contenuto', 'url' 'autore' e 'categorie' e il loro contenuto viene convertito in minuscolo per facilitare il confronto delle stringhe."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "Indietro"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "Torna per accedere"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "Estensioni del browser"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "Annulla"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "Categoria"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "La modifica della password genererà una nuova chiave API"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "Verifica che il feed funzioni"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed è un progetto open source. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "CommaFeed successivo elemento non letto"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "Versione CommaFeed {versione} ({revisione})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "Compatto"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "Conferma"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "Conferma password"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "Accogliente"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "Crea tag: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "ctrl"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "Password attuale"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "Data di creazione"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "Elimina"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "Elimina categoria"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "Elimina account"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "Elimina utente"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "Visualizzazione"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "Scarica"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "Trascina il collegamento sulla barra dei preferiti"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "Indirizzo e-mail"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "Modifica utente"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "Abilitato"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "Invio"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "Inserisci la tua password attuale per modificare le impostazioni del profilo"
#: src/components/Alert.tsx
msgid "Error"
msgstr "Errore"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "Esempio: {esempio}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "Espanso"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "Esporta le tue iscrizioni e categorie come file OPML che può essere importato in altri servizi di lettura feed"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "URL feed"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "Nome del feed"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "Espressione filtrante"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "Password dimenticata?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "Genera prima una chiave API nel tuo profilo."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "Genera nuova chiave API"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "URL feed generato"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "Vai alla documentazione dell'API."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "Vai alla vista Tutto"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "Chicche"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "Se non è vuota, un'espressione valutata come 'vero' o 'falso'. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "Se riscontri un problema, segnalalo nella pagina dei problemi del progetto GitHub."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "Se ti piace questo progetto, prendi in considerazione una donazione per supportare lo sviluppatore e aiutare a coprire i costi per mantenere questo sito online."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "Importa"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "Nella vista espansa, scorrendo le voci contrassegnale come lette"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "Mantieni non letto"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "Scorciatoie da tastiera"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "Lingua"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "Data dell'ultimo accesso"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "Ultimo aggiornamento"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "Ultimo messaggio di aggiornamento"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "Collegamento"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "Caricamento profilo..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "Caricamento impostazioni..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "Caricamento abbonamenti..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "Caricamento tag..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "Accedi"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "Disconnessione"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "Gestisci utenti"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "Contrassegna tutto come letto"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "Contrassegna tutte le voci come lette"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "Contrassegna come letto"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "Contrassegna come letto fino a qui"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "Metriche"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "Sposta la pagina in basso"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "Sposta la pagina in alto"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "Nome"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "Navigare verso un abbonamento inserendo il suo nome"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "Nuova password"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "Il più recente prima"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "Avanti"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "Prossimo aggiornamento"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "Segnalibro successivo elemento non letto"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "Non ci sono più voci"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "Non è stato trovato nulla"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "Esportazione OPML"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "file OPML"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "Il più vecchio prima"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "Ops!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "Apri la voce corrente in una nuova scheda"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "Apri la voce corrente in una nuova scheda in background"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "Apri collegamento"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "Apri voce successiva"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "Apri voce precedente"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "Apri/chiudi voce corrente"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "Ordine"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "Genitore"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "Categoria padre"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "Recupero password"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "Le password non corrispondono"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "Posizione"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "Profilo"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr "API REST"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "Recupera password"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "Aggiorna"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "Le registrazioni sono chiuse su questa istanza CommaFeed"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "Salva"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "Scorrere senza problemi durante la navigazione tra le voci"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "Cerca"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "La ricerca richiede almeno 3 caratteri"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "Imposta il focus sulla voce successiva senza aprirla"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "Imposta il focus sulla voce precedente senza aprirla"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "Impostazioni"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "Impostazioni salvate."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "Condividi"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "Condivisione di siti"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "Cambio"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "Mostra feed e categorie senza voci non lette"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "Mostra la guida alle scorciatoie da tastiera"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "Iscriviti"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "È appena successo qualcosa di brutto..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "Spazio"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "Stella"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "Speciali"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "Iscriviti"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "URL di iscrizione"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "Iscriviti al feed"
#: src/components/Alert.tsx
msgid "Success"
msgstr "Successo"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "Passa al tema scuro"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "Passa al tema della luce"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "Tag"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "L'URL del feed a cui vuoi iscriverti. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "Tema"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "Commuta lo stato di lettura della voce corrente"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "Prova CommaFeed con il conto demo: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "Non letto"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "Elimina le stelle"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "Annulla iscrizione"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "Nome utente o e-mail"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "Nome utente"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "Avviso"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "Sito web"
#: 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 "Non hai ancora abbonamenti. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "è richiesto il file"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ja\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>アカウントをお持ちですか?</0><1>ログインしてください!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>アカウントが必要ですか?</0><1>サインアップ!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "APIキー"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "約"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "アクション"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "追記"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "カテゴリを追加"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "ユーザー追加"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "管理人"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "全員"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "このアドレスが登録されていれば、メールが送信されました。"
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "opml ファイルは、フィードの URL とカテゴリを含む XML ファイルです。"
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "フィードを分析する"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "カテゴリ <0>{categoryName}</0> を削除してもよろしいですか?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "ユーザー <0>{userName}</0> を削除してもよろしいですか?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "本当にアカウントを削除しますか?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "<0>{sourceLabel}</0> のすべてのエントリを既読にしますか?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "<0>{sourceLabel}</0> の {threshold} 日より前のエントリを既読としてマークしてもよろしいですか?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "<0>{feedName}</0> の登録を解除してもよろしいですか?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "昇順"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "使用可能な変数は「title」、「content」、「url」、「author」、および「categories」であり、それらのコンテンツは文字列の比較を容易にするために小文字に変換されます。"
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "裏"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "ログインに戻る"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "ブラウザ拡張機能"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "キャンセル"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "カテゴリー"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "パスワードを変更すると、新しい API キーが生成されます"
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "フィードが動作していることを確認してください"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed はオープンソース プロジェクトです。"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "次の未読アイテムをカンマフィード"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "コンマフィードのバージョン {version} ({revision})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "コンパクト"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "確認"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "パスワード確認"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "コージー"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "タグを作成: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "コントロール"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "現在のパスワード"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "作成日"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "削除"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "カテゴリを削除"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "アカウント削除"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "ユーザーの削除"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "説明"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "ディスプレイ"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "ダウンロード"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "リンクをブックマークバーにドラッグ"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "メール"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "メールアドレス"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "ユーザー編集"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "有効"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "入力"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "プロファイル設定を変更するには、現在のパスワードを入力してください"
#: src/components/Alert.tsx
msgid "Error"
msgstr "エラー"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "例: {例}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "拡張"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "サブスクリプションとカテゴリを、他のフィード読み取りサービスにインポートできる OPML ファイルとしてエクスポートします"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "フィード URL"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "フィード名"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "フィルタリング式"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "パスワードをお忘れですか?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "最初にプロファイルで API キーを生成します。"
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "新しい API キーを生成する"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "生成されたフィード URL"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "API ドキュメントに移動します。"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "すべてのビューに移動"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "グッディーズ"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "ID"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "空でない場合は、'true' または 'false' に評価される式。 "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "問題が発生した場合は、GitHub プロジェクトの問題ページで報告してください。"
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "このプロジェクトが気に入った場合は、開発者をサポートし、この Web サイトをオンラインに維持するための費用を賄うための寄付を検討してください。"
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "インポート"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "展開ビューでエントリをスクロールすると、それらが既読としてマークされます"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "未読のままにする"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "キーボードショートカット"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "言語"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "最終ログイン日"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "最終更新"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "最終更新メッセージ"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "リンク"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "プロファイルを読み込んでいます..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "設定を読み込んでいます..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "サブスクリプションを読み込んでいます..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "タグを読み込んでいます..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "ログイン"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "ログアウト"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "ユーザーの管理"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "すべて既読にする"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "すべてのエントリを既読にする"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "既読にする"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "ここまで既読にする"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "メトリクス"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "ページを下に移動"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "ページを上に移動"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "該当なし"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "名前"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "名前を入力してサブスクリプションに移動します"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "新しいパスワード"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "最新順"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "次へ"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "次の更新"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "次の未読アイテムのブックマークレット"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "これ以上エントリはありません"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "何も見つかりませんでした"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML エクスポート"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPMLファイル"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "古い順"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "おっと!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "現在のエントリを新しいタブで開く"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "現在のエントリをバックグラウンドで新しいタブで開く"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "リンクを開く"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "次のエントリを開く"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "前のエントリを開く"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "現在のエントリを開く/閉じる"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "オーダー"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "親"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "親カテゴリ"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "パスワード"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "パスワード回復"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "パスワードが一致しません"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "位置"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "プロフィール"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "パスワードの回復"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "リフレッシュ"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "この CommaFeed インスタンスの登録は終了しています"
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "保存"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "エントリ間を移動するときにスムーズにスクロールする"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "検索"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "検索には少なくとも 3 文字が必要です"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "次のエントリを開かずにフォーカスを設定する"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "前のエントリを開かずにフォーカスを設定する"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "設定"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "設定が保存されました。"
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "シェア"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "共有サイト"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "シフト"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "未読エントリのないフィードとカテゴリを表示する"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "キーボード ショートカットのヘルプを表示"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "サインアップ"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "何か悪いことが起こった..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "スペース"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "スター"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "スター付き"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "購読する"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "購読URL"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "フィードを購読する"
#: src/components/Alert.tsx
msgid "Success"
msgstr "成功"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "ダークテーマに切り替え"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "ライトテーマに切り替え"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "タグ"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "購読したいフィードのURL。 "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "テーマ"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "現在のエントリの読み取りステータスを切り替えます"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "デモアカウントで CommaFeed を試す: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "未読"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "スターを外す"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "退会"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "ユーザー名またはメールアドレス"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "ユーザー名"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "警告"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "ウェブサイト"
#: 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 "まだサブスクリプションがありません。"
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "ファイルが必要です"

View File

@@ -0,0 +1,801 @@
msgid ""
msgstr ""
"POT-Creation-Date: 2022-10-28 13:47+0200\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: @lingui/cli\n"
"Language: ko\n"
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Plural-Forms: \n"
#: src/pages/app/FeedDetailsPage.tsx
msgid "<0>Complete syntax is available </0><1>here</1>."
msgstr ""
#: src/pages/auth/RegistrationPage.tsx
msgid "<0>Have an account?</0><1>Log in!</1>"
msgstr "<0>계정이 있습니까?</0><1>로그인하세요!</1>"
#: src/pages/auth/LoginPage.tsx
msgid "<0>Need an account?</0><1>Sign up!</1>"
msgstr "<0>계정이 필요하십니까?</0><1>가입하세요!</1>"
#: src/components/settings/ProfileSettings.tsx
msgid "API key"
msgstr "API 키"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/AboutPage.tsx
msgid "About"
msgstr "정보"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Actions"
msgstr "액션"
#: src/components/content/add/AddCategory.tsx
msgid "Add"
msgstr "추가"
#: src/pages/app/AddPage.tsx
msgid "Add category"
msgstr "카테고리 추가"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Add user"
msgstr "사용자 추가"
#: src/components/admin/UserEdit.tsx
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Admin"
msgstr "관리자"
#: src/app/constants.ts
#: src/components/content/add/CategorySelect.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/Tree.tsx
msgid "All"
msgstr "전체"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "An email has been sent if this address was registered. Check your inbox."
msgstr "이 주소가 등록된 경우 이메일이 전송되었습니다. "
#: src/components/content/add/ImportOpml.tsx
msgid "An opml file is an XML file containing feed URLs and categories. You can get an OPML file by exporting your data from other feed reading services."
msgstr "opml 파일은 피드 URL과 카테고리를 포함하는 XML 파일입니다. "
#: src/components/content/add/Subscribe.tsx
msgid "Analyze feed"
msgstr "피드 분석"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Are you sure you want to delete category <0>{categoryName}</0>?"
msgstr "<0>{categoryName}</0> 카테고리를 삭제하시겠습니까?"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Are you sure you want to delete user <0>{userName}</0> ?"
msgstr "<0>{userName}</0> 사용자를 삭제하시겠습니까?"
#: src/components/settings/ProfileSettings.tsx
msgid "Are you sure you want to delete your account? There's no turning back!"
msgstr "정말 계정을 삭제하시겠습니까? "
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark all entries of <0>{sourceLabel}</0> as read?"
msgstr "<0>{sourceLabel}</0>의 모든 항목을 읽은 것으로 표시하시겠습니까?"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Are you sure you want to mark entries older than {threshold} days of <0>{sourceLabel}</0> as read?"
msgstr "<0>{sourceLabel}</0>의 {threshold}일보다 오래된 항목을 읽은 것으로 표시하시겠습니까?"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Are you sure you want to unsubscribe from <0>{feedName}</0>?"
msgstr "<0>{feedName}</0> 구독을 취소하시겠습니까?"
#: src/components/header/Header.tsx
msgid "Asc"
msgstr "오름차순"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Available variables are 'title', 'content', 'url' 'author' and 'categories' and their content is converted to lower case to ease string comparison."
msgstr "사용 가능한 변수는 'title', 'content', 'url' 'author' 및 'categories'이며 해당 내용은 문자열 비교를 쉽게 하기 위해 소문자로 변환됩니다."
#: src/components/content/add/Subscribe.tsx
msgid "Back"
msgstr "뒤로"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Back to log in"
msgstr "로그인으로 돌아가기"
#: src/pages/app/AboutPage.tsx
msgid "Browser extentions"
msgstr "브라우저 확장"
#: src/components/admin/UserEdit.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/ImportOpml.tsx
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Cancel"
msgstr "취소"
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/AddCategory.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AboutPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Category"
msgstr "카테고리"
#: src/components/settings/ProfileSettings.tsx
msgid "Changing password will generate a new API key"
msgstr "비밀번호를 변경하면 새 API 키가 생성됩니다."
#: src/components/content/add/Subscribe.tsx
msgid "Check that the feed is working"
msgstr "피드가 작동하는지 확인"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed is an open-source project. Sources are hosted on <0>GitHub</0>."
msgstr "CommaFeed는 오픈 소스 프로젝트입니다. "
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed next unread item"
msgstr "다음 읽지 않은 항목을 쉼표로 피드"
#: src/pages/app/AboutPage.tsx
msgid "CommaFeed version {version} ({revision})"
msgstr "쉼표 피드 버전 {버전}({개정})"
#: src/components/header/ProfileMenu.tsx
msgid "Compact"
msgstr "컴팩트"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Confirm"
msgstr "확인"
#: src/components/settings/ProfileSettings.tsx
msgid "Confirm password"
msgstr "비밀번호 확인"
#: src/components/header/ProfileMenu.tsx
msgid "Cozy"
msgstr "코지"
#: src/components/content/FeedEntryFooter.tsx
msgid "Create tag: {query}"
msgstr "태그 생성: {query}"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Ctrl"
msgstr "컨트롤"
#: src/components/settings/ProfileSettings.tsx
msgid "Current password"
msgstr "현재 비밀번호"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Date created"
msgstr "생성 날짜"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete"
msgstr "삭제"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Delete Category"
msgstr "카테고리 삭제"
#: src/components/settings/ProfileSettings.tsx
#: src/components/settings/ProfileSettings.tsx
msgid "Delete account"
msgstr "계정 삭제"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Delete user"
msgstr "사용자 삭제"
#: src/components/header/Header.tsx
msgid "Desc"
msgstr "설명"
#: src/components/header/ProfileMenu.tsx
#: src/pages/app/SettingsPage.tsx
msgid "Display"
msgstr "디스플레이"
#: src/components/settings/ProfileSettings.tsx
msgid "Download"
msgstr "다운로드"
#: src/pages/app/AboutPage.tsx
msgid "Drag link to bookmark bar"
msgstr "링크를 북마크바로 드래그"
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "E-mail"
msgstr "이메일"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "E-mail address"
msgstr "이메일 주소"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Edit user"
msgstr "사용자 편집"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Enabled"
msgstr "활성화"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Enter"
msgstr "입력"
#: src/components/settings/ProfileSettings.tsx
msgid "Enter your current password to change profile settings"
msgstr "프로필 설정을 변경하려면 현재 비밀번호를 입력하세요."
#: src/components/Alert.tsx
msgid "Error"
msgstr "오류"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Example: {example}."
msgstr "예: {예}."
#: src/components/header/ProfileMenu.tsx
msgid "Expanded"
msgstr "확장"
#: src/components/settings/ProfileSettings.tsx
msgid "Export your subscriptions and categories as an OPML file that can be imported in other feed reading services"
msgstr "구독 및 카테고리를 다른 피드 읽기 서비스에서 가져올 수 있는 OPML 파일로 내보내기"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Feed URL"
msgstr "피드 URL"
#: src/components/content/add/Subscribe.tsx
msgid "Feed name"
msgstr "피드 이름"
#: src/components/header/RefreshMenu.tsx
msgid "Fetch all my feeds now"
msgstr ""
#: src/pages/app/FeedDetailsPage.tsx
msgid "Filtering expression"
msgstr "필터링 표현식"
#: src/pages/auth/LoginPage.tsx
msgid "Forgot password?"
msgstr "비밀번호를 잊으셨나요?"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generate an API key in your profile first."
msgstr "먼저 프로필에서 API 키를 생성하십시오."
#: src/components/settings/ProfileSettings.tsx
msgid "Generate new API key"
msgstr "새 API 키 생성"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Generated feed url"
msgstr "생성된 피드 URL"
#: src/pages/app/AboutPage.tsx
msgid "Go to the API documentation."
msgstr "API 문서로 이동합니다."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Go to the All view"
msgstr "전체 보기로 이동"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Go to {0}"
msgstr ""
#: src/pages/app/AboutPage.tsx
msgid "Goodies"
msgstr "굿즈"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Id"
msgstr "아이디"
#: src/pages/app/FeedDetailsPage.tsx
msgid "If not empty, an expression evaluating to 'true' or 'false'. If false, new entries for this feed will be marked as read automatically."
msgstr "비어 있지 않은 경우 'true' 또는 'false'로 평가되는 표현식입니다. "
#: src/pages/app/AboutPage.tsx
msgid "If you encounter an issue, please report it on the issues page of the GitHub project."
msgstr "문제가 발생하면 GitHub 프로젝트의 문제 페이지에서 보고하세요."
#: src/pages/app/AboutPage.tsx
msgid "If you like this project, please consider a donation to support the developer and help cover the costs of keeping this website online."
msgstr "이 프로젝트가 마음에 들면 개발자를 지원하고 이 웹사이트를 온라인 상태로 유지하는 데 드는 비용을 충당하기 위한 기부를 고려하십시오."
#: src/components/content/add/ImportOpml.tsx
msgid "Import"
msgstr "가져오기"
#: src/components/settings/DisplaySettings.tsx
msgid "In expanded view, scrolling through entries mark them as read"
msgstr "확장 보기에서 항목을 스크롤하면 읽은 것으로 표시됩니다."
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Keep unread"
msgstr "읽지 않은 상태로 유지"
#: src/components/content/FeedEntries.tsx
#: src/pages/app/AboutPage.tsx
msgid "Keyboard shortcuts"
msgstr "키보드 단축키"
#: src/components/settings/DisplaySettings.tsx
msgid "Language"
msgstr "언어"
#: src/pages/admin/AdminUsersPage.tsx
msgid "Last login date"
msgstr "마지막 로그인 날짜"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh"
msgstr "마지막 새로 고침"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Last refresh message"
msgstr "마지막 새로고침 메시지"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/TagDetailsPage.tsx
msgid "Link"
msgstr "링크"
#: src/hooks/useAppLoading.ts
msgid "Loading profile..."
msgstr "프로필 로드 중..."
#: src/hooks/useAppLoading.ts
msgid "Loading settings..."
msgstr "설정 로드 중..."
#: src/hooks/useAppLoading.ts
msgid "Loading subscriptions..."
msgstr "구독 로드 중..."
#: src/hooks/useAppLoading.ts
msgid "Loading tags..."
msgstr "태그 로드 중..."
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "Log in"
msgstr "로그인"
#: src/components/header/ProfileMenu.tsx
msgid "Logout"
msgstr "로그아웃"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Long press"
msgstr ""
#: src/components/header/ProfileMenu.tsx
#: src/pages/admin/AdminUsersPage.tsx
msgid "Manage users"
msgstr "사용자 관리"
#: src/components/header/MarkAllAsReadButton.tsx
msgid "Mark all as read"
msgstr "모두 읽은 상태로 표시"
#: src/components/header/MarkAllAsReadButton.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Mark all entries as read"
msgstr "모든 항목을 읽은 상태로 표시"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read"
msgstr "읽은 상태로 표시"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Mark as read up to here"
msgstr "여기까지 읽은 것으로 표시"
#: src/components/header/ProfileMenu.tsx
msgid "Metrics"
msgstr "메트릭스"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Middle click"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page down"
msgstr "페이지를 아래로 이동"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Move the page up"
msgstr "페이지를 위로 이동"
#: src/components/RelativeDate.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "N/A"
msgstr "해당 없음"
#: src/components/admin/UserEdit.tsx
#: src/pages/admin/AdminUsersPage.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Name"
msgstr "이름"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Navigate to a subscription by entering its name"
msgstr "이름을 입력하여 구독으로 이동"
#: src/components/settings/ProfileSettings.tsx
msgid "New password"
msgstr "새 비밀번호"
#: src/pages/app/AboutPage.tsx
msgid "Newest first"
msgstr "최신순"
#: src/components/content/add/Subscribe.tsx
msgid "Next"
msgstr "다음"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Next refresh"
msgstr "다음 새로고침"
#: src/pages/app/AboutPage.tsx
msgid "Next unread item bookmarklet"
msgstr "읽지 않은 다음 항목 북마크"
#: src/pages/app/FeedEntriesPage.tsx
msgid "No more entries"
msgstr "더 이상 항목이 없습니다"
#: src/components/sidebar/TreeSearch.tsx
msgid "Nothing found"
msgstr "아무것도 찾을 수 없습니다"
#: src/pages/app/AddPage.tsx
msgid "OPML"
msgstr ""
#: src/components/settings/ProfileSettings.tsx
msgid "OPML export"
msgstr "OPML 내보내기"
#: src/components/content/add/ImportOpml.tsx
#: src/components/content/add/ImportOpml.tsx
msgid "OPML file"
msgstr "OPML 파일"
#: src/pages/app/AboutPage.tsx
msgid "Oldest first"
msgstr "가장 오래된 것부터"
#: src/pages/ErrorPage.tsx
msgid "Oops!"
msgstr "앗!"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab"
msgstr "새 탭에서 현재 항목 열기"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open current entry in a new tab in the background"
msgstr "배경의 새 탭에서 현재 항목 열기"
#: src/components/content/FeedEntryFooter.tsx
msgid "Open link"
msgstr "링크 열기"
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new background tab"
msgstr ""
#: src/components/content/FeedEntryContextMenu.tsx
msgid "Open link in new tab"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open next entry"
msgstr "다음 항목 열기"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open previous entry"
msgstr "이전 항목 열기"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Open/close current entry"
msgstr "현재 항목 열기/닫기"
#: src/pages/app/AboutPage.tsx
msgid "Order"
msgstr "주문"
#: src/components/content/add/AddCategory.tsx
msgid "Parent"
msgstr "부모"
#: src/pages/app/CategoryDetailsPage.tsx
msgid "Parent Category"
msgstr "부모 카테고리"
#: src/components/admin/UserEdit.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Password"
msgstr "비밀번호"
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Password Recovery"
msgstr "비밀번호 복구"
#: src/components/settings/ProfileSettings.tsx
msgid "Passwords do not match"
msgstr "비밀번호가 일치하지 않습니다"
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Position"
msgstr "위치"
#: src/pages/app/SettingsPage.tsx
msgid "Profile"
msgstr "프로필"
#: src/pages/app/AboutPage.tsx
msgid "REST API"
msgstr ""
#: src/pages/auth/PasswordRecoveryPage.tsx
msgid "Recover password"
msgstr "비밀번호 복구"
#: src/components/header/Header.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Refresh"
msgstr "새로 고침"
#: src/pages/auth/RegistrationPage.tsx
msgid "Registrations are closed on this CommaFeed instance"
msgstr "이 CommaFeed 인스턴스에 대한 등록이 마감되었습니다."
#: src/components/header/RefreshMenu.tsx
msgid "Reload"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Right click"
msgstr ""
#: src/components/admin/UserEdit.tsx
#: src/components/settings/ProfileSettings.tsx
#: src/pages/app/CategoryDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Save"
msgstr "저장"
#: src/components/settings/DisplaySettings.tsx
msgid "Scroll smoothly when navigating between entries"
msgstr "항목 간 탐색 시 부드럽게 스크롤"
#: src/components/header/Header.tsx
#: src/components/header/Header.tsx
#: src/components/sidebar/TreeSearch.tsx
#: src/components/sidebar/TreeSearch.tsx
msgid "Search"
msgstr "검색"
#: src/components/header/Header.tsx
msgid "Search requires at least 3 characters"
msgstr "검색에 최소 3자가 필요합니다."
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on next entry without opening it"
msgstr "열지 않고 다음 항목에 포커스 설정"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Set focus on previous entry without opening it"
msgstr "이전 항목을 열지 않고 포커스 설정"
#: src/components/header/ProfileMenu.tsx
msgid "Settings"
msgstr "설정"
#: src/app/slices/user.ts
msgid "Settings saved."
msgstr "설정이 저장되었습니다."
#: src/components/content/FeedEntryFooter.tsx
msgid "Share"
msgstr "공유"
#: src/components/settings/DisplaySettings.tsx
msgid "Sharing sites"
msgstr "사이트 공유"
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Shift"
msgstr "시프트"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (desktop)"
msgstr ""
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show entry menu (mobile)"
msgstr ""
#: src/components/settings/DisplaySettings.tsx
msgid "Show feeds and categories with no unread entries"
msgstr "읽지 않은 항목이 없는 피드 및 카테고리 표시"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Show keyboard shortcut help"
msgstr "키보드 단축키 도움말 표시"
#: src/pages/auth/RegistrationPage.tsx
#: src/pages/auth/RegistrationPage.tsx
msgid "Sign up"
msgstr "가입"
#: src/pages/ErrorPage.tsx
msgid "Something bad just happened..."
msgstr "뭔가 안 좋은 일이 일어났어..."
#: src/components/KeyboardShortcutsHelp.tsx
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Space"
msgstr "우주"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Star"
msgstr "스타"
#: src/app/constants.ts
#: src/components/sidebar/Tree.tsx
msgid "Starred"
msgstr "별표"
#: src/components/content/add/Subscribe.tsx
#: src/components/content/add/Subscribe.tsx
#: src/pages/app/AddPage.tsx
msgid "Subscribe"
msgstr "구독"
#: src/pages/app/AboutPage.tsx
msgid "Subscribe URL"
msgstr "구독 URL"
#: src/components/content/add/Subscribe.tsx
msgid "Subscribe to the feed"
msgstr "피드 구독"
#: src/components/Alert.tsx
msgid "Success"
msgstr "성공"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Swipe header to the right"
msgstr ""
#: src/components/header/ProfileMenu.tsx
msgid "Switch to dark theme"
msgstr "어두운 테마로 전환"
#: src/components/header/ProfileMenu.tsx
msgid "Switch to light theme"
msgstr "밝은 테마로 전환"
#: src/components/content/FeedEntryFooter.tsx
msgid "Tags"
msgstr "태그"
#: src/components/content/add/Subscribe.tsx
msgid "The URL for the feed you want to subscribe to. You can also use the website's url directly and CommaFeed will try to find the feed in the page."
msgstr "구독하려는 피드의 URL입니다. "
#: src/components/header/ProfileMenu.tsx
msgid "Theme"
msgstr "테마"
#: src/components/KeyboardShortcutsHelp.tsx
msgid "Toggle read status of current entry"
msgstr "현재 항목의 읽기 상태 전환"
#: src/pages/auth/LoginPage.tsx
msgid "Try out CommaFeed with the demo account: demo/demo"
msgstr "데모 계정으로 CommaFeed를 사용해 보세요: demo/demo"
#: src/components/header/Header.tsx
msgid "Unread"
msgstr "읽지 않음"
#: src/components/content/FeedEntryContextMenu.tsx
#: src/components/content/FeedEntryFooter.tsx
msgid "Unstar"
msgstr "별표 제거"
#: src/pages/app/FeedDetailsPage.tsx
#: src/pages/app/FeedDetailsPage.tsx
msgid "Unsubscribe"
msgstr "구독 취소"
#: src/pages/auth/LoginPage.tsx
#: src/pages/auth/LoginPage.tsx
msgid "User Name or E-mail"
msgstr "사용자 이름 또는 이메일"
#: src/components/settings/ProfileSettings.tsx
msgid "User name"
msgstr "사용자 이름"
#: src/components/Alert.tsx
msgid "Warning"
msgstr "경고"
#: src/pages/app/FeedDetailsPage.tsx
msgid "Website"
msgstr "웹사이트"
#: 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 "아직 구독이 없습니다. "
#: src/components/header/RefreshMenu.tsx
msgid "Your feeds have been queued for refresh."
msgstr ""
#: src/components/content/add/ImportOpml.tsx
msgid "file is required"
msgstr "파일이 필요합니다"

Some files were not shown because too many files have changed in this diff Show More