@rmdes/indiekit-endpoint-microsub 1.0.28 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -0
- package/index.js +9 -0
- package/locales/de.json +104 -0
- package/locales/es-419.json +104 -0
- package/locales/es.json +104 -0
- package/locales/fr.json +104 -0
- package/locales/hi.json +104 -0
- package/locales/id.json +104 -0
- package/locales/it.json +104 -0
- package/locales/nl.json +104 -0
- package/locales/pl.json +104 -0
- package/locales/pt-BR.json +104 -0
- package/locales/pt.json +104 -0
- package/locales/sr.json +104 -0
- package/locales/sv.json +104 -0
- package/locales/zh-Hans-CN.json +104 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# @rmdes/indiekit-endpoint-microsub
|
|
2
|
+
|
|
3
|
+
A comprehensive Microsub social reader plugin for Indiekit. Subscribe to feeds (RSS, Atom, JSON Feed, h-feed), organize them into channels, and read posts in a unified timeline interface with a built-in web reader UI.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Microsub Protocol**: Full implementation of the [Microsub spec](https://indieweb.org/Microsub)
|
|
8
|
+
- **Multi-Format Feeds**: RSS, Atom, JSON Feed, h-feed (microformats)
|
|
9
|
+
- **Smart Polling**: Adaptive tiered polling (2 minutes to 17+ hours) based on update frequency
|
|
10
|
+
- **Real-Time Updates**: WebSub (PubSubHubbub) support for instant notifications
|
|
11
|
+
- **Web Reader UI**: Built-in reader interface with channel navigation and timeline view
|
|
12
|
+
- **Feed Discovery**: Automatic discovery of feeds from website URLs
|
|
13
|
+
- **Read State**: Per-user read tracking with automatic cleanup
|
|
14
|
+
- **Compose Interface**: Post replies, likes, reposts, and bookmarks via Micropub
|
|
15
|
+
- **Webmention Support**: Receive webmentions in your notifications channel
|
|
16
|
+
- **Media Proxy**: Privacy-friendly image proxying
|
|
17
|
+
- **OPML Export**: Export your subscriptions as OPML
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @rmdes/indiekit-endpoint-microsub
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
Add to your Indiekit config:
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
import MicrosubEndpoint from "@rmdes/indiekit-endpoint-microsub";
|
|
31
|
+
|
|
32
|
+
export default {
|
|
33
|
+
plugins: [
|
|
34
|
+
new MicrosubEndpoint({
|
|
35
|
+
mountPath: "/microsub", // Default mount path
|
|
36
|
+
}),
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
### Web Reader UI
|
|
44
|
+
|
|
45
|
+
Navigate to `/microsub/reader` in your Indiekit installation to access the web interface.
|
|
46
|
+
|
|
47
|
+
**Channels**: Organize feeds into channels (Technology, News, Friends, etc.)
|
|
48
|
+
- Create new channels
|
|
49
|
+
- Configure content filters (exclude types, regex patterns)
|
|
50
|
+
- Reorder channels
|
|
51
|
+
|
|
52
|
+
**Feeds**: Manage subscriptions within each channel
|
|
53
|
+
- Subscribe to feeds by URL
|
|
54
|
+
- Search and discover feeds from websites
|
|
55
|
+
- Edit or rediscover feed URLs
|
|
56
|
+
- Force refresh feeds
|
|
57
|
+
- View feed health status
|
|
58
|
+
|
|
59
|
+
**Timeline**: Read posts from subscribed feeds
|
|
60
|
+
- Paginated timeline view
|
|
61
|
+
- Mark individual items or all items as read
|
|
62
|
+
- View read items separately
|
|
63
|
+
- Click through to original posts
|
|
64
|
+
|
|
65
|
+
**Compose**: Create posts via Micropub
|
|
66
|
+
- Reply to posts
|
|
67
|
+
- Like posts
|
|
68
|
+
- Repost posts
|
|
69
|
+
- Bookmark posts
|
|
70
|
+
- Include syndication targets
|
|
71
|
+
|
|
72
|
+
### Microsub API
|
|
73
|
+
|
|
74
|
+
Compatible with Microsub clients like [Indigenous](https://indigenous.realize.be/) and [Monocle](https://monocle.p3k.io/).
|
|
75
|
+
|
|
76
|
+
**Endpoint:** Your Indiekit URL + `/microsub`
|
|
77
|
+
|
|
78
|
+
**Supported Actions:**
|
|
79
|
+
- `channels` - List, create, update, delete, reorder channels
|
|
80
|
+
- `timeline` - Get timeline items (paginated)
|
|
81
|
+
- `follow` - Subscribe to a feed
|
|
82
|
+
- `unfollow` - Unsubscribe from a feed
|
|
83
|
+
- `mute` - Mute URLs
|
|
84
|
+
- `unmute` - Unmute URLs
|
|
85
|
+
- `block` - Block authors
|
|
86
|
+
- `unblock` - Unblock authors
|
|
87
|
+
- `search` - Discover feeds from URL
|
|
88
|
+
- `preview` - Preview feed before subscribing
|
|
89
|
+
|
|
90
|
+
**Example:**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# List channels
|
|
94
|
+
curl "https://your-site.example/microsub?action=channels" \
|
|
95
|
+
-H "Authorization: Bearer YOUR_TOKEN"
|
|
96
|
+
|
|
97
|
+
# Get timeline for channel
|
|
98
|
+
curl "https://your-site.example/microsub?action=timeline&channel=CHANNEL_UID" \
|
|
99
|
+
-H "Authorization: Bearer YOUR_TOKEN"
|
|
100
|
+
|
|
101
|
+
# Subscribe to feed
|
|
102
|
+
curl "https://your-site.example/microsub" \
|
|
103
|
+
-X POST \
|
|
104
|
+
-H "Authorization: Bearer YOUR_TOKEN" \
|
|
105
|
+
-d "action=follow&channel=CHANNEL_UID&url=https://example.com/feed"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Feed Polling
|
|
109
|
+
|
|
110
|
+
Feeds are polled using an adaptive tiered system:
|
|
111
|
+
|
|
112
|
+
- **Tier 0**: 1 minute (very active feeds)
|
|
113
|
+
- **Tier 1**: 2 minutes (active feeds)
|
|
114
|
+
- **Tier 2**: 4 minutes
|
|
115
|
+
- **Tier 3**: 8 minutes
|
|
116
|
+
- ...
|
|
117
|
+
- **Tier 10**: ~17 hours (inactive feeds)
|
|
118
|
+
|
|
119
|
+
Tiers adjust automatically:
|
|
120
|
+
- Feed updates → decrease tier (faster polling)
|
|
121
|
+
- No changes for 2+ fetches → increase tier (slower polling)
|
|
122
|
+
|
|
123
|
+
WebSub-enabled feeds receive instant updates when available.
|
|
124
|
+
|
|
125
|
+
## Read State Management
|
|
126
|
+
|
|
127
|
+
Read items are tracked per user. To prevent database bloat, only the last 30 read items per channel are kept. Unread items are never deleted.
|
|
128
|
+
|
|
129
|
+
Cleanup runs automatically:
|
|
130
|
+
- On server startup
|
|
131
|
+
- After marking items read
|
|
132
|
+
|
|
133
|
+
## Integration with Other Plugins
|
|
134
|
+
|
|
135
|
+
### Blogroll Plugin
|
|
136
|
+
|
|
137
|
+
If `@rmdes/indiekit-endpoint-blogroll` is installed, Microsub will automatically sync feed subscriptions:
|
|
138
|
+
- Subscribe to feed → adds to blogroll
|
|
139
|
+
- Unsubscribe → soft-deletes from blogroll
|
|
140
|
+
|
|
141
|
+
### Micropub Plugin
|
|
142
|
+
|
|
143
|
+
The compose interface posts via Micropub. Ensure `@indiekit/endpoint-micropub` is configured.
|
|
144
|
+
|
|
145
|
+
## OPML Export
|
|
146
|
+
|
|
147
|
+
Export your subscriptions:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
GET /microsub/reader/opml
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Returns OPML XML with all subscribed feeds organized by channel.
|
|
154
|
+
|
|
155
|
+
## Webmentions
|
|
156
|
+
|
|
157
|
+
The plugin accepts webmentions at `/microsub/webmention`. Received webmentions appear in the special "Notifications" channel.
|
|
158
|
+
|
|
159
|
+
To advertise your webmention endpoint, add to your site's `<head>`:
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<link rel="webmention" href="https://your-site.example/microsub/webmention" />
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Media Proxy
|
|
166
|
+
|
|
167
|
+
External images are proxied through `/microsub/media/:hash` for privacy and caching. This prevents your IP address from being sent to third-party image hosts.
|
|
168
|
+
|
|
169
|
+
## API Response Format
|
|
170
|
+
|
|
171
|
+
All API responses follow the Microsub spec. Timeline items use the [jf2 format](https://jf2.spec.indieweb.org/).
|
|
172
|
+
|
|
173
|
+
**Example timeline response:**
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"items": [
|
|
178
|
+
{
|
|
179
|
+
"type": "entry",
|
|
180
|
+
"uid": "https://example.com/post/123",
|
|
181
|
+
"url": "https://example.com/post/123",
|
|
182
|
+
"published": "2026-02-13T12:00:00.000Z",
|
|
183
|
+
"name": "Post Title",
|
|
184
|
+
"content": {
|
|
185
|
+
"text": "Plain text content",
|
|
186
|
+
"html": "<p>HTML content</p>"
|
|
187
|
+
},
|
|
188
|
+
"author": {
|
|
189
|
+
"name": "Author Name",
|
|
190
|
+
"url": "https://author.example/",
|
|
191
|
+
"photo": "https://author.example/photo.jpg"
|
|
192
|
+
},
|
|
193
|
+
"_id": "507f1f77bcf86cd799439011",
|
|
194
|
+
"_is_read": false
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"paging": {
|
|
198
|
+
"after": "cursor-string"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Database Collections
|
|
204
|
+
|
|
205
|
+
The plugin creates these MongoDB collections:
|
|
206
|
+
|
|
207
|
+
- `microsub_channels` - User channels
|
|
208
|
+
- `microsub_feeds` - Feed subscriptions with polling metadata
|
|
209
|
+
- `microsub_items` - Timeline items (posts)
|
|
210
|
+
- `microsub_notifications` - Notifications channel items
|
|
211
|
+
- `microsub_muted` - Muted URLs
|
|
212
|
+
- `microsub_blocked` - Blocked authors
|
|
213
|
+
|
|
214
|
+
## Troubleshooting
|
|
215
|
+
|
|
216
|
+
### Feeds not updating
|
|
217
|
+
|
|
218
|
+
- Check the feed's `nextFetchAt` time in the admin UI
|
|
219
|
+
- Use "Force Refresh" button to poll immediately
|
|
220
|
+
- Try "Rediscover" to find the correct feed URL
|
|
221
|
+
|
|
222
|
+
### "Unable to detect feed type" error
|
|
223
|
+
|
|
224
|
+
- The URL may not be a valid feed
|
|
225
|
+
- Try using the search feature to discover feeds from the homepage
|
|
226
|
+
- Check if the feed requires authentication
|
|
227
|
+
|
|
228
|
+
### Items disappearing after marking read
|
|
229
|
+
|
|
230
|
+
This is normal behavior - only the last 30 read items per channel are kept to prevent database bloat. Unread items are never deleted.
|
|
231
|
+
|
|
232
|
+
### Duplicate items
|
|
233
|
+
|
|
234
|
+
Deduplication is based on the feed's GUID/URL. If a feed doesn't provide stable GUIDs, duplicates may appear.
|
|
235
|
+
|
|
236
|
+
## Contributing
|
|
237
|
+
|
|
238
|
+
Issues and pull requests welcome at [github.com/rmdes/indiekit-endpoint-microsub](https://github.com/rmdes/indiekit-endpoint-microsub)
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT
|
|
243
|
+
|
|
244
|
+
## Credits
|
|
245
|
+
|
|
246
|
+
Built by [Ricardo Mendes](https://rmendes.net) for the IndieWeb community.
|
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
2
3
|
|
|
3
4
|
import express from "express";
|
|
4
5
|
|
|
@@ -29,6 +30,14 @@ export default class MicrosubEndpoint {
|
|
|
29
30
|
this.mountPath = this.options.mountPath;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Locales directory path
|
|
35
|
+
* @returns {string} Path to locales directory
|
|
36
|
+
*/
|
|
37
|
+
get localesDirectory() {
|
|
38
|
+
return path.join(path.dirname(fileURLToPath(import.meta.url)), "locales");
|
|
39
|
+
}
|
|
40
|
+
|
|
32
41
|
/**
|
|
33
42
|
* Navigation items for Indiekit admin
|
|
34
43
|
* @returns {object} Navigation item configuration
|
package/locales/de.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"microsub": {
|
|
3
|
+
"reader": {
|
|
4
|
+
"title": "Leser",
|
|
5
|
+
"empty": "Keine Elemente zum Anzeigen",
|
|
6
|
+
"markAllRead": "Alle als gelesen markieren",
|
|
7
|
+
"showRead": "Gelesene anzeigen ({{count}})",
|
|
8
|
+
"hideRead": "Gelesene Elemente ausblenden",
|
|
9
|
+
"allRead": "Alles aufgeholt!",
|
|
10
|
+
"newer": "Neuer",
|
|
11
|
+
"older": "Älter"
|
|
12
|
+
},
|
|
13
|
+
"channels": {
|
|
14
|
+
"title": "Kanäle",
|
|
15
|
+
"name": "Kanalname",
|
|
16
|
+
"new": "Neuer Kanal",
|
|
17
|
+
"create": "Kanal erstellen",
|
|
18
|
+
"delete": "Kanal löschen",
|
|
19
|
+
"settings": "Kanaleinstellungen",
|
|
20
|
+
"empty": "Noch keine Kanäle. Erstellen Sie einen, um zu beginnen.",
|
|
21
|
+
"notifications": "Benachrichtigungen"
|
|
22
|
+
},
|
|
23
|
+
"timeline": {
|
|
24
|
+
"title": "Zeitleiste",
|
|
25
|
+
"empty": "Keine Elemente in diesem Kanal",
|
|
26
|
+
"markRead": "Als gelesen markieren",
|
|
27
|
+
"markUnread": "Als ungelesen markieren",
|
|
28
|
+
"remove": "Entfernen"
|
|
29
|
+
},
|
|
30
|
+
"feeds": {
|
|
31
|
+
"title": "Feeds",
|
|
32
|
+
"follow": "Folgen",
|
|
33
|
+
"subscribe": "Einen Feed abonnieren",
|
|
34
|
+
"unfollow": "Entfolgen",
|
|
35
|
+
"empty": "Keine Feeds in diesem Kanal abonniert",
|
|
36
|
+
"url": "Feed-URL",
|
|
37
|
+
"urlPlaceholder": "https://beispiel.de/feed.xml",
|
|
38
|
+
"edit": "Feed bearbeiten",
|
|
39
|
+
"rediscover": "Feed neu entdecken",
|
|
40
|
+
"refresh": "Jetzt aktualisieren",
|
|
41
|
+
"status": {
|
|
42
|
+
"active": "Aktiv",
|
|
43
|
+
"error": "Fehler",
|
|
44
|
+
"stale": "Veraltet"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"item": {
|
|
48
|
+
"reply": "Antworten",
|
|
49
|
+
"like": "Gefällt mir",
|
|
50
|
+
"repost": "Teilen",
|
|
51
|
+
"bookmark": "Lesezeichen",
|
|
52
|
+
"viewOriginal": "Original anzeigen"
|
|
53
|
+
},
|
|
54
|
+
"compose": {
|
|
55
|
+
"title": "Verfassen",
|
|
56
|
+
"content": "Was beschäftigt Sie?",
|
|
57
|
+
"comment": "Kommentar hinzufügen (optional)",
|
|
58
|
+
"commentHint": "Ihr Kommentar wird bei der Syndizierung mit einbezogen",
|
|
59
|
+
"syndicateTo": "Syndizieren an",
|
|
60
|
+
"syndicateHint": "Wählen Sie aus, wo dies quergepostet werden soll",
|
|
61
|
+
"submit": "Veröffentlichen",
|
|
62
|
+
"cancel": "Abbrechen",
|
|
63
|
+
"replyTo": "Antworten an",
|
|
64
|
+
"likeOf": "Gefällt mir",
|
|
65
|
+
"repostOf": "Teilen",
|
|
66
|
+
"bookmarkOf": "Lesezeichen setzen"
|
|
67
|
+
},
|
|
68
|
+
"settings": {
|
|
69
|
+
"title": "{{channel}}-Einstellungen",
|
|
70
|
+
"excludeTypes": "Interaktionstypen ausschließen",
|
|
71
|
+
"excludeTypesHelp": "Wählen Sie Beitragstypen aus, die in diesem Kanal ausgeblendet werden sollen",
|
|
72
|
+
"excludeRegex": "Ausschlussmuster",
|
|
73
|
+
"excludeRegexHelp": "Regulärer Ausdruck zum Herausfiltern übereinstimmender Inhalte",
|
|
74
|
+
"save": "Einstellungen speichern",
|
|
75
|
+
"dangerZone": "Gefahrenzone",
|
|
76
|
+
"deleteWarning": "Das Löschen dieses Kanals entfernt dauerhaft alle Feeds und Elemente. Diese Aktion kann nicht rückgängig gemacht werden.",
|
|
77
|
+
"deleteConfirm": "Sind Sie sicher, dass Sie diesen Kanal und alle seine Inhalte löschen möchten?",
|
|
78
|
+
"delete": "Kanal löschen",
|
|
79
|
+
"types": {
|
|
80
|
+
"like": "Gefällt mir",
|
|
81
|
+
"repost": "Geteilte Beiträge",
|
|
82
|
+
"bookmark": "Lesezeichen",
|
|
83
|
+
"reply": "Antworten",
|
|
84
|
+
"checkin": "Check-ins"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"search": {
|
|
88
|
+
"title": "Suchen",
|
|
89
|
+
"placeholder": "URL oder Suchbegriff eingeben",
|
|
90
|
+
"submit": "Suchen",
|
|
91
|
+
"noResults": "Keine Ergebnisse gefunden"
|
|
92
|
+
},
|
|
93
|
+
"preview": {
|
|
94
|
+
"title": "Vorschau",
|
|
95
|
+
"subscribe": "Diesen Feed abonnieren"
|
|
96
|
+
},
|
|
97
|
+
"error": {
|
|
98
|
+
"channelNotFound": "Kanal nicht gefunden",
|
|
99
|
+
"feedNotFound": "Feed nicht gefunden",
|
|
100
|
+
"invalidUrl": "Ungültige URL",
|
|
101
|
+
"invalidAction": "Ungültige Aktion"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"microsub": {
|
|
3
|
+
"reader": {
|
|
4
|
+
"title": "Lector",
|
|
5
|
+
"empty": "No hay elementos para mostrar",
|
|
6
|
+
"markAllRead": "Marcar todo como leído",
|
|
7
|
+
"showRead": "Mostrar leídos ({{count}})",
|
|
8
|
+
"hideRead": "Ocultar elementos leídos",
|
|
9
|
+
"allRead": "¡Todo al día!",
|
|
10
|
+
"newer": "Más reciente",
|
|
11
|
+
"older": "Más antiguo"
|
|
12
|
+
},
|
|
13
|
+
"channels": {
|
|
14
|
+
"title": "Canales",
|
|
15
|
+
"name": "Nombre del canal",
|
|
16
|
+
"new": "Nuevo canal",
|
|
17
|
+
"create": "Crear canal",
|
|
18
|
+
"delete": "Eliminar canal",
|
|
19
|
+
"settings": "Configuración del canal",
|
|
20
|
+
"empty": "Todavía no hay canales. Creá uno para empezar.",
|
|
21
|
+
"notifications": "Notificaciones"
|
|
22
|
+
},
|
|
23
|
+
"timeline": {
|
|
24
|
+
"title": "Línea de tiempo",
|
|
25
|
+
"empty": "No hay elementos en este canal",
|
|
26
|
+
"markRead": "Marcar como leído",
|
|
27
|
+
"markUnread": "Marcar como no leído",
|
|
28
|
+
"remove": "Eliminar"
|
|
29
|
+
},
|
|
30
|
+
"feeds": {
|
|
31
|
+
"title": "Feeds",
|
|
32
|
+
"follow": "Seguir",
|
|
33
|
+
"subscribe": "Suscribirse a un feed",
|
|
34
|
+
"unfollow": "Dejar de seguir",
|
|
35
|
+
"empty": "No se sigue ningún feed en este canal",
|
|
36
|
+
"url": "URL del feed",
|
|
37
|
+
"urlPlaceholder": "https://ejemplo.com/feed.xml",
|
|
38
|
+
"edit": "Editar feed",
|
|
39
|
+
"rediscover": "Redescubrir feed",
|
|
40
|
+
"refresh": "Actualizar ahora",
|
|
41
|
+
"status": {
|
|
42
|
+
"active": "Activo",
|
|
43
|
+
"error": "Error",
|
|
44
|
+
"stale": "Obsoleto"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"item": {
|
|
48
|
+
"reply": "Responder",
|
|
49
|
+
"like": "Me gusta",
|
|
50
|
+
"repost": "Repostear",
|
|
51
|
+
"bookmark": "Marcador",
|
|
52
|
+
"viewOriginal": "Ver original"
|
|
53
|
+
},
|
|
54
|
+
"compose": {
|
|
55
|
+
"title": "Redactar",
|
|
56
|
+
"content": "¿Qué estás pensando?",
|
|
57
|
+
"comment": "Agregar un comentario (opcional)",
|
|
58
|
+
"commentHint": "Tu comentario se incluirá cuando esto se sindique",
|
|
59
|
+
"syndicateTo": "Sindicar a",
|
|
60
|
+
"syndicateHint": "Seleccioná dónde publicar esto",
|
|
61
|
+
"submit": "Publicar",
|
|
62
|
+
"cancel": "Cancelar",
|
|
63
|
+
"replyTo": "Respondiendo a",
|
|
64
|
+
"likeOf": "Me gusta",
|
|
65
|
+
"repostOf": "Reposteando",
|
|
66
|
+
"bookmarkOf": "Marcando"
|
|
67
|
+
},
|
|
68
|
+
"settings": {
|
|
69
|
+
"title": "Configuración de {{channel}}",
|
|
70
|
+
"excludeTypes": "Excluir tipos de interacción",
|
|
71
|
+
"excludeTypesHelp": "Seleccioná los tipos de publicaciones que querés ocultar de este canal",
|
|
72
|
+
"excludeRegex": "Patrón de exclusión",
|
|
73
|
+
"excludeRegexHelp": "Expresión regular para filtrar contenido coincidente",
|
|
74
|
+
"save": "Guardar configuración",
|
|
75
|
+
"dangerZone": "Zona de peligro",
|
|
76
|
+
"deleteWarning": "Eliminar este canal eliminará permanentemente todos los feeds y elementos. Esta acción no se puede deshacer.",
|
|
77
|
+
"deleteConfirm": "¿Estás seguro de que querés eliminar este canal y todo su contenido?",
|
|
78
|
+
"delete": "Eliminar canal",
|
|
79
|
+
"types": {
|
|
80
|
+
"like": "Me gusta",
|
|
81
|
+
"repost": "Reposteos",
|
|
82
|
+
"bookmark": "Marcadores",
|
|
83
|
+
"reply": "Respuestas",
|
|
84
|
+
"checkin": "Registros"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"search": {
|
|
88
|
+
"title": "Buscar",
|
|
89
|
+
"placeholder": "Ingresá URL o término de búsqueda",
|
|
90
|
+
"submit": "Buscar",
|
|
91
|
+
"noResults": "No se encontraron resultados"
|
|
92
|
+
},
|
|
93
|
+
"preview": {
|
|
94
|
+
"title": "Vista previa",
|
|
95
|
+
"subscribe": "Suscribirse a este feed"
|
|
96
|
+
},
|
|
97
|
+
"error": {
|
|
98
|
+
"channelNotFound": "Canal no encontrado",
|
|
99
|
+
"feedNotFound": "Feed no encontrado",
|
|
100
|
+
"invalidUrl": "URL no válida",
|
|
101
|
+
"invalidAction": "Acción no válida"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
package/locales/es.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"microsub": {
|
|
3
|
+
"reader": {
|
|
4
|
+
"title": "Lector",
|
|
5
|
+
"empty": "No hay elementos para mostrar",
|
|
6
|
+
"markAllRead": "Marcar todo como leído",
|
|
7
|
+
"showRead": "Mostrar leídos ({{count}})",
|
|
8
|
+
"hideRead": "Ocultar elementos leídos",
|
|
9
|
+
"allRead": "¡Todo al día!",
|
|
10
|
+
"newer": "Más reciente",
|
|
11
|
+
"older": "Más antiguo"
|
|
12
|
+
},
|
|
13
|
+
"channels": {
|
|
14
|
+
"title": "Canales",
|
|
15
|
+
"name": "Nombre del canal",
|
|
16
|
+
"new": "Nuevo canal",
|
|
17
|
+
"create": "Crear canal",
|
|
18
|
+
"delete": "Eliminar canal",
|
|
19
|
+
"settings": "Configuración del canal",
|
|
20
|
+
"empty": "Aún no hay canales. Crea uno para empezar.",
|
|
21
|
+
"notifications": "Notificaciones"
|
|
22
|
+
},
|
|
23
|
+
"timeline": {
|
|
24
|
+
"title": "Cronología",
|
|
25
|
+
"empty": "No hay elementos en este canal",
|
|
26
|
+
"markRead": "Marcar como leído",
|
|
27
|
+
"markUnread": "Marcar como no leído",
|
|
28
|
+
"remove": "Eliminar"
|
|
29
|
+
},
|
|
30
|
+
"feeds": {
|
|
31
|
+
"title": "Fuentes",
|
|
32
|
+
"follow": "Seguir",
|
|
33
|
+
"subscribe": "Suscribirse a una fuente",
|
|
34
|
+
"unfollow": "Dejar de seguir",
|
|
35
|
+
"empty": "No se sigue ninguna fuente en este canal",
|
|
36
|
+
"url": "URL de la fuente",
|
|
37
|
+
"urlPlaceholder": "https://ejemplo.com/feed.xml",
|
|
38
|
+
"edit": "Editar fuente",
|
|
39
|
+
"rediscover": "Redescubrir fuente",
|
|
40
|
+
"refresh": "Actualizar ahora",
|
|
41
|
+
"status": {
|
|
42
|
+
"active": "Activa",
|
|
43
|
+
"error": "Error",
|
|
44
|
+
"stale": "Obsoleta"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"item": {
|
|
48
|
+
"reply": "Responder",
|
|
49
|
+
"like": "Me gusta",
|
|
50
|
+
"repost": "Republicar",
|
|
51
|
+
"bookmark": "Marcador",
|
|
52
|
+
"viewOriginal": "Ver original"
|
|
53
|
+
},
|
|
54
|
+
"compose": {
|
|
55
|
+
"title": "Redactar",
|
|
56
|
+
"content": "¿Qué estás pensando?",
|
|
57
|
+
"comment": "Añadir un comentario (opcional)",
|
|
58
|
+
"commentHint": "Tu comentario se incluirá cuando esto se sindique",
|
|
59
|
+
"syndicateTo": "Sindicar a",
|
|
60
|
+
"syndicateHint": "Selecciona dónde publicar esto",
|
|
61
|
+
"submit": "Publicar",
|
|
62
|
+
"cancel": "Cancelar",
|
|
63
|
+
"replyTo": "Respondiendo a",
|
|
64
|
+
"likeOf": "Me gusta",
|
|
65
|
+
"repostOf": "Republicando",
|
|
66
|
+
"bookmarkOf": "Marcando"
|
|
67
|
+
},
|
|
68
|
+
"settings": {
|
|
69
|
+
"title": "Configuración de {{channel}}",
|
|
70
|
+
"excludeTypes": "Excluir tipos de interacción",
|
|
71
|
+
"excludeTypesHelp": "Selecciona los tipos de publicaciones que deseas ocultar de este canal",
|
|
72
|
+
"excludeRegex": "Patrón de exclusión",
|
|
73
|
+
"excludeRegexHelp": "Expresión regular para filtrar contenido coincidente",
|
|
74
|
+
"save": "Guardar configuración",
|
|
75
|
+
"dangerZone": "Zona de peligro",
|
|
76
|
+
"deleteWarning": "Eliminar este canal eliminará permanentemente todas las fuentes y elementos. Esta acción no se puede deshacer.",
|
|
77
|
+
"deleteConfirm": "¿Estás seguro de que deseas eliminar este canal y todo su contenido?",
|
|
78
|
+
"delete": "Eliminar canal",
|
|
79
|
+
"types": {
|
|
80
|
+
"like": "Me gusta",
|
|
81
|
+
"repost": "Republicaciones",
|
|
82
|
+
"bookmark": "Marcadores",
|
|
83
|
+
"reply": "Respuestas",
|
|
84
|
+
"checkin": "Registros"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"search": {
|
|
88
|
+
"title": "Buscar",
|
|
89
|
+
"placeholder": "Introduce URL o término de búsqueda",
|
|
90
|
+
"submit": "Buscar",
|
|
91
|
+
"noResults": "No se encontraron resultados"
|
|
92
|
+
},
|
|
93
|
+
"preview": {
|
|
94
|
+
"title": "Vista previa",
|
|
95
|
+
"subscribe": "Suscribirse a esta fuente"
|
|
96
|
+
},
|
|
97
|
+
"error": {
|
|
98
|
+
"channelNotFound": "Canal no encontrado",
|
|
99
|
+
"feedNotFound": "Fuente no encontrada",
|
|
100
|
+
"invalidUrl": "URL no válida",
|
|
101
|
+
"invalidAction": "Acción no válida"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
package/locales/fr.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"microsub": {
|
|
3
|
+
"reader": {
|
|
4
|
+
"title": "Lecteur",
|
|
5
|
+
"empty": "Aucun élément à afficher",
|
|
6
|
+
"markAllRead": "Tout marquer comme lu",
|
|
7
|
+
"showRead": "Afficher les lus ({{count}})",
|
|
8
|
+
"hideRead": "Masquer les éléments lus",
|
|
9
|
+
"allRead": "Tout est à jour !",
|
|
10
|
+
"newer": "Plus récent",
|
|
11
|
+
"older": "Plus ancien"
|
|
12
|
+
},
|
|
13
|
+
"channels": {
|
|
14
|
+
"title": "Chaînes",
|
|
15
|
+
"name": "Nom de la chaîne",
|
|
16
|
+
"new": "Nouvelle chaîne",
|
|
17
|
+
"create": "Créer une chaîne",
|
|
18
|
+
"delete": "Supprimer la chaîne",
|
|
19
|
+
"settings": "Paramètres de la chaîne",
|
|
20
|
+
"empty": "Aucune chaîne pour le moment. Créez-en une pour commencer.",
|
|
21
|
+
"notifications": "Notifications"
|
|
22
|
+
},
|
|
23
|
+
"timeline": {
|
|
24
|
+
"title": "Fil d'actualité",
|
|
25
|
+
"empty": "Aucun élément dans cette chaîne",
|
|
26
|
+
"markRead": "Marquer comme lu",
|
|
27
|
+
"markUnread": "Marquer comme non lu",
|
|
28
|
+
"remove": "Retirer"
|
|
29
|
+
},
|
|
30
|
+
"feeds": {
|
|
31
|
+
"title": "Flux",
|
|
32
|
+
"follow": "Suivre",
|
|
33
|
+
"subscribe": "S'abonner à un flux",
|
|
34
|
+
"unfollow": "Ne plus suivre",
|
|
35
|
+
"empty": "Aucun flux suivi dans cette chaîne",
|
|
36
|
+
"url": "URL du flux",
|
|
37
|
+
"urlPlaceholder": "https://exemple.com/feed.xml",
|
|
38
|
+
"edit": "Modifier le flux",
|
|
39
|
+
"rediscover": "Redécouvrir le flux",
|
|
40
|
+
"refresh": "Actualiser maintenant",
|
|
41
|
+
"status": {
|
|
42
|
+
"active": "Actif",
|
|
43
|
+
"error": "Erreur",
|
|
44
|
+
"stale": "Périmé"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"item": {
|
|
48
|
+
"reply": "Répondre",
|
|
49
|
+
"like": "J'aime",
|
|
50
|
+
"repost": "Repartager",
|
|
51
|
+
"bookmark": "Marque-page",
|
|
52
|
+
"viewOriginal": "Voir l'original"
|
|
53
|
+
},
|
|
54
|
+
"compose": {
|
|
55
|
+
"title": "Composer",
|
|
56
|
+
"content": "Qu'avez-vous en tête ?",
|
|
57
|
+
"comment": "Ajouter un commentaire (facultatif)",
|
|
58
|
+
"commentHint": "Votre commentaire sera inclus lors de la syndication",
|
|
59
|
+
"syndicateTo": "Syndiquer vers",
|
|
60
|
+
"syndicateHint": "Sélectionnez où publier ceci",
|
|
61
|
+
"submit": "Publier",
|
|
62
|
+
"cancel": "Annuler",
|
|
63
|
+
"replyTo": "En réponse à",
|
|
64
|
+
"likeOf": "J'aime",
|
|
65
|
+
"repostOf": "Repartage",
|
|
66
|
+
"bookmarkOf": "Mise en marque-page"
|
|
67
|
+
},
|
|
68
|
+
"settings": {
|
|
69
|
+
"title": "Paramètres de {{channel}}",
|
|
70
|
+
"excludeTypes": "Exclure les types d'interaction",
|
|
71
|
+
"excludeTypesHelp": "Sélectionnez les types de publications à masquer de cette chaîne",
|
|
72
|
+
"excludeRegex": "Modèle d'exclusion",
|
|
73
|
+
"excludeRegexHelp": "Expression régulière pour filtrer le contenu correspondant",
|
|
74
|
+
"save": "Enregistrer les paramètres",
|
|
75
|
+
"dangerZone": "Zone dangereuse",
|
|
76
|
+
"deleteWarning": "La suppression de cette chaîne supprimera définitivement tous les flux et éléments. Cette action ne peut pas être annulée.",
|
|
77
|
+
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer cette chaîne et tout son contenu ?",
|
|
78
|
+
"delete": "Supprimer la chaîne",
|
|
79
|
+
"types": {
|
|
80
|
+
"like": "J'aime",
|
|
81
|
+
"repost": "Repartages",
|
|
82
|
+
"bookmark": "Marque-pages",
|
|
83
|
+
"reply": "Réponses",
|
|
84
|
+
"checkin": "Enregistrements"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"search": {
|
|
88
|
+
"title": "Rechercher",
|
|
89
|
+
"placeholder": "Entrez une URL ou un terme de recherche",
|
|
90
|
+
"submit": "Rechercher",
|
|
91
|
+
"noResults": "Aucun résultat trouvé"
|
|
92
|
+
},
|
|
93
|
+
"preview": {
|
|
94
|
+
"title": "Aperçu",
|
|
95
|
+
"subscribe": "S'abonner à ce flux"
|
|
96
|
+
},
|
|
97
|
+
"error": {
|
|
98
|
+
"channelNotFound": "Chaîne introuvable",
|
|
99
|
+
"feedNotFound": "Flux introuvable",
|
|
100
|
+
"invalidUrl": "URL invalide",
|
|
101
|
+
"invalidAction": "Action invalide"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|