From a4a1990dbb16e3e4599500299c32c980c9cbd5bf Mon Sep 17 00:00:00 2001 From: byte Date: Sat, 25 Oct 2025 16:21:42 +0200 Subject: rendering visibility conditionally, with lesser reach if needed --- html.c | 72 +++++++++++++++++++++++++++++------------------------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/html.c b/html.c index 584059b..7c39237 100644 --- a/html.c +++ b/html.c @@ -398,6 +398,37 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, return actor_icon; } +void html_note_render_visibility(snac* user, xs_html *form, const int scope) +{ + // scopes aren't sorted by value unfortunately, so simple math won't work to limit them. using map-like thing here + static const int public_scopes[5] = {SCOPE_PUBLIC, SCOPE_UNLISTED, SCOPE_FOLLOWERS, SCOPE_MENTIONED, -1}; + static const int unlisted_scopes[4] = {SCOPE_UNLISTED, SCOPE_FOLLOWERS, SCOPE_MENTIONED, -1}; + static const int followers_scopes[3] = {SCOPE_FOLLOWERS, SCOPE_MENTIONED, -1}; + static const int mentioned_scopes[2] = {SCOPE_MENTIONED, -1}; + static const int * const scopes[4] = { public_scopes, mentioned_scopes, unlisted_scopes, followers_scopes}; + static const char * const scopes_tags[4] = { "public", "mentioned", "unlisted", "followers"}; + static const char * const scopes_names[4] = { "Public", "Direct Message", "Unlisted", "Followers-only"}; + + xs_html *paragraph = xs_html_tag("p", xs_html_text(L("Visibility: "))); + const int* to_render = scopes[scope]; + for( int i = 0; to_render[i] != -1; i++ ){ + const int scope_i = to_render[i]; + const char* value = scopes_tags[scope_i]; + const char* name = scopes_names[scope_i]; + xs_html_add(paragraph, + xs_html_tag("label", + xs_html_sctag("input", + xs_html_attr("type", "radio"), + xs_html_attr("name", "visibility"), + xs_html_attr("value", value), + xs_html_attr(scope == scope_i ? "checked" : "", NULL)), + xs_html_text(" "), + xs_html_text(L(name)), + xs_html_text(" ")) + ); + } + xs_html_add(form, paragraph); +} xs_html *html_note(snac *user, const char *summary, const char *div_id, const char *form_id, @@ -455,46 +486,7 @@ xs_html *html_note(snac *user, const char *summary, xs_html_attr("type", "hidden"), xs_html_attr("name", "to"), xs_html_attr("value", actor_id))); - else { - xs_html_add(form, - xs_html_tag("p", - xs_html_text(L("Visibility: ")), - xs_html_tag("label", - xs_html_sctag("input", - xs_html_attr("type", "radio"), - xs_html_attr("name", "visibility"), - xs_html_attr("value", "public"), - xs_html_attr(scope == SCOPE_PUBLIC ? "checked" : "", NULL)), - xs_html_text(" "), - xs_html_text(L("Public"))), - xs_html_text(" "), - xs_html_tag("label", - xs_html_sctag("input", - xs_html_attr("type", "radio"), - xs_html_attr("name", "visibility"), - xs_html_attr("value", "unlisted"), - xs_html_attr(scope == SCOPE_UNLISTED ? "checked" : "", NULL)), - xs_html_text(" "), - xs_html_text(L("Unlisted"))), - xs_html_text(" "), - xs_html_tag("label", - xs_html_sctag("input", - xs_html_attr("type", "radio"), - xs_html_attr("name", "visibility"), - xs_html_attr("value", "followers"), - xs_html_attr(scope == SCOPE_FOLLOWERS ? "checked" : "", NULL)), - xs_html_text(" "), - xs_html_text(L("Followers-only"))), - xs_html_text(" "), - xs_html_tag("label", - xs_html_sctag("input", - xs_html_attr("type", "radio"), - xs_html_attr("name", "visibility"), - xs_html_attr("value", "mentioned"), - xs_html_attr(scope == SCOPE_MENTIONED ? "checked" : "", NULL)), - xs_html_text(" "), - xs_html_text(L("Direct Message"))))); - } + html_note_render_visibility(user, form, scope); if (redir) xs_html_add(form, -- cgit v1.2.3 From daee7581dbf5b458f28e486fd89804b91209a9bb Mon Sep 17 00:00:00 2001 From: byte Date: Sat, 1 Nov 2025 01:18:28 +0100 Subject: no visibility for editing --- html.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index a2dfb79..84636e9 100644 --- a/html.c +++ b/html.c @@ -486,7 +486,8 @@ xs_html *html_note(snac *user, const char *summary, xs_html_attr("type", "hidden"), xs_html_attr("name", "to"), xs_html_attr("value", actor_id))); - html_note_render_visibility(user, form, scope); + if (edit_id == NULL) + html_note_render_visibility(user, form, scope); if (redir) xs_html_add(form, -- cgit v1.2.3 From f0702ea06bcb43745c1f6c85e7f592ab3c1349b5 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 24 Nov 2025 05:58:25 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ba86212..570cc1a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,8 @@ Quoted posts are now shown. +Added metadata to remote users in the people page (contributed by dandelions). + Fixed memory leak (contributed by dandelions). Fixed typo in man page (contributed by spky). -- cgit v1.2.3 From fcae55fcb1542f6fa0a330c45e3b806f902a84de Mon Sep 17 00:00:00 2001 From: grunfink Date: Wed, 26 Nov 2025 17:21:16 +0100 Subject: Some attachments are of type 'Video' instead of a MIME type (bsky). --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index df5b508..12d269a 100644 --- a/html.c +++ b/html.c @@ -2634,7 +2634,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_attr("title", name)))); } else - if (xs_startswith(type, "video/")) { + if (xs_startswith(type, "video/") || strcmp(type, "Video") == 0) { xs_html_add(content_attachments, xs_html_tag("video", xs_html_attr("preload", "none"), -- cgit v1.2.3 From 5c2c7b27aca8bec59f90007481e5e2c6e961827f Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 29 Nov 2025 06:08:37 +0100 Subject: New function is_msg_mine(). --- activitypub.c | 14 ++++++++++++++ snac.h | 1 + 2 files changed, 15 insertions(+) diff --git a/activitypub.c b/activitypub.c index 2c0fa2e..65eed05 100644 --- a/activitypub.c +++ b/activitypub.c @@ -669,6 +669,20 @@ xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) } +int is_msg_mine(snac *user, const char *id) +/* returns true if a post id is by the given user */ +{ + int ret = 0; + + if (xs_is_string(id)) { + xs *s1 = xs_fmt("%s/", user->actor); + ret = xs_startswith(id, s1); + } + + return ret; +} + + int is_msg_public(const xs_dict *msg) /* checks if a message is public */ { diff --git a/snac.h b/snac.h index 91dfa27..4d387a6 100644 --- a/snac.h +++ b/snac.h @@ -388,6 +388,7 @@ int send_to_inbox(snac *snac, const xs_str *inbox, const xs_dict *msg, xs_str *get_actor_inbox(const char *actor, int shared); int send_to_actor(snac *snac, const char *actor, const xs_dict *msg, xs_val **payload, int *p_size, int timeout); +int is_msg_mine(snac *user, const char *id); int is_msg_public(const xs_dict *msg); int is_msg_from_private_user(const xs_dict *msg); int is_msg_for_me(snac *snac, const xs_dict *msg); -- cgit v1.2.3 From 46bb87c2b54c9b9d9a4cd462b47158ede1eec170 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 29 Nov 2025 06:17:27 +0100 Subject: Moved is_msg_mine() to data.c. --- activitypub.c | 14 -------------- data.c | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/activitypub.c b/activitypub.c index 65eed05..2c0fa2e 100644 --- a/activitypub.c +++ b/activitypub.c @@ -669,20 +669,6 @@ xs_list *recipient_list(snac *snac, const xs_dict *msg, int expand_public) } -int is_msg_mine(snac *user, const char *id) -/* returns true if a post id is by the given user */ -{ - int ret = 0; - - if (xs_is_string(id)) { - xs *s1 = xs_fmt("%s/", user->actor); - ret = xs_startswith(id, s1); - } - - return ret; -} - - int is_msg_public(const xs_dict *msg) /* checks if a message is public */ { diff --git a/data.c b/data.c index d291ba7..c2fdccb 100644 --- a/data.c +++ b/data.c @@ -1358,6 +1358,20 @@ int pending_count(snac *user) } +int is_msg_mine(snac *user, const char *id) +/* returns true if a post id is by the given user */ +{ + int ret = 0; + + if (xs_is_string(id)) { + xs *s1 = xs_fmt("%s/", user->actor); + ret = xs_startswith(id, s1); + } + + return ret; +} + + /** timeline **/ double timeline_mtime(snac *snac) -- cgit v1.2.3 From a45c1ce152011e8fe25eb1d25594ac5705f65404 Mon Sep 17 00:00:00 2001 From: rako Date: Fri, 28 Nov 2025 10:37:49 +0100 Subject: Fix user matching In order to be a proper prefix, the actor url must end with a '/' otherwise it can match another user that starts with the same prefix: for example 'testuser' will match anything made by 'testuser2' --- activitypub.c | 14 +++++++------- data.c | 8 ++++---- html.c | 6 +++--- mastoapi.c | 4 ++-- rss.c | 2 +- upgrade.c | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/activitypub.c b/activitypub.c index 2c0fa2e..90230d8 100644 --- a/activitypub.c +++ b/activitypub.c @@ -779,7 +779,7 @@ int is_msg_for_me(snac *snac, const xs_dict *c_msg) object_get(object, &obj); /* if it's about one of our posts, accept it */ - if (xs_startswith(object, snac->actor)) + if (is_msg_mine(snac, object)) return 2; /* blocked by hashtag? */ @@ -1242,7 +1242,7 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor, if (xs_match(type, "Like|Announce|EmojiReact")) { /* if it's not an admiration about something by us, done */ - if (xs_is_null(objid) || !xs_startswith(objid, snac->actor)) + if (xs_is_null(objid) || !is_msg_mine(snac, objid)) return; /* if it's an announce by our own relay, done */ @@ -1267,7 +1267,7 @@ void notify(snac *snac, const char *type, const char *utype, const char *actor, return; /* if it's not ours and we didn't vote, discard */ - if (!xs_startswith(poll_id, snac->actor) && !was_question_voted(snac, poll_id)) + if (!is_msg_mine(snac, poll_id) && !was_question_voted(snac, poll_id)) return; } @@ -2792,10 +2792,10 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) if (xs_is_null(object)) snac_log(snac, xs_fmt("malformed message: no 'id' field")); else - if (is_muted(snac, actor) && !xs_startswith(object, snac->actor)) + if (is_muted(snac, actor) && !is_msg_mine(snac, object)) snac_log(snac, xs_fmt("dropped 'Announce' from muted actor %s", actor)); else - if (is_limited(snac, actor) && !xs_startswith(object, snac->actor)) + if (is_limited(snac, actor) && !is_msg_mine(snac, object)) snac_log(snac, xs_fmt("dropped 'Announce' from limited actor %s", actor)); else { xs *a_msg = NULL; @@ -2903,7 +2903,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) snac_log(snac, xs_fmt("malformed message: no 'id' field")); else if (object_here(object)) { - if (xs_startswith(object, srv_baseurl) && !xs_startswith(object, actor)) + if (xs_startswith(object, srv_baseurl) && !is_msg_mine(snac, object)) snac_log(snac, xs_fmt("ignored incorrect 'Delete' %s %s", actor, object)); else { timeline_del(snac, object); @@ -3716,7 +3716,7 @@ int activitypub_get_handler(const xs_dict *req, const char *q_path, const char *type = xs_dict_get(i, "type"); const char *id = xs_dict_get(i, "id"); - if (type && id && strcmp(type, "Note") == 0 && xs_startswith(id, snac.actor)) { + if (type && id && strcmp(type, "Note") == 0 && is_msg_mine(&snac, id)) { if (is_msg_public(i)) { xs *c_msg = msg_create(&snac, i); list = xs_list_append(list, c_msg); diff --git a/data.c b/data.c index c2fdccb..688d2e3 100644 --- a/data.c +++ b/data.c @@ -1467,7 +1467,7 @@ void timeline_update_indexes(snac *snac, const char *id) { object_user_cache_add(snac, id, "private"); - if (xs_startswith(id, snac->actor)) { + if (is_msg_mine(snac, id)) { xs *msg = NULL; if (valid_status(object_get(id, &msg))) { @@ -1927,7 +1927,7 @@ int pin(snac *user, const char *id) { int ret = -2; - if (xs_startswith(id, user->actor)) { + if (is_msg_mine(user, id)) { if (is_pinned(user, id)) ret = -3; else @@ -3527,7 +3527,7 @@ void enqueue_output(snac *snac, const xs_dict *msg, const xs_str *inbox, int retries, int p_status) /* enqueues an output message to an inbox */ { - if (xs_startswith(inbox, snac->actor)) { + if (is_msg_mine(snac, inbox)) { snac_debug(snac, 1, xs_str_new("refusing enqueue to myself")); return; } @@ -4055,7 +4055,7 @@ void delete_purged_posts(snac *user, int days) if (xs_is_dict(msg)) { const char *id = xs_dict_get(msg, "id"); - if (xs_is_string(id) && xs_startswith(id, user->actor)) { + if (xs_is_string(id) && is_msg_mine(user, id)) { xs *d_msg = msg_delete(user, id); enqueue_message(user, d_msg); diff --git a/html.c b/html.c index 12d269a..d6223b9 100644 --- a/html.c +++ b/html.c @@ -1898,7 +1898,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, xs_html_attr("name", "redir"), xs_html_attr("value", redir)))); - if (!xs_startswith(id, user->actor)) { + if (!is_msg_mine(user, id)) { if (xs_list_in(likes, user->md5) == -1) { /* not already liked; add button */ xs_html_add(form, @@ -2426,7 +2426,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (read_only) closed = 1; /* non-identified page; show as closed */ else - if (user && xs_startswith(id, user->actor)) + if (user && is_msg_mine(user, id)) closed = 1; /* we questioned; closed for us */ else if (user && was_question_voted(user, id)) @@ -5022,7 +5022,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, } else { /* delete an entry */ - if (xs_startswith(id, snac.actor) && !is_draft(&snac, id)) { + if (is_msg_mine(&snac, id) && !is_draft(&snac, id)) { /* it's a post by us: generate a delete */ xs *msg = msg_delete(&snac, id); diff --git a/mastoapi.c b/mastoapi.c index 94912f1..acb95a0 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1919,7 +1919,7 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, /* add only posts by the author */ if (!xs_is_null(msg_id) && strcmp(xs_dict_get(msg, "type"), "Note") == 0 && - xs_startswith(xs_dict_get(msg, "id"), snac2.actor) && is_msg_public(msg)) { + is_msg_mine(&snac2, xs_dict_get(msg, "id")) && is_msg_public(msg)) { /* if max_id is set, skip entries until we find it */ if (skip_until_max) { @@ -3824,7 +3824,7 @@ int mastoapi_delete_handler(const xs_dict *req, const char *q_path, if (valid_status(object_get_by_md5(p, &obj))) { const char *id = xs_dict_get(obj, "id"); - if (xs_is_string(id) && xs_startswith(id, snac.actor)) { + if (xs_is_string(id) && is_msg_mine(&snac, id)) { xs *out = mastoapi_status(&snac, obj); xs *msg = msg_delete(&snac, id); diff --git a/rss.c b/rss.c index 6e77205..6124e7a 100644 --- a/rss.c +++ b/rss.c @@ -59,7 +59,7 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline, const char *content = xs_dict_get(msg, "content"); const char *published = xs_dict_get(msg, "published"); - if (user && !xs_startswith(id, user->actor)) + if (user && !is_msg_mine(user, id)) continue; if (!id || !content || !published) diff --git a/upgrade.c b/upgrade.c index 87ddfc8..9e0ae6e 100644 --- a/upgrade.c +++ b/upgrade.c @@ -213,7 +213,7 @@ int snac_upgrade(xs_str **error) object_add_ow(id, o); /* if it's from us, add to public */ - if (xs_startswith(id, snac.actor)) { + if (is_msg_mine(&snac, id)) { const xs_list *p; const char *v; int c; -- cgit v1.2.3 From 512e701609917367e141d83a330b275ea18f6c09 Mon Sep 17 00:00:00 2001 From: pmjv Date: Mon, 1 Dec 2025 09:06:23 +0100 Subject: fine-tuning czech translation --- po/cs.po | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/po/cs.po b/po/cs.po index d855e79..28ac218 100644 --- a/po/cs.po +++ b/po/cs.po @@ -14,7 +14,7 @@ msgstr "Citlivý obsah: " #: html.c:448 msgid "Sensitive content description" -msgstr "Varování k citlivému obsahu" +msgstr "Varování o citlivém obsahu" msgid "Only for mentioned people: " msgstr "Pouze pro zmíněné osoby:" @@ -185,11 +185,11 @@ msgstr "Vaše jméno" #: html.c:1507 msgid "Avatar: " -msgstr "Avatar: " +msgstr "Profilový obrázek: " #: html.c:1515 msgid "Delete current avatar" -msgstr "Smazat současný avatar" +msgstr "Smazat profilový obrázek" #: html.c:1517 msgid "Header image (banner): " @@ -197,7 +197,7 @@ msgstr "Obrázek v záhlaví profilu: " #: html.c:1525 msgid "Delete current header image" -msgstr "Smazat současný obrázek v záhlaví" +msgstr "Smazat obrázek v záhlaví" #: html.c:1527 msgid "Bio:" @@ -205,11 +205,11 @@ msgstr "Bio:" #: html.c:1533 msgid "Write about yourself here..." -msgstr "Napište sem něco o sobě..." +msgstr "Napište něco o sobě..." #: html.c:1542 msgid "Always show sensitive content" -msgstr "Vždy zobrazit příspěvky s varováním o citlivém obsahu" +msgstr "Rozbalit citlivé příspěvky" #: html.c:1544 msgid "Email address for notifications:" @@ -233,11 +233,11 @@ msgstr "Zahodit soukromé zprávy od lidí, které nesledujete" #: html.c:1611 msgid "This account is a bot" -msgstr "Tenhle účet je robot" +msgstr "Tento účet je robotem" #: html.c:1620 msgid "Auto-boost all mentions to this account" -msgstr "Automaticky boostovat všechny zmíňky o tomto účtu" +msgstr "Automaticky boostit všechna zmínění tohoto účtu" #: html.c:1629 msgid "This account is private (posts are not shown through the web)" @@ -246,11 +246,11 @@ msgstr "" #: html.c:1639 msgid "Collapse top threads by default" -msgstr "Zobrazovat vlákna složená" +msgstr "Složit vlákna" #: html.c:1648 msgid "Follow requests must be approved" -msgstr "Žádosti o sledování je nutno manuálně potvrdit" +msgstr "Žádosti o sledování je nutné manuálně potvrdit" #: html.c:1657 msgid "Publish follower and following metrics" @@ -274,7 +274,7 @@ msgstr "Nové heslo:" #: html.c:1710 msgid "Repeat new password:" -msgstr "Zopakujte nové heslo:" +msgstr "Nové heslo znovu:" #: html.c:1720 msgid "Update user info" @@ -330,7 +330,7 @@ msgstr "Odboostit" #: html.c:1930 msgid "I regret I boosted this" -msgstr "Boostit to byl blbej nápad" +msgstr "Boostit to byl špatný nápad" #: html.c:1936 html.c:4922 msgid "Unbookmark" @@ -438,7 +438,7 @@ msgstr "Událost" #: html.c:2246 html.c:2275 msgid "boosted" -msgstr "boostuje" +msgstr "boostí" #: html.c:2289 msgid "in reply to" @@ -519,7 +519,7 @@ msgstr "Rozepsané příspěvky" #: html.c:3177 msgid "No more unseen posts" -msgstr "Nic víc nového" +msgstr "Nic nového" #: html.c:3181 html.c:3290 msgid "Back to top" @@ -623,7 +623,7 @@ msgstr "Nové" #: html.c:3707 msgid "Already seen" -msgstr "Zobrazeno dříve" +msgstr "Již viděno" #: html.c:3722 msgid "None" -- cgit v1.2.3 From 6f3894da7b6039cc6bc57ab3c274ed752d72828a Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 2 Dec 2025 09:55:38 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 570cc1a..505d080 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,6 +8,8 @@ Added metadata to remote users in the people page (contributed by dandelions). Fixed memory leak (contributed by dandelions). +Fixed user matching (contributed by rakoo). + Fixed typo in man page (contributed by spky). ## 2.84 -- cgit v1.2.3 From 76f95d8df7d64037eb60013a98e48b81d3935fa3 Mon Sep 17 00:00:00 2001 From: pmjv Date: Tue, 2 Dec 2025 11:06:22 +0100 Subject: Update po/cs.po --- po/cs.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/cs.po b/po/cs.po index 28ac218..b987137 100644 --- a/po/cs.po +++ b/po/cs.po @@ -478,7 +478,7 @@ msgstr "Popisek..." #: html.c:2697 msgid "Source channel or community" -msgstr "" +msgstr "Původní kanál nebo komunita" #: html.c:2791 msgid "Time: " -- cgit v1.2.3 From 627ccf47d57567f9253a1f01e79c13a4eaa22deb Mon Sep 17 00:00:00 2001 From: grunfink Date: Wed, 3 Dec 2025 18:43:24 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 505d080..f0fdb95 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,8 +10,14 @@ Fixed memory leak (contributed by dandelions). Fixed user matching (contributed by rakoo). +Rendering visibility conditionally, with lesser reach if needed (contributed by byte). + +Added a button next to a follow notification to follow back. + Fixed typo in man page (contributed by spky). +Updated Czech and German translations (contributed by pmjv and zen). + ## 2.84 Implemented more scopes to match other ActivityPub implementations (public, unlisted, followers-only and direct message) (contributed by byte). -- cgit v1.2.3 From 1ec7d7c8219d7f39da50ca097a6d900da64a19a2 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 4 Dec 2025 10:50:24 +0100 Subject: Version 2.85 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 4d387a6..732d0b2 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.85-dev" +#define VERSION "2.85" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From c741c3078e4dcc0fcdda15f9082a87788383b61d Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 4 Dec 2025 11:09:58 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f0fdb95..2ec8dcd 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.85 Quoted posts are now shown. -- cgit v1.2.3 From 4102a6a7ac7ab7c651fe0b03358148e8d15418cc Mon Sep 17 00:00:00 2001 From: violette p. Date: Tue, 9 Dec 2025 04:58:13 +0100 Subject: make webpush use our notification server vkey instead of a random, ill-formated key (necessary for some client notifications, such as moshidon) --- doc/snac.8 | 2 ++ mastoapi.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/snac.8 b/doc/snac.8 index a6d925d..0dc0769 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -294,6 +294,8 @@ The URL to a favicon. If it's not set, the default one is used instead. The maximum number of days an instance is considered down after continuous failed outgoing messages (default: 15). Anyway, whenever any incoming activity from a failed instance is detected, this counter is reset for it. +.It Ic vkey +Public vapid key. Used for notification on some client. .El .Pp You must restart the server to make effective these changes. diff --git a/mastoapi.c b/mastoapi.c index acb95a0..9aa29d8 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -3044,7 +3044,10 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, xs *app = xs_dict_new(); xs *id = xs_replace_i(tid(0), ".", ""); xs *csec = random_str(); - xs *vkey = random_str(); + char *vkey = (char *)xs_dict_get(srv_config, "vkey"); + if (vkey == NULL) + vkey = random_str(); + xs *cid = NULL; /* pick a non-existent random cid */ -- cgit v1.2.3 From a8b706b193d8d22191fa85ac290b90491be54ee3 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 05:01:06 +0100 Subject: Fixed small memory leak. --- mastoapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mastoapi.c b/mastoapi.c index 9aa29d8..9503447 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -3044,7 +3044,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, xs *app = xs_dict_new(); xs *id = xs_replace_i(tid(0), ".", ""); xs *csec = random_str(); - char *vkey = (char *)xs_dict_get(srv_config, "vkey"); + xs *vkey = xs_dup(xs_dict_get(srv_config, "vkey")); if (vkey == NULL) vkey = random_str(); -- cgit v1.2.3 From bdfc10963f9aa001bbd3569effea345e0ff30a72 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 05:03:33 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2ec8dcd..7727aec 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## UNRELEASED + +Mastodon API: Fix for some client notifications (contributed by violette). + ## 2.85 Quoted posts are now shown. -- cgit v1.2.3 From deb76261bf32734be73c68b94dc1cbdfb00dc70d Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 05:34:26 +0100 Subject: Updated TODO. --- TODO.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TODO.md b/TODO.md index 1f13c6b..9c3fcad 100644 --- a/TODO.md +++ b/TODO.md @@ -8,8 +8,6 @@ Investigate the problem with boosts inside the same instance (see https://codebe Editing / Updating a post does not index newly added hashtags. -Unfollowing guppe groups seems to work (http status of 200), but messages continue to arrive as if it didn't. - Important: deleting a follower should do more that just delete the object, see https://codeberg.org/grunfink/snac2/issues/43#issuecomment-956721 ## Wishlist @@ -32,10 +30,6 @@ Track "FEP-ef61: Portable Objects" https://codeberg.org/fediverse/fep/src/branch Integrate "Added handling for International Domain Names" PR https://codeberg.org/grunfink/snac2/pulls/104 -Do something about Akkoma and Misskey's quoted replies (they use the `quoteUrl` field instead of `inReplyTo`). - -Take a look at crashes in the brittle Mastodon official app (crashes when hitting the reply button, crashes or 'ownVotes is null' errors when trying to show polls). - The 'history' pages are just monthly HTML snapshots of the local timeline. This is ok and cheap and easy, but is problematic if you e.g. intentionally delete a post because it will remain there in the history forever. If you activate local timeline purging, purged entries will remain in the history as 'ghosts', which may or may not be what the user wants. ## Closed @@ -381,3 +375,9 @@ Add command-line tools for creating and manipulating lists (2025-04-18T10:04:41+ Do a [Webmention](https://www.w3.org/TR/webmention/) to every link written in a post (2025-05-04T11:16:21+0200). The local purge should generate `Delete` activities for local posts (2025-07-25T18:55:16+0200). + +Unfollowing guppe groups seems to work (http status of 200), but messages continue to arrive as if it didn't. (No longer relevant, as guppe seems to not exist anymore) (2025-12-09T05:31:56+0100). + +Do something about Akkoma and Misskey's quoted replies (they use the `quoteUrl` field instead of `inReplyTo`) (2025-12-09T05:31:56+0100). + +Take a look at crashes in the brittle Mastodon official app (crashes when hitting the reply button, crashes or 'ownVotes is null' errors when trying to show polls) (2025-12-09T05:31:56+0100). -- cgit v1.2.3 From ee7483cf0dd007d104a815fce47a0d5f050ca870 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 13:31:37 +0100 Subject: New query variable terse=anything. If set to any value, a public post page doesn't show any headline. --- html.c | 38 +++++++++++++++++++++++--------------- httpd.c | 4 ++-- snac.h | 2 +- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/html.c b/html.c index 9ac57f8..32ed057 100644 --- a/html.c +++ b/html.c @@ -2996,7 +2996,7 @@ xs_html *html_footer(const snac *user) xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int skip, int show, int show_more, const char *title, const char *page, - int utl, const char *error) + int utl, const char *error, int terse) /* returns the HTML for the timeline */ { xs_list *p = (xs_list *)list; @@ -3024,7 +3024,11 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, if (user) { head = html_user_head(user, desc, alternate); - body = html_user_body(user, read_only); + + if (terse) + body = xs_html_tag("body", NULL); + else + body = html_user_body(user, read_only); } else { head = html_instance_head(); @@ -3902,6 +3906,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, int cache = 1; int save = 1; int proxy = 0; + int terse = 0; const char *v; const xs_dict *q_vars = xs_dict_get(req, "q_vars"); @@ -3914,6 +3919,9 @@ int html_get_handler(const xs_dict *req, const char *q_path, return HTTP_STATUS_NOT_FOUND; } + if (!xs_is_null(xs_dict_get(q_vars, "terse"))) + terse = 1; + if (strcmp(v, "share-bridge") == 0) { /* temporary redirect for a post */ const char *login = xs_dict_get(q_vars, "login"); @@ -4014,7 +4022,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) { /** empty public timeline for private users **/ - *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1, error); + *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4037,7 +4045,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *pins = pinned_list(&snac); pins = xs_list_cat(pins, list); - *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error); + *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -4161,7 +4169,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *title = xs_fmt(xs_list_len(tl) ? L("Search results for tag %s") : L("Nothing found for tag %s"), q); - *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0, error); + *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4186,7 +4194,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, title = xs_fmt(L("Nothing found for '%s'"), q); *body = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show, - title, page, 0, error); + title, page, 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4213,7 +4221,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); *body = html_timeline(&snac, list, 0, skip, show, - more, NULL, "/admin", 1, error); + more, NULL, "/admin", 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -4240,7 +4248,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list0 = xs_list_append(xs_list_new(), md5); xs *list = timeline_top_level(&snac, list0); - *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error); + *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4281,7 +4289,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *next = timeline_instance_list(skip + show, 1); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), L("Showing instance timeline"), "/instance", 0, error); + xs_list_len(next), L("Showing instance timeline"), "/instance", 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4296,7 +4304,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = pinned_list(&snac); *body = html_timeline(&snac, list, 0, skip, show, - 0, L("Pinned posts"), "", 0, error); + 0, L("Pinned posts"), "", 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4311,7 +4319,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = bookmark_list(&snac); *body = html_timeline(&snac, list, 0, skip, show, - 0, L("Bookmarked posts"), "", 0, error); + 0, L("Bookmarked posts"), "", 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4326,7 +4334,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = draft_list(&snac); *body = html_timeline(&snac, list, 0, skip, show, - 0, L("Post drafts"), "", 0, error); + 0, L("Post drafts"), "", 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4341,7 +4349,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = scheduled_list(&snac); *body = html_timeline(&snac, list, 0, skip, show, - 0, L("Scheduled posts"), "", 0, error); + 0, L("Scheduled posts"), "", 0, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4367,7 +4375,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *title = xs_fmt(L("Showing timeline for list '%s'"), name); *body = html_timeline(&snac, ttl, 0, skip, show, - xs_list_len(next), title, base, 1, error); + xs_list_len(next), title, base, 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } @@ -4387,7 +4395,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, list = xs_list_append(list, md5); - *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1, error); + *body = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1, error, terse); *b_size = strlen(*body); status = HTTP_STATUS_OK; } diff --git a/httpd.c b/httpd.c index a8cd849..f93f197 100644 --- a/httpd.c +++ b/httpd.c @@ -257,7 +257,7 @@ int server_get_handler(xs_dict *req, const char *q_path, else { xs *page = xs_fmt("?t=%s", t); xs *title = xs_fmt(L("Search results for tag #%s"), t); - *body = html_timeline(NULL, tl, 0, skip, show, more, title, page, 0, NULL); + *body = html_timeline(NULL, tl, 0, skip, show, more, title, page, 0, NULL, 0); } } else @@ -265,7 +265,7 @@ int server_get_handler(xs_dict *req, const char *q_path, /** instance timeline **/ xs *tl = timeline_instance_list(0, 30); *body = html_timeline(NULL, tl, 0, 0, 0, 0, - L("Recent posts by users in this instance"), NULL, 0, NULL); + L("Recent posts by users in this instance"), NULL, 0, NULL, 0); } else *body = greeting_html(); diff --git a/snac.h b/snac.h index 732d0b2..01947c5 100644 --- a/snac.h +++ b/snac.h @@ -411,7 +411,7 @@ xs_str *encode_html(const char *str); xs_str *html_timeline(snac *user, const xs_list *list, int read_only, int skip, int show, int show_more, - const char *title, const char *page, int utl, const char *error); + const char *title, const char *page, int utl, const char *error, int terse); int html_get_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype, -- cgit v1.2.3 From 1b3a36de4e1f9167e36c47fa4e40de1fed389e1c Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 13:34:21 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7727aec..57f3048 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,8 @@ Mastodon API: Fix for some client notifications (contributed by violette). +If the query variable `terse` of a public post page is set to anything, no header is shown. + ## 2.85 Quoted posts are now shown. -- cgit v1.2.3 From 481c0315ef7ccd2eaf0ec9c6eaa17cbbd7efeb2c Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 9 Dec 2025 13:38:56 +0100 Subject: If terse is set, history is also hidden. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index 32ed057..8f7c4a9 100644 --- a/html.c +++ b/html.c @@ -3248,7 +3248,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, if (list && user && read_only) { /** history **/ - if (xs_type(xs_dict_get(srv_config, "disable_history")) != XSTYPE_TRUE) { + if (xs_type(xs_dict_get(srv_config, "disable_history")) != XSTYPE_TRUE && !terse) { xs_html *ul = xs_html_tag("ul", NULL); xs_html *history = xs_html_tag("div", -- cgit v1.2.3 From e66446a57d79623227353e57cd553cbb42e4ca93 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 07:51:30 +0100 Subject: Bumped version. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 01947c5..e1d25f2 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ -#define VERSION "2.85" +#define VERSION "2.86-dev" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From 85ed0eb0d535700a5df837c37f51848811e461a0 Mon Sep 17 00:00:00 2001 From: violette Date: Thu, 18 Dec 2025 07:58:24 +0100 Subject: Added emoji reactions (contributed by violette). --- activitypub.c | 161 ++++++++++++++++++++++++++++- data.c | 124 +++++++++++++++++++++-- format.c | 3 + html.c | 317 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- main.c | 2 +- mastoapi.c | 160 ++++++++++++++++++++++++++++- snac.h | 10 +- xs_unicode.h | 7 ++ xs_url.h | 33 ++++++ 9 files changed, 786 insertions(+), 31 deletions(-) diff --git a/activitypub.c b/activitypub.c index 90230d8..19f0cc6 100644 --- a/activitypub.c +++ b/activitypub.c @@ -4,6 +4,7 @@ #include "xs.h" #include "xs_json.h" #include "xs_curl.h" +#include "xs_url.h" #include "xs_mime.h" #include "xs_openssl.h" #include "xs_regex.h" @@ -1530,11 +1531,24 @@ xs_dict *msg_update(snac *snac, const xs_dict *object) xs_dict *msg_admiration(snac *snac, const char *object, const char *type) -/* creates a Like or Announce message */ +/* creates a Like, Announce or EmojiReact message */ { xs *a_msg = NULL; xs_dict *msg = NULL; xs *wrk = NULL; + char t = 0; + + switch (*type) { + case 'L': + t = 'l'; + break; + case 'A': + t = 'a'; + break; + case 'E': + t = 'e'; + break; + } /* call the object */ timeline_request(snac, &object, &wrk, 0); @@ -1542,7 +1556,7 @@ xs_dict *msg_admiration(snac *snac, const char *object, const char *type) if (valid_status(object_get(object, &a_msg))) { xs *rcpts = xs_list_new(); xs *o_md5 = xs_md5_hex(object, strlen(object)); - xs *id = xs_fmt("%s/%s/%s", snac->actor, *type == 'L' ? "l" : "a", o_md5); + xs *id = xs_fmt("%s/%c/%s", snac->actor, t, o_md5); msg = msg_base(snac, type, id, snac->actor, "@now", object); @@ -1586,6 +1600,113 @@ xs_dict *msg_repulsion(snac *user, const char *id, const char *type) return msg; } +xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid) +/* creates an emoji reaction from a local user */ +{ + xs_dict *n_msg = msg_admiration(snac, mid, "EmojiReact"); + + eid = xs_strip_chars_i(xs_dup(eid), ":"); + xs *content = NULL; + xs *tag = xs_list_new(); + xs *dict = xs_dict_new(); + xs *icon = xs_dict_new(); + xs *accounts = xs_list_new(); + + /* may be a default emoji */ + xs *eidd = xs_dup(eid); + const char *eidda = eid; + + if (xs_is_emoji(xs_utf8_dec(&eidda))) + content = xs_dup(eid); + + else if (*eid == '%') { + content = xs_url_dec_emoji(xs_dup(eid)); + if (content == NULL) { + return NULL; + } + } + else if (xs_dict_get(emojis(), xs_fmt(":%s:", eid)) == NULL) + return NULL; + else { + content = xs_fmt(":%s:", eid); + icon = xs_dict_set(icon, "type", "Image"); + icon = xs_dict_set(icon, "url", xs_fmt("%s/s/%s.png", snac->actor, eid)); + dict = xs_dict_set(dict, "icon", icon); + + dict = xs_dict_set(dict, "id", xs_fmt("%s/s/%s.png", snac->actor, eid)); + dict = xs_dict_set(dict, "name", content); + dict = xs_dict_set(dict, "type", "Emoji"); + tag = xs_list_append(tag, dict); + } + + accounts = xs_list_append(accounts, snac->actor); + + n_msg = xs_dict_set(n_msg, "content", content); + n_msg = xs_dict_set(n_msg, "accounts", accounts); + n_msg = xs_dict_set(n_msg, "attributedTo", xs_list_get(xs_dup(xs_dict_get(n_msg, "to")), 1)); + n_msg = xs_dict_set(n_msg, "accountId", snac->uid); + n_msg = xs_dict_set(n_msg, "tag", tag); + + int ret = timeline_admire(snac, xs_dict_get(n_msg, "object"), snac->actor, 1, n_msg); + if (ret == 200 || ret == 201) { + enqueue_message(snac, n_msg); + return n_msg; + } + + return NULL; +} + +xs_dict *msg_emoji_unreact(snac *user, const char *mid, const char *eid) +/* creates an Undo + emoji reaction message */ +{ + xs *a_msg = NULL; + xs_dict *msg = NULL; + + if (valid_status(object_get(mid, &a_msg))) { + /* create a clone of the original admiration message */ + xs *object = msg_admiration(user, mid, "EmojiReact"); + + /* delete the published date */ + object = xs_dict_del(object, "published"); + + /* create an undo message for this object */ + msg = msg_undo(user, object); + + /* copy the 'to' field */ + msg = xs_dict_set(msg, "to", xs_dict_get(object, "to")); + } + + xs *emotes = object_get_emoji_reacts(mid); + const char *v; + int c = 0; + + /* may be a default emoji */ + if (strlen(eid) == 12 && *eid == '%') { + eid = xs_url_dec(eid); + if (eid == NULL) { + return NULL; + } + } + + /* lets get all emotes for this msg, and compare it to our content */ + while (xs_list_next(emotes, &v, &c)) { + xs_dict *e = NULL; + if (valid_status(object_get_by_md5(v, &e))) { + const char *content = xs_dict_get(e, "content"); + const char *id = xs_dict_get(e, "id"); + const char *actor = xs_dict_get(e, "actor"); + /* maybe formated as :{emoteName}: too */ + if (xs_str_in(eid, content) != -1) + if (strcmp(user->actor, actor) == 0) { + object_rm_emoji_react(mid, id); + return msg; + } + } + } + + return NULL; +} + xs_dict *msg_actor_place(snac *user, const char *label) /* creates a Place object, if the user has a location defined */ @@ -2605,6 +2726,16 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) else if (strcmp(type, "Undo") == 0) { /** **/ const char *id = xs_dict_get(object, "object"); + const char *content = xs_dict_get(object, "content"); + /* misskey sends emojis as like + tag */ + xs *cd = xs_dup(content); + const char *sna = cd; + const xs_dict *tag = xs_dict_get(object, "tag"); + unsigned int utf = xs_utf8_dec((const char **)&sna); + + int isEmoji = 0; + if (xs_is_emoji(utf) || (tag && xs_list_len(tag) > 0)) + isEmoji = 1; if (xs_type(object) != XSTYPE_DICT) { snac_debug(snac, 1, xs_fmt("undo: overriding utype %s | %s | %s", @@ -2633,8 +2764,19 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) else snac_log(snac, xs_fmt("error deleting follower %s", actor)); } + /* *key emojis are like w/ Emoji tag */ + else + if ((isEmoji || strcmp(utype, "EmojiReact") == 0) && + (content && strcmp(content, "♥") != 0)) { + const xs_val *mid = xs_dict_get(object, "id"); + int status = object_rm_emoji_react((char *)id, mid); + /* ensure *key notifications type */ + utype = "EmojiReact"; + + snac_log(snac, xs_fmt("Undo 'EmojiReact' for %s %d", id, status)); + } else - if (strcmp(utype, "Like") == 0 || strcmp(utype, "EmojiReact") == 0) { /** **/ + if (strcmp(utype, "Like") == 0) { /** **/ int status = object_unadmire(id, actor, 1); snac_log(snac, xs_fmt("Undo '%s' for %s %d", utype, id, status)); @@ -2771,13 +2913,22 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) } else if (strcmp(type, "Like") == 0 || strcmp(type, "EmojiReact") == 0) { /** **/ + /* misskey sends emojis as Like + tag. + * It is easier to handle them both at the same time. */ + const char *sna = xs_dict_get(msg, "content"); + const xs_dict *tag = xs_dict_get(msg, "tag"); + unsigned int utf = xs_utf8_dec((const char **)&sna); + + if (xs_is_emoji(utf) || (tag && xs_list_len(tag) > 0)) + type = "EmojiReact"; + if (xs_type(object) == XSTYPE_DICT) object = xs_dict_get(object, "id"); if (xs_is_null(object)) snac_log(snac, xs_fmt("malformed message: no 'id' field")); else - if (timeline_admire(snac, object, actor, 1) == HTTP_STATUS_CREATED) + if (timeline_admire(snac, object, actor, 1, xs_dup(msg)) == HTTP_STATUS_CREATED) snac_log(snac, xs_fmt("new '%s' %s %s", type, actor, object)); else snac_log(snac, xs_fmt("repeated '%s' from %s to %s", type, actor, object)); @@ -2818,7 +2969,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) xs *this_relay = xs_fmt("%s/relay", srv_baseurl); if (strcmp(actor, this_relay) != 0) { - if (valid_status(timeline_admire(snac, object, actor, 0))) + if (valid_status(timeline_admire(snac, object, actor, 0, a_msg))) snac_log(snac, xs_fmt("new 'Announce' %s %s", actor, object)); else snac_log(snac, xs_fmt("repeated 'Announce' from %s to %s", diff --git a/data.c b/data.c index 688d2e3..07eea3c 100644 --- a/data.c +++ b/data.c @@ -1043,6 +1043,14 @@ xs_list *object_children(const char *id) } +xs_list *object_get_emoji_reacts(const char *id) +/* returns the list of an object's emoji reactions */ +{ + xs *fn = _object_index_fn(id, "_e.idx"); + return index_list(fn, XS_ALL); +} + + xs_list *object_likes(const char *id) { xs *fn = _object_index_fn(id, "_l.idx"); @@ -1086,12 +1094,26 @@ int object_admire(const char *id, const char *actor, int like) int object_unadmire(const char *id, const char *actor, int like) -/* actor no longer likes or announces this object */ +/* actor retrives their likes, announces or emojis this object */ { + switch (like) { + case 0: + like = 'a'; + break; + case 1: + like = 'l'; + break; + case 2: + like = 'e'; + break; + } int status; xs *fn = _object_fn(id); - fn = xs_replace_i(fn, ".json", like ? "_l.idx" : "_a.idx"); + char sfx[7] = "_x.idx"; + sfx[1] = like; + + fn = xs_replace_i(fn, ".json", sfx); status = index_del(fn, actor); @@ -1099,7 +1121,46 @@ int object_unadmire(const char *id, const char *actor, int like) index_gc(fn); srv_debug(0, - xs_fmt("object_unadmire (%s) %s %s %d", like ? "Like" : "Announce", actor, fn, status)); + xs_fmt("object_unadmire (%s) %s %s %d", like >= 'e' ? + (like == 'l' ? "Like" : "EmojiReact") : "Announce" , actor, fn, status)); + + return status; +} + +int object_emoji_react(const char *mid, const char *eid) +/* actor reacts w/ an emoji */ +{ + int status = HTTP_STATUS_OK; + xs *fn = _object_fn(mid); + + fn = xs_replace_i(fn, ".json", "_e.idx"); + + if (!index_in(fn, eid)) { + status = index_add(fn, eid); + + srv_debug(1, xs_fmt("object_emoji_react (%s) added %s to %s", "EmojiReact", eid, fn)); + } + + return status; +} + + +int object_rm_emoji_react(const char *mid, const char *eid) +/* actor retrives their emoji reaction */ +{ + int status; + xs *fn = _object_fn(mid); + + fn = xs_replace_i(fn, ".json", "_e.idx"); + + status = index_del(fn, eid); + object_del(eid); + + if (valid_status(status)) + index_gc(fn); + + srv_debug(0, + xs_fmt("object_unadmire (EmojiReact) %s %s %d", eid, fn, status)); return status; } @@ -1506,19 +1567,47 @@ int timeline_add(snac *snac, const char *id, const xs_dict *o_msg) } -int timeline_admire(snac *snac, const char *id, const char *admirer, int like) -/* updates a timeline entry with a new admiration */ +int timeline_emoji_react(const char *act, const char *id, xs_dict *msg) +/* adds an emoji reaction to a message */ +{ + msg = xs_dict_append(msg, "attributedTo", act); + msg = xs_dict_set(msg, "type", "EmojiReact"); + const char *emote_id = xs_dict_get(msg, "id"); + + int ret = object_add(emote_id, msg); + if (ret == HTTP_STATUS_OK || ret == HTTP_STATUS_CREATED) + ret = object_emoji_react(id, emote_id); + + return ret; +} + + +int timeline_admire(snac *snac, const char *id, + const char *admirer, int like, xs_dict *msg) +/* updates a timeline entry with a new admiration or emoji reaction */ { + int ret; + const char *content = xs_dict_get_path(msg, "content"); + const char *type = xs_dict_get_path(msg, "type"); + /* if we are admiring this, add to both timelines */ if (!like && strcmp(admirer, snac->actor) == 0) { object_user_cache_add(snac, id, "public"); object_user_cache_add(snac, id, "private"); } - int ret = object_admire(id, admirer, like); + /* use utf <3 as a like, as it is ugly */ + if (type && xs_match(type, "Like|EmojiReact|Emoji") && + content && strcmp(content, "❤") != 0) { + ret = timeline_emoji_react(xs_dup(snac->actor), id, xs_dup(msg)); + snac_debug(snac, 1, xs_fmt("timeline_emoji_react %s", id)); + } - snac_debug(snac, 1, xs_fmt("timeline_admire (%s) %s %s", - like ? "Like" : "Announce", id, admirer)); + else { + ret = object_admire(id, admirer, like); + snac_debug(snac, 1, xs_fmt("timeline_admire (%s) %s %s", + like ? "Like" : "Announce", id, admirer)); + } return ret; } @@ -1867,6 +1956,25 @@ xs_list *muted_list(snac *user) return l; } +/** emojis react **/ + +const xs_str *emoji_reacted(snac *user, const char *id) +/* returns the emoji an user reacted to a message */ +{ + xs *emojis = object_get_emoji_reacts(id); + int c = 0; + const char *v; + xs_dict *msg; + + while (xs_list_next(emojis, &v, &c)) { + if (object_get_by_md5(v, &msg)) { + const xs_val *act = xs_dict_get(msg, "actor"); + if (act && strcmp(act, user->actor) == 0) + return xs_dict_get(msg, "content"); + } + } + return NULL; +} /** bookmarking **/ diff --git a/format.c b/format.c index 84c634d..4f93b7b 100644 --- a/format.c +++ b/format.c @@ -459,6 +459,9 @@ xs_str *sanitize(const char *content) char *p; const char *v; + if (!content) + return NULL; + sl = xs_regex_split(content, "]+>"); p = sl; diff --git a/html.c b/html.c index 8f7c4a9..8cc0067 100644 --- a/html.c +++ b/html.c @@ -54,9 +54,10 @@ int login(snac *user, const xs_dict *headers) return logged_in; } - -xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *proxy) -/* replaces all the :shortnames: with the emojis in tag */ +xs_str *_replace_shortnames(xs_str *s, const xs_list *tag, int ems, + const char *proxy, const xs_list *cl, const char *act) +/* replace but also adds a class list and an actor in its alt text. + * Used for emoji reactions */ { if (!xs_is_null(tag)) { xs *tag_list = NULL; @@ -69,11 +70,15 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p tag_list = xs_dup(tag); } - xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems); + xs *style = xs_fmt("max-height: %dem; max-width: %dem;", ems, ems); xs *class = xs_fmt("snac-emoji snac-emoji-%d-em", ems); + if (cl) + class = xs_str_cat(class, " ", xs_join(cl, " ")); - const xs_dict *v; int c = 0; + const xs_val *v; + + c = 0; xs_set rep_emoji; xs_set_init(&rep_emoji); @@ -100,6 +105,8 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p if (!xs_is_string(mt)) mt = xs_mime_by_ext(u); + act = act ? xs_fmt("%s\n%s", n, act) : xs_fmt("%s", n); + if (strcmp(mt, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg"))) s = xs_replace_i(s, n, ""); else { @@ -108,8 +115,8 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p xs_html *img = xs_html_sctag("img", xs_html_attr("loading", "lazy"), xs_html_attr("src", url), - xs_html_attr("alt", n), - xs_html_attr("title", n), + xs_html_attr("alt", act), + xs_html_attr("title", act), xs_html_attr("class", class), xs_html_attr("style", style)); @@ -130,6 +137,13 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p } +xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *proxy) +/* replaces all the :shortnames: with the emojis in tag */ +{ + return _replace_shortnames(s, tag, ems, proxy, NULL, NULL); +} + + xs_str *actor_name(xs_dict *actor, const char *proxy) /* gets the actor name */ { @@ -430,6 +444,52 @@ void html_note_render_visibility(snac* user, xs_html *form, const int scope) xs_html_add(form, paragraph); } +/* html_note but moddled for emoji's needs. here and not bellow, since the + * other one is already so complex. */ +xs_html *html_emoji(snac *user, const char *summary, + const char *div_id, const char *form_id, + const char* placeholder, const char *post_id, + const char* eid) +{ + xs *action = xs_fmt("%s/admin/action", user->actor); + + xs_html *form; + const int react = eid == NULL ? 0 : 1; + + xs_html *note = xs_html_tag("div", + xs_html_tag("details", + xs_html_tag("summary", + xs_html_text(summary)), + xs_html_tag("p", NULL), + xs_html_tag("div", + xs_html_attr("class", "snac-note"), + xs_html_attr("id", div_id), + form = xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", action), + xs_html_attr("enctype", "multipart/form-data"), + xs_html_attr("id", form_id), + xs_html_sctag("input", + xs_html_attr("type", "hidden"), + xs_html_attr("name", "id"), + xs_html_attr("value", post_id)), + xs_html_sctag("input", + xs_html_attr("type", react ? "hidden" : "text"), + xs_html_attr("name", "eid"), + xs_html_attr(react ? "value" : "placeholder", react ? eid : placeholder)), + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "submit"), + xs_html_attr("name", "action"), + xs_html_attr("eid", "action"), + xs_html_attr("value", react ? L("EmojiUnreact") : L("EmojiReact"))), + xs_html_text(" "), + xs_html_tag("p", NULL))))); + + return note; +} + xs_html *html_note(snac *user, const char *summary, const char *div_id, const char *form_id, const char *ta_plh, const char *ta_content, @@ -1356,6 +1416,28 @@ xs_html *html_top_controls(snac *user) xs_html_attr("value", L("Like"))), xs_html_text(" "), xs_html_text(L("(by URL)"))), + xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", ops_action), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "eid"), + xs_html_attr("required", "required"), + xs_html_attr("placeholder", ":neocat:")), + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "id"), + xs_html_attr("required", "required"), + xs_html_attr("placeholder", "https:/" "/fedi.example.com/bob/...")), + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "submit"), + xs_html_attr("name", "action"), + xs_html_attr("value", L("EmojiReact"))), + xs_html_text(" "), + xs_html_text(L("(by URL)"))), xs_html_tag("p", NULL))); /** user settings **/ @@ -2019,6 +2101,21 @@ xs_html *html_entry_controls(snac *user, const char *actor, xs_html_tag("p", NULL)); } + { /** emoji react **/ + /* the post textarea */ + xs *div_id = xs_fmt("%s_reply", md5); + xs *form_id = xs_fmt("%s_reply_form", md5); + + xs_html_add(controls, xs_html_tag("div", + xs_html_tag("p", NULL), + html_emoji( + user, L("Emoji react"), + div_id, form_id, + ":neocat:", id, + emoji_reacted(user, id))), + xs_html_tag("p", NULL)); + } + { /** reply **/ /* the post textarea */ xs *ct = build_mentions(user, msg); @@ -2345,6 +2442,168 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_add(snac_content_wrap, snac_content); + /* add all emoji reacts */ + int is_emoji = 0; + { + int c = 0; + const xs_dict *k; + xs *ls = xs_list_new(); + xs *sfrl = xs_dict_new(); + xs *rl = object_get_emoji_reacts(id); + + xs_dict *m = NULL; + while (xs_list_next(rl, &v, &c)) { + if (valid_status(object_get_by_md5(v, &m))) { + const char *content = xs_dict_get(m, "content"); + const char *actor = xs_dict_get(m, "actor"); + const xs_list *contentl = xs_dict_get(sfrl, content); + xs *actors = xs_list_new(); + actors = xs_list_append(actors, actor); + char me = actor && user && strcmp(actor, user->actor) == 0; + int count = 1; + + if (contentl) { + count = atoi(xs_list_get(contentl, 0)) + 1; + const xs_list *actorsc = xs_list_get(contentl, 1); + if (strncmp(xs_list_get(contentl, 2), "1", 1) == 0) + me = 1; + + if (xs_list_in(actorsc, actor) != -1) { + xs_free(actors); + actors = xs_dup(actorsc); + } + else + actors = xs_list_cat(actors, actorsc); + } + + xs *fl = xs_list_new(); + fl = xs_list_append(fl, xs_fmt("%d", count), actors, xs_fmt("%d", me)); + sfrl = xs_dict_append(sfrl, content, fl); + } + } + + c = 0; + + while (xs_list_next(rl, &k, &c)) { + if (valid_status(object_get_by_md5(k, &m))) { + const xs_dict *tag = xs_dict_get(m, "tag"); + const xs_dict *ide = xs_dict_get(m, "id"); + + const char *content = xs_dict_get(m, "content"); + const char *shortname; + shortname = xs_dict_get(m, "content"); + + const xs_list *items = xs_dict_get(sfrl, content); + const char *nb = xs_list_get(items, 0); + const xs_list *actors = xs_list_get(items, 1); + const char me = *xs_list_get(items, 2) == '1'; + + if (!xs_is_null(nb)) { + is_emoji = 1; + + const char *act = atoi(nb) > 1 ? + xs_fmt("%d different actors \n\t%s", atoi(nb), xs_join(actors, ",\n\t")) : + xs_dict_get(m, "actor"); + + xs *class = xs_list_new(); + class = xs_list_append(class, "snac-reaction"); + + xs_html *ret = NULL; + if (tag && shortname) { + xs *cl = xs_list_new(); + cl = xs_list_append(cl, "snac-reaction-image"); + xs *emoji = _replace_shortnames(xs_dup(shortname), tag, 2, proxy, cl, act); + + if (me) + class = xs_list_append(class, "snac-reacted"); + + ret = xs_html_tag("button", + xs_html_attr("type", "submit"), + xs_html_attr("name", "action"), + xs_html_attr("value", me ? L("EmojiReact") : L("EmojiUnreact")), + xs_html_raw(emoji), + xs_html_tag("span", + xs_html_raw(nb), + xs_html_attr("style", "padding-left: 5px;")), + xs_html_attr("title", act), + xs_html_attr("class", xs_join(class, " "))); + + if (!(ide && xs_startswith(ide, srv_baseurl))) + xs_html_add(ret, xs_html_attr("disabled", "true")); + } + else if (shortname) { + xs *sn = xs_dup(shortname); + const char *sna = sn; + unsigned int utf = xs_utf8_dec((const char **)&sna); + + if (xs_is_emoji(utf)) { + const char *style = "font-size: large;"; + if (me) + class = xs_list_append(class, "snac-reacted"); + ret = xs_html_tag("button", + xs_html_attr("type", "submit"), + xs_html_attr("name", "action"), + xs_html_attr("value", me ? L("EmojiUnreact") : L("EmojiReact")), + xs_html_raw(xs_fmt("&#%d", utf)), + xs_html_tag("span", + xs_html_raw(nb), + xs_html_attr("style", "font-size: initial; padding-left: 5px;")), + xs_html_attr("title", act), + xs_html_attr("class", xs_join(class, " ")), + xs_html_attr("style", style)); + } + } + if (ret) { + xs *s1; + if (user) { + xs *action = xs_fmt("%s/admin/action", user->actor); + xs *form_id = xs_fmt("%s_reply_form", md5); + + xs_html *form = + xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", action), + xs_html_attr("enctype", "multipart/form-data"), + xs_html_attr("style", "display: inline-flex;" + "vertical-align: middle;"), + xs_html_attr("id", form_id), + xs_html_sctag("input", + xs_html_attr("type", "hidden"), + xs_html_attr("name", "id"), + xs_html_attr("value", id)), + xs_html_sctag("input", + xs_html_attr("type", "hidden"), + xs_html_attr("name", "eid"), + xs_html_attr("value", shortname)), + ret); + s1 = xs_html_render(form); + } + else + s1 = xs_html_render(ret); + + ls = xs_list_append(ls, s1); + sfrl = xs_dict_del(sfrl, content); + } + } + } + } + + c = 0; + + xs_html *emoji_div; + if (xs_list_len(ls) > 0) { + emoji_div = xs_html_tag("div", xs_html_text(L("Emoji reactions: ")), + xs_html_attr("class", "snac-reaction-div")); + + while (ls != NULL && xs_list_next(ls, &k, &c)) + xs_html_add(emoji_div, xs_html_raw(k)); + + xs_html_add(snac_content_wrap, emoji_div); + } + + } + { /** build the content string **/ const char *content = xs_dict_get(msg, "content"); @@ -2371,7 +2630,8 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, c = xs_replace_i(c, "

", "

"); - c = xs_str_cat(c, "

"); + if (is_emoji == 0) + c = xs_str_cat(c, "

"); /* replace the :shortnames: */ c = replace_shortnames(c, xs_dict_get(msg, "tag"), 2, proxy); @@ -3686,9 +3946,18 @@ xs_str *html_notifications(snac *user, int skip, int show) if (strcmp(type, "EmojiReact") == 0 || strcmp(type, "Like") == 0) { const char *content = xs_dict_get_path(noti, "msg.content"); + xs *cd = xs_dup(content); + const char *sna = cd; + const xs_dict *tag = xs_dict_get_path(noti, "msg.tag"); + unsigned int utf = xs_utf8_dec((const char **)&sna); + + int isEmoji = 0; + if (xs_is_emoji(utf) || (tag && xs_list_len(tag) > 0)) + isEmoji = 1; + if (xs_type(content) == XSTYPE_STRING) { xs *emoji = replace_shortnames(xs_dup(content), xs_dict_get_path(noti, "msg.tag"), 1, proxy); - wrk = xs_fmt("%s (%s️)", type, emoji); + wrk = xs_fmt("%s (%s️)", isEmoji ? "EmojiReact" : "Like", emoji); label = wrk; } } @@ -4583,8 +4852,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *msg = msg_admiration(&snac, id, *action == 'L' ? "Like" : "Announce"); if (msg != NULL) { + timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, *action == 'L' ? 1 : 0, msg); enqueue_message(&snac, msg); - timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, *action == 'L' ? 1 : 0); status = HTTP_STATUS_SEE_OTHER; } @@ -4892,12 +5161,36 @@ int html_post_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_SEE_OTHER; + if (strcmp(action, L("EmojiUnreact")) == 0) { /** **/ + const char *eid = xs_dict_get(p_vars, "eid"); + + if (eid != NULL) { + xs *n_msg = msg_emoji_unreact(&snac, id, eid); + + if (n_msg != NULL) + enqueue_message(&snac, n_msg); + } + } + else + if (strcmp(action, L("EmojiReact")) == 0) { /** **/ + const char *eid = xs_dict_get(p_vars, "eid"); + + eid = xs_strip_chars_i(xs_dup(eid), ":"); + + const xs_dict *ret = msg_emoji_init(&snac, id, eid); + /* fails if either invalid or already reacted */ + if (!ret) + ret = msg_emoji_unreact(&snac, id, eid); + if (!ret) + status = HTTP_STATUS_NOT_FOUND; + } + else if (strcmp(action, L("Like")) == 0) { /** **/ xs *msg = msg_admiration(&snac, id, "Like"); if (msg != NULL) { + timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 1, msg); enqueue_message(&snac, msg); - timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 1); } } else @@ -4905,8 +5198,8 @@ int html_post_handler(const xs_dict *req, const char *q_path, xs *msg = msg_admiration(&snac, id, "Announce"); if (msg != NULL) { + timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 0, msg); enqueue_message(&snac, msg); - timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 0); } } else diff --git a/main.c b/main.c index 6915bd0..4b0463e 100644 --- a/main.c +++ b/main.c @@ -498,7 +498,7 @@ int main(int argc, char *argv[]) if (msg != NULL) { enqueue_message(&snac, msg); - timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 0); + timeline_admire(&snac, xs_dict_get(msg, "object"), snac.actor, 0, ""); if (dbglevel) { xs_json_dump(msg, 4, stdout); diff --git a/mastoapi.c b/mastoapi.c index 9503447..1d99cd5 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1158,6 +1158,97 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) st = xs_dict_append(st, "tags", htl); st = xs_dict_append(st, "emojis", eml); } + { + xs *rl = object_get_emoji_reacts(id); + xs *frl = xs_list_new(); /* final */ + xs *sfrl = xs_dict_new(); /* seen */ + int c = 0; + const char *v; + + xs_dict *msg = NULL; + while (xs_list_next(rl, &v, &c)) { + if (valid_status(object_get_by_md5(v, &msg))) { + const char *content = xs_dict_get(msg, "content"); + const char *actor = xs_dict_get(msg, "actor"); + const xs_list *contentl = xs_dict_get(sfrl, content); + /* NOTE: idk when there are no actor, but i encountered that bug. + * Probably because of one of my previous attempts. + * Keeping this just in case, can remove later */ + const char *me = actor && strcmp(actor, snac->actor) == 0 ? + xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE); + int count = 1; + + if (contentl) { + count = atoi(xs_list_get(contentl, 0)) + 1; + if (strncmp(xs_list_get(contentl, 1), xs_stock(XSTYPE_TRUE), 1) == 0) + me = xs_stock(XSTYPE_TRUE); + } + + xs *fl = xs_list_new(); + fl = xs_list_append(fl, xs_fmt("%d", count), me); + sfrl = xs_dict_append(sfrl, content, fl); + } + } + + c = 0; + + while (xs_list_next(rl, &v, &c)) { + if (valid_status(object_get_by_md5(v, &msg))) { + xs *d1 = xs_dict_new(); + + const xs_dict *icon = xs_dict_get(xs_list_get(xs_dict_get(msg, "tag"), 0), "icon"); + const char *o_url = xs_dict_get(icon, "url"); + const char *name = xs_dict_get(msg, "content"); + const char *actor = xs_dict_get(msg, "actor"); + + xs *nm = xs_dup(name); + xs *url = NULL; + + if (!xs_is_null(o_url)) { + if (actor && snac && !strcmp(actor, snac->actor)) + url = make_url(o_url, NULL, 1); + else + url = xs_dup(o_url); + } + + xs *accounts = xs_list_new(); + if (actor) { + xs *d2 = xs_dict_new(); + object_get(actor, &d2); + xs *e_acct = mastoapi_account(snac, d2); + accounts = xs_list_append(accounts, e_acct); + } + + const xs_list *item = xs_dict_get(sfrl, nm); + const xs_str *nb = xs_list_get(item, 0); + const xs_val *me = xs_list_get(item, 1); + if (item == NULL) + continue; + + if (nm && strcmp(nm, "")) { + if (url && strcmp(url, "")) { + d1 = xs_dict_append(d1, "name", nm); + d1 = xs_dict_append(d1, "shortcode", nm); + d1 = xs_dict_append(d1, "accounts", accounts); + d1 = xs_dict_append(d1, "me", me); + d1 = xs_dict_append(d1, "url", url); + d1 = xs_dict_append(d1, "static_url", url); + d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); + d1 = xs_dict_append(d1, "count", nb); + } else { + d1 = xs_dict_append(d1, "name", nm); + d1 = xs_dict_append(d1, "count", nb); + d1 = xs_dict_append(d1, "me", me); + d1 = xs_dict_append(d1, "visible_in_picker", xs_stock(XSTYPE_TRUE)); + } + sfrl = xs_dict_del(sfrl, nm); + frl = xs_list_append(frl, d1); + } + } + } + + st = xs_dict_append(st, "reactions", frl); + } xs_free(idx); xs_free(ixc); @@ -2202,15 +2293,24 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, if (noti == NULL) continue; + const xs_dict *tag = xs_list_get(xs_dict_get_path(noti, "msg.tag"), 0); + const char *type = xs_dict_get(noti, "type"); const char *utype = xs_dict_get(noti, "utype"); const char *objid = xs_dict_get(noti, "objid"); const char *id = xs_dict_get(noti, "id"); const char *actid = xs_dict_get(noti, "actor"); + + int isEmoji = 0; + xs *fid = xs_replace(id, ".", ""); xs *actor = NULL; xs *entry = NULL; + if (tag) { + isEmoji = strcmp(xs_dict_get(tag, "type"), "Emoji") ? 0 : 1; + } + if (!valid_status(actor_get(actid, &actor))) continue; @@ -2234,9 +2334,12 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, } /* convert the type */ - if (strcmp(type, "Like") == 0 || strcmp(type, "EmojiReact") == 0) + if (strcmp(type, "Like") == 0 && !isEmoji) type = "favourite"; else + if (isEmoji || strcmp(type, "EmojiReact") == 0) + type = "reaction"; + else if (strcmp(type, "Announce") == 0) type = "reblog"; else @@ -2277,8 +2380,29 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, if (strcmp(type, "follow") != 0 && !xs_is_null(objid)) { xs *st = mastoapi_status(&snac1, entry); - if (st) + if (st) { mn = xs_dict_append(mn, "status", st); + + if (strcmp(type, "reaction") == 0 && !xs_is_null(objid)) { + const char *eid = NULL; + const char *url = NULL; + int utf = 0; + + const xs_dict *tag = xs_list_get(xs_dict_get_path(noti, "msg.tag"), 0); + const char *content = xs_dict_get_path(noti, "msg.content"); + + url = xs_dict_get(xs_dict_get(tag, "icon"), "url"); + eid = xs_dict_get(tag, "name"); + + if (eid && url) { + mn = xs_dict_append(mn, "emoji", eid); + mn = xs_dict_append(mn, "emoji_url", url); + } + + if (xs_is_emoji((utf = xs_utf8_dec(&content)))) + mn = xs_dict_append(mn, "name", xs_fmt("&#%d;", utf)); + } + } } out = xs_list_append(out, mn); @@ -2594,6 +2718,11 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, "\"max_expiration\":2629746," "\"max_options\":8,\"min_expiration\":300}"); cfg = xs_dict_append(cfg, "polls", d14); + + + xs *d15 = xs_json_loads("{\"max_reactions\":50}"); + cfg = xs_dict_append(cfg, "reactions", d15); + } ins = xs_dict_append(ins, "configuration", cfg); @@ -3219,7 +3348,7 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, if (n_msg != NULL) { enqueue_message(&snac, n_msg); - timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 1); + timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 1, msg); out = mastoapi_status(&snac, msg); } @@ -3234,13 +3363,36 @@ int mastoapi_post_handler(const xs_dict *req, const char *q_path, out = mastoapi_status(&snac, msg); } } + else + if (strcmp(op, "react") == 0) { /** **/ + const char *eid = xs_list_get(l, 5); + xs *n_msg = msg_emoji_init(&snac, id, eid); + if (n_msg) + out = mastoapi_status(&snac, n_msg); + } + else + if (strcmp(op, "unreact") == 0) { /** **/ + const char *eid = xs_list_get(l, 5); + xs *content = xs_fmt("%s", eid); + + if (eid) { + xs *n_msg = msg_emoji_unreact(&snac, id, content); + + if (n_msg != NULL) { + enqueue_message(&snac, n_msg); + + out = mastoapi_status(&snac, msg); + } + } + } + else if (strcmp(op, "reblog") == 0) { /** **/ xs *n_msg = msg_admiration(&snac, id, "Announce"); if (n_msg != NULL) { enqueue_message(&snac, n_msg); - timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 0); + timeline_admire(&snac, xs_dict_get(n_msg, "object"), snac.actor, 0, msg); out = mastoapi_status(&snac, msg); } diff --git a/snac.h b/snac.h index e1d25f2..3d98aac 100644 --- a/snac.h +++ b/snac.h @@ -146,12 +146,15 @@ void object_touch(const char *id); int object_admire(const char *id, const char *actor, int like); int object_unadmire(const char *id, const char *actor, int like); +int object_emoji_react(const char *mid, const char *eid); +int object_rm_emoji_react(const char *mid, const char *eid); int object_likes_len(const char *id); int object_announces_len(const char *id); xs_list *object_children(const char *id); xs_list *object_likes(const char *id); xs_list *object_announces(const char *id); +xs_list *object_get_emoji_reacts(const char *id); int object_parent(const char *md5, char parent[MD5_HEX_SIZE]); int object_user_cache_add(snac *snac, const char *id, const char *cachedir); @@ -180,7 +183,8 @@ xs_str *user_index_fn(snac *user, const char *idx_name); xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more); xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more); int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); -int timeline_admire(snac *snac, const char *id, const char *admirer, int like); +int timeline_admire(snac *snac, const char *id, const char *admirer, int like, xs_dict *msg); +int timeline_emoji_react(const char *atto, const char *id, xs_dict *o_msg); xs_list *timeline_top_level(snac *snac, const xs_list *list); void timeline_add_mark(snac *user); @@ -201,6 +205,8 @@ void unmute(snac *snac, const char *actor); int is_muted(snac *snac, const char *actor); xs_list *muted_list(snac *user); +const xs_str *emoji_reacted(snac *user, const char *id); + int is_bookmarked(snac *user, const char *id); int bookmark(snac *user, const char *id); int unbookmark(snac *user, const char *id); @@ -358,6 +364,8 @@ xs_list *get_attachments(const xs_dict *msg); xs_dict *msg_admiration(snac *snac, const char *object, const char *type); xs_dict *msg_repulsion(snac *user, const char *id, const char *type); +xs_dict *msg_emoji_init(snac *user, const char *mid, const char *eid); +xs_dict *msg_emoji_unreact(snac *user, const char *id, const char *type); xs_dict *msg_create(snac *snac, const xs_dict *object); xs_dict *msg_follow(snac *snac, const char *actor); diff --git a/xs_unicode.h b/xs_unicode.h index 67b3827..0b4de1c 100644 --- a/xs_unicode.h +++ b/xs_unicode.h @@ -22,6 +22,7 @@ int xs_unicode_nfc(unsigned int base, unsigned int diac, unsigned int *cpoint); int xs_unicode_is_alpha(unsigned int cpoint); int xs_unicode_is_right_to_left(unsigned int cpoint); + int xs_is_emoji(unsigned int cpoint); #ifdef _XS_H xs_str *xs_utf8_insert(xs_str *str, unsigned int cpoint, int *offset); @@ -134,6 +135,12 @@ static unsigned int xs_unicode_width_table[] = { 0x20000, 0x2fffd, 2 /* more CJK */ }; +/* magic number from https://en.wikipedia.org/wiki/Emoji#Unicode_blocks */ +int xs_is_emoji(unsigned int cpoint) { +/* returns wether the input is an utf8 emoji */ + return cpoint > 0x00A9 && cpoint < 0x1ffff; +} + int xs_unicode_width(unsigned int cpoint) /* returns the width in columns of a Unicode codepoint (somewhat simplified) */ { diff --git a/xs_url.h b/xs_url.h index 7bdff49..222771f 100644 --- a/xs_url.h +++ b/xs_url.h @@ -6,6 +6,7 @@ xs_str *xs_url_dec(const char *str); xs_str *xs_url_enc(const char *str); +xs_str *xs_url_dec_emoji(const char *str); xs_dict *xs_url_vars(const char *str); xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *header); @@ -79,6 +80,38 @@ xs_str *xs_url_dec(const char *str) } +xs_str *xs_url_dec_emoji(const char *str) +/* decodes an URL, returns NULL if not every char is an encoded hex */ +{ + xs_str *s = xs_str_new(NULL); + + while (*str) { + if (!xs_is_string(str)) + break; + + if (*str == '%') { + unsigned int i; + + if (sscanf(str + 1, "%02x", &i) == 1) { + unsigned char uc = i; + + if (!xs_is_string((char *)&uc)) + break; + + s = xs_append_m(s, (char *)&uc, 1); + str += 2; + } + } + else + return NULL; + + str++; + } + + return s; +} + + xs_str *xs_url_enc(const char *str) /* URL-encodes a string (RFC 3986) */ { -- cgit v1.2.3 From 7c065cbc9879582985cef3d3ad8b2ae197b8b851 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:09:10 +0100 Subject: Fixed some xs_dup() leaks. --- activitypub.c | 2 +- data.c | 2 +- html.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/activitypub.c b/activitypub.c index 19f0cc6..d19a428 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1643,7 +1643,7 @@ xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid) n_msg = xs_dict_set(n_msg, "content", content); n_msg = xs_dict_set(n_msg, "accounts", accounts); - n_msg = xs_dict_set(n_msg, "attributedTo", xs_list_get(xs_dup(xs_dict_get(n_msg, "to")), 1)); + n_msg = xs_dict_set(n_msg, "attributedTo", xs_list_get(xs_dict_get(n_msg, "to"), 1)); n_msg = xs_dict_set(n_msg, "accountId", snac->uid); n_msg = xs_dict_set(n_msg, "tag", tag); diff --git a/data.c b/data.c index 07eea3c..bbe92b8 100644 --- a/data.c +++ b/data.c @@ -1599,7 +1599,7 @@ int timeline_admire(snac *snac, const char *id, /* use utf <3 as a like, as it is ugly */ if (type && xs_match(type, "Like|EmojiReact|Emoji") && content && strcmp(content, "❤") != 0) { - ret = timeline_emoji_react(xs_dup(snac->actor), id, xs_dup(msg)); + ret = timeline_emoji_react(snac->actor, id, xs_dup(msg)); snac_debug(snac, 1, xs_fmt("timeline_emoji_react %s", id)); } diff --git a/html.c b/html.c index 8cc0067..dae84b7 100644 --- a/html.c +++ b/html.c @@ -5173,9 +5173,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, } else if (strcmp(action, L("EmojiReact")) == 0) { /** **/ - const char *eid = xs_dict_get(p_vars, "eid"); + xs *eid = xs_dup(xs_dict_get(p_vars, "eid")); - eid = xs_strip_chars_i(xs_dup(eid), ":"); + eid = xs_strip_chars_i(eid, ":"); const xs_dict *ret = msg_emoji_init(&snac, id, eid); /* fails if either invalid or already reacted */ -- cgit v1.2.3 From ce667add2cfedcc6d57c521899dfb9d2e3e6e1d7 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:13:54 +0100 Subject: Fixed some xs_join() uses. --- html.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index dae84b7..6ee0707 100644 --- a/html.c +++ b/html.c @@ -72,8 +72,10 @@ xs_str *_replace_shortnames(xs_str *s, const xs_list *tag, int ems, xs *style = xs_fmt("max-height: %dem; max-width: %dem;", ems, ems); xs *class = xs_fmt("snac-emoji snac-emoji-%d-em", ems); - if (cl) - class = xs_str_cat(class, " ", xs_join(cl, " ")); + if (cl) { + xs *l = xs_join(cl, " "); + class = xs_str_cat(class, " ", l); + } int c = 0; const xs_val *v; @@ -2501,9 +2503,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (!xs_is_null(nb)) { is_emoji = 1; - const char *act = atoi(nb) > 1 ? - xs_fmt("%d different actors \n\t%s", atoi(nb), xs_join(actors, ",\n\t")) : - xs_dict_get(m, "actor"); + xs *al = xs_join(actors, ",\n\t"); + xs *act = atoi(nb) > 1 ? + xs_fmt("%d different actors \n\t%s", atoi(nb), al) : + xs_dup(xs_dict_get(m, "actor")); xs *class = xs_list_new(); class = xs_list_append(class, "snac-reaction"); @@ -2517,6 +2520,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (me) class = xs_list_append(class, "snac-reacted"); + xs *l1 = xs_join(class, " "); ret = xs_html_tag("button", xs_html_attr("type", "submit"), xs_html_attr("name", "action"), @@ -2526,7 +2530,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_raw(nb), xs_html_attr("style", "padding-left: 5px;")), xs_html_attr("title", act), - xs_html_attr("class", xs_join(class, " "))); + xs_html_attr("class", l1)); if (!(ide && xs_startswith(ide, srv_baseurl))) xs_html_add(ret, xs_html_attr("disabled", "true")); @@ -2540,6 +2544,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *style = "font-size: large;"; if (me) class = xs_list_append(class, "snac-reacted"); + xs *l1 = xs_join(class, " "); ret = xs_html_tag("button", xs_html_attr("type", "submit"), xs_html_attr("name", "action"), @@ -2549,7 +2554,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_raw(nb), xs_html_attr("style", "font-size: initial; padding-left: 5px;")), xs_html_attr("title", act), - xs_html_attr("class", xs_join(class, " ")), + xs_html_attr("class", l1), xs_html_attr("style", style)); } } -- cgit v1.2.3 From c8ee70f6df7276b7c02f902cc544d209139697b2 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:20:15 +0100 Subject: Fixed some xs_fmt() usages. --- html.c | 11 +++++++---- mastoapi.c | 9 ++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index 6ee0707..c317c1a 100644 --- a/html.c +++ b/html.c @@ -55,7 +55,7 @@ int login(snac *user, const xs_dict *headers) } xs_str *_replace_shortnames(xs_str *s, const xs_list *tag, int ems, - const char *proxy, const xs_list *cl, const char *act) + const char *proxy, const xs_list *cl, const char *act_o) /* replace but also adds a class list and an actor in its alt text. * Used for emoji reactions */ { @@ -107,7 +107,7 @@ xs_str *_replace_shortnames(xs_str *s, const xs_list *tag, int ems, if (!xs_is_string(mt)) mt = xs_mime_by_ext(u); - act = act ? xs_fmt("%s\n%s", n, act) : xs_fmt("%s", n); + xs *act = act_o ? xs_fmt("%s\n%s", n, act) : xs_fmt("%s", n); if (strcmp(mt, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg"))) s = xs_replace_i(s, n, ""); @@ -2479,7 +2479,9 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } xs *fl = xs_list_new(); - fl = xs_list_append(fl, xs_fmt("%d", count), actors, xs_fmt("%d", me)); + xs *c1 = xs_fmt("%d", count); + xs *c2 = xs_fmt("%d", me); + fl = xs_list_append(fl, c1, actors, c2); sfrl = xs_dict_append(sfrl, content, fl); } } @@ -2545,11 +2547,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, if (me) class = xs_list_append(class, "snac-reacted"); xs *l1 = xs_join(class, " "); + xs *s1 = xs_fmt("&#%d", utf); ret = xs_html_tag("button", xs_html_attr("type", "submit"), xs_html_attr("name", "action"), xs_html_attr("value", me ? L("EmojiUnreact") : L("EmojiReact")), - xs_html_raw(xs_fmt("&#%d", utf)), + xs_html_raw(s1), xs_html_tag("span", xs_html_raw(nb), xs_html_attr("style", "font-size: initial; padding-left: 5px;")), diff --git a/mastoapi.c b/mastoapi.c index 1d99cd5..72379b5 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1185,7 +1185,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) } xs *fl = xs_list_new(); - fl = xs_list_append(fl, xs_fmt("%d", count), me); + xs *c1 = xs_fmt("%d", count); + fl = xs_list_append(fl, c1, me); sfrl = xs_dict_append(sfrl, content, fl); } } @@ -2399,8 +2400,10 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, mn = xs_dict_append(mn, "emoji_url", url); } - if (xs_is_emoji((utf = xs_utf8_dec(&content)))) - mn = xs_dict_append(mn, "name", xs_fmt("&#%d;", utf)); + if (xs_is_emoji((utf = xs_utf8_dec(&content)))) { + xs *s1 = xs_fmt("&#%d;", utf); + mn = xs_dict_append(mn, "name", s1); + } } } } -- cgit v1.2.3 From fd45b94c09233221d7b98a7270c768272bd25ac9 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:41:28 +0100 Subject: Fixed leak in timeline_admire(). --- data.c | 7 ++++--- snac.h | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/data.c b/data.c index bbe92b8..8f7050c 100644 --- a/data.c +++ b/data.c @@ -1567,9 +1567,10 @@ int timeline_add(snac *snac, const char *id, const xs_dict *o_msg) } -int timeline_emoji_react(const char *act, const char *id, xs_dict *msg) +int timeline_emoji_react(const char *act, const char *id, const xs_dict *msg_o) /* adds an emoji reaction to a message */ { + xs *msg = xs_dup(msg_o); msg = xs_dict_append(msg, "attributedTo", act); msg = xs_dict_set(msg, "type", "EmojiReact"); const char *emote_id = xs_dict_get(msg, "id"); @@ -1583,7 +1584,7 @@ int timeline_emoji_react(const char *act, const char *id, xs_dict *msg) int timeline_admire(snac *snac, const char *id, - const char *admirer, int like, xs_dict *msg) + const char *admirer, int like, const xs_dict *msg) /* updates a timeline entry with a new admiration or emoji reaction */ { int ret; @@ -1599,7 +1600,7 @@ int timeline_admire(snac *snac, const char *id, /* use utf <3 as a like, as it is ugly */ if (type && xs_match(type, "Like|EmojiReact|Emoji") && content && strcmp(content, "❤") != 0) { - ret = timeline_emoji_react(snac->actor, id, xs_dup(msg)); + ret = timeline_emoji_react(snac->actor, id, msg); snac_debug(snac, 1, xs_fmt("timeline_emoji_react %s", id)); } diff --git a/snac.h b/snac.h index 3d98aac..23f363c 100644 --- a/snac.h +++ b/snac.h @@ -183,8 +183,8 @@ xs_str *user_index_fn(snac *user, const char *idx_name); xs_list *timeline_simple_list(snac *user, const char *idx_name, int skip, int show, int *more); xs_list *timeline_list(snac *snac, const char *idx_name, int skip, int show, int *more); int timeline_add(snac *snac, const char *id, const xs_dict *o_msg); -int timeline_admire(snac *snac, const char *id, const char *admirer, int like, xs_dict *msg); -int timeline_emoji_react(const char *atto, const char *id, xs_dict *o_msg); +int timeline_admire(snac *snac, const char *id, const char *admirer, int like, const xs_dict *msg); +int timeline_emoji_react(const char *atto, const char *id, const xs_dict *o_msg); xs_list *timeline_top_level(snac *snac, const xs_list *list); void timeline_add_mark(snac *user); -- cgit v1.2.3 From 219f3e6808bdcf8a03cce404caa5cb6a008d00c5 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:54:21 +0100 Subject: Fixed leak in emoji_reacted(). --- data.c | 6 +++--- html.c | 5 +++-- snac.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/data.c b/data.c index 8f7050c..023bae6 100644 --- a/data.c +++ b/data.c @@ -1959,19 +1959,19 @@ xs_list *muted_list(snac *user) /** emojis react **/ -const xs_str *emoji_reacted(snac *user, const char *id) +xs_str *emoji_reacted(snac *user, const char *id) /* returns the emoji an user reacted to a message */ { xs *emojis = object_get_emoji_reacts(id); int c = 0; const char *v; - xs_dict *msg; while (xs_list_next(emojis, &v, &c)) { + xs *msg = NULL; if (object_get_by_md5(v, &msg)) { const xs_val *act = xs_dict_get(msg, "actor"); if (act && strcmp(act, user->actor) == 0) - return xs_dict_get(msg, "content"); + return xs_dup(xs_dict_get(msg, "content")); } } return NULL; diff --git a/html.c b/html.c index c317c1a..48273f2 100644 --- a/html.c +++ b/html.c @@ -2107,14 +2107,15 @@ xs_html *html_entry_controls(snac *user, const char *actor, /* the post textarea */ xs *div_id = xs_fmt("%s_reply", md5); xs *form_id = xs_fmt("%s_reply_form", md5); + xs *e_react = emoji_reacted(user, id); xs_html_add(controls, xs_html_tag("div", xs_html_tag("p", NULL), html_emoji( - user, L("Emoji react"), + user, L("Emoji react..."), div_id, form_id, ":neocat:", id, - emoji_reacted(user, id))), + e_react)), xs_html_tag("p", NULL)); } diff --git a/snac.h b/snac.h index 23f363c..bcff7f8 100644 --- a/snac.h +++ b/snac.h @@ -205,7 +205,7 @@ void unmute(snac *snac, const char *actor); int is_muted(snac *snac, const char *actor); xs_list *muted_list(snac *user); -const xs_str *emoji_reacted(snac *user, const char *id); +xs_str *emoji_reacted(snac *user, const char *id); int is_bookmarked(snac *user, const char *id); int bookmark(snac *user, const char *id); -- cgit v1.2.3 From 2903b29e653d8549319ceabbb65de408d2e5c073 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 08:58:04 +0100 Subject: Fixed more minor leaks. --- html.c | 3 ++- mastoapi.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/html.c b/html.c index 48273f2..8700ac4 100644 --- a/html.c +++ b/html.c @@ -2454,8 +2454,8 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs *sfrl = xs_dict_new(); xs *rl = object_get_emoji_reacts(id); - xs_dict *m = NULL; while (xs_list_next(rl, &v, &c)) { + xs *m = NULL; if (valid_status(object_get_by_md5(v, &m))) { const char *content = xs_dict_get(m, "content"); const char *actor = xs_dict_get(m, "actor"); @@ -2490,6 +2490,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, c = 0; while (xs_list_next(rl, &k, &c)) { + xs *m = NULL; if (valid_status(object_get_by_md5(k, &m))) { const xs_dict *tag = xs_dict_get(m, "tag"); const xs_dict *ide = xs_dict_get(m, "id"); diff --git a/mastoapi.c b/mastoapi.c index 72379b5..041f37e 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1165,8 +1165,8 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) int c = 0; const char *v; - xs_dict *msg = NULL; while (xs_list_next(rl, &v, &c)) { + xs *msg = NULL; if (valid_status(object_get_by_md5(v, &msg))) { const char *content = xs_dict_get(msg, "content"); const char *actor = xs_dict_get(msg, "actor"); @@ -1194,6 +1194,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) c = 0; while (xs_list_next(rl, &v, &c)) { + xs *msg = NULL; if (valid_status(object_get_by_md5(v, &msg))) { xs *d1 = xs_dict_new(); -- cgit v1.2.3 From 2b1d108653bd8c37fb1c0962e860704783f309f0 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 09:06:30 +0100 Subject: Use the emoji value from emojis.json instead of creating a link to the static storage. --- activitypub.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/activitypub.c b/activitypub.c index d19a428..de3a4dc 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1600,17 +1600,18 @@ xs_dict *msg_repulsion(snac *user, const char *id, const char *type) return msg; } -xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid) +xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid_o) /* creates an emoji reaction from a local user */ { xs_dict *n_msg = msg_admiration(snac, mid, "EmojiReact"); - eid = xs_strip_chars_i(xs_dup(eid), ":"); + xs *eid = xs_strip_chars_i(xs_dup(eid_o), ":"); xs *content = NULL; xs *tag = xs_list_new(); xs *dict = xs_dict_new(); xs *icon = xs_dict_new(); xs *accounts = xs_list_new(); + xs *emjs = emojis(); /* may be a default emoji */ xs *eidd = xs_dup(eid); @@ -1625,15 +1626,18 @@ xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid) return NULL; } } - else if (xs_dict_get(emojis(), xs_fmt(":%s:", eid)) == NULL) - return NULL; else { content = xs_fmt(":%s:", eid); + const char *url = xs_dict_get(emjs, content); + + if (url == NULL) + return NULL; + icon = xs_dict_set(icon, "type", "Image"); - icon = xs_dict_set(icon, "url", xs_fmt("%s/s/%s.png", snac->actor, eid)); + icon = xs_dict_set(icon, "url", url); dict = xs_dict_set(dict, "icon", icon); - dict = xs_dict_set(dict, "id", xs_fmt("%s/s/%s.png", snac->actor, eid)); + dict = xs_dict_set(dict, "id", url); dict = xs_dict_set(dict, "name", content); dict = xs_dict_set(dict, "type", "Emoji"); tag = xs_list_append(tag, dict); -- cgit v1.2.3 From 765cd34527052970892ca33b80fd977c37b6b608 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 09:24:39 +0100 Subject: Only generate an Image tag if the emoji is an URL. --- activitypub.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/activitypub.c b/activitypub.c index de3a4dc..e1f3210 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1628,19 +1628,25 @@ xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid_o) } else { content = xs_fmt(":%s:", eid); - const char *url = xs_dict_get(emjs, content); + const char *emo = xs_dict_get(emjs, content); - if (url == NULL) + if (emo == NULL) return NULL; - icon = xs_dict_set(icon, "type", "Image"); - icon = xs_dict_set(icon, "url", url); - dict = xs_dict_set(dict, "icon", icon); + if (xs_match(emo, "https://*|http://*")) { /* emoji is an URL to an image */ + icon = xs_dict_set(icon, "type", "Image"); + icon = xs_dict_set(icon, "url", emo); + dict = xs_dict_set(dict, "icon", icon); - dict = xs_dict_set(dict, "id", url); - dict = xs_dict_set(dict, "name", content); - dict = xs_dict_set(dict, "type", "Emoji"); - tag = xs_list_append(tag, dict); + dict = xs_dict_set(dict, "id", emo); + dict = xs_dict_set(dict, "name", content); + dict = xs_dict_set(dict, "type", "Emoji"); + tag = xs_list_append(tag, dict); + } + else { + xs_free(content); + content = xs_dup(emo); + } } accounts = xs_list_append(accounts, snac->actor); -- cgit v1.2.3 From 4a56b57be746b828a67b621c7fd6c7c134f64e09 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 09:36:16 +0100 Subject: If the emoji starts with &#, convert to an utf-8 string. --- activitypub.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/activitypub.c b/activitypub.c index e1f3210..59df31a 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1643,7 +1643,22 @@ xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid_o) dict = xs_dict_set(dict, "type", "Emoji"); tag = xs_list_append(tag, dict); } + else + if (xs_startswith(emo, "&#")) { + /* snac default emoji as an HTML entity: decode */ + content = xs_free(content); + + xs *s1 = xs_strip_chars_i(xs_dup(emo), "&#"); + unsigned int cpoint = 0; + sscanf(s1, "%u;", &cpoint); + + if (cpoint) + content = xs_utf8_cat(xs_str_new(NULL), cpoint); + else + content = xs_dup(emo); + } else { + /* use as it is and hope for the best */ xs_free(content); content = xs_dup(emo); } -- cgit v1.2.3 From da6d275933e9dac513386ac2bc567d3568ab0217 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 09:45:55 +0100 Subject: Strip surrounding colons in emoji pictures, if they are still there. --- html.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/html.c b/html.c index 8700ac4..e59e622 100644 --- a/html.c +++ b/html.c @@ -2521,6 +2521,8 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, cl = xs_list_append(cl, "snac-reaction-image"); xs *emoji = _replace_shortnames(xs_dup(shortname), tag, 2, proxy, cl, act); + emoji = xs_strip_chars_i(emoji, ":"); + if (me) class = xs_list_append(class, "snac-reacted"); -- cgit v1.2.3 From 9f3f8d237ac32f60c8471515dcb64095f1c4ccd6 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 10:02:43 +0100 Subject: Fixed typo. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index e59e622..f1b004b 100644 --- a/html.c +++ b/html.c @@ -107,7 +107,7 @@ xs_str *_replace_shortnames(xs_str *s, const xs_list *tag, int ems, if (!xs_is_string(mt)) mt = xs_mime_by_ext(u); - xs *act = act_o ? xs_fmt("%s\n%s", n, act) : xs_fmt("%s", n); + xs *act = act_o ? xs_fmt("%s\n%s", n, act_o) : xs_fmt("%s", n); if (strcmp(mt, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg"))) s = xs_replace_i(s, n, ""); -- cgit v1.2.3 From 08fec06d5e28b1d05154953249ba6a8b602f3f4a Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 18 Dec 2025 10:09:15 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 57f3048..341206f 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,8 @@ ## UNRELEASED +Added emoji reactions (contributed by violette). + Mastodon API: Fix for some client notifications (contributed by violette). If the query variable `terse` of a public post page is set to anything, no header is shown. -- cgit v1.2.3 From aefdd0169b0170c8c264374474e4eeeab2920cc9 Mon Sep 17 00:00:00 2001 From: violette Date: Fri, 19 Dec 2025 09:54:28 +0100 Subject: Updated CSS. --- doc/style.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/style.css b/doc/style.css index 5289332..2981926 100644 --- a/doc/style.css +++ b/doc/style.css @@ -32,7 +32,10 @@ blockquote { font-style: italic; } .snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px; margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; } .snac-no-more-unseen-posts { border-top: 1px solid #a0a0a0; border-bottom: 1px solid #a0a0a0; padding: 0.5em 0; margin: 1em 0; } -@media (prefers-color-scheme: dark) { +.snac-reaction { padding:5px; padding-left: 10px; padding-right: 10px; display: inline-flex; margin-right: 5px; font-family: inherit; font-size: medium; height: 2.5rem; vertical-align:middle; align-items:center;} +.snac-reaction-image { max-width: 100%; max-height: 100%; } +.snac-reaction-div { border-left: darkgray; border-left-style: solid; margin-bottom: .3em; padding-left: .3em; border-left-width: 2px; } +@media (prefers-color-scheme: dark) { body, input, textarea { background-color: #000; color: #fff; } a { color: #7799dd } a:visited { color: #aa99dd } -- cgit v1.2.3 From e233f3f904e64d6ecaffdf68f8532e1587681fe3 Mon Sep 17 00:00:00 2001 From: violette Date: Fri, 19 Dec 2025 09:54:50 +0100 Subject: Some fixes. --- html.c | 9 +++++---- mastoapi.c | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/html.c b/html.c index f1b004b..f6c93c7 100644 --- a/html.c +++ b/html.c @@ -2500,11 +2500,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, shortname = xs_dict_get(m, "content"); const xs_list *items = xs_dict_get(sfrl, content); - const char *nb = xs_list_get(items, 0); - const xs_list *actors = xs_list_get(items, 1); - const char me = *xs_list_get(items, 2) == '1'; - if (!xs_is_null(nb)) { + if (!xs_is_null(items)) { + const char *nb = xs_list_get(items, 0); + const xs_list *actors = xs_list_get(items, 1); + const char me = *xs_list_get(items, 2) == '1'; + is_emoji = 1; xs *al = xs_join(actors, ",\n\t"); diff --git a/mastoapi.c b/mastoapi.c index 041f37e..d38e902 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1174,7 +1174,7 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) /* NOTE: idk when there are no actor, but i encountered that bug. * Probably because of one of my previous attempts. * Keeping this just in case, can remove later */ - const char *me = actor && strcmp(actor, snac->actor) == 0 ? + const char *me = actor && snac && strcmp(actor, snac->actor) == 0 ? xs_stock(XSTYPE_TRUE) : xs_stock(XSTYPE_FALSE); int count = 1; -- cgit v1.2.3 From f7ae53b2d26c53ac77524d50281cdf294242126f Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 19 Dec 2025 09:56:27 +0100 Subject: Added violette styles to the embedded CSS. --- utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/utils.c b/utils.c index b76c0f8..44e4006 100644 --- a/utils.c +++ b/utils.c @@ -78,6 +78,9 @@ static const char * const default_css = ".snac-list-of-lists li { display: inline; border: 1px solid #a0a0a0; border-radius: 25px;\n" " margin-right: 0.5em; padding-left: 0.5em; padding-right: 0.5em; }\n" ".snac-no-more-unseen-posts { border-top: 1px solid #a0a0a0; border-bottom: 1px solid #a0a0a0; padding: 0.5em 0; margin: 1em 0; }\n" + ".snac-reaction { padding:5px; padding-left: 10px; padding-right: 10px; display: inline-flex; margin-right: 5px; font-family: inherit; font-size: medium; height: 2.5rem; vertical-align:middle; align-items:center;}\n" + ".snac-reaction-image { max-width: 100%; max-height: 100%; }\n" + ".snac-reaction-div { border-left: darkgray; border-left-style: solid; margin-bottom: .3em; padding-left: .3em; border-left-width: 2px; }\n" "@media (prefers-color-scheme: dark) { \n" " body, input, textarea { background-color: #000; color: #fff; }\n" " a { color: #7799dd }\n" -- cgit v1.2.3 From 758c0a367fd873fa67f1afd196e9458e42985222 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 19 Dec 2025 10:30:33 +0100 Subject: Updated documentation. --- FEDERATION.md | 2 +- doc/snac.8 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FEDERATION.md b/FEDERATION.md index 3e7ea31..02c97c1 100644 --- a/FEDERATION.md +++ b/FEDERATION.md @@ -37,7 +37,7 @@ ### Supported activities and objects - **Inbound**: `Follow`, `Accept`, `Create`, `Update`, `Delete`, `Announce`, `Like`, `EmojiReact`, `Undo` (for Follow/Like/Announce), and `Move` covering `Note`, `Question`, `Page`, `Article`, `Event`, and `Video`. -- **Outbound**: the same set, except for `EmojiReact` (normalised into `Like` internally) and `Create` currently emits `Note` and `Question` objects. +- **Outbound**: the same set. `Create` currently emits `Note` and `Question` objects. - Ordered collections: outboxes present the latest entries; follower/following collections hide membership by default. ### Delivery and moderation diff --git a/doc/snac.8 b/doc/snac.8 index 0dc0769..b8a75fa 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -407,7 +407,7 @@ objects, on input and output. .It Vt EmojiReact For .Vt Note -objects, on input. +objects, on input and output. .It Vt Announce For .Vt Note -- cgit v1.2.3 From 34735ff0422ef92de7812baf31b1f3707cdcf483 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 19 Dec 2025 10:54:18 +0100 Subject: Updated language files. --- po/cs.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/de_DE.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/el_GR.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/en.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/es.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/es_AR.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/es_UY.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/fi.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/fr.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/fy_NL.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/it.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/nl_NL.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/pt_BR.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/ru.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/uk.po | 392 +++++++++++++++++++++++++++++++----------------------------- po/zh.po | 392 +++++++++++++++++++++++++++++++----------------------------- 16 files changed, 3232 insertions(+), 3040 deletions(-) diff --git a/po/cs.po b/po/cs.po index b987137..daf1523 100644 --- a/po/cs.po +++ b/po/cs.po @@ -8,694 +8,694 @@ msgstr "" "Language: cs\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Citlivý obsah: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Varování o citlivém obsahu" msgid "Only for mentioned people: " msgstr "Pouze pro zmíněné osoby:" -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Odpovědět na (URL):" -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Nesdílet, pouze uložit do rozepsaných" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Rozepsané:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Přílohy..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Soubor:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Pro smazání přilohy vymažte toto pole" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Popisek přílohy" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Anketa..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Možnosti ankety (jedna na řádek, max 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Vyber jednu" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Vyber více možností" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Konec za 5 minut" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Konec za 1 hodinu" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Konec za 1 den" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Poslat" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Popisek stránky" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email administrátora" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Účet adminitrátora" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d sledovaných, %d sledujících" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "soukromé" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "veřejné" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "upozornění" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "lidé" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instance" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" msgstr "" "Vyhledat příspěvek podle URL (regex), @uživatel@instance účtu, nebo #tagu" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Hledání obsahu" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "ověřený odkaz" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Místo: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nový příspěvek..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Co se vám honí hlavou?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operace..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Sledovat" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(podle URL nebo @uživatel@instance)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Boostit" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(podle URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Líbí" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Nastavení..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Jméno:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Vaše jméno" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Profilový obrázek: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Smazat profilový obrázek" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Obrázek v záhlaví profilu: " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Smazat obrázek v záhlaví" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Napište něco o sobě..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Rozbalit citlivé příspěvky" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Emailová adresa pro upozornění" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Upozornění na Telegram (bot klíč a chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ntfy notifikace (ntfy server a token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Životnost příspěvků ve dnech (0: nastavení serveru):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Zahodit soukromé zprávy od lidí, které nesledujete" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Tento účet je robotem" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Automaticky boostit všechna zmínění tohoto účtu" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "" "Tento účet je soukromý (příspěvky nejsou zobrazitelné napříč internetem)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Složit vlákna" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Žádosti o sledování je nutné manuálně potvrdit" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Zobrazit údaje o počtu sledovaných a sledujících" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Geolokace:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Metadata profilu (klíč=hodnota na jeden řádek):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Jazyk rozhraní:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nové heslo:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Nové heslo znovu:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Uložit" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Sledované hashtagy..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Jeden hashtag na řádek" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Aktualizovat hashtagy" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Dát najevo, že se vám příspěvek líbí" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Nelíbí" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Vlastně se mi to zas tak nelíbí" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Odepnout" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Odepnout tento příspěvek z vaší osy" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Připnout" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Připnout tento příspěvěk na začátek vaší osy" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Ukázat tento příspěvek vaším sledujícím" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Odboostit" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Boostit to byl špatný nápad" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Zahodit" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Odstranit tento příspěvěk ze záložek" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Uložit" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Uložit tento příspěvek do záložek" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Přestat sledovat" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Přestat sledovat tohoto uživatele" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Začít sledovat tohoto uživatele" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Přestat Sledovat Skupinu" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Přestat sledovat tuto skupinu nebo kanál" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Sledovat Skupinu" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Začít sledovat tuto skupinu nebo kanál" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "ZTIŠIT" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Jednou provždy zablokovat všechno od tohoto uživatele" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Smazat" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Smazat tento příspěvek" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Schovat" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Schovat tento příspěvek a příspěvky pod ním" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Editovat..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Odpovědět..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Ořezáno (moc hluboké)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "sleduje vás" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Připnuto" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Zazáložkováno" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Anketa" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Odhlasováno" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Událost" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "boostí" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "odpověď pro" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr "[CITLIVÝ OBSAH]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Hlasuj" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Uzavřeno" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Končí za" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Příloha" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Popisek..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Původní kanál nebo komunita" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Čas:" -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Starší..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "o této stránce" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "pohání " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Zahodit" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Časová osa pro seznam '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Připnuté příspěvky" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Záložky" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Rozepsané příspěvky" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Nic nového" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Zpátky nahoru" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historie" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Více..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Povolit boosty" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Zobrazovat boosty od tohoto uživatele" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Skrýt boosty" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Ztišit boosty od tohoto uživatele" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Smazat tohoto uživatele" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Schválit" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Schválit žádost o sledování" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Zahodit" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Zahodit žádost o sledování" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Zrušit ztišení" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Přestat blokovat tohoto uživatele" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Zablokovat všechno od tohoto uživatele" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Soukomá zpráva..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Dosud nepotvrzené žádosti o sledování" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Lidé, které sledujete" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Lidé, kteří vás sledují" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Smazat vše" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Zmínil vás" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Ukončená anketa" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Žádost o sledování" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Kontext" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nové" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Již viděno" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Nic" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Výsledky vyhledávání účtu %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Účet %s nenalezen" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Výsledky k tagu %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Nic k tagu %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Výsledky vyhledávání pro '%s' (může toho být víc)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Výsledky vyhledávání pro '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Nic víc pro '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Žádný výsledek pro '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Časová osa místní instance" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Časová osa pro seznam '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Výsledky vyhledávání tagu #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Nedávné příspěvky od uživatelů této instance" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Blokované hashtagy..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL adresa příspěvku, na který odpovědět" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -707,94 +707,106 @@ msgstr "" "Možnost 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "API klíč Bota" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Chat id" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy server - celá URL adresa (např: https://ntfy.sh/VaseTema)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy token - pokud je zapotřebí" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "připnuté" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "záložky" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "rozepsané" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Naplánovat příspěvek..." msgid "Post date and time:" msgstr "Den a čas:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Naplánované příspěvky" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "naplánované příspěvky" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Den a čas (časové pásmo: %s)" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Časové pásmo:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Jazyk:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Notify webhook:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "http://priklad.cz/webhook" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Jazyky ve kterých píšete:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "cs en fr de_AT" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Viditelnost" -#: html.c:468 msgid "Public" msgstr "Veřejné" -#: html.c:477 msgid "Unlisted" msgstr "Neveřejné" -#: html.c:486 msgid "Followers-only" msgstr "Pouze pro sledující" -#: html.c:495 msgid "Direct Message" msgstr "Soukromá Zpráva" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/de_DE.po b/po/de_DE.po index bb6876c..6257354 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,119 +7,119 @@ msgstr "" "Language: de_DE\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Sensibler Inhalt: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Beschreibung des sensiblen Inhalts" msgid "Only for mentioned people: " msgstr "Nur für erwähnte Personen: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Antwort an (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Nicht senden, aber als Entwurf speichern" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Entwurf: " -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Anhänge..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Datei:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Feld löschen, um den Anhang zu löschen" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Beschreibung des Anhangs" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Umfrage..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Umfrageoptionen (eine pro Zeile, bis zu 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Einfachauswahl" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Mehrfachauswahl" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Endet in 5 Minuten" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Endet in 1 Stunde" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Endet in 1 Tag" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Beitrag veröffentlichen" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Seitenbeschreibung" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Admin E-Mail" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Admin-Konto" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d Gefolgte, %d Folgende" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "Privat" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "Öffentlich" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "Benachrichtigungen" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "Personen" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "Instanz" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -127,576 +127,576 @@ msgstr "" "Durchsuche Beiträge nach URL oder Inhalt (regulärer Ausdruck), @user@host " "Konten, oder #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Inhaltssuche" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "verifizierter Link" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Standort: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Neuer Beitrag..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Was beschäftigt dich?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Aktionen..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Folgen" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(mit URL oder user@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Boosten" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(mit URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Gefällt mir" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Einstellungen..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Anzeigename:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Dein Name" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Aktuellen Avatar löschen" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Titelbild (Banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Aktuelles Titelbild löschen" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Über dich:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Erzähle etwas von dir..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Sensible Inhalte immer anzeigen" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "E-Mail Adresse für Benachrichtigungen:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Telegram Benachrichtigungen (Bot Schlüssel und Chat ID):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "NTFY Benachrichtigungen (ntfy Server und Token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Aufbewahrungsfrist der Beiträge in Tagen (0 = Serverstandard):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Blocke Direktnachrichten von Personen denen du nicht folgst" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Dieses Konto ist ein Bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Automatisches Boosten bei Erwähnungen dieses Kontos" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "" "Dieses Konto ist privat (Beiträge werden nicht in der Weboberfläche " "angezeigt)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Themen standardmäßig einklappen" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Folgeanfragen müssen genehmigt werden" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Veröffentliche die Anzahl von Followern und Gefolgten." -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Standort:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Profil-Metadaten (Begriff=Wert Paare, einer pro Zeile):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Sprache der Weboberfläche:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Neues Passwort:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Neues Passwort wiederholen:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Benutzerinformationen aktualisieren" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Gefolgte Hashtags..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Ein Hashtag pro Zeile" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Hashtags aktualisieren" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Sag, dass dir dieser Beiträg gefällt" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Gefällt mir zurücknehmen" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nee, gefällt mir nicht so gut" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Pin entfernen" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Pin für diesen Beitrag aus deiner Zeitleiste entfernen" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Anpinnen" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Pinne diesen Beitrag an den Anfang deiner Zeitleiste" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Diesen Beitrag an deine Follower weiterschicken" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Boost zurücknehmen" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Ich bedauere, dass ich das weiterverschickt habe" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Lesezeichen entfernen" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Diesen Beitrag aus den Lesezeichen entfernen" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Lesezeichen" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Diesen Beitrag zu deinen Lesezeichen hinzufügen" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Nicht mehr folgen" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Aktivitäten dieses Benutzers nicht mehr folgen" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Folge den Aktivitäten dieses Benutzers" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Der Gruppe nicht mehr folgen" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Der Gruppe oder dem Kanal nicht mehr folgen" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Der Gruppe folgen" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Der Gruppe oder dem Kanal folgen" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "Stummschalten" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Alle Aktivitäten dieses Benutzers für immer blockieren" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Löschen" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Diesen Beitrag löschen" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Verstecken" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Verstecke diesen Beitrag und seine Kommentare" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Bearbeiten..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Antworten..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Abgeschnitten (zu tief)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "folgt dir" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Angeheftet" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Lesezeichen gesetzt" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Umfrage" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Abgestimmt" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Ereignis" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "teilte" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "als Antwort auf" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [SENSIBLER INHALT]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Abstimmen" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Geschlossen" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Beendet in" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Anhang" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt.-Text..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Ursprungskanal oder -gemeinschaft" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Zeit: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Älter..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "Über diese Seite" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "powered by " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Ablehnen" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Zeitleiste für Liste '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Angeheftete Beiträge" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Beiträge mit Lesezeichen" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Entwurf veröffentlichen" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Keine weiteren ungesehenen Beiträge" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Nach oben" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historie" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Mehr..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Nicht mehr limitieren" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Erlaube Boosts dieses Benutzers" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Limitieren" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Blocke Boosts dieses Benutzers" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Benutzer löschen" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Bestätigen" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Diese Folgeanfrage bestätigen" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Verwerfen" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Diese Folgeanfrage verwerfen" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Stummschaltung aufheben" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Aktivitäten dieses Benutzers nicht mehr blockieren" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Alle Aktivitäten dieses Benutzers blockieren" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Direktnachricht..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Ausstehende Folgebestätigungen" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Personen denen du folgst" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Personen die dir folgen" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Aufräumen" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Erwähnung" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Beendete Umfrage" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Folge-Anfrage" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Zusammenhang anzeigen" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Neu" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Bereits gesehen" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Nichts" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Suchergebnisse für Konto %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Konto %s wurde nicht gefunden" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Suchergebnisse für Hashtag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Nicht gefunden zu Hashtag %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Suchergebnisse für '%s' (könnten mehr sein)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Keine Suchergebnisse für '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Keine weiteren Treffer für '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Nichts gefunden für '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Zeitleiste der Instanz anzeigen" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Zeitleiste der Liste '%s' anzeigen" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Suchergebnisse für Hashtag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Neueste Beiträge von Benutzern dieser Instanz" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Geblockte Hashtags..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Optionale URL zum Antworten" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -708,94 +708,106 @@ msgstr "" "Option 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Bot API Schlüssel" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Chat ID" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy Server - vollständige URL (Bsp.: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy Token - falls nötig" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "Angeheftet" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "Lesezeichen" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "Entwürfe" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Geplanter Beitrag..." msgid "Post date and time:" msgstr "Datum und Uhrzeit des Beitrags:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Geplante Beiträge" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "Geplante Beiträge" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Datum und Uhrzeit des Beitrags (Zeitzone: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Zeitzone:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Sprache:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Notify webhook:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "http://example.com/webhook" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Sprache, in der du normalerweise schreibst:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "en fr es de_DE" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Sichtbarkeit" -#: html.c:468 msgid "Public" msgstr "Öffentlich" -#: html.c:477 msgid "Unlisted" msgstr "Ungelistete" -#: html.c:486 msgid "Followers-only" msgstr "Nur Follower" -#: html.c:495 msgid "Direct Message" msgstr "Direktnachricht" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/el_GR.po b/po/el_GR.po index 84239f4..76e6d9d 100644 --- a/po/el_GR.po +++ b/po/el_GR.po @@ -14,119 +14,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.5\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Ευαίσθητο περιεχόμενο: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Περιγραφή ευαίσθητου περιεχομένου" msgid "Only for mentioned people: " msgstr "Μόνο για αναφερόμενα άτομα: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Απάντηση σε (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Μη δημοσιεύσεις, αλλά αποθήκευσε σαν προσχέδιο" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Προσχέδιο:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Επισυνάψεις..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Αρχείο:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Καθάρισε αυτό το πεδίο για να διαγράψεις την επισύναψη" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Περιγραφή επισύναψης" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Δημοσκόπηση..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Επιλογές δημοσκόπησης (μία ανά σειρά, μέχρι 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Μία επιλογή" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Πολλαπλές επιλογές" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Τελειώνει σε 5 λεπτά" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Τελειώνει σε 1 ώρα" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Τελειώνει σε 1 ημέρα" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Δημοσίευση" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Περιγραφή ιστότοπου" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email διαχειριστή" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Διαχειριστής" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d ακολουθείτε, %d ακόλουθοι" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "ιδιωτικό" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "δημόσιο" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "ειδοποιήσεις" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "άνθρωποι" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "διακομιστής" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -134,576 +134,576 @@ msgstr "" "Αναζήτηση δημοσιεύσεων με URL ή περιεχόμενο (κανονική έκφραση), " "@χρήστης@διακομιστής, ή #ετικέτα" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Αναζήτηση περιεχομένου" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "πιστοποιημένος σύνδεσμος" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Τοποθεσία: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Νέα Δημοσίευση..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Τι έχεις στο μυαλό σου;" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Λειτουργίες..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Ακολούθησε" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(με URL ή user@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Ενίσχυση" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(από URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Μου αρέσει" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Ρυθμίσεις Χρήστη..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Προβαλλόμενο όνομα:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Το όνομα σου" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Εικόνα προφίλ: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Διαγραφή τρέχουσας εικόνας προφίλ" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Εικόνα κεφαλίδας (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Διαγραφή τρέχουσας εικόνας κεφαλίδας" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Βιογραφικό:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Γράψε για τον εαυτό σου εδώ..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Πάντα πρόβαλε ευαίσθητο περιεχόμενο" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Διεύθυνση email για ειδοποιήσεις:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Ειδοποιήσεις Telegram (κλειδί bot και chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ειδοποιήσεις ntfy (διακομιστής ntfy και token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Διατήρηση δημοσιεύσεων για ημέρες (0: ρυθμίσεις διακομιστή):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Απόρριψη άμεσων μηνυμάτων από άτομα που δεν ακολουθείτε" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Αυτός ο λογαριασμός είναι αυτοματοποιημένος (bot)" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Αυτόματη ενίσχυση όλων των αναφορών σε αυτό το λογαριασμό" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "" "Αυτός ο λογαριασμός είναι ιδιωτικός (οι δημοσιεύσεις δεν εμφανίζονται στο " "διαδίκτυο)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Αναδίπλωση κορυφαίων συζητήσεων εξ'ορισμού" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Τα αιτήματα ακόλουθων πρέπει να εγκρίνονται" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Δημοσίευση στατιστικών ακόλουθων και ακολουθούμενων" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Τρέχουσα τοποθεσία:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Μεταστοιχεία προφίλ (κλειδί=τιμή ζευγάρια σε κάθε γραμμή):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Γλώσσα περιβάλλοντος web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Νέος κωδικός:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Επανάληψη νέου κωδικού:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Ενημέρωση στοιχείων χρήστη" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Ετικέτες που ακολουθείτε..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Μία ετικέτα ανά γραμμή" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Ενημέρωση ετικετών" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Ανάφερε ότι σου αρέσει αυτή η δημοσίευση" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Αναίρεση μου αρέσει" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Μπα δεν μ' αρέσει τόσο" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Ξεκαρφίτσωμα" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Ξεκαρφίτσωμα αυτής της δημοσίευσης από τη ροή σας" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Καρφίτσωμα" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Καρφίτσωμα αυτής της δημοσίευσης στη κορυφή της ροής σας" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Ανακοίνωση αυτής της δημοσίευσης στους ακόλουθους σας" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Αφαίρεση ενίσχυσης" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Μετάνιωσα που το ενίσχυσα" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Αφαίρεση σελιδοδείκτη" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Διαγραφή αυτής της δημοσίευσης από τους σελιδοδείκτες σου" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Εισαγωγή σελιδοδείκτη" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Προσθήκη αυτής της δημοσίευσης στους σελιδοδείκτες σου" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Αναίρεση ακολουθίας" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Σταμάτα να ακολουθείς τη δραστηριότητα αυτού του χρήστη" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Ξεκίνα να ακολουθείς τη δραστηριότητα αυτού του χρήστη" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Αναίρεση ακολουθίας ομάδας" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Σταμάτα να ακολουθείς αυτή την ομάδα ή κανάλι" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Ακολούθησε την Ομάδα" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Ξεκίνα να ακολουθείς αυτή την ομάδα ή κανάλι" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "ΣΙΓΑΣΗ" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Αποκλεισμός οποιασδήποτε δραστηριότητας από αυτόν τον χρήστη για πάντα" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Διαγραφή" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Διαγραφή αυτής της δημοσίευσης" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Απόκρυψη" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Απόκρυψη αυτής της δημοσίευσης και των απαντήσεων της" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Επεξεργασία..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Απάντηση..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Έγινε περικοπή (πολύ βαθύ)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "σε ακολουθεί" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Καρφιτσωμένο" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Εισήχθηκε σελιδοδείκτης" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Δημοσκόπηση" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Ψήφισες" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Εκδήλωση" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "ενισχύθηκε" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "σε απάντηση του" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [ΕΥΑΙΣΘΗΤΟ ΠΕΡΙΕΧΟΜΕΝΟ]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Ψήφισε" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Έκλεισε" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Κλείνει σε" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Βίντεο" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Ήχος" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Επισύναψη" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Εναλλακτικό κείμενο..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Πηγή κανάλι ή κοινότητα" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Ώρα: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Παλαιότερα..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "σχετικά με αυτό τον ιστότοπο" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "λειτουργεί με " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Απόρριψη" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Ροή για λίστα '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Καρφιτσωμένες δημοσιεύσεις" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Σελιδοδείκτες" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Προσχέδια δημοσιεύσεων" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Δεν υπάρχουν άλλες αδιάβαστες δημοσιεύσεις" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Πίσω στη κορυφή" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Ιστορικό" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Περισσότερα..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Αφαίρεση περιορισμού" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Επέτρεψε ανακοινώσεις (ενισχύσεις) από αυτό το χρήστη" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Περιορισμός" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Απέκλεισε ανακοινώσεις (ενισχύσεις) από αυτό το χρήστη" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Διαγραφή αυτού του χρήστη" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Έγκριση" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Έγκριση αυτού του αιτήματος ακόλουθου" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Απόρριψη" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Απόρριψη αυτού του αιτήματος ακόλουθου" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Αφαίρεση σίγασης" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Διακοπή αποκλεισμού δραστηριοτήτων από αυτό το χρήστη" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Αποκλεισμός οποιασδήποτε δραστηριότητας από αυτό τον χρήστη" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Απευθείας Μήνυμα..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Εκκεμείς επιβεβαιώσεις ακολουθήσεων" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Άνθρωποι που ακολουθείτε" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Άνθρωποι που σας ακολουθούν" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Εκκαθάριση όλων" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Αναφορά" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Ολοκληρωμένη δημοσκόπηση" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Αίτημα Ακόλουθου" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Περιεχόμενο" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Νέο" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Έχει ήδη προβληθεί" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Κανένα" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Αποτελέσματα αναζήτηση για λογαριασμό %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Ο λογαριασμός %s δεν βρέθηκε" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Αποτελέσματα αναζήτησης για ετικέτα %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Δε βρέθηκε κάτι για ετικέτα %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Αποτελέσματα αναζήτησης για '%s' (μπορεί να υπάρχουν περισσότερα)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Αποτελέσματα αναζήτησης για '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Δεν υπάρχουν άλλα αποτελέσματα για '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Δε βρέθηκε κάτι για '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Προβάλλεται η ροή του διακομιστή" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Προβάλετε η ροή της λίστας '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Αποτελέσματα αναζήτησης για ετικέτα #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Πρόσφατες αναρτήσεις από χρήστες σε αυτό τον ιστότοπο" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Αποκλεισμένες ετικέτες..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -711,94 +711,106 @@ msgid "" "..." msgstr "" -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "" msgid "Post date and time:" msgstr "" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/en.po b/po/en.po index d18f979..0f8abe1 100644 --- a/po/en.po +++ b/po/en.po @@ -8,692 +8,692 @@ msgstr "" "Language: en\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "" -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "" msgid "Only for mentioned people: " msgstr "" -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "" -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "" -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "" -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" msgstr "" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "" -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "" -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "" -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "" -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "" -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "" -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "" -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "" -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "" -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "" -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr "" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "" -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "" -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "" -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "" -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "" -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "" -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "" -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -701,94 +701,106 @@ msgid "" "..." msgstr "" -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "" msgid "Post date and time:" msgstr "" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/es.po b/po/es.po index 9086acc..b68bdc8 100644 --- a/po/es.po +++ b/po/es.po @@ -8,119 +8,119 @@ msgstr "" "Language: es\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Contenido sensible: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Descripción del contenido sensible" msgid "Only for mentioned people: " msgstr "Solo personas mencionadas: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Responder a (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "No enviar. Guardar como borrador" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Borrador:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Adjuntos..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Archivo:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Limpiar este campo para eliminar el adjunto" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Descripción del adjunto" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Encuesta..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Opciones de encuesta (una por línea, hasta 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Una opción" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Opciones múltiples" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Finalizar en 5 minutos" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Finalizar en 1 hora" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Finalizar en 1 día" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Publicar" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Descripción del sitio" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email del Administrador" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Cuenta del Administrador" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d siguiendo, %d seguidores" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privado" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "público" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notificaciones" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "personas" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instancia" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,576 +128,576 @@ msgstr "" "Buscar publicaciones por URL o contenido (expresiones regulares), cuenta " "@usuario@host , ó #etiqueta" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Buscar contenido" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "link verificado" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Ubicación: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nueva Publicación..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "¿En qué estás pensando?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operaciones..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Seguir" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(por URL o usuario@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Impulsar" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(por URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Me gusta" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Configuración de usuario..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nombre para mostrar:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Su nombre" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Eliminar avatar" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Imagen de cabecera (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Eliminar imagen de cabecera" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Escriba algo sobre usted aquí..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Siempre mostrar contenido sensible" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Cuenta de email para las notificaciones:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notificaciones en Telegram (llave del bot e id del chat):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "Notificaciones en ntfy (servidor ntfy y token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" "Plazo máximo de conservación de publicaciones en días (0: usar configuración " "del servidor):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Descartar mensajes directos de personas a las que no sigue" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Esta cuenta es un bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Impulsar automáticamente todas las menciones a esta cuenta" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Esta cuenta es privada (las publicaciones no se muestran en la web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Contraer hilo de publicaciones por defecto" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Las solicitudes de seguimiento deben ser aprobadas" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Mostrar cantidad de seguidores y seguidos" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Ubicación actual:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Metadata del perfil (pares llave=valor en cada línea):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Idioma de la interfaz Web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nueva contraseña:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Repetir nueva contraseña:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Actualizar información de usuario" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Etiquetas en seguimiento..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Una etiqueta por línea" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Actualizar etiquetas" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Decir que te gusta esta publicación" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "No me gusta" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nah, no me gusta tanto" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Desanclar" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Desanclar esta publicación de su línea de tiempo" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Anclar" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Anclar esta publicación al inicio de su línea de tiempo" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Anunciar esta publicación a sus seguidores" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Eliminar impulso" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Me arrepiento de haber impulsado esto" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Eliminar marcador" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Eliminar marcador de esta publicación" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Marcador" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Agregar esta publicación a mis marcadores" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Dejar de seguir" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Dejar de seguir la actividad de este usuario" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Seguir la actividad de este usuario" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Dejar de seguir este Grupo" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Dejar de seguir este grupo o canal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Seguir Grupo" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Seguir grupo o canal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "SILENCIAR" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Bloquear toda la actividad de este usuario para siempre" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Eliminar" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Eliminar esta publicación" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Ocultar" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Ocultar esta publicación y sus respuestas" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Editar..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Responder..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Truncado (demasiado profundo)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "te sigue" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Anclado" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Marcado" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Encuesta" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Votado" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evento" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "impulsado" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "en respuesta a" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTENIDO SENSIBLE]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Votar" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Cerrado" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Cierra en" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Adjunto" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Canal o comunidad de origen" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Hora: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Más antiguo..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "acerca de este sitio" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "provisto por " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Descartar" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Línea de tiempo de la lista '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Publicaciones ancladas" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Publicaciones marcadas" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Borradores de publicaciones" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "No quedan publicaciones sin ver" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Volver al inicio" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historia" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Más..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Sin límite" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permitir anuncios (impulsos) de este usuario" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Límite" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Bloquear anuncios (impulsos) de este usuario" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Eliminar este usuario" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Aprobar" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Aprobar solicitud de seguimiento" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Descartar" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Descartar solicitud de seguimiento" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Dejar de SILENCIAR" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Dejar de bloquear actividad de este usuario" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Bloquear toda actividad de este usuario" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Mensaje Directo..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Confirmaciones de seguimiento pendientes" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Personas que sigues" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Personas que te siguen" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Limpiar todo" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Mención" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Encuesta finalizada" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Solicitud de Seguimiento" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contexto" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nuevo" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Ya visto" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Ninguno" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Buscar resultados para la cuenta %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "No se encontró la cuenta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Buscar resultados para la etiqueta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "No se encontró nada con la etiqueta %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Resultados de búsqueda para '%s' (puede haber más)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Resultados de búsqueda para '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "No hay más coincidencias para '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "No se encontró nada para '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Mostrando línea de tiempo de la instancia" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Mostrando línea de tiempo de la lista '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Resultado de búsqueda para la etiqueta #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Publicaciones recientes de los usuarios de esta instancia" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Etiquetas bloqueadas..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL opcional a la que responder" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -709,91 +709,103 @@ msgstr "" "Opción 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Clave del API del Bot" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Identificador de chat" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "Servidor ntfy - URL completa (example: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "Token ntft - si es necesario" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "Anclados" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "Marcados" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "Borradores" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Envío programado..." -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Envíos programados" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "envíos programados" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Fecha y hora de publicación (zona horaria: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Zona horaria:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Idioma:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Webhook de notificación:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Idiomas en los que sueles escribir:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Visibilidad: " -#: html.c:468 msgid "Public" msgstr "Público" -#: html.c:477 msgid "Unlisted" msgstr "No listado" -#: html.c:486 msgid "Followers-only" msgstr "Solo seguidores" -#: html.c:495 msgid "Direct Message" msgstr "Mensaje directo" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "Reaccionar con un emoji..." + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "Reacciones con emoji: " diff --git a/po/es_AR.po b/po/es_AR.po index 2579865..3b43fe5 100644 --- a/po/es_AR.po +++ b/po/es_AR.po @@ -8,119 +8,119 @@ msgstr "" "Language: es_AR\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Contenido sensible: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Descripción del contenido sensible" msgid "Only for mentioned people: " msgstr "Solo personas mencionadas: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Responder a (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "No enviar. Guardar como borrador" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Borrador:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Adjuntos..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Archivo:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Limpiar este campo para eliminar el adjunto" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Descripción del adjunto" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Encuesta..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Opciones de encuesta (una por línea, hasta 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Una opción" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Opciones múltiples" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Finalizar en 5 minutos" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Finalizar en 1 hora" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Finalizar en 1 día" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Publicar" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Descripción del sitio" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email del Administrador" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Cuenta del Administrador" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d siguiendo, %d seguidores" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privado" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "público" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notificaciones" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "personas" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instancia" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,576 +128,576 @@ msgstr "" "Buscar publicaciones por URL o contenido (expresiones regulares), cuenta " "@usuario@host , ó #etiqueta" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Buscar contenido" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "link verificado" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Ubicación: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nueva Publicación..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "¿En qué estás pensando?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operaciones..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Seguir" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(por URL o usuario@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Impulsar" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(por URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Me gusta" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Configuración de usuario..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nombre para mostrar:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Su nombre" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Eliminar avatar" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Imagen de cabecera (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Eliminar imagen de cabecera" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Escriba algo sobre usted aquí..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Siempre mostrar contenido sensible" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Cuenta de email para las notificaciones:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notificaciones en Telegram (llave del bot e id del chat):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "Notificaciones en ntfy (servidor ntfy y token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" "Plazo máximo de conservación de publicaciones en días (0: usar configuración " "del servidor):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Descartar mensajes directos de personas a las que no sigue" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Esta cuenta es un bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Impulsar automáticamente todas las menciones a esta cuenta" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Esta cuenta es privada (las publicaciones no se muestran en la web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Contraer hilo de publicaciones por defecto" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Las solicitudes de seguimiento deben ser aprobadas" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Mostrar cantidad de seguidores y seguidos" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Ubicación actual:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Metadata del perfil (pares llave=valor en cada línea):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Idioma de la interfaz Web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nueva contraseña:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Repetir nueva contraseña:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Actualizar información de usuario" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Etiquetas en seguimiento..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Una etiqueta por línea" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Actualizar etiquetas" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Decir que te gusta esta publicación" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "No me gusta" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nah, no me gusta tanto" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Desanclar" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Desanclar esta publicación de su línea de tiempo" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Anclar" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Anclar esta publicación al inicio de su línea de tiempo" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Anunciar esta publicación a sus seguidores" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Eliminar impulso" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Me arrepiento de haber impulsado esto" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Eliminar marcador" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Eliminar marcador de esta publicación" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Marcador" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Agregar esta publicación a mis marcadores" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Dejar de seguir" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Dejar de seguir la actividad de este usuario" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Seguir la actividad de este usuario" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Dejar de seguir este Grupo" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Dejar de seguir este grupo o canal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Seguir Grupo" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Seguir grupo o canal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "SILENCIAR" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Bloquear toda la actividad de este usuario para siempre" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Eliminar" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Eliminar esta publicación" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Ocultar" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Ocultar esta publicación y sus respuestas" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Editar..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Responder..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Truncado (demasiado profundo)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "te sigue" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Anclado" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Marcado" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Encuesta" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Votado" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evento" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "impulsado" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "en respuesta a" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTENIDO SENSIBLE]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Votar" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Cerrado" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Cierra en" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Adjunto" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Canal o comunidad de origen" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Hora: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Más antiguo..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "acerca de este sitio" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "provisto por " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Descartar" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Línea de tiempo de la lista '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Publicaciones ancladas" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Publicaciones marcadas" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Borradores de publicaciones" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "No quedan publicaciones sin ver" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Volver al inicio" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historia" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Más..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Sin límite" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permitir anuncios (impulsos) de este usuario" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Límite" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Bloquear anuncios (impulsos) de este usuario" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Eliminar este usuario" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Aprobar" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Aprobar solicitud de seguimiento" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Descartar" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Descartar solicitud de seguimiento" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Dejar de SILENCIAR" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Dejar de bloquear actividad de este usuario" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Bloquear toda actividad de este usuario" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Mensaje Directo..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Confirmaciones de seguimiento pendientes" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Personas que sigues" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Personas que te siguen" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Limpiar todo" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Mención" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Encuesta finalizada" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Solicitud de Seguimiento" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contexto" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nuevo" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Ya visto" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Ninguno" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Buscar resultados para la cuenta %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "No se encontró la cuenta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Buscar resultados para la etiqueta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "No se encontró nada con la etiqueta %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Resultados de búsqueda para '%s' (puede haber más)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Resultados de búsqueda para '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "No hay más coincidencias para '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "No se encontró nada para '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Mostrando línea de tiempo de la instancia" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Mostrando línea de tiempo de la lista '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Resultado de búsqueda para la etiqueta #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Publicaciones recientes de los usuarios de esta instancia" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Etiquetas bloqueadas..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL opcional a la que responder" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -709,91 +709,103 @@ msgstr "" "Opción 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Clave del API del Bot" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Identificador de chat" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "Servidor ntfy - URL completa (example: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "Token ntft - si es necesario" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "Anclados" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "Marcados" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "Borradores" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Envío programado..." -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Envíos programados" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "envíos programados" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Fecha y hora de publicación (zona horaria: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Zona horaria:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Idioma:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Webhook de notificación:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Idiomas en los que sueles escribir:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Visibilidad: " -#: html.c:468 msgid "Public" msgstr "Público" -#: html.c:477 msgid "Unlisted" msgstr "No listado" -#: html.c:486 msgid "Followers-only" msgstr "Solo seguidores" -#: html.c:495 msgid "Direct Message" msgstr "Mensaje directo" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "Reaccionar con un emoji..." + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "Reacciones con emoji: " diff --git a/po/es_UY.po b/po/es_UY.po index d4d9918..68cfa06 100644 --- a/po/es_UY.po +++ b/po/es_UY.po @@ -8,119 +8,119 @@ msgstr "" "Language: es_UY\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Contenido sensible: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Descripción del contenido sensible" msgid "Only for mentioned people: " msgstr "Solo personas mencionadas: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Responder a (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "No enviar. Guardar como borrador" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Borrador:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Adjuntos..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Archivo:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Limpiar este campo para eliminar el adjunto" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Descripción del adjunto" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Encuesta..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Opciones de encuesta (una por línea, hasta 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Una opción" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Opciones múltiples" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Finalizar en 5 minutos" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Finalizar en 1 hora" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Finalizar en 1 día" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Publicar" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Descripción del sitio" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email del Administrador" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Cuenta del Administrador" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d siguiendo, %d seguidores" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privado" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "público" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notificaciones" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "personas" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instancia" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,576 +128,576 @@ msgstr "" "Buscar publicaciones por URL o contenido (expresiones regulares), cuenta " "@usuario@host , ó #etiqueta" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Buscar contenido" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "link verificado" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Ubicación: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nueva Publicación..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "¿En qué estás pensando?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operaciones..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Seguir" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(por URL o usuario@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Impulsar" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(por URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Me gusta" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Configuración de usuario..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nombre para mostrar:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Su nombre" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Eliminar avatar" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Imagen de cabecera (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Eliminar imagen de cabecera" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Escriba algo sobre usted aquí..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Siempre mostrar contenido sensible" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Cuenta de email para las notificaciones:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notificaciones en Telegram (llave del bot e id del chat):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "Notificaciones en ntfy (servidor ntfy y token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" "Plazo máximo de conservación de publicaciones en días (0: usar configuración " "del servidor):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Descartar mensajes directos de personas a las que no sigue" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Esta cuenta es un bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Impulsar automáticamente todas las menciones a esta cuenta" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Esta cuenta es privada (las publicaciones no se muestran en la web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Contraer hilo de publicaciones por defecto" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Las solicitudes de seguimiento deben ser aprobadas" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Mostrar cantidad de seguidores y seguidos" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Ubicación actual:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Metadata del perfil (pares llave=valor en cada línea):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Idioma de la interfaz Web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nueva contraseña:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Repetir nueva contraseña:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Actualizar información de usuario" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Etiquetas en seguimiento..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Una etiqueta por línea" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Actualizar etiquetas" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Decir que te gusta esta publicación" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "No me gusta" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nah, no me gusta tanto" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Desanclar" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Desanclar esta publicación de su línea de tiempo" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Anclar" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Anclar esta publicación al inicio de su línea de tiempo" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Anunciar esta publicación a sus seguidores" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Eliminar impulso" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Me arrepiento de haber impulsado esto" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Eliminar marcador" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Eliminar marcador de esta publicación" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Marcador" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Agregar esta publicación a mis marcadores" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Dejar de seguir" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Dejar de seguir la actividad de este usuario" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Seguir la actividad de este usuario" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Dejar de seguir este Grupo" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Dejar de seguir este grupo o canal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Seguir Grupo" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Seguir grupo o canal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "SILENCIAR" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Bloquear toda la actividad de este usuario para siempre" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Eliminar" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Eliminar esta publicación" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Ocultar" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Ocultar esta publicación y sus respuestas" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Editar..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Responder..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Truncado (demasiado profundo)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "te sigue" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Anclado" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Marcado" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Encuesta" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Votado" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evento" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "impulsado" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "en respuesta a" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTENIDO SENSIBLE]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Votar" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Cerrado" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Cierra en" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Adjunto" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Canal o comunidad de origen" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Hora: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Más antiguo..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "acerca de este sitio" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "provisto por " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Descartar" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Línea de tiempo de la lista '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Publicaciones ancladas" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Publicaciones marcadas" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Borradores de publicaciones" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "No quedan publicaciones sin ver" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Volver al inicio" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historia" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Más..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Sin límite" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permitir anuncios (impulsos) de este usuario" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Límite" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Bloquear anuncios (impulsos) de este usuario" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Eliminar este usuario" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Aprobar" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Aprobar solicitud de seguimiento" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Descartar" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Descartar solicitud de seguimiento" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Dejar de SILENCIAR" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Dejar de bloquear actividad de este usuario" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Bloquear toda actividad de este usuario" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Mensaje Directo..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Confirmaciones de seguimiento pendientes" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Personas que sigues" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Personas que te siguen" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Limpiar todo" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Mención" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Encuesta finalizada" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Solicitud de Seguimiento" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contexto" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nuevo" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Ya visto" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Ninguno" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Buscar resultados para la cuenta %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "No se encontró la cuenta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Buscar resultados para la etiqueta %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "No se encontró nada con la etiqueta %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Resultados de búsqueda para '%s' (puede haber más)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Resultados de búsqueda para '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "No hay más coincidencias para '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "No se encontró nada para '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Mostrando línea de tiempo de la instancia" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Mostrando línea de tiempo de la lista '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Resultado de búsqueda para la etiqueta #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Publicaciones recientes de los usuarios de esta instancia" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Etiquetas bloqueadas..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL opcional a la que responder" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -709,91 +709,103 @@ msgstr "" "Opción 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Clave del API del Bot" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Identificador de chat" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "Servidor ntfy - URL completa (example: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "Token ntft - si es necesario" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "Anclados" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "Marcados" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "Borradores" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Envío programado..." -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Envíos programados" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "envíos programados" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Fecha y hora de publicación (zona horaria: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Zona horaria:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Idioma:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Webhook de notificación:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Idiomas en los que sueles escribir:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Visibilidad: " -#: html.c:468 msgid "Public" msgstr "Público" -#: html.c:477 msgid "Unlisted" msgstr "No listado" -#: html.c:486 msgid "Followers-only" msgstr "Solo seguidores" -#: html.c:495 msgid "Direct Message" msgstr "Mensaje directo" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "Reaccionar con un emoji..." + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "Reacciones con emoji: " diff --git a/po/fi.po b/po/fi.po index 530a660..29269be 100644 --- a/po/fi.po +++ b/po/fi.po @@ -8,119 +8,119 @@ msgstr "" "Language: fi\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Arkaluontoista sisältöä: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Arkaluontoisen sisällön kuvaus" msgid "Only for mentioned people: " msgstr "Vain mainituille: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Vastaus (osoite): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Älä lähetä, tallenna luonnoksena" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Luonnos:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Liitteet..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Tiedosto:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Tyhjennä kenttä poistaaksesi liiteen" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Liitteen kuvaus" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Kysely..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Kyselyn vaihtoehdot (riveittäin, korkeintaan 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Yksi valinta" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Monta valintaa" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Päättyy viiden minuutin päästä" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Päättyy tunnin päästä" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Päättyy päivän päästä" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Julkaise" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Sivuston kuvaus" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Ylläpitäjän sähköposti" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Ylläpitäjän tili" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "Seuraa %d, %d seuraajaa" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "yksityinen" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "julkinen" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "ilmoitukset" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "ihmiset" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "palvelin" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,574 +128,574 @@ msgstr "" "Etsi julkaisuja osoitteella tai sisällön perusteella, @käyttäjä@palvelin " "tai #tagi" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Sisälöhaku" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "varmistettu linkki" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Sijainti: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Uusi julkaisu..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Mitä on mielessäsi?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Toiminnot..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Seuraa" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(osoite tai käyttäjä@palvelin)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Tehosta" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(osoite)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Tykkää" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Käyttäjäasetukset..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Näytetty nimi:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Nimesi" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Poista nykyinen avatar" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Otsikkokuva: " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Poista nykyinen otsikkokuva" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Kuvaus:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Kirjoita itsestäsi tähän..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Näytä arkaluontoinen sisältö aina" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Sähköposti ilmoituksille:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Telegram-ilmoitukset (botin avain ja chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "nfty-ilmoitukset (ntfy-palvelin ja token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Säilytä julkaisut korkeintaan (päivää, 0: palvelimen asetukset)" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Poista yksityisviestit ihmisiltä, joita et seuraa" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Tämä tili on botti" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Tehosta tilin maininnat automaattisesti" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Tili on yksityinen (julkaisuja ei näytetä sivustolla)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Avaa säikeet automaattisesti" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Vaadi hyväksyntä seurantapyynnöille" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Julkaise seuraamistilastot" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Nykyinen sijainti:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Profiilin metadata (avain=arvo, riveittäin):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Käyttöliitymän kieli:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Uusi salasana:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Toista salasana:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Päivitä käyttäjätiedot" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Seuratut aihetunnisteet..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Aihetunnisteet, riveittäin" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Päivitä aihetunnisteet" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Tykkää tästä julkaisusta" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Poista tykkäys" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Ei ole omaan makuuni" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Poista kiinnitys" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Poista julkaisun kiinnitys aikajanalle" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Kiinnitä" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Kiinnitä julkaisu aikajanasi alkuun" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Ilmoita julkaisusta seuraajillesi" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Poista tehostus" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Kadun tehostaneeni tätä" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Poista kirjanmerkki" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Poista julkaisu kirjanmerkeistäsi" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Lisää kirjanmerkki" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Lisää julkaisu kirjanmerkkeihisi" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Älä seuraa" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Lakkaa seuraamasta käyttäjän toimintaa" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Seuraa käyttäjän toimintaa" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Älä seuraa ryhmää" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Lopeta ryhnän tai kanavan seuraaminen" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Seuraa ryhmää" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Seuraa tätä ryhmää tai kanavaa" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "VAIMENNA" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Estä kaikki toiminta tältä käyttäjältä" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Poista" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Poista julkaisu" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Piilota" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Piilota julkaisu ja vastaukset" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Muokkaa..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Vastaa..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Katkaistu (liian syvä)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "seuraa sinua" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Kiinnitetty" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Kirjanmerkitty" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Kysely" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Äänestetty" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Tapahtuma" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "tehostettu" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "vastauksena" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [ARKALUONTOISTA SISÄLTÖÄ]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Äänestä" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Sulkeutunut" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Sulkeutuu" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Ääni" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Liite" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Kuvaus..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Lähdekanava tai -yhteisö" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Aika: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Vanhemmat..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "tietoa sivustosta" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "moottorina " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Kuittaa" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Listan ”%s” aikajana" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Kiinnitetyt julkaisut" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Kirjanmerkit" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Vedokset" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Ei lukemattonia julkaisuja" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Takaisin" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historia" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Enemmän..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Poista rajoitus" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Salli tehostukset käyttäjältä" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Rajoita" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Kiellö tehostukset käyttäjältä" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Poista käyttäjä" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Hyväksy" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Hyväksy seurantapyyntö" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Hylkää" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Hylkää seurantapyyntö" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Poista vaimennus" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Salli toiminta käyttäjältä" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Estä kaikki toiminnat käyttäjältä" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Yksityisviesti..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Hyväksymistä odottavat seurantapyynnöt" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Seuraamasi ihniset" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Sinua seuraavat" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Tyhjennä" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Mainitse" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Päättynyt kysely" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Seurantapyyntö" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Konteksti" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Uusi" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Nähty" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Ei ilmoituksia" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Hakutulokset tilille %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Tiliä %s ei löytynyt" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Hakutulokset aihetunnisteelle %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Aihetunnisteella %s ei löytynyt tuloksia" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Tulokset haulle ”%s” (mahdollisesti enemmän tuloksia)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Tulokset haulle ”%s”" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Ei enempää tuloksia haulle ”%s”" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Haulla ”%s” ei löytynyt tuloksia" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Palvelimen aikajana" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Listan ”%s” aikajana" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Hakutulokset aihetunnisteelle #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Viimeaikaisia julkaisuja tällä palvelimella" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Estetyt aihetunnisteet..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Vastaus julkaisuun (osoite, valinnainen)" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -707,94 +707,106 @@ msgstr "" "Vaihtoehto 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "botin API-avain" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "chat id" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy-palvelin - täydellinen osoite (esim: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy token - tarvittaessa" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "kiinnitetyt" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "kirjanmerkit" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "vedokset" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Ajastettu julkaisu..." msgid "Post date and time:" msgstr "Julkaisuajankohta:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Ajastetut julkaisut" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "ajastetut julkaisut" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Julkaisuajankohta (aikavyöhyke: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Aikavyöhyke: " -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/fr.po b/po/fr.po index 25dbfcf..43376d3 100644 --- a/po/fr.po +++ b/po/fr.po @@ -8,119 +8,119 @@ msgstr "" "Language: fr\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Contenu sensible :" -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Description du contenu sensible :" msgid "Only for mentioned people: " msgstr "Seulement pour les personnes mentionnées :" -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Répondre à (URL) :" -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Ne pas envoyer, mais sauvegarder en tant que brouillon" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Brouillon :" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Pièces jointes…" -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Fichier :" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Nettoyer ce champs pour supprimer la pièce jointe" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Description de la pièce jointe" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Sondage…" -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Options du sondage (une par ligne, jusqu'à 8) :" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Un seul choix" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Choix multiples" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Se termine dans 5 minutes" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Se termine dans 1 heure" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Se termine dans 1 jour" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Envoyer" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Description du site" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email de l'admin" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Compte de l'admin" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d abonnements, %d personnes abonnées" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privé" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "public" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notifications" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "personnes" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instance" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,575 +128,575 @@ msgstr "" "Chercher les messages par URL ou contenu (expression régulière), comptes " "@pseudo@hôte, ou #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Recherche de contenu" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "Lien vérifié" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Emplacement : " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nouveau message…" -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Qu'avez-vous en tête ?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Opérations…" -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Suivre" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(par URL ou pseudo@hôte)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Repartager" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(par URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Aime" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Paramètre du compte…" -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nom affiché :" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Votre nom" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar : " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Supprimer l'avatar actuel" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Image d'entête (bannière) : " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Supprimer l'image d'entête actuelle" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Description :" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Décrivez-vous ici…" -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Toujours afficher le contenu sensible" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Adresse email pour les notifications :" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notifications Telegram (clé de bot et ID de discussion) :" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "notifications ntfy (serveur et jeton ntfy) :" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" "Nombre de jours maximum de rétention des messages (0 : réglages du serveur) :" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Rejeter les messages directs des personnes que vous ne suivez pas" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Ce compte est un bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Auto-repartage de toutes les mentions de ce compte" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Ce compte est privé (les messages ne sont pas affiché sur le web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "replier les fils de discussion principaux par défaut" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Les demande de suivi doivent être approuvées" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Publier les statistiques d'abonnements" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Localisation actuelle :" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Métadonnées du profile (paires clé=valeur à chaque ligne) :" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Langue de l'interface web :" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nouveau mot de passe :" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Répétez le nouveau mot de passe :" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Mettre à jour les infos du compte" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "hashtags suivis…" -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Un hashtag par ligne" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Mettre à jour les hashtags" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Dire que vous aimez ce message" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "N'aime plus" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nan, j'aime pas tant que ça" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Dés-épingler" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Dés-épingler ce message de votre chronologie" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Épingler" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Épingler ce message en haut de votre chronologie" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Annoncer ce message aux personnes abonnées" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Dé-repartager" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Je regrette d'avoir repartagé ceci" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Retirer le signet" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Supprime ce message de vos signets" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Signet" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Ajouter ce message à vos signets" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Ne plus suivre" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Arrêter de suivre les activités de cette personne" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Commencer à suivre les activité de cette personne" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Ne plus suivre le Groupe" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Arrêter de suivre ce groupe ou canal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Suivre le Groupe" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Commencer à suivre ce groupe ou canal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "SOURDINE" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Bloquer toute activité de cette personne à jamais" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Supprimer" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Supprimer ce message" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Cacher" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Cacher ce message et ses réponses" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Modifier…" -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Répondre…" -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Tronqué (trop profond)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "vous suit" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Épinglé" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Ajouté aux signets" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Sondage" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Voté" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Événement" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "Repartagé" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "En réponse à" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTENU SENSIBLE]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Vote" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Terminé" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Termine dans" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Vidéo" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Pièce jointe" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt…" -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Canal ou communauté source" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Date : " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Plus anciens…" -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "à propos de ce site" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "fonctionne grace à " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Rejeter" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Chronologie pour la liste '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Messages épinglés" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Messages en signets" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Brouillons de messages" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Pas d'avantage de message non vus" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Retourner en haut" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Historique" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Plus…" -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Illimité" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permettre les annonces (repartages) par cette personne" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Limite" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Bloquer les annonces (repartages) par cette personne" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Supprimer cette personne" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Approuver" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Approuver cette demande de suivi" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Rejeter" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Rejeter la demande suivante" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Ne plus taire" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Arrêter de bloquer les activités de cette personne" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Bloque toutes les activités de cette personne" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Message direct…" -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Confirmation de suivi en attente" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Personnes que vous suivez" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Personnes qui vous suivent" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Tout nettoyer" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Mention" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Sondage terminé" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Requête de suivi" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contexte" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nouveau" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Déjà vu" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Aucun" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Résultats de recherche pour le compte %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Compte %s non trouvé" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Résultats de recherche pour le tag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Rien n'a été trouvé pour le tag %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Résultats de recherche pour '%s' (il pourrait y en avoir davantage)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Résultats de recherche pour '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Pas davantage de résultats pour '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Rien n'a été trouvé pour '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Montrer la chronologie de l'instance" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Montrer le chronologie pour la liste '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Résultats de recherche pour le tag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Messages récents des internautes de cette instance" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Hashtags bloqués…" -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL optionnelle pour répondre à" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -708,94 +708,106 @@ msgstr "" "Option 3…\n" "…" -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Clé API de bot" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Identifiant du salon" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "serveur ntfy – adresse complète (ex : https://ntfy.sh/VotreSujet)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "jeton ntfy – si nécessaire" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "épinglé" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "signets" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "brouillons" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Publication planifiée…" msgid "Post date and time:" msgstr "Date et heure de publication :" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Publications planifiées" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "publications planifiées" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Date et heure de publication (fuseau horaire : %s) :" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Fuseau horaire :" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/fy_NL.po b/po/fy_NL.po index d34377b..083c679 100644 --- a/po/fy_NL.po +++ b/po/fy_NL.po @@ -8,119 +8,119 @@ msgstr "" "Language: fy_NL\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Gefoelige ynhâld: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Beskriuwing fan gefoelige ynhâld" msgid "Only for mentioned people: " msgstr "Allinnich foar neamde personen: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Antwurd op (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Net ferstjoere, mar bewarje as konsept" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Konsept:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Bylagen..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Bestân:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Fjild leech meitsje om de bylage fuort te smiten" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Beskriuwing fan bylage" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Peiling..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Peilingopsjes (ien per rigel, oant 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Ien keuze" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Mear keuzes" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Einiget oer 5 minuten" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Einiget oer 1 oere" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Einiget oer 1 dei" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Berjocht" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Beskriuwing fan de side" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Admin e-mail" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Admin akkount" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d folgjend, %d folgers" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privé" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "publik" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notifikaasjes" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "minsken" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instantsje" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,575 +128,575 @@ msgstr "" "Sykje berjochten op URL of ynh??ld (reguliere ekspresje), @brûker@host " "akkounts, of #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Ynhâld sêkje" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "ferifiearre keppeling" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Lokaasje: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nij berjocht..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Wat wolst diele?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Hannelens..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Folgje" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(fia URL of brûker@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Boost" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(fia URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Lyk" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Brûkersynstellings..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Werjeftenamme:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Jo namme" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Profylplaatsje: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Hjoeddeistige profylplaatsje fuortsmite" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Koptekstplaatsje (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Hjoeddeistige koptekstplaatsje fuortsmite" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Skriuw hjir wat oer josels..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Altyd gefoelige ynhâld toanje" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "E-mailadres foar notifikaasjes:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Telegram notifikaasjes (bot kaai en chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ntfy notifikaasjes (ntfy server en token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "" "Maksimaal oantal dagen om berjochten te bewarjen (0: serverynstellings):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Direktte berjochten fan minsken dy't jo net folgje fuortsmite" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Dit akkount is in bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Automatysk boostje fan alle fermeldingen fan dit akkount" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Dit akkount is privé (berjochten wurde net toand fia it web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Standert topthreads ynklappe" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Folchfersiken moatte goedkeard wurde" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Folger- en folchstatistiken publisearje" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Hjoeddeistige lokaasje:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Profylmetadata (kaai=wearde pearen yn eltse rigel):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Webynterfacetaal:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nij wachtwurd:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Nij wachtwurd werhelje:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Brûkerynformaasje bywurkje" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Folge hashtags..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Ien hashtag per rigel" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Hashtags bywurkje" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Sis dat jo dit berjocht mooi fine" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Net mooi fine" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nee, ik find it net sa mooi" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Net fêstsette" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Dit berjocht net mear fêstsette op jo tiidline" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Fêstsette" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Dit berjocht fêstsette boppe-oan jo tiidline" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Dit berjocht oankondichje by jo folgers" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Untboostje" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Ik betreure dat ik dit boostet ha" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Ut favorite fuortsmite" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Dit berjocht ut jo favorite fuortsmite" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Favoryt" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Dit berjocht tafoegje oan jo favorite" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Untfolgje" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Stopje mei it folgjen fan de aktiviteit fan dizze brûker" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Begjinne mei it folgjen fan de aktiviteit fan dizze brûker" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Untfolgje groep" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Stopje mei it folgjen fan dizze groep of kanaal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Folgje groep" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Begjinne mei it folgjen fan dizze groep of kanaal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "STILJE" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Alle aktiviteit fan dizze brûker foar altyd blokkearje" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Fuortsmite" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Dit berjocht fuortsmite" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Ferbergje" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Dit berjocht en syn bern ferbergje" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Bewurkje..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Antwurd..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Ofkapte (te djip)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "folget jo" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Fêstsetten" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Favoryt" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Peiling" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Stimme" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Barrens" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "boostet" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "as antwurd op" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [GEFOELIGE YNHÂLD]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Stimme" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Sletten" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Slut oer" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Fideo" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Bylage" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Boarnekanaal of mienskip" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Tiid: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Alder..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "oer dizze side" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "oanjoegen troch " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Wegerje" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Tiidline foar list '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Fêstsette berjochten" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Favorite berjochten" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Berjochtkonsepten" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Gjin net-lêzene berjochten mear" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Werom nei boppe" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Skiednis" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Mear..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Unbeheind" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Oankondichings (boosts) fan dizze brûker tasteane" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Beheine" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Oankondichings (boosts) fan dizze brûker blokkearje" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Dizze brûker fuortsmite" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Goedkarre" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Dit folchfersk goedkarre" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Wegerje" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Dit folchfersk wegerje" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Net mear stilje" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Stopje mei it blokkearjen fan aktiviteiten fan dizze brûker" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Alle aktiviteit fan dizze brûker blokkearje" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Persoanlik berjocht..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Iepenstjitte folchbefestichings" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Minsken dy't jo folge" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Minsken dy't jo folge" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Alles wiskje" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Neame" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Ofêrunde peiling" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Folchfersk" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Kontekst" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nij" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Al sjoen" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Gjin" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Sêkresultaten foar akkount %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Akkount %s net foun" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Sêkresultaten foar tag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Neat foun foar tag %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Sêkresultaten foar '%s' (mooglik mear)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Sêkresultaten foar '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Gjin fjirder oerienkomsten foar '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Neat foun foar '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Tiidline fan ynstallaasje toane" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Tiidline foar list '%s' toane" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Sêkresultaten foar tag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Resinte berjochten fan brûkers yn dizze ynstallaasje" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Blokkearre hashtags..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Opsjonele URL om op te antwurdjen" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -708,94 +708,106 @@ msgstr "" "Optie 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Bot API kaai" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Chat id" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy server - folsleine URL (foarbyld: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy token - as nedich" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "fêssetten" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "favorite" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "konsepten" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Planne berjocht..." msgid "Post date and time:" msgstr "Berjocht datum en tiid:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Planne berjochten" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "planne berjochten" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Berjocht datum en tiid (tiidsone: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Tiidsone:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/it.po b/po/it.po index a074635..ba5fe54 100644 --- a/po/it.po +++ b/po/it.po @@ -8,119 +8,119 @@ msgstr "" "Language: it\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Contenuto sensibile" -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Descrizione del contenuto sensibile" msgid "Only for mentioned people: " msgstr "Riservato alle persone indicate: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Rispondi a (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Salva come bozza senza inviare" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Bozza" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Allegati..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "File:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Pulisci ed elimina l'allegato" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Descrizione dell'allegato" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Sondaggio..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Scelte per il sondaggio (una per linea, massimo 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Una scelta" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Scelte multiple" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Termina in 5 minuti" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Termina in 1 ora" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Termina in 1 giorno" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Post" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Descrizione del sito web" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Email dell'amministratore" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Account amministratore" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d seguiti, %d seguenti" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privato" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "pubblico" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notifiche" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "persone" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "istanza" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,574 +128,574 @@ msgstr "" "Ricerca post per URL o contenuto (espressione regolare), @user@host " "accounts, #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Ricerca contenuto" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "link verificato" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Posizione: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nuovo post..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Cosa stai pensando?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operazioni..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Segui" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(per URL o user@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Annuncia" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(per URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Mi piace" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Impostazioni..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nome visualizzato:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Il tuo nome" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Elimina l'avatar" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Immagine intestazione (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Elimina l'immagine d'intestazione" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Descriviti qui..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Mostra sempre i contenuti sensibili" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Indirizzo email per le notifiche:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notifiche Telegram (bot key e chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "Notifiche ntfy (server ntfy e token)" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Giorni di mantenimento dei post (0: impostazione server)" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Elimina i messaggi diretti delle persone non seguite" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Questo account è un bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Annuncio automatico delle citazioni a quest'account" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Quest'account è privato (post invisibili nel web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Tieni chiuse le discussioni" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Devi approvare le richieste dei seguenti" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Rendi pubblici seguenti e seguiti" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Posizione corrente:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Dati del profilo (coppie di chiave=valore per ogni linea):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Lingua dell'interfaccia web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nuova password:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Reinserisci la password:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Aggiorna dati utente" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Hashtag seguiti..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Un hashtag per linea" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Aggiorna hashtags" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Questo post ti piace" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Non mi piace" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "No, non mi piace molto" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Sgancia" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Sgancia questo post dalla timeline" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Aggancia" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Aggancia questo post in cima alla timeline" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Annuncia questo post ai tuoi seguenti" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Rimuovi annuncio" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Mi pento di aver annunciato questo" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Elimina segnalibro" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Elimina questo post dai segnalibri" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Segnalibro" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Aggiungi questo post ai segnalibri" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Smetti di seguire" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Smetti di seguire l'utente" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Sequi l'utente" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Smetti di seguire il gruppo" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Smetti di seguire il gruppo o canale" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Segui grupp" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Segui il gruppo o canale" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "Silenzia" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Blocca l'utente" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Elimina" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Elimina questo post" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Nascondi" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Nascondi questo post completamente" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Modifica..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Rispondi..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Troncato (troppo lungo)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "Ti segue" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Aggancia" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Segnalibro" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Sondaggio" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Votato" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evento" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "Annunciato" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "in risposta a" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTENUTO SENSIBILE]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Vota" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Chiuso" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Chiude in" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Allegato" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Testo alternativo..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Provenienza del canale o comunità" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Orario:" -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Vecchi..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "descrizione" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "gestito da " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Congeda" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Timeline per la lista '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Post appuntati" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Post segnati" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Bozze" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Nessun ulteriore post" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Torna in cima" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Storico" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Ancora..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Senza limite" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permetti annunci dall'utente" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Limite" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Blocca annunci dall'utente" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Elimina l'utente" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Approva" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Approva richiesta di seguirti" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Scarta" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Scarta richiesta di seguirti" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Rimuovi silenziamento" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Sblocca l'utente" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Blocca l'utente completamente" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Messaggio diretto..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Conferme di seguirti in attesa" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Persone che segui" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Persone che ti seguono" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Pulisci" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Citazione" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Sondaggio concluso" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Richiesta di seguire" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contesto" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nuovo" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Già visto" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Niente" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Risultati per account %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Account %s non trovato" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Risultati per tag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Nessun risultato per il tag %S" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Risultati per tag %s (ancora...)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Risultati per %s" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Nessuna corrispondenza per '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Non trovato per '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Mostra la timeline dell'istanza" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Mostra la timeline della lista '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Risultati per tag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Post recenti in questa istanza" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Hashtag bloccati..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL facoltativo di risposta" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -707,94 +707,106 @@ msgstr "" "Scelta 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Chiave per le API del bot" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Id della chat" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "Server ntfy - URL completo (esempio: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "Token ntfy - se richiesto" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "appuntati" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "segnalibri" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "bozze" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "" msgid "Post date and time:" msgstr "" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/nl_NL.po b/po/nl_NL.po index 26f6e6c..37233dd 100644 --- a/po/nl_NL.po +++ b/po/nl_NL.po @@ -8,119 +8,119 @@ msgstr "" "Language: nl_NL\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Gevoelige inhoud: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Omschrijving van gevoelige inhoud" msgid "Only for mentioned people: " msgstr "Enkel voor genoemde personen: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Antwoord op (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Niet verzenden, maar opslaan als concept" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Concept:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Bijlagen..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Bestand:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Veld leegmaken om de bijlage te verwijderen" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Omschrijving van bijlage" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Peiling..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Peiling opties (één per regel, tot 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Eén keuze" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Meerdere keuzes" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Eindigt over 5 minuten" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Eindigt over 1 uur" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Eindigt over 1 dag" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Bericht" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Omschrijving van de site" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Admin e-mail" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Admin account" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d volgend, %d volgers" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privé" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "publiek" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notificaties" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "mensen" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instantie" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -128,574 +128,574 @@ msgstr "" "Zoek berichten op URL of inhoud (reguliere expressie), @user@host accounts, " "of #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Inhoud zoeken" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "verifieerde link" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Locatie: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nieuw bericht..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Wat wil je delen?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Handelingen..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Volg" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(via URL of gebruiker@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Boost" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(via URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Leuk" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Gebruikersinstellingen..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Weergavenaam:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Jouw naam" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Profielafbeelding: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Verwijder huidige profielafbeelding" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Header afbeelding (banner): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Verwijder huidige header afbeelding" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Bio:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Schrijf hier iets over jezelf..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Altijd gevoelige inhoud tonen" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "E-mailadres voor notificaties:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Telegram notificaties (bot sleutel en chat id):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ntfy notificaties (ntfy server en token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Maximaal aantal dagen om berichten te bewaren (0: serverinstellingen):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Verwijder directe berichten van mensen die je niet volgt" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Dit account is een bot" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Automatisch boosten van alle vermeldingen van dit account" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Dit account is privé (berichten worden niet getoond via het web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Klap standaard top threads in" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Volgverzoeken moeten worden goedgekeurd" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Publiceer volger- en volgstatistieken" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Huidige locatie:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Profiel metadata (sleutel=waarde paren in elke regel):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Webinterface taal:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nieuw wachtwoord:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Herhaal nieuw wachtwoord:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Werk gebruikersinformatie bij" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Gevolgde hashtags..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Eén hashtag per regel" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Werk hashtags bij" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Zeg dat je dit bericht leuk vindt" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Niet leuk vinden" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Nee, ik vind het niet zo leuk" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Niet vastzetten" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Zet dit bericht niet meer vast op je tijdlijn" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Vastzetten" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Zet dit bericht vast bovenaan je tijdlijn" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Kondig dit bericht aan bij je volgers" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Ontboosten" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Ik betreur dat ik dit heb geboost" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Uit favorieten verwijderen" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Verwijder dit bericht uit je favorieten" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Favoriet" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Voeg dit bericht toe aan je favorieten" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Ontvolgen" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Stop met het volgen van de activiteit van deze gebruiker" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Start met het volgen van de activiteit van deze gebruiker" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Ontvolg groep" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Stop met het volgen van deze groep of kanaal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Volg groep" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Start met het volgen van deze groep of kanaal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "DEMP" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Blokkeer alle activiteit van deze gebruiker voor altijd" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Verwijderen" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Verwijder dit bericht" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Verberg" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Verberg dit bericht en zijn kinderen" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Bewerken..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Antwoord..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Afgekapt (te diep)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "volgt jou" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Vastgezet" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Favoriet" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Peiling" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Gestemd" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evenement" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "geboost" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "als antwoord op" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [GEVOELIGE INHOUD]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Stem" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Gesloten" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Sluit over" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Video" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Audio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Bijlage" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Alt..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Bron kanaal of gemeenschap" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Tijd: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Ouder..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "over deze site" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "aangedreven door " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Verwerp" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Tijdlijn voor lijst '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Vastgezette berichten" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Favoriete berichten" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Berichtenconcepten" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Geen ongelezen berichten meer" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Terug naar boven" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Geschiedenis" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Meer..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Ongelimiteerd" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Sta aankondigingen (boosts) van deze gebruiker toe" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Limiteer" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Blokkeer aankondigingen (boosts) van deze gebruiker" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Verwijder deze gebruiker" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Goedkeuren" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Keurt dit volgverzoek goed" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Afwijzen" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Wijs dit volgverzoek af" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Niet meer dempen" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Stop met het blokkeren van activiteiten van deze gebruiker" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Blokkeer alle activiteit van deze gebruiker" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Persoonlijk bericht..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Openstaande volgbevestigingen" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Mensen die je volgt" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Mensen die jou volgen" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Alle wissen" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Benoemen" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Afgeronde peiling" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Volgverzoek" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Context" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Nieuw" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Al gezien" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Geen" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Zoekresultaten voor account %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Account %s niet gevonden" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Zoekresultaten voor tag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Niets gevonden voor tag %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Zoekresultaten voor '%s' (mogelijk meer)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Zoekresultaten voor '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Geen verdere overeenkomsten voor '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Niets gevonden voor '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Toond tijdlijn van instantie" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Toond tijdlijn voor lijst '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Zoekresultaten voor tag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Recente berichten van gebruikers in deze instantie" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Geblokkeerde hashtags..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Optionele URL om op te antwoorden" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -707,94 +707,106 @@ msgstr "" "Optie 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Bot API sleutel" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Chat id" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy server - volledige URL (voorbeeld: https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy token - indien nodig" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "vastgezet" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "favorieten" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "concepten" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Gepland bericht..." msgid "Post date and time:" msgstr "Bericht datum en tijd:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Geplande berichten" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "geplande berichten" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Bericht datum en tijd (tijdzone: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Tijdzone:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/pt_BR.po b/po/pt_BR.po index 12f8a83..e930490 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -12,119 +12,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.7\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Conteúdo sensível: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Descrição do conteúdo sensível" msgid "Only for mentioned people: " msgstr "Apenas para pessoas mencionadas: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Resposta para (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Não enviar, mas guardar como rascunho" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Rascunho:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Anexos..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Arquivo:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Limpe este campo para remover o anexo" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Descrição do anexo" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Enquete..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Alternativas da enquete (uma por linha, até 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Escolha única" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Escolhas múltiplas" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Encerrar em 5 minutos" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Encerrar em 1 hora" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Encerrar em 1 dia" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Publicar" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Descrição do sítio eletrônico" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "E-mail da administração" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Conta de quem administra" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d seguidos, %d seguidores" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "privado" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "público" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "notificações" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "pessoas" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "instância" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -132,574 +132,574 @@ msgstr "" "Procurar publicações por URL ou conteúdo (expressão regular), contas " "(@perfil@servidor) ou #tag" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Buscar conteúdo" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "ligação verificada" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Localização: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Nova publicação..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "O que tem em mente?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Operações..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Seguir" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(por URL ou conta@servidor)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Impulsionar" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(por URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Curtir" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Definições da conta..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Nome a ser exibido:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Seu nome" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Avatar: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Remover avatar atual" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Imagem de cabeçalho (capa): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Remover imagem de cabeçalho atual" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Biografia:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Escreva aqui sobre você..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Sempre exibir conteúdo sensível" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Endereço de e-mail para notificações:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Notificações Telegram (chave do robô e ID da conversa):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ntfy - notificações (servidor ntfy e token):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Máximo de dias a preservar publicações (0: definições do servidor):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Descartar mensagens diretas de quem você não segue" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Esta conta é robotizada" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Impulsionar automaticamente todas as menções a esta conta" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Esta conta é privada (as publicações não são exibidas na Web)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Recolher por padrão as sequências de publicações" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Solicitações de seguimento precisam ser aprovadas" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Publicar métricas de seguidores e seguidos" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Localização atual:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Metadados do perfil (par de chave=valor em cada linha):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Idioma da interface Web:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Nova senha:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Repita a nova senha:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Atualizar informações da conta" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Hashtags seguidas..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Uma hashtag por linha" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Atualizar hashtags" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Declarar que gosta desta publicação" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Descurtir" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Não gosto tanto assim disso" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Desafixar" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Desafixar esta publicação da sua linha do tempo" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Afixar" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Afixar esta publicação no topo de sua linha do tempo" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Anunciar esta publicação para seus seguidores" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Desimpulsionar" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Arrependo-me de ter impulsionado isso" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Desmarcar" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Remover esta publicação dos seus marcadores" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Marcar" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Adicionar esta publicação aos seus marcadores" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Deixar de seguir" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Parar de acompanhar a atividade deste perfil" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Começar a acompanhar a atividade deste perfil" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Deixar de seguir grupo" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Parar de acompanhar este grupo ou canal" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Seguir grupo" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Começar a acompanhar este grupo ou canal" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "MUDO" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Bloquear toda atividade deste perfil para sempre" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Eliminar" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Apagar esta publicação" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Ocultar" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Ocultar esta publicação e suas respostas" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Editar..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Responder..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Truncada (muito extensa)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "segue você" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Afixada" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Marcada" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Enquete" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Votou" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Evento" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "impulsionou" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "em resposta a" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [CONTEÚDO SENSÍVEL]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Votar" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Encerrada" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Encerra em" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Vídeo" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Áudio" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Anexo" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Texto alternativo..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Canal ou comunidade de origem" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Horário: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Anteriores..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "sobre este sítio eletrônico" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "movido por " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Dispensar" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Linha do tempo da lista '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Publicações afixadas" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Publicações marcadas" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Publicações em rascunho" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Sem mais publicações não vistas" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Voltar ao topo" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Histórico" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Mais..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Retirar restrição" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Permitir anúncios (impulsionamentos) deste perfil" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Restringir" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Bloquear anúncios (impulsionamentos) deste perfil" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Apagar este perfil" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Aprovar" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Aprovar esta solicitação de seguimento" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Descartar" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Descartar esta solicitação de seguimento" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Desbloquear" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Parar de bloquear as atividades deste perfil" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Bloquear toda atividade deste perfil" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Mensagem direta..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Confirmações de seguimento pendentes" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Pessoas que você segue" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Pessoas que seguem você" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Limpar tudo" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Menção" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Enquete encerrada" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Solicitação de seguimento" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Contexto" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Novas" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Já vistas" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Nenhuma" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Resultados da busca pela conta %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Conta %s não encontrada" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Resultados da busca pela hashtag %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Nada consta com hashtag %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Resultados da busca por '%s' (pode haver mais)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Resultados da busca por '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Sem mais combinações para '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Nada consta com '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Exibindo linha do tempo da instância" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Exibindo linha do tempo da lista '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Resultados da busca pela hashtag #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Publicações recentes de perfis desta instância" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Hashtags bloqueadas..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "URL opcional para a qual responder" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -711,94 +711,106 @@ msgstr "" "Opção 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Chave de API do robô" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "ID da conversa" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy - servidor - URL completa (exemplo: https://ntfy.sh/SeuTópico)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntfy - token (se necessário)" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "afixadas" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "marcadores" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "rascunhos" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Publicação agendada..." msgid "Post date and time:" msgstr "Data e horário da publicação:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Publicações agendadas" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "publicações agendadas" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Data e hora da publicação (fuso horário: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Fuso horário:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "Idioma:" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "Webhook para notificar:" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "http://exemplo.com.br/webhook" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "Idiomas em que costuma postar:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "pt en fr es de_AT" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "Visibilidade: " -#: html.c:468 msgid "Public" msgstr "Pública" -#: html.c:477 msgid "Unlisted" msgstr "Não listada" -#: html.c:486 msgid "Followers-only" msgstr "Seguidores apenas" -#: html.c:495 msgid "Direct Message" msgstr "Mensagem direta" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/ru.po b/po/ru.po index f91ccf1..0de03ac 100644 --- a/po/ru.po +++ b/po/ru.po @@ -15,119 +15,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Чувствительное содержимое: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Описание чувствительного содержимого" msgid "Only for mentioned people: " msgstr "Только для упомянутых людей: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Ответ на (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Не отправлять, сохранить черновик" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Черновик:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Вложения..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Файл:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Очистите это поле, чтоб удалить вложение" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Описание вложения" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Опрос..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Варианты ответа (один на строку, до 8 шт):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Один выбор" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Множественный выбор" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Заканчивается через 5 минут" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Заканчивается через 1 час" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Заканчивается через 1 день" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Отправить" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Описание сайта" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Почта админа" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Учётная запись админа" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d подписан, %d подписчиков" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "личное" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "публичное" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "уведомления" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "люди" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "сервер" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -135,574 +135,574 @@ msgstr "" "Поиск сообщений по URL или содержимому (регулярное выражение), учетной " "записи вида @user@host, или #тегу" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Поиск содержимого" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "проверенная ссылка" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Местоположение: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Новое сообщение..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Что у вас на уме?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Действия..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Подписаться" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(по URL или user@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Продвинуть" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(по URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Лайкнуть" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Пользовательские настройки..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Отображаемое имя:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Ваше имя" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Аватар: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Удалить текущий аватар" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Заглавное изображение (баннер): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Удалить текущее заглавное изображение" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "О себе:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Напишите что-нибудь про себя..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Всегда показывать чувствительное содержимое" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Почтовый адрес для уведомлений:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Уведомления в Telegram (ключ бота и id чата):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "уведомления в ntfy (сервер и токен ntfy):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Максимальное время хранения сообщений (0: настройки сервера):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Отклонять личные сообщения от незнакомцев" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Это аккаунт бота" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Автоматически продвигать все упоминания этого аккаунта" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Это закрытый аккаунт (сообщения не показываются в сети)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Сворачивать обсуждения по умолчанию" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Запросы подписки требуют подтверждения" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Публиковать статистику подписок и подписчиков" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Текущее метоположение:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Метаданные профиля (пары ключ=значение, по одной на строку)" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Язык интерфейса:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Новый пароль:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Повторите новый пароль:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Обновить данные пользователя" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Отслеживаемые хештеги..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "По одному на строку" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Обновить хештеги" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Отметить сообщение понравившимся" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Больше не нравится" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Не так уж и понравилось" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Открепить" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Открепить это сообщение из своей ленты" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Закрепить" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Закрепить это сообщение в своей ленте" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Поделиться этим сообщением со своими подписчиками" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Отменить продвижение" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Не буду продвигать, пожалуй" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Удалить из закладок" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Удалить это сообщение из закладок" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Добавить в закладки" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Добавить сообщение в закладки" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Отписаться" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Отменить подписку на этого пользователя" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Начать следовать за этим пользователем" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Отписаться от группы" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Отписаться от группы или канала" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Подписаться на группу" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Подписаться на группу или канал" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "Заглушить" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Заглушить всю активность от этого пользователя, навсегда" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Удалить" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Удалить это сообщение" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Скрыть" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Скрыть это сообщение вместе с обсуждением" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Редактировать..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Ответить..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Обрезано (слишком много)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "подписан на вас" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Закреплено" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Добавлено в закладки" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Опрос" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Проголосовано" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Событие" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "поделился" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "в ответ на" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [ЧУВСТВИТЕЛЬНО СОДЕРЖИМОЕ]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Голос" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Закрыт" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Закрывается через" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Видео" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Аудио" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Вложение" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Описание..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Исходный канал или сообщество" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Время: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Ранее..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "про этот сайт" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "на основе " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Скрыть" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Ленты для списка '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Закреплённые сообщения" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Сообщения в закладках" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Черновики сообщений" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Всё просмотрено" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Вернуться наверх" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "История" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Ещё..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Без ограничения" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Разрешить продвижения от этого пользователя" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Лимит" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Запретить продвижения от этого пользователя" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Удалить пользователя" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Подтвердить" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Подтвердить запрос на подписку" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Отклонить" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Отклонить этот запрос на подписку" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Отменить глушение" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Прекратить глушение действий этого пользователя" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Заглушить все действия этого пользователя" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Личное сообщение..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Ожидающие запросы на подписку" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Ваши подписки" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Ваши подписчики" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Очистить всё" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Упоминание" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Завершённый опрос" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Запрос на подписку" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Контекст" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Новое" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Уже просмотрено" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Нет" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Результаты поиска для учётной записи %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Учётная запись %s не найдена" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Результаты поиска тега %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Ничего не найдено по тегу %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Результаты поиска для '%s' (возможно, есть ещё)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Результаты поиска для '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Больше нет совпадений для '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Ничего не найдено для '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Показываем ленту сервера" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Показываем ленту для списка '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Результаты поиска для тега #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Последние сообщения на этом сервере" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Заблокированные теги..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Необязательный URL для ответа" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -714,94 +714,106 @@ msgstr "" "Вариант 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Ключ API для бота" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Id чата" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "полный URL сервера ntfy (например https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "токен ntfy - если нужен" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "закреплено" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "закладки" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "черновики" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Запланировать..." msgid "Post date and time:" msgstr "Время поста:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Запланированные посты" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "запланированные посты" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Время поста (Часовой пояс: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Часовой пояс:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/uk.po b/po/uk.po index cf8c204..d342978 100644 --- a/po/uk.po +++ b/po/uk.po @@ -15,119 +15,119 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 3.0\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "Делікатний вміст: " -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "Опис делікатного вмісту" msgid "Only for mentioned people: " msgstr "Тільки для зазначених осіб: " -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "Відповісти до (URL): " -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "Не надсилати, але зберігти як чернетку" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "Чернетка:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "Вкладення..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "Файл:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "Очистіть це поле, щоб видалити вкладення" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "Опис вкладення" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "Опитування..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "Варіанти відповідей (по одному в рядку, до 8):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "Єдиний вибір" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "Декілька варіантів вибору" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "Закінчення через 5 хвилин" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "Закінчення через 1 годину" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "Закінчення через 1 день" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "Надіслати" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "Опис сайту" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "Пошта админа" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "Обліковий запис адміна" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d підписок, %d підписників" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "особисте" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "публічне" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "повідомлення" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "люди" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "сервер" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" @@ -135,574 +135,574 @@ msgstr "" "Шукати дописи за URL або вмістом (регулярний вираз), акаунтами @user@host " "або #тегом" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "Пошук за вмістом" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "перевірене посилання" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "Місце знаходження: " -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "Новий допис..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "Що у вас на думці?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "Дії..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "Підписатися" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(за URL або user@host)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "Просувати" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(за URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "Вподобайка" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "Налаштування користувача..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "Видиме ім'я:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "Ваше ім'я" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "Аватар: " -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "Видалити поточний аватар" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "Зображення заголовка (банер): " -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "Видалити поточне зображення заголовка" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "Про себе:" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "Напишіть про себе тут..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "Завжди показувати делікатний вміст" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "Поштова адреса для повідомлень:" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Повідомлення в Telegram (ключ бота та id чату):" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "Повідомлення в ntfy (сервер та токен ntfy):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "Максимальний час для зберігання дописів (0: налаштування сервера):" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "Відхиляти особисті повідомлення від незнайомців" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "Цей акаунт є ботом" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "Автоматично просувати всі згадки цього акаунта" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "Це закритий акаунт (дописи не показуються в мережі)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "Згорнути потоки за замовчуванням" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "Запити на підписку мають бути схвалені" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "Публікувати метрики підписок та підписників" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "Поточне місцезнаходження:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "Метадані профілю (пари ключ=значення в кожному рядку):" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "Мова інтерфейсу:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "Новий пароль:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "Повторити новий пароль:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "Оновлення даних користувача" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "Підписані хештеги..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "Один хештег на рядок" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "Оновити хештеги" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "Позначте допис як вподобаний" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "Більше не подобається" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "Мені це не дуже подобається" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "Відкріпити" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "Відкріпити цей допис зі власної стрічки" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "Закріпити" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "Закріпити цей допис до власної стрічки" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "Поділитися цим дописом зі своїми підписниками" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "Скасувати просування" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "Я шкодую, що просував це" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "Видалити з закладок" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "Видалити цей допис з закладок" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "Додати в закладки" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "Додайте цей допис в закладки" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "Відписатися" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "Відписатися від цього користувача" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "Підписатися до цього користувача" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "Відписатися від групи" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "Відписатися від групи чи канала" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "Підписатися на групу" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "Підписатися на групу чи канал" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "Заглушити" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "Назавжди заблокувати активність цього користувача" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "Видалити" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "Видалити цей допис" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "Приховати" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "Приховати цей допис разом з обговоренням" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "Редагувати..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "Відповісти..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "Обрізано (занадто багато)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "підписан на вас" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "Закріплено" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "Додано до закладок" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "Опитування" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "Проголосовано" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "Подія" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "просунуто" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "у відповідь на" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr " [ДЕЛІКАТНИЙ ВМІСТ]" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "Голос" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "Завершено" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "Завершується через" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "Відео" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "Аудіо" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "Вкладення" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "Опис..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "Вихідний канал або спільнота" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "Час: " -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "Раніше..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "про цей сайт" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "на базі " -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "Відхилити" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "Стрічки для списку '%s'" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "Закріплені дописи" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "Дописи у закладках" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "Чернетки дописів" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "Усе переглянуто" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "Повернутися до початку" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "Історія" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "Більше..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "Без обмеження" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "Дозволити просування від цього користувача" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "Обмежити" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "Заборонити просування від цього користувача" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "Видалити користувача" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "Підтвердити" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "Підтвердити цей запит на підписку" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "Відхилити" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "Відхилити цей запит на підписку" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "Скасувати глушіння" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "Припинити глушіння дій цього користувача" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "Заглушити всі дії цього користувача" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "Особисте повідомлення..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "Запити на підписку очікують на розгляд" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "Ваші підписки" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "Ваші підписники" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "Очистити все" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "Згадка" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "Завершене опитування" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "Запит на підписку" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "Контекст" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "Нове" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "Вже переглянуто" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "Нема" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "Результати пошуку для облікового запису %s" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "Обліковий запис %s не знайдений" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "Результати пошуку тега %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "Нічого не знайдено за тегом %s" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "Результати пошуку для '%s' (можливо є більше)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "Результати пошуку для '%s'" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "Немає більше збігів для '%s'" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "Нічого не знайдено для '%s'" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "Показуємо стрічку сервера" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "Показуємо стрічку для списку '%s'" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "Результати пошуку для тега #%s" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "Останні повідомлення на цьому сервері" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "Заблоковані теги..." -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "Необов'язковий URL для відповіді" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -714,94 +714,106 @@ msgstr "" "Варіант 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Ключ API для бота" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "Id чату" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "повна URL сервера ntfy (наприклад https://ntfy.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "токен ntfy - якщо потрібно" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "закріплено" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "закладки" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "чернетки" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "Запланувати..." msgid "Post date and time:" msgstr "Час допису:" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "Заплановані дописи" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "заплановані дописи" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "Дата та час допису (часовий пояс: %s):" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "Часовий пояс:" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" diff --git a/po/zh.po b/po/zh.po index 5ed5edc..1e2897d 100644 --- a/po/zh.po +++ b/po/zh.po @@ -8,693 +8,693 @@ msgstr "" "Language: zh\n" "Content-Type: text/plain; charset=UTF-8\n" -#: html.c:440 +#: html.c:534 msgid "Sensitive content: " msgstr "敏感内容:" -#: html.c:448 +#: html.c:542 msgid "Sensitive content description" msgstr "敏感内容描述" msgid "Only for mentioned people: " msgstr "只有提及到的人:" -#: html.c:514 +#: html.c:570 msgid "Reply to (URL): " msgstr "回复给(URL):" -#: html.c:523 +#: html.c:579 msgid "Don't send, but store as a draft" msgstr "不发送,但保存为草稿" -#: html.c:524 +#: html.c:580 msgid "Draft:" msgstr "草稿:" -#: html.c:614 +#: html.c:670 msgid "Attachments..." msgstr "附件..." -#: html.c:637 +#: html.c:693 msgid "File:" msgstr "文件:" -#: html.c:641 +#: html.c:697 msgid "Clear this field to delete the attachment" msgstr "清除此项以删除附件" -#: html.c:650 html.c:675 +#: html.c:706 html.c:731 msgid "Attachment description" msgstr "附件描述" -#: html.c:686 +#: html.c:742 msgid "Poll..." msgstr "投票..." -#: html.c:688 +#: html.c:744 msgid "Poll options (one per line, up to 8):" msgstr "投票选项(每行一项,最多八项):" -#: html.c:700 +#: html.c:756 msgid "One choice" msgstr "单选" -#: html.c:703 +#: html.c:759 msgid "Multiple choices" msgstr "多选" -#: html.c:709 +#: html.c:765 msgid "End in 5 minutes" msgstr "五分钟后结束" -#: html.c:713 +#: html.c:769 msgid "End in 1 hour" msgstr "一小时后结束" -#: html.c:716 +#: html.c:772 msgid "End in 1 day" msgstr "一天后结束" -#: html.c:724 +#: html.c:780 msgid "Post" msgstr "发布" -#: html.c:826 html.c:833 +#: html.c:882 html.c:889 msgid "Site description" msgstr "站点描述" -#: html.c:844 +#: html.c:900 msgid "Admin email" msgstr "管理员邮箱" -#: html.c:857 +#: html.c:913 msgid "Admin account" msgstr "管理员帐号" -#: html.c:922 html.c:1278 +#: html.c:978 html.c:1334 #, c-format msgid "%d following, %d followers" msgstr "%d 个正在关注,%d 个关注者" -#: html.c:1019 +#: html.c:1075 msgid "RSS" msgstr "RSS" -#: html.c:1024 html.c:1063 +#: html.c:1080 html.c:1119 msgid "private" msgstr "私密" -#: html.c:1059 +#: html.c:1115 msgid "public" msgstr "公开" -#: html.c:1067 +#: html.c:1123 msgid "notifications" msgstr "通知" -#: html.c:1072 +#: html.c:1128 msgid "people" msgstr "成员" -#: html.c:1077 +#: html.c:1133 msgid "instance" msgstr "实例" -#: html.c:1086 +#: html.c:1142 msgid "" "Search posts by URL or content (regular expression), @user@host accounts, or " "#tag" msgstr "" "通过 URL、内容(正则表达式)、@<用户名>@<主机名>帐号,或者 #话题标签 搜索贴子" -#: html.c:1087 +#: html.c:1143 msgid "Content search" msgstr "搜索内容" -#: html.c:1213 +#: html.c:1269 msgid "verified link" msgstr "已验证的链接" -#: html.c:1270 html.c:2726 html.c:2739 html.c:2748 html.c:3680 +#: html.c:1326 html.c:3010 html.c:3023 html.c:3032 html.c:4095 msgid "Location: " msgstr "位置:" -#: html.c:1302 +#: html.c:1358 msgid "New Post..." msgstr "新贴子..." -#: html.c:1304 +#: html.c:1360 msgid "What's on your mind?" msgstr "你在想什么?" -#: html.c:1313 +#: html.c:1369 msgid "Operations..." msgstr "操作..." -#: html.c:1328 html.c:1949 html.c:3400 html.c:4817 +#: html.c:1384 html.c:2027 html.c:3776 html.c:4044 html.c:5261 msgid "Follow" msgstr "关注" -#: html.c:1330 +#: html.c:1386 msgid "(by URL or user@host)" msgstr "(通过 URL 或者 <用户名>@<主机名>)" -#: html.c:1345 html.c:1925 html.c:4766 +#: html.c:1401 html.c:2003 html.c:5210 msgid "Boost" msgstr "转发" -#: html.c:1347 html.c:1364 +#: html.c:1403 html.c:1420 html.c:1442 msgid "(by URL)" msgstr "(通过 URL)" -#: html.c:1362 html.c:1904 html.c:4757 +#: html.c:1418 html.c:1982 html.c:5201 msgid "Like" msgstr "点赞" -#: html.c:1490 +#: html.c:1568 msgid "User Settings..." msgstr "用户设置..." -#: html.c:1499 +#: html.c:1577 msgid "Display name:" msgstr "显示名字:" -#: html.c:1505 +#: html.c:1583 msgid "Your name" msgstr "你的名字" -#: html.c:1507 +#: html.c:1585 msgid "Avatar: " msgstr "头像:" -#: html.c:1515 +#: html.c:1593 msgid "Delete current avatar" msgstr "删除当前头像" -#: html.c:1517 +#: html.c:1595 msgid "Header image (banner): " msgstr "页眉图像(横幅)" -#: html.c:1525 +#: html.c:1603 msgid "Delete current header image" msgstr "删除当前的页眉图像" -#: html.c:1527 +#: html.c:1605 msgid "Bio:" msgstr "简介" -#: html.c:1533 +#: html.c:1611 msgid "Write about yourself here..." msgstr "在这里介绍你自己..." -#: html.c:1542 +#: html.c:1620 msgid "Always show sensitive content" msgstr "总是显示敏感内容" -#: html.c:1544 +#: html.c:1622 msgid "Email address for notifications:" msgstr "用于通知的电子邮箱地址" -#: html.c:1552 +#: html.c:1630 msgid "Telegram notifications (bot key and chat id):" msgstr "Telegram 通知(bot 密钥和聊天 ID)" -#: html.c:1566 +#: html.c:1644 msgid "ntfy notifications (ntfy server and token):" msgstr "ntfy 通知(ntfy 服务器和令牌):" -#: html.c:1588 +#: html.c:1666 msgid "Maximum days to keep posts (0: server settings):" msgstr "保存贴子的最大天数(0:服务器设置)" -#: html.c:1602 +#: html.c:1680 msgid "Drop direct messages from people you don't follow" msgstr "丢弃你没有关注的人的私信" -#: html.c:1611 +#: html.c:1689 msgid "This account is a bot" msgstr "此帐号是机器人" -#: html.c:1620 +#: html.c:1698 msgid "Auto-boost all mentions to this account" msgstr "自动转发所有对此帐号的提及" -#: html.c:1629 +#: html.c:1707 msgid "This account is private (posts are not shown through the web)" msgstr "这是一个私密帐号(贴子不会在网页中显示)" -#: html.c:1639 +#: html.c:1717 msgid "Collapse top threads by default" msgstr "默认收起主题帖" -#: html.c:1648 +#: html.c:1726 msgid "Follow requests must be approved" msgstr "关注请求必须经过审批" -#: html.c:1657 +#: html.c:1735 msgid "Publish follower and following metrics" msgstr "展示关注者和正在关注的数量" -#: html.c:1659 +#: html.c:1737 msgid "Current location:" msgstr "当前位置:" -#: html.c:1673 +#: html.c:1751 msgid "Profile metadata (key=value pairs in each line):" msgstr "个人资料元数据(每行一条 键=值)" -#: html.c:1684 +#: html.c:1762 msgid "Web interface language:" msgstr "网页界面语言:" -#: html.c:1703 +#: html.c:1781 msgid "New password:" msgstr "新密码:" -#: html.c:1710 +#: html.c:1788 msgid "Repeat new password:" msgstr "重复新密码:" -#: html.c:1720 +#: html.c:1798 msgid "Update user info" msgstr "更新用户信息:" -#: html.c:1731 +#: html.c:1809 msgid "Followed hashtags..." msgstr "关注的标签..." -#: html.c:1733 html.c:1766 +#: html.c:1811 html.c:1844 msgid "One hashtag per line" msgstr "每行一个标签" -#: html.c:1755 html.c:1787 +#: html.c:1833 html.c:1865 msgid "Update hashtags" msgstr "更新标签" -#: html.c:1904 +#: html.c:1982 msgid "Say you like this post" msgstr "说你喜欢这个贴子" -#: html.c:1909 html.c:4775 +#: html.c:1987 html.c:5219 msgid "Unlike" msgstr "不喜欢" -#: html.c:1909 +#: html.c:1987 msgid "Nah don't like it that much" msgstr "啊,不怎么喜欢这个" -#: html.c:1915 html.c:4912 +#: html.c:1993 html.c:5356 msgid "Unpin" msgstr "取消置顶" -#: html.c:1915 +#: html.c:1993 msgid "Unpin this post from your timeline" msgstr "从你的时间线上取消置顶这个贴子" -#: html.c:1918 html.c:4907 +#: html.c:1996 html.c:5351 msgid "Pin" msgstr "置顶" -#: html.c:1918 +#: html.c:1996 msgid "Pin this post to the top of your timeline" msgstr "把这条贴子置顶在你的时间线上" -#: html.c:1925 +#: html.c:2003 msgid "Announce this post to your followers" msgstr "向你的关注者宣布这条贴子" -#: html.c:1930 html.c:4783 +#: html.c:2008 html.c:5227 msgid "Unboost" msgstr "取消转发" -#: html.c:1930 +#: html.c:2008 msgid "I regret I boosted this" msgstr "我后悔转发这个了" -#: html.c:1936 html.c:4922 +#: html.c:2014 html.c:5366 msgid "Unbookmark" msgstr "取消收藏" -#: html.c:1936 +#: html.c:2014 msgid "Delete this post from your bookmarks" msgstr "从收藏夹中删除这个贴子" -#: html.c:1939 html.c:4917 +#: html.c:2017 html.c:5361 msgid "Bookmark" msgstr "收藏" -#: html.c:1939 +#: html.c:2017 msgid "Add this post to your bookmarks" msgstr "把这个贴子加入收藏夹" -#: html.c:1945 html.c:3386 html.c:3577 html.c:4830 +#: html.c:2023 html.c:3762 html.c:3957 html.c:4042 html.c:5274 msgid "Unfollow" msgstr "取消关注" -#: html.c:1945 html.c:3387 +#: html.c:2023 html.c:3763 html.c:4042 msgid "Stop following this user's activity" msgstr "停止关注此用户的动态" -#: html.c:1949 html.c:3401 +#: html.c:2027 html.c:3777 html.c:4044 msgid "Start following this user's activity" msgstr "开始关注此用户的动态" -#: html.c:1955 html.c:4860 +#: html.c:2033 html.c:5304 msgid "Unfollow Group" msgstr "取消关注群组" -#: html.c:1956 +#: html.c:2034 msgid "Stop following this group or channel" msgstr "取消关注这个群组或频道" -#: html.c:1960 html.c:4847 +#: html.c:2038 html.c:5291 msgid "Follow Group" msgstr "关注群组" -#: html.c:1961 +#: html.c:2039 msgid "Start following this group or channel" msgstr "开始关注这个群组或频道" -#: html.c:1966 html.c:3423 html.c:4791 +#: html.c:2044 html.c:3799 html.c:5235 msgid "MUTE" msgstr "静音" -#: html.c:1967 +#: html.c:2045 msgid "Block any activity from this user forever" msgstr "永久屏蔽来自这个用户的任何动态" -#: html.c:1972 html.c:3405 html.c:4877 +#: html.c:2050 html.c:3781 html.c:5321 msgid "Delete" msgstr "删除" -#: html.c:1972 +#: html.c:2050 msgid "Delete this post" msgstr "删除这条贴子" -#: html.c:1975 html.c:4799 +#: html.c:2053 html.c:5243 msgid "Hide" msgstr "隐藏" -#: html.c:1975 +#: html.c:2053 msgid "Hide this post and its children" msgstr "删除这条贴子及其回复" -#: html.c:2017 +#: html.c:2095 msgid "Edit..." msgstr "编辑..." -#: html.c:2039 +#: html.c:2133 msgid "Reply..." msgstr "回复..." -#: html.c:2090 +#: html.c:2184 msgid "Truncated (too deep)" msgstr "已被截断(太深了)" -#: html.c:2108 +#: html.c:2202 msgid "follows you" msgstr "关注了你" -#: html.c:2182 +#: html.c:2276 msgid "Pinned" msgstr "已置顶" -#: html.c:2190 +#: html.c:2284 msgid "Bookmarked" msgstr "已收藏" -#: html.c:2198 +#: html.c:2292 msgid "Poll" msgstr "投票" -#: html.c:2205 +#: html.c:2299 msgid "Voted" msgstr "已投票" -#: html.c:2214 +#: html.c:2308 msgid "Event" msgstr "事件" -#: html.c:2246 html.c:2275 +#: html.c:2340 html.c:2369 msgid "boosted" msgstr "已转发" -#: html.c:2289 +#: html.c:2383 msgid "in reply to" msgstr "回复给" -#: html.c:2345 +#: html.c:2439 msgid " [SENSITIVE CONTENT]" msgstr "【敏感内容】" -#: html.c:2512 +#: html.c:2796 msgid "Vote" msgstr "投票" -#: html.c:2522 +#: html.c:2806 msgid "Closed" msgstr "已关闭" -#: html.c:2547 +#: html.c:2831 msgid "Closes in" msgstr "距离关闭还有" -#: html.c:2627 +#: html.c:2911 msgid "Video" msgstr "视频" -#: html.c:2642 +#: html.c:2926 msgid "Audio" msgstr "音频" -#: html.c:2670 +#: html.c:2954 msgid "Attachment" msgstr "附件" -#: html.c:2684 +#: html.c:2968 msgid "Alt..." msgstr "描述..." -#: html.c:2697 +#: html.c:2981 msgid "Source channel or community" msgstr "来源频道或者社群" -#: html.c:2791 +#: html.c:3075 msgid "Time: " msgstr "时间:" -#: html.c:2872 +#: html.c:3156 msgid "Older..." msgstr "更早的..." -#: html.c:2974 +#: html.c:3258 msgid "about this site" msgstr "关于此站点" -#: html.c:2976 +#: html.c:3260 msgid "powered by " msgstr "驱动自" -#: html.c:3041 +#: html.c:3329 msgid "Dismiss" msgstr "忽略" -#: html.c:3058 +#: html.c:3346 #, c-format msgid "Timeline for list '%s'" msgstr "列表'%s'的时间线" -#: html.c:3077 html.c:4169 +#: html.c:3365 html.c:4589 msgid "Pinned posts" msgstr "置顶的贴子" -#: html.c:3089 html.c:4184 +#: html.c:3377 html.c:4604 msgid "Bookmarked posts" msgstr "收藏的贴子" -#: html.c:3101 html.c:4199 +#: html.c:3389 html.c:4619 msgid "Post drafts" msgstr "贴子草稿" -#: html.c:3177 +#: html.c:3465 msgid "No more unseen posts" msgstr "没有更多未读贴子了" -#: html.c:3181 html.c:3290 +#: html.c:3469 html.c:3578 msgid "Back to top" msgstr "返回顶部" -#: html.c:3243 +#: html.c:3531 msgid "History" msgstr "历史" -#: html.c:3295 html.c:3734 +#: html.c:3583 html.c:4149 msgid "More..." msgstr "更多..." -#: html.c:3391 html.c:4813 +#: html.c:3767 html.c:5257 msgid "Unlimit" msgstr "取消限制" -#: html.c:3392 +#: html.c:3768 msgid "Allow announces (boosts) from this user" msgstr "允许来自这个用户的通知(转发)" -#: html.c:3395 html.c:4809 +#: html.c:3771 html.c:5253 msgid "Limit" msgstr "限制" -#: html.c:3396 +#: html.c:3772 msgid "Block announces (boosts) from this user" msgstr "屏蔽来自这个用户的通知(转发)" -#: html.c:3405 +#: html.c:3781 msgid "Delete this user" msgstr "删除此用户" -#: html.c:3410 html.c:4927 +#: html.c:3786 html.c:5371 msgid "Approve" msgstr "允许" -#: html.c:3411 +#: html.c:3787 msgid "Approve this follow request" msgstr "允许这个关注请求" -#: html.c:3414 html.c:4951 +#: html.c:3790 html.c:5395 msgid "Discard" msgstr "丢弃" -#: html.c:3414 +#: html.c:3790 msgid "Discard this follow request" msgstr "丢弃这个关注请求" -#: html.c:3419 html.c:4795 +#: html.c:3795 html.c:5239 msgid "Unmute" msgstr "取消静音" -#: html.c:3420 +#: html.c:3796 msgid "Stop blocking activities from this user" msgstr "停止屏蔽来自此用户的动态" -#: html.c:3424 +#: html.c:3800 msgid "Block any activity from this user" msgstr "屏蔽来自此用户的任何动态" -#: html.c:3432 +#: html.c:3808 msgid "Direct Message..." msgstr "私信..." -#: html.c:3467 +#: html.c:3843 msgid "Pending follow confirmations" msgstr "待处理的关注确认" -#: html.c:3471 +#: html.c:3847 msgid "People you follow" msgstr "你关注的人" -#: html.c:3472 +#: html.c:3848 msgid "People that follow you" msgstr "关注你的人" -#: html.c:3511 +#: html.c:3887 msgid "Clear all" msgstr "清除全部" -#: html.c:3571 +#: html.c:3951 msgid "Mention" msgstr "提及" -#: html.c:3574 +#: html.c:3954 msgid "Finished poll" msgstr "结束投票" -#: html.c:3590 +#: html.c:3979 msgid "Follow Request" msgstr "关注请求" -#: html.c:3674 +#: html.c:4089 msgid "Context" msgstr "上下文" -#: html.c:3692 +#: html.c:4107 msgid "New" msgstr "新建" -#: html.c:3707 +#: html.c:4122 msgid "Already seen" msgstr "已经看过" -#: html.c:3722 +#: html.c:4137 msgid "None" msgstr "没有" -#: html.c:3994 +#: html.c:4414 #, c-format msgid "Search results for account %s" msgstr "账户 %s 的搜索结果" -#: html.c:4001 +#: html.c:4421 #, c-format msgid "Account %s not found" msgstr "没有找到账户 %s" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Search results for tag %s" msgstr "标签 %s 的搜索结果" -#: html.c:4032 +#: html.c:4452 #, c-format msgid "Nothing found for tag %s" msgstr "没有找到标签'%s'的结果" -#: html.c:4048 +#: html.c:4468 #, c-format msgid "Search results for '%s' (may be more)" msgstr "'%s'的搜索结果(可能还有更多)" -#: html.c:4051 +#: html.c:4471 #, c-format msgid "Search results for '%s'" msgstr "'%s'的搜索结果" -#: html.c:4054 +#: html.c:4474 #, c-format msgid "No more matches for '%s'" msgstr "没有更多匹配'%s'的结果了" -#: html.c:4056 +#: html.c:4476 #, c-format msgid "Nothing found for '%s'" msgstr "没有找到'%s'的结果" -#: html.c:4154 +#: html.c:4574 msgid "Showing instance timeline" msgstr "显示实例时间线" -#: html.c:4237 +#: html.c:4657 #, c-format msgid "Showing timeline for list '%s'" msgstr "显示列表'%s'的事件线" -#: httpd.c:258 +#: httpd.c:259 #, c-format msgid "Search results for tag #%s" msgstr "标签 #%s 的搜索结果" -#: httpd.c:267 +#: httpd.c:268 msgid "Recent posts by users in this instance" msgstr "此实例上的用户最近的贴子" -#: html.c:1764 +#: html.c:1842 msgid "Blocked hashtags..." msgstr "已屏蔽的话题标签" -#: html.c:518 +#: html.c:574 msgid "Optional URL to reply to" msgstr "可选的回复的网址" -#: html.c:695 +#: html.c:751 msgid "" "Option 1...\n" "Option 2...\n" @@ -706,94 +706,106 @@ msgstr "" "选项 3...\n" "..." -#: html.c:1558 +#: html.c:1636 msgid "Bot API key" msgstr "Bot API 密钥" -#: html.c:1564 +#: html.c:1642 msgid "Chat id" msgstr "聊天 ID" -#: html.c:1572 +#: html.c:1650 msgid "ntfy server - full URL (example: https://ntfy.sh/YourTopic)" msgstr "ntfy 服务器 - 完整网址(例如:https://ntft.sh/YourTopic)" -#: html.c:1578 +#: html.c:1656 msgid "ntfy token - if needed" msgstr "ntft 令牌 - 如果需要的话" -#: html.c:3078 +#: html.c:3366 msgid "pinned" msgstr "置顶" -#: html.c:3090 +#: html.c:3378 msgid "bookmarks" msgstr "收藏夹" -#: html.c:3102 +#: html.c:3390 msgid "drafts" msgstr "草稿" -#: html.c:584 +#: html.c:640 msgid "Scheduled post..." msgstr "计划发布定时贴文" msgid "Post date and time:" msgstr "发布日期和时间" -#: html.c:3113 html.c:4214 +#: html.c:3401 html.c:4634 msgid "Scheduled posts" msgstr "已发布的定时帖文" -#: html.c:3114 +#: html.c:3402 msgid "scheduled posts" msgstr "计划发布定时贴文" -#: html.c:578 +#: html.c:634 #, c-format msgid "Post date and time (timezone: %s):" msgstr "发布日期和时间(时区: %s)" -#: html.c:1689 +#: html.c:1767 msgid "Time zone:" msgstr "时区" -#: html.c:559 +#: html.c:615 msgid "Language:" msgstr "语言" -#: html.c:1580 +#: html.c:1658 msgid "Notify webhook:" msgstr "" -#: html.c:1586 +#: html.c:1664 msgid "http://example.com/webhook" msgstr "" -#: html.c:1694 +#: html.c:1772 msgid "Languages you usually post in:" msgstr "您通常使用的语言:" -#: html.c:1700 +#: html.c:1778 msgid "en fr es de_AT" msgstr "" -#: html.c:460 +#: html.c:428 msgid "Visibility: " msgstr "" -#: html.c:468 msgid "Public" msgstr "" -#: html.c:477 msgid "Unlisted" msgstr "" -#: html.c:486 msgid "Followers-only" msgstr "" -#: html.c:495 msgid "Direct Message" msgstr "" + +#: html.c:488 html.c:2534 html.c:2559 html.c:5177 +msgid "EmojiUnreact" +msgstr "" + +#: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 +msgid "EmojiReact" +msgstr "" + +#: html.c:2115 +msgid "Emoji react..." +msgstr "" + +#: html.c:2609 +msgid "Emoji reactions: " +msgstr "" -- cgit v1.2.3 From a97d3ac11628cd9244f97d2304d972abfb2b4824 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 19 Dec 2025 15:27:51 +0100 Subject: Reindex tags when editing a post. Tags that were deleted in the post message are not deleted, though. --- html.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html.c b/html.c index f6c93c7..0b84e56 100644 --- a/html.c +++ b/html.c @@ -5141,6 +5141,9 @@ int html_post_handler(const xs_dict *req, const char *q_path, /* overwrite object, not updating the indexes */ object_add_ow(edit_id, msg); + /* index tags */ + tag_index(edit_id, msg); + /* update message */ c_msg = msg_update(&snac, msg); } -- cgit v1.2.3 From b3df34f4f1fe2ca14ef0a50d34c7bc41e9325653 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 19 Dec 2025 15:29:51 +0100 Subject: Updated TODO. --- TODO.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 9c3fcad..799988b 100644 --- a/TODO.md +++ b/TODO.md @@ -6,8 +6,6 @@ It seems that Microsoft is planning to laminate Basic HTTP Auth, so make a plan, Investigate the problem with boosts inside the same instance (see https://codeberg.org/grunfink/snac2/issues/214). -Editing / Updating a post does not index newly added hashtags. - Important: deleting a follower should do more that just delete the object, see https://codeberg.org/grunfink/snac2/issues/43#issuecomment-956721 ## Wishlist @@ -381,3 +379,5 @@ Unfollowing guppe groups seems to work (http status of 200), but messages contin Do something about Akkoma and Misskey's quoted replies (they use the `quoteUrl` field instead of `inReplyTo`) (2025-12-09T05:31:56+0100). Take a look at crashes in the brittle Mastodon official app (crashes when hitting the reply button, crashes or 'ownVotes is null' errors when trying to show polls) (2025-12-09T05:31:56+0100). + +Editing / Updating a post does not index newly added hashtags (2025-12-19T15:29:38+0100). -- cgit v1.2.3 From 55b5b17f2e74374c83db6e1846f439e320b60d62 Mon Sep 17 00:00:00 2001 From: pmjv Date: Sat, 20 Dec 2025 13:09:10 +0100 Subject: Update po/cs.po --- po/cs.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/po/cs.po b/po/cs.po index daf1523..bf2b03a 100644 --- a/po/cs.po +++ b/po/cs.po @@ -781,7 +781,7 @@ msgstr "cs en fr de_AT" #: html.c:428 msgid "Visibility: " -msgstr "Viditelnost" +msgstr "Viditelnost: " msgid "Public" msgstr "Veřejné" @@ -797,16 +797,16 @@ msgstr "Soukromá Zpráva" #: html.c:488 html.c:2534 html.c:2559 html.c:5177 msgid "EmojiUnreact" -msgstr "" +msgstr "EmojiOdebrat" #: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 msgid "EmojiReact" -msgstr "" +msgstr "EmojiReakce" #: html.c:2115 msgid "Emoji react..." -msgstr "" +msgstr "Reagovat emoji..." #: html.c:2609 msgid "Emoji reactions: " -msgstr "" +msgstr "Emoji reakce: " -- cgit v1.2.3 From 79c32485dffa95107216c2251ffa111d7cdef432 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 20 Dec 2025 13:15:34 +0100 Subject: Fixed failed search when blank surround the query string. --- html.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index 0b84e56..20ad839 100644 --- a/html.c +++ b/html.c @@ -4343,9 +4343,13 @@ int html_get_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_UNAUTHORIZED; } else { - const char *q = xs_dict_get(q_vars, "q"); + xs *q = NULL; + const char *q1 = xs_dict_get(q_vars, "q"); xs *url_acct = NULL; + if (xs_is_string(q1)) + q = xs_strip_i(xs_dup(q1)); + /* searching for an URL? */ if (q && xs_match(q, "https://*|http://*")) { /* may by an actor; try a webfinger */ -- cgit v1.2.3 From 267e39eccea2264651bcd510ce5a0b53a1909993 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 20 Dec 2025 13:16:33 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 341206f..9d41588 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,6 +8,8 @@ Mastodon API: Fix for some client notifications (contributed by violette). If the query variable `terse` of a public post page is set to anything, no header is shown. +Fixed search failures when the query string has any leading blank. + ## 2.85 Quoted posts are now shown. -- cgit v1.2.3 From 209f53bbb61d2d8198da1365ef892476e908ee8d Mon Sep 17 00:00:00 2001 From: zen Date: Sun, 21 Dec 2025 16:39:09 +0100 Subject: po/de_DE.po aktualisiert --- po/de_DE.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/po/de_DE.po b/po/de_DE.po index 6257354..2db7ca3 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -798,16 +798,16 @@ msgstr "Direktnachricht" #: html.c:488 html.c:2534 html.c:2559 html.c:5177 msgid "EmojiUnreact" -msgstr "" +msgstr "Emoji-Reaktion löschen" #: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 msgid "EmojiReact" -msgstr "" +msgstr "Emoji-Reaktion" #: html.c:2115 msgid "Emoji react..." -msgstr "" +msgstr "Emoji-Reaktion..." #: html.c:2609 msgid "Emoji reactions: " -msgstr "" +msgstr "Emoji-Reaktionen:" -- cgit v1.2.3 From 1985ae4354f1e55fa87199a36bc2122f48fe7da6 Mon Sep 17 00:00:00 2001 From: Daltux Date: Sun, 21 Dec 2025 13:52:45 -0300 Subject: Update pt_BR translation --- po/pt_BR.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index e930490..e11f040 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -4,13 +4,13 @@ msgid "" msgstr "" "Project-Id-Version: snac\n" -"PO-Revision-Date: 2025-10-11 16:48-0300\n" +"PO-Revision-Date: 2025-12-21 13:44-0300\n" "Last-Translator: Daltux <@daltux@snac.daltux.net>\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 3.7\n" +"X-Generator: Geany / PoHelper 2.0\n" #: html.c:534 msgid "Sensitive content: " @@ -801,16 +801,16 @@ msgstr "Mensagem direta" #: html.c:488 html.c:2534 html.c:2559 html.c:5177 msgid "EmojiUnreact" -msgstr "" +msgstr "DesreaçãoEmoji" #: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 msgid "EmojiReact" -msgstr "" +msgstr "ReaçãoEmoji" #: html.c:2115 msgid "Emoji react..." -msgstr "" +msgstr "Reação com emoji..." #: html.c:2609 msgid "Emoji reactions: " -msgstr "" +msgstr "Reações com emoji: " -- cgit v1.2.3 From c5824038b88e4dc5a5d121361ad7078084fb60c9 Mon Sep 17 00:00:00 2001 From: fruye Date: Mon, 22 Dec 2025 20:52:14 +0100 Subject: mastoapi: fixed status visibility error. --- mastoapi.c | 82 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/mastoapi.c b/mastoapi.c index d38e902..6a12ced 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1985,60 +1985,64 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, } else if (strcmp(opt, "statuses") == 0) { /** **/ - /* the public list of posts of a user */ - const char *limit_s = xs_dict_get(args, "limit"); - const char *o_max_id = xs_dict_get(args, "max_id"); - int limit = limit_s ? atoi(limit_s) : 20; - xs *max_id = o_max_id ? xs_tolower_i(xs_dup(o_max_id)) : NULL; + if (logged_in || xs_type(xs_dict_get(snac2.config, "private")) == XSTYPE_FALSE) { + /* the public list of posts of a user */ + const char *limit_s = xs_dict_get(args, "limit"); + const char *o_max_id = xs_dict_get(args, "max_id"); + int limit = limit_s ? atoi(limit_s) : 20; + xs *max_id = o_max_id ? xs_tolower_i(xs_dup(o_max_id)) : NULL; - srv_debug(1, xs_fmt("account statuses: max_id=%s limit=%d", max_id ? max_id : "(null)", limit)); + srv_debug(1, xs_fmt("account statuses: max_id=%s limit=%d", max_id ? max_id : "(null)", limit)); - xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); - xs_list *p = timeline; - const xs_str *v; - xs_set seen; - int cnt = 0; - int skip_until_max = max_id != NULL; + xs *timeline = timeline_simple_list(&snac2, "public", 0, 256, NULL); + xs_list *p = timeline; + const xs_str *v; + xs_set seen; + int cnt = 0; + int skip_until_max = max_id != NULL; - out = xs_list_new(); - xs_set_init(&seen); + out = xs_list_new(); + xs_set_init(&seen); - while (xs_list_iter(&p, &v) && cnt < limit) { - xs *msg = NULL; + while (xs_list_iter(&p, &v) && cnt < limit) { + xs *msg = NULL; - if (valid_status(timeline_get_by_md5(&snac2, v, &msg))) { - const char *msg_id = xs_dict_get(msg, "id"); + if (valid_status(timeline_get_by_md5(&snac2, v, &msg))) { + const char *msg_id = xs_dict_get(msg, "id"); - /* add only posts by the author */ - if (!xs_is_null(msg_id) && - strcmp(xs_dict_get(msg, "type"), "Note") == 0 && - is_msg_mine(&snac2, xs_dict_get(msg, "id")) && is_msg_public(msg)) { + /* add only posts by the author */ + if (!xs_is_null(msg_id) && + strcmp(xs_dict_get(msg, "type"), "Note") == 0 && + is_msg_mine(&snac2, xs_dict_get(msg, "id")) && is_msg_public(msg)) { - /* if max_id is set, skip entries until we find it */ - if (skip_until_max) { - xs *mid = mastoapi_id(msg); - if (strcmp(mid, max_id) == 0) { - skip_until_max = 0; - srv_debug(2, xs_fmt("account statuses: found max_id, starting from next post")); + /* if max_id is set, skip entries until we find it */ + if (skip_until_max) { + xs *mid = mastoapi_id(msg); + if (strcmp(mid, max_id) == 0) { + skip_until_max = 0; + srv_debug(2, xs_fmt("account statuses: found max_id, starting from next post")); + } + continue; } - continue; - } - /* deduplicate by message id */ - if (xs_set_add(&seen, msg_id) == 1) { - xs *st = mastoapi_status(&snac2, msg); + /* deduplicate by message id */ + if (xs_set_add(&seen, msg_id) == 1) { + xs *st = mastoapi_status(&snac2, msg); - if (st) { - out = xs_list_append(out, st); - cnt++; + if (st) { + out = xs_list_append(out, st); + cnt++; + } } } } } - } - srv_debug(1, xs_fmt("account statuses: returning %d posts (requested %d)", cnt, limit)); - xs_set_free(&seen); + srv_debug(1, xs_fmt("account statuses: returning %d posts (requested %d)", cnt, limit)); + xs_set_free(&seen); + } + else + status = HTTP_STATUS_UNAUTHORIZED; } else if (strcmp(opt, "featured_tags") == 0) { -- cgit v1.2.3 From 53043a6785e8880e8ec1b71d6ad2b13096347a44 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 22 Dec 2025 20:54:22 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9d41588..d28b125 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,7 +4,7 @@ Added emoji reactions (contributed by violette). -Mastodon API: Fix for some client notifications (contributed by violette). +Mastodon API: Fix for some client notifications (contributed by violette), fix for a status visibility error (contributed by fruye). If the query variable `terse` of a public post page is set to anything, no header is shown. -- cgit v1.2.3 From 9d08379c8aaf1b03de7e6e0ff322b869ed9000db Mon Sep 17 00:00:00 2001 From: Daltux Date: Fri, 26 Dec 2025 15:13:04 -0300 Subject: Update pt_BR translation --- po/pt_BR.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/po/pt_BR.po b/po/pt_BR.po index e11f040..71b0132 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -4,7 +4,7 @@ msgid "" msgstr "" "Project-Id-Version: snac\n" -"PO-Revision-Date: 2025-12-21 13:44-0300\n" +"PO-Revision-Date: 2025-12-22 07:55-0300\n" "Last-Translator: Daltux <@daltux@snac.daltux.net>\n" "Language: pt_BR\n" "MIME-Version: 1.0\n" @@ -800,17 +800,17 @@ msgid "Direct Message" msgstr "Mensagem direta" #: html.c:488 html.c:2534 html.c:2559 html.c:5177 -msgid "EmojiUnreact" -msgstr "DesreaçãoEmoji" +msgid "Desfazer EmojiReação" +msgstr "" #: html.c:488 html.c:1440 html.c:2534 html.c:2559 html.c:5188 msgid "EmojiReact" -msgstr "ReaçãoEmoji" +msgstr "EmojiReação" #: html.c:2115 msgid "Emoji react..." -msgstr "Reação com emoji..." +msgstr "EmojiReagir..." #: html.c:2609 msgid "Emoji reactions: " -msgstr "Reações com emoji: " +msgstr "EmojiReações: " -- cgit v1.2.3 From a1f0a89931ad1ac51e28c318e29ef7f1cfc25255 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 26 Dec 2025 21:15:19 +0100 Subject: Revert "Fixed failed search when blank surround the query string." This reverts commit 79c32485dffa95107216c2251ffa111d7cdef432. --- html.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/html.c b/html.c index 20ad839..0b84e56 100644 --- a/html.c +++ b/html.c @@ -4343,13 +4343,9 @@ int html_get_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_UNAUTHORIZED; } else { - xs *q = NULL; - const char *q1 = xs_dict_get(q_vars, "q"); + const char *q = xs_dict_get(q_vars, "q"); xs *url_acct = NULL; - if (xs_is_string(q1)) - q = xs_strip_i(xs_dup(q1)); - /* searching for an URL? */ if (q && xs_match(q, "https://*|http://*")) { /* may by an actor; try a webfinger */ -- cgit v1.2.3 From be4dd4ea7f58a31546ad873d5b464fdb8b289ec8 Mon Sep 17 00:00:00 2001 From: grunfink Date: Fri, 26 Dec 2025 21:24:08 +0100 Subject: Fixed failed search when blank surround the query string. This time, without fucking up everything. --- html.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index 0b84e56..3e692bd 100644 --- a/html.c +++ b/html.c @@ -4343,9 +4343,15 @@ int html_get_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_UNAUTHORIZED; } else { - const char *q = xs_dict_get(q_vars, "q"); + const char *q = NULL; + xs *cq = xs_dup(xs_dict_get(q_vars, "q")); xs *url_acct = NULL; + if (xs_is_string(cq)) { + cq = xs_strip_i(cq); + q = cq; + } + /* searching for an URL? */ if (q && xs_match(q, "https://*|http://*")) { /* may by an actor; try a webfinger */ -- cgit v1.2.3 From b64bebd412f10e7a29f92220624e8423aaf5d883 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Sun, 28 Dec 2025 20:59:12 +0100 Subject: introduce separate people/ pages When you have lots of followers or followees or pending follows, constructing the entire people page to look up information about a single user can take a while and be quite wasteful when you want to look up a single user. Introduce and prefer people/ over people#. While at that, fix a memory leak in webfinger search: the empty list was allocated twice. --- RELEASE_NOTES.md | 2 ++ html.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d28b125..0cb2c86 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,8 @@ ## UNRELEASED +Link contacts to single-user people pages (contributed by lxo). + Added emoji reactions (contributed by violette). Mastodon API: Fix for some client notifications (contributed by violette), fix for a status visibility error (contributed by fruye). diff --git a/html.c b/html.c index 3e692bd..c03c867 100644 --- a/html.c +++ b/html.c @@ -221,7 +221,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, anchored link to the people page instead of the actor url */ if (fwer || fwing) { xs *md5 = xs_md5_hex(actor_id, strlen(actor_id)); - href = xs_fmt("%s/people#%s", user->actor, md5); + href = xs_fmt("%s/people/%s", user->actor, md5); } } @@ -2355,7 +2355,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } if (!read_only && (fwers || fwing)) - href = xs_fmt("%s/people#%s", user->actor, p); + href = xs_fmt("%s/people/%s", user->actor, p); else href = xs_dup(id); @@ -3856,6 +3856,29 @@ xs_str *html_people(snac *user) return xs_html_render_s(html, "\n"); } +xs_str *html_people_one(snac *user, const char *actor) +{ + const char *proxy = NULL; + + if (xs_is_true(xs_dict_get(srv_config, "proxy_media"))) + proxy = user->actor; + + xs_html *lists = xs_html_tag("div", + xs_html_attr("class", "snac-posts")); + + xs *foll = xs_list_append(xs_list_new(), actor); + + xs_html_add(lists, + html_people_list(user, foll, L("People - single"), "p", proxy)); + + xs_html *html = xs_html_tag("html", + html_user_head(user, NULL, NULL), + xs_html_add(html_user_body(user, 0), + lists, + html_footer(user))); + + return xs_html_render_s(html, "\n"); +} xs_str *html_notifications(snac *user, int skip, int show) { @@ -4415,7 +4438,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, actor_add(actor, actor_obj); /* create a people list with only one element */ - l = xs_list_append(xs_list_new(), actor); + l = xs_list_append(l, actor); xs *title = xs_fmt(L("Search results for account %s"), q); @@ -4555,6 +4578,30 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else + if (xs_startswith(p_path, "people/")) { /** the list of people **/ + if (!login(&snac, req)) { + *body = xs_dup(uid); + status = HTTP_STATUS_UNAUTHORIZED; + } + else { + xs *actor_dict = NULL; + const char *actor_id = NULL; + xs *actor = NULL; + + if (valid_status(object_get_by_md5(p_path + strlen("people/"), &actor_dict)) && + (actor_id = xs_dict_get(actor_dict, "id")) != NULL && + valid_status(actor_get(actor_id, &actor))) { + *body = html_people_one(&snac, actor_id); + *b_size = strlen(*body); + status = HTTP_STATUS_OK; + } + else { + *body = xs_dup(uid); + status = HTTP_STATUS_NOT_FOUND; + } + } + } + else if (strcmp(p_path, "notifications") == 0) { /** the list of notifications **/ if (!login(&snac, req)) { *body = xs_dup(uid); -- cgit v1.2.3 From 93f82fae9e024ae4a7338701db762e390056e990 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Tue, 30 Dec 2025 13:12:46 +0100 Subject: Add posts by actor to people page Select posts by the actor from the given timeline range. Since posts by the actor may be very sparse in the timeline, add a "More (x 10)" button to bump the show count, that controls how many timeline posts we'll filter *from*. We could conceivably keep searching the timeline until we find as many posts as requested or reach the end, but that could take a very long time. Just filtering the given ranges is much simpler, and probably sufficiently intuitive despite the potential initial surprise. --- html.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index c03c867..70c599f 100644 --- a/html.c +++ b/html.c @@ -3856,25 +3856,89 @@ xs_str *html_people(snac *user) return xs_html_render_s(html, "\n"); } -xs_str *html_people_one(snac *user, const char *actor) +/* Filter list to display only posts by actor. We'll probably show + fewer than show posts. Should we try harder to find some? */ +xs_str *html_people_one(snac *user, const char *actor, const xs_list *list, + int skip, int show, int show_more, const char *page) { const char *proxy = NULL; + xs_list *p = (xs_list *)list; + const char *v; if (xs_is_true(xs_dict_get(srv_config, "proxy_media"))) proxy = user->actor; + xs_html *body = html_user_body(user, 0); + xs_html *lists = xs_html_tag("div", xs_html_attr("class", "snac-posts")); xs *foll = xs_list_append(xs_list_new(), actor); xs_html_add(lists, - html_people_list(user, foll, L("People - single"), "p", proxy)); + html_people_list(user, foll, L("Contact's posts"), "p", proxy)); + + xs_html_add(body, lists); + + while (xs_list_iter(&p, &v)) { + xs *msg = NULL; + int status; + + status = timeline_get_by_md5(user, v, &msg); + + if (!valid_status(status)) + continue; + + const char *by = xs_dict_get(msg, "attributedTo"); + if (!by || strcmp(actor, by) != 0) + continue; + + xs_html *entry = html_entry(user, msg, 0, 0, v, 1); + + if (entry != NULL) + xs_html_add(lists, + entry); + } + + if (show_more) { + xs *m = NULL; + xs *m10 = NULL; + xs *ss = xs_fmt("skip=%d&show=%d", skip + show, show); + + xs *url = xs_dup(user == NULL ? srv_baseurl : user->actor); + + if (page != NULL) + url = xs_str_cat(url, page); + + if (xs_str_in(url, "?") != -1) + m = xs_fmt("%s&%s", url, ss); + else + m = xs_fmt("%s?%s", url, ss); + m10 = xs_fmt("%s0", m); + + xs_html *more_links = xs_html_tag("p", + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("name", "snac-more"), + xs_html_text(L("Back to top"))), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", m), + xs_html_attr("name", "snac-more"), + xs_html_text(L("More..."))), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", m10), + xs_html_attr("name", "snac-more"), + xs_html_text(L("More (x 10)...")))); + + xs_html_add(body, + more_links); + } xs_html *html = xs_html_tag("html", html_user_head(user, NULL, NULL), - xs_html_add(html_user_body(user, 0), - lists, + xs_html_add(body, html_footer(user))); return xs_html_render_s(html, "\n"); @@ -4578,7 +4642,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else - if (xs_startswith(p_path, "people/")) { /** the list of people **/ + if (xs_startswith(p_path, "people/")) { /** a single actor **/ if (!login(&snac, req)) { *body = xs_dup(uid); status = HTTP_STATUS_UNAUTHORIZED; @@ -4587,11 +4651,18 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *actor_dict = NULL; const char *actor_id = NULL; xs *actor = NULL; + xs_list *page_lst = xs_split_n(p_path, "?", 2); + xs *page = xs_str_cat(xs_str_new("/"), xs_list_get(page_lst, 0)); + xs_list *l = xs_split_n(page, "/", 3); + const char *actor_md5 = xs_list_get(l, 2); - if (valid_status(object_get_by_md5(p_path + strlen("people/"), &actor_dict)) && + if (valid_status(object_get_by_md5(actor_md5, &actor_dict)) && (actor_id = xs_dict_get(actor_dict, "id")) != NULL && valid_status(actor_get(actor_id, &actor))) { - *body = html_people_one(&snac, actor_id); + int more = 0; + xs *list = timeline_list(&snac, "private", skip, show, &more); + + *body = html_people_one(&snac, actor_id, list, skip, show, more, page); *b_size = strlen(*body); status = HTTP_STATUS_OK; } -- cgit v1.2.3 From f99895032e33d5c9a80c45bae50fa433f4ea1c48 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 30 Dec 2025 13:14:50 +0100 Subject: Fixed indentation in previous patch (my fault). --- html.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index 70c599f..223cf4c 100644 --- a/html.c +++ b/html.c @@ -3914,7 +3914,8 @@ xs_str *html_people_one(snac *user, const char *actor, const xs_list *list, m = xs_fmt("%s&%s", url, ss); else m = xs_fmt("%s?%s", url, ss); - m10 = xs_fmt("%s0", m); + + m10 = xs_fmt("%s0", m); xs_html *more_links = xs_html_tag("p", xs_html_tag("a", -- cgit v1.2.3 From 4b22bb8929c1c7d2e9cf531bb4b0f40c19ccc423 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 30 Dec 2025 13:17:11 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0cb2c86..7e5b722 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,7 +2,7 @@ ## UNRELEASED -Link contacts to single-user people pages (contributed by lxo). +Link contacts to single-user people pages. Also, user's posts are shown (contributed by lxo). Added emoji reactions (contributed by violette). -- cgit v1.2.3 From 20eba6f5192176ad0fc3c468cd4bd8dda62f15e6 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 1 Jan 2026 16:25:00 +0100 Subject: Add boosts, likes and reacts to actor's people page Show in an actor's page anything that the user could have seen from actor in timeline or notifications, namely: - posts by actor (use get_atto to identify the actor) - boosts by actor - user's posts with likes or emojireacts by actor That said, in this view, only the latest boost is shown for a post, so it might not seem like the boost is by actor. Likes and emojireacts aren't even shown, so the reason why a post appears might be puzzling. Use timeline_simple_list, since we don't show entire conversations, and we want to identify all posts with actor's interactions. Saturate show at max_timeline_entries, so that we don't silently skip entries. --- html.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/html.c b/html.c index 223cf4c..3e1d7ba 100644 --- a/html.c +++ b/html.c @@ -3889,8 +3889,22 @@ xs_str *html_people_one(snac *user, const char *actor, const xs_list *list, if (!valid_status(status)) continue; - const char *by = xs_dict_get(msg, "attributedTo"); - if (!by || strcmp(actor, by) != 0) + const char *id = xs_dict_get(msg, "id"); + const char *by = get_atto(msg); + xs *actor_md5 = NULL; + xs_list *boosts = NULL; + xs_list *likes = NULL; + xs_list *reacts = NULL; + /* Besides actor's posts, also show actor's boosts, and also + posts by user with likes or reacts by actor. I.e., any + actor's actions that user could have seen in the timeline + or in notifications. */ + if (!(by && strcmp(actor, by) == 0) && + xs_list_in((boosts = object_announces(id)), + (actor_md5 = xs_md5_hex(actor, strlen(actor)))) == -1 && + (!(by && strcmp(user->actor, by) == 0) || + (xs_list_in((likes = object_likes(id)), actor_md5) == -1 && + xs_list_in((reacts = object_get_emoji_reacts(id)), actor_md5) == -1))) continue; xs_html *entry = html_entry(user, msg, 0, 0, v, 1); @@ -4359,8 +4373,12 @@ int html_get_handler(const xs_dict *req, const char *q_path, cache = 0; int skip = 0; + const char *max_show_default = "50"; + int max_show = xs_number_get(xs_dict_get_def(srv_config, "max_timeline_entries", + max_show_default)); int def_show = xs_number_get(xs_dict_get_def(srv_config, "def_timeline_entries", - xs_dict_get_def(srv_config, "max_timeline_entries", "50"))); + xs_dict_get_def(srv_config, "max_timeline_entries", + max_show_default))); int show = def_show; if ((v = xs_dict_get(q_vars, "skip")) != NULL) @@ -4386,6 +4404,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, /* a show of 0 has no sense */ if (show == 0) show = def_show; + if (show > max_show) + show = max_show; if (p_path == NULL) { /** public timeline **/ xs *h = xs_str_localtime(0, "%Y-%m.html"); @@ -4661,7 +4681,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, (actor_id = xs_dict_get(actor_dict, "id")) != NULL && valid_status(actor_get(actor_id, &actor))) { int more = 0; - xs *list = timeline_list(&snac, "private", skip, show, &more); + xs *list = timeline_simple_list(&snac, "private", skip, show, &more); *body = html_people_one(&snac, actor_id, list, skip, show, more, page); *b_size = strlen(*body); -- cgit v1.2.3 From 89053095eb70eff4527dfc3052d517eeb07fc816 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 1 Jan 2026 16:27:21 +0100 Subject: truncate rss title at utf8 char boundary Advance a whole utf8 char at a time while looking for where to truncate the title. --- RELEASE_NOTES.md | 2 ++ rss.c | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7e5b722..174b873 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -2,6 +2,8 @@ ## UNRELEASED +Truncate RSS titles at UTF-8 character boundaries (contributed by lxo). + Link contacts to single-user people pages. Also, user's posts are shown (contributed by lxo). Added emoji reactions (contributed by violette). diff --git a/rss.c b/rss.c index 6124e7a..09446dc 100644 --- a/rss.c +++ b/rss.c @@ -10,6 +10,7 @@ #include "xs_openssl.h" #include "xs_json.h" #include "xs_http.h" +#include "xs_unicode.h" #include "snac.h" @@ -74,7 +75,14 @@ xs_str *rss_from_timeline(snac *user, const xs_list *timeline, title = xs_regex_replace_i(title, "&[^;]+;", " "); int i; - for (i = 0; title[i] && title[i] != '\n' && i < 50; i++); + for (i = 0; title[i] && title[i] != '\n' && i < 50; ) { + const char *p = &title[i]; + unsigned int cp = xs_utf8_dec(&p); + int n = p - title; + if (cp == 0xfffd || n > 50) + break; + i = n; + } if (title[i] != '\0') { title[i] = '\0'; -- cgit v1.2.3 From 11af00194e3e0ec15e17a23556dc2929f92e0210 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 1 Jan 2026 17:01:03 +0100 Subject: Bumped copyright year. --- LICENSE | 2 +- activitypub.c | 2 +- data.c | 2 +- format.c | 2 +- html.c | 2 +- http.c | 2 +- httpd.c | 2 +- main.c | 4 ++-- mastoapi.c | 2 +- rss.c | 2 +- snac.c | 2 +- snac.h | 2 +- upgrade.c | 2 +- utils.c | 2 +- webfinger.c | 2 +- xs.h | 2 +- xs_curl.h | 2 +- xs_fcgi.h | 2 +- xs_glob.h | 2 +- xs_hex.h | 2 +- xs_html.h | 2 +- xs_http.h | 2 +- xs_httpd.h | 2 +- xs_io.h | 2 +- xs_json.h | 4 +++- xs_match.h | 2 +- xs_mime.h | 2 +- xs_openssl.h | 2 +- xs_po.h | 2 +- xs_random.h | 2 +- xs_regex.h | 2 +- xs_set.h | 2 +- xs_socket.h | 2 +- xs_time.h | 2 +- xs_unicode.h | 2 +- xs_unix_socket.h | 2 +- xs_url.h | 2 +- xs_version.h | 2 +- xs_webmention.h | 2 +- 39 files changed, 42 insertions(+), 40 deletions(-) diff --git a/LICENSE b/LICENSE index 702b487..3fa58d1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 - 2025 grunfink et al. (Fediverse: @grunfink@comam.es) +Copyright (c) 2022 - 2026 grunfink et al. (Fediverse: @grunfink@comam.es) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/activitypub.c b/activitypub.c index 59df31a..617fd30 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_json.h" diff --git a/data.c b/data.c index 023bae6..22ea7b0 100644 --- a/data.c +++ b/data.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_hex.h" diff --git a/format.c b/format.c index 4f93b7b..803e5a5 100644 --- a/format.c +++ b/format.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_regex.h" diff --git a/html.c b/html.c index 3e1d7ba..ef8816d 100644 --- a/html.c +++ b/html.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" diff --git a/http.c b/http.c index f0b1314..4f0b2fa 100644 --- a/http.c +++ b/http.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" diff --git a/httpd.c b/httpd.c index f93f197..f46cfca 100644 --- a/httpd.c +++ b/httpd.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" diff --git a/main.c b/main.c index 4b0463e..29a8a51 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" @@ -18,7 +18,7 @@ int usage(const char *cmd) { printf("snac " VERSION " - A simple, minimalistic ActivityPub instance\n"); - printf("Copyright (c) 2022 - 2025 grunfink et al. / MIT license\n"); + printf("Copyright (c) 2022 - 2026 grunfink et al. / MIT license\n"); printf("\n"); if (cmd == NULL) { diff --git a/mastoapi.c b/mastoapi.c index 6a12ced..0cadf2c 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef NO_MASTODON_API diff --git a/rss.c b/rss.c index 09446dc..dc26071 100644 --- a/rss.c +++ b/rss.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2025 grunfink et al. / MIT license */ +/* copyright (c) 2025 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_html.h" diff --git a/snac.c b/snac.c index 31f524f..965edbb 100644 --- a/snac.c +++ b/snac.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #define XS_IMPLEMENTATION diff --git a/snac.h b/snac.h index bcff7f8..430b551 100644 --- a/snac.h +++ b/snac.h @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #define VERSION "2.86-dev" diff --git a/upgrade.c b/upgrade.c index 9e0ae6e..07e9c51 100644 --- a/upgrade.c +++ b/upgrade.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" diff --git a/utils.c b/utils.c index 44e4006..4bdbaaf 100644 --- a/utils.c +++ b/utils.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_io.h" diff --git a/webfinger.c b/webfinger.c index 1ce5e76..264cb85 100644 --- a/webfinger.c +++ b/webfinger.c @@ -1,5 +1,5 @@ /* snac - A simple, minimalistic ActivityPub instance */ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #include "xs.h" #include "xs_json.h" diff --git a/xs.h b/xs.h index 5f2e6aa..11f0722 100644 --- a/xs.h +++ b/xs.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_H diff --git a/xs_curl.h b/xs_curl.h index feb23e0..4b510ac 100644 --- a/xs_curl.h +++ b/xs_curl.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_CURL_H diff --git a/xs_fcgi.h b/xs_fcgi.h index b3cb892..0af6fcc 100644 --- a/xs_fcgi.h +++ b/xs_fcgi.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ /* This is an intentionally-dead-simple FastCGI implementation; diff --git a/xs_glob.h b/xs_glob.h index 6d87ca1..c38ec9a 100644 --- a/xs_glob.h +++ b/xs_glob.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_GLOB_H diff --git a/xs_hex.h b/xs_hex.h index 2507d5d..91c528e 100644 --- a/xs_hex.h +++ b/xs_hex.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_HEX_H diff --git a/xs_html.h b/xs_html.h index 29886c6..ab77499 100644 --- a/xs_html.h +++ b/xs_html.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_HTML_H diff --git a/xs_http.h b/xs_http.h index f2fd296..b9b5f80 100644 --- a/xs_http.h +++ b/xs_http.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_HTTP_H diff --git a/xs_httpd.h b/xs_httpd.h index 9be51e6..4a4689c 100644 --- a/xs_httpd.h +++ b/xs_httpd.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_HTTPD_H diff --git a/xs_io.h b/xs_io.h index 9c5018e..9a03e5b 100644 --- a/xs_io.h +++ b/xs_io.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_IO_H diff --git a/xs_json.h b/xs_json.h index 07800fa..a9577ee 100644 --- a/xs_json.h +++ b/xs_json.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_JSON_H @@ -28,6 +28,8 @@ int xs_json_load_object(FILE *f, int maxdepth, xs_dict **d); /** IMPLEMENTATION **/ +#include "xs_unicode.h" + /** JSON dumps **/ static void _xs_json_dump_str(const char *data, FILE *f) diff --git a/xs_match.h b/xs_match.h index 76c1bf3..21830e8 100644 --- a/xs_match.h +++ b/xs_match.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_MATCH_H diff --git a/xs_mime.h b/xs_mime.h index 0146385..6709ec6 100644 --- a/xs_mime.h +++ b/xs_mime.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_MIME_H diff --git a/xs_openssl.h b/xs_openssl.h index f215bcc..64b59dd 100644 --- a/xs_openssl.h +++ b/xs_openssl.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_OPENSSL_H diff --git a/xs_po.h b/xs_po.h index c6feec9..c1ad2c9 100644 --- a/xs_po.h +++ b/xs_po.h @@ -1,4 +1,4 @@ -/* copyright (c) 2025 grunfink et al. / MIT license */ +/* copyright (c) 2025 - 2026 grunfink et al. / MIT license */ #ifndef _XS_PO_H diff --git a/xs_random.h b/xs_random.h index f936099..357f9cb 100644 --- a/xs_random.h +++ b/xs_random.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_RANDOM_H diff --git a/xs_regex.h b/xs_regex.h index 1e157d2..5ccefda 100644 --- a/xs_regex.h +++ b/xs_regex.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_REGEX_H diff --git a/xs_set.h b/xs_set.h index 8946e42..ae67cc7 100644 --- a/xs_set.h +++ b/xs_set.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_SET_H diff --git a/xs_socket.h b/xs_socket.h index 7bf5298..70bfe98 100644 --- a/xs_socket.h +++ b/xs_socket.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_SOCKET_H diff --git a/xs_time.h b/xs_time.h index 507d238..46b35a1 100644 --- a/xs_time.h +++ b/xs_time.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_TIME_H diff --git a/xs_unicode.h b/xs_unicode.h index 0b4de1c..7686dcd 100644 --- a/xs_unicode.h +++ b/xs_unicode.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_UNICODE_H diff --git a/xs_unix_socket.h b/xs_unix_socket.h index 462a5b3..1ef7d39 100644 --- a/xs_unix_socket.h +++ b/xs_unix_socket.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_UNIX_SOCKET_H diff --git a/xs_url.h b/xs_url.h index 222771f..56d6d9d 100644 --- a/xs_url.h +++ b/xs_url.h @@ -1,4 +1,4 @@ -/* copyright (c) 2022 - 2025 grunfink et al. / MIT license */ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ #ifndef _XS_URL_H diff --git a/xs_version.h b/xs_version.h index 34a7a45..598c72e 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* 0a8b987d7bb945fe7844411727d03ac73f417455 2025-10-14T05:21:05+02:00 */ +/* ad74258be9b1585840a5366cdb4b6ef707c0e95a 2026-01-01T16:58:39+01:00 */ diff --git a/xs_webmention.h b/xs_webmention.h index f9578b4..035b3a6 100644 --- a/xs_webmention.h +++ b/xs_webmention.h @@ -1,4 +1,4 @@ -/* copyright (c) 2025 grunfink et al. / MIT license */ +/* copyright (c) 2025 - 2026 grunfink et al. / MIT license */ #ifndef _XS_WEBMENTION_H -- cgit v1.2.3 From a77e4c813256c3196cd858325487b4a8ab2c6f53 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 5 Jan 2026 09:31:10 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 174b873..4680262 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.86 Truncate RSS titles at UTF-8 character boundaries (contributed by lxo). -- cgit v1.2.3 From b84b92df74ed0e8f92617e37fdcb2f0aba2138cf Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 5 Jan 2026 09:31:33 +0100 Subject: Version 2.86 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 430b551..8a7dad6 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ -#define VERSION "2.86-dev" +#define VERSION "2.86" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From 688c54c87355b5424f33f7b089814460a74af594 Mon Sep 17 00:00:00 2001 From: Stefano Marinelli Date: Tue, 6 Jan 2026 11:02:36 +0100 Subject: Implement configurable EXIF stripping for uploaded media - Add `strip_exif` configuration option to enable metadata removal. - Add `mogrify_path` configuration to specify external tool location. - Implement strip_media using `mogrify -strip`. - Support multiple image formats: jpg, png, webp, heic, heif, avif, tiff, gif, bmp. - Add strict startup check: fail to start if `strip_exif` is enabled but `mogrify` is missing/broken. - Update documentation in `doc/snac.8`. --- data.c | 13 +++++++++++-- doc/snac.8 | 8 ++++++++ snac.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ snac.h | 3 +++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/data.c b/data.c index 22ea7b0..f32dc81 100644 --- a/data.c +++ b/data.c @@ -89,8 +89,15 @@ int srv_open(const char *basedir, int auto_upgrade) else { if (xs_number_get(xs_dict_get(srv_config, "layout")) < disk_layout) error = xs_fmt("ERROR: disk layout changed - execute 'snac upgrade' first"); - else - ret = 1; + else { + if (!check_strip_tool()) { + const char *mp = xs_dict_get(srv_config, "mogrify_path"); + if (mp == NULL) mp = "mogrify"; + error = xs_fmt("ERROR: strip_exif enabled but '%s' not found or not working (set 'mogrify_path' in server.json)", mp); + } + else + ret = 1; + } } } @@ -2710,6 +2717,8 @@ void static_put(snac *snac, const char *id, const char *data, int size) if (fn && (f = fopen(fn, "wb")) != NULL) { fwrite(data, size, 1, f); fclose(f); + + strip_media(fn); } } diff --git a/doc/snac.8 b/doc/snac.8 index b8a75fa..8283ac6 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -296,6 +296,14 @@ outgoing messages (default: 15). Anyway, whenever any incoming activity from a failed instance is detected, this counter is reset for it. .It Ic vkey Public vapid key. Used for notification on some client. +.It Ic strip_exif +If set to true, EXIF metadata will be stripped from uploaded images (jpg, png, webp, heic, avif, tiff, gif, bmp). This requires the +.Nm mogrify +tool to be installed. If +.Nm snac +cannot find or execute the tool at startup, it will refuse to run. +.It Ic mogrify_path +Overrides the default "mogrify" command name or path. Use this if the tool is not in the system PATH or has a different name. .El .Pp You must restart the server to make effective these changes. diff --git a/snac.c b/snac.c index 965edbb..f4528cd 100644 --- a/snac.c +++ b/snac.c @@ -32,6 +32,7 @@ #include #include +#include xs_str *srv_basedir = NULL; xs_dict *srv_config = NULL; @@ -170,3 +171,66 @@ int check_password(const char *uid, const char *passwd, const char *hash) return ret; } + + +int strip_media(const char *fn) +/* strips EXIF data from a file */ +{ + int ret = 0; + const xs_val *v = xs_dict_get(srv_config, "strip_exif"); + + if (xs_type(v) == XSTYPE_TRUE) { + xs *l_fn = xs_tolower_i(xs_dup(fn)); + + /* check extensions */ + if (xs_endswith(l_fn, ".jpg") || xs_endswith(l_fn, ".jpeg") || + xs_endswith(l_fn, ".png") || xs_endswith(l_fn, ".webp") || + xs_endswith(l_fn, ".heic") || xs_endswith(l_fn, ".heif") || + xs_endswith(l_fn, ".avif") || xs_endswith(l_fn, ".tiff") || + xs_endswith(l_fn, ".gif") || xs_endswith(l_fn, ".bmp")) { + + const char *mp = xs_dict_get(srv_config, "mogrify_path"); + if (mp == NULL) + mp = "mogrify"; + + xs *cmd = xs_fmt("%s -strip \"%s\" 2>/dev/null", mp, fn); + + ret = system(cmd); + + if (ret != 0) { + int code = 0; + if (WIFEXITED(ret)) + code = WEXITSTATUS(ret); + + if (code == 127) + srv_log(xs_fmt("strip_media: error stripping %s. '%s' not found (exit 127). Set 'mogrify_path' in server.json.", fn, mp)); + else + srv_log(xs_fmt("strip_media: error stripping %s %d", fn, ret)); + } + else + srv_debug(1, xs_fmt("strip_media: stripped %s", fn)); + } + } + + return ret; +} + + +int check_strip_tool(void) +{ + const xs_val *v = xs_dict_get(srv_config, "strip_exif"); + int ret = 1; + + if (xs_type(v) == XSTYPE_TRUE) { + const char *mp = xs_dict_get(srv_config, "mogrify_path"); + if (mp == NULL) + mp = "mogrify"; + + xs *cmd = xs_fmt("%s -version 2>/dev/null >/dev/null", mp); + + if (system(cmd) != 0) + ret = 0; + } + + return ret; +} diff --git a/snac.h b/snac.h index 8a7dad6..c307dbd 100644 --- a/snac.h +++ b/snac.h @@ -105,6 +105,9 @@ int validate_uid(const char *uid); xs_str *hash_password(const char *uid, const char *passwd, const char *nonce); int check_password(const char *uid, const char *passwd, const char *hash); +int strip_media(const char *fn); +int check_strip_tool(void); + void srv_archive(const char *direction, const char *url, xs_dict *req, const char *payload, int p_size, int status, xs_dict *headers, -- cgit v1.2.3 From 03d270a56b751bc53b83381d9fef21da8d4cbb91 Mon Sep 17 00:00:00 2001 From: Stefano Marinelli Date: Tue, 6 Jan 2026 12:18:00 +0100 Subject: Implement metadata stripping for uploaded videos - Extend `strip_media` to support video files using `ffmpeg`. - Use `ffmpeg -map_metadata -1 -c copy` to strip global metadata. - Support formats: mp4, m4v, mov, webm, mkv, avi. - Add `ffmpeg_path` configuration option. - Implement robust relative path handling (`user/` heuristic) to support jailed environments. - Enforce strict checks on startup: fail if tools (mogrify/ffmpeg) are missing when enabled. --- doc/snac.8 | 10 ++++-- snac.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 106 insertions(+), 16 deletions(-) diff --git a/doc/snac.8 b/doc/snac.8 index 8283ac6..c53bb59 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -297,13 +297,17 @@ failed instance is detected, this counter is reset for it. .It Ic vkey Public vapid key. Used for notification on some client. .It Ic strip_exif -If set to true, EXIF metadata will be stripped from uploaded images (jpg, png, webp, heic, avif, tiff, gif, bmp). This requires the +If set to true, EXIF and other metadata will be stripped from uploaded images (jpg, png, webp, heic, avif, tiff, gif, bmp) and videos (mp4, m4v, mov, webm, mkv, avi). This requires the .Nm mogrify -tool to be installed. If +(from ImageMagick) and +.Nm ffmpeg +tools to be installed. If .Nm snac -cannot find or execute the tool at startup, it will refuse to run. +cannot find or execute these tools at startup, it will refuse to run. .It Ic mogrify_path Overrides the default "mogrify" command name or path. Use this if the tool is not in the system PATH or has a different name. +.It Ic ffmpeg_path +Overrides the default "ffmpeg" command name or path. Use this if the tool is not in the system PATH or has a different name. .El .Pp You must restart the server to make effective these changes. diff --git a/snac.c b/snac.c index f4528cd..a3ba6b7 100644 --- a/snac.c +++ b/snac.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include xs_str *srv_basedir = NULL; xs_dict *srv_config = NULL; @@ -177,12 +179,25 @@ int strip_media(const char *fn) /* strips EXIF data from a file */ { int ret = 0; + const xs_val *v = xs_dict_get(srv_config, "strip_exif"); if (xs_type(v) == XSTYPE_TRUE) { - xs *l_fn = xs_tolower_i(xs_dup(fn)); + /* Heuristic: find 'user/' in the path to make it relative */ + /* This works for ~/user/..., /var/snac/user/..., etc. */ + const char *r_fn = strstr(fn, "user/"); + + if (r_fn == NULL) { + /* Fallback: try to strip ~/ if present */ + if (strncmp(fn, "~/", 2) == 0) + r_fn = fn + 2; + else + r_fn = fn; + } - /* check extensions */ + xs *l_fn = xs_tolower_i(xs_dup(r_fn)); + + /* check image extensions */ if (xs_endswith(l_fn, ".jpg") || xs_endswith(l_fn, ".jpeg") || xs_endswith(l_fn, ".png") || xs_endswith(l_fn, ".webp") || xs_endswith(l_fn, ".heic") || xs_endswith(l_fn, ".heif") || @@ -193,7 +208,7 @@ int strip_media(const char *fn) if (mp == NULL) mp = "mogrify"; - xs *cmd = xs_fmt("%s -strip \"%s\" 2>/dev/null", mp, fn); + xs *cmd = xs_fmt("cd \"%s\" && %s -auto-orient -strip \"%s\" 2>/dev/null", srv_basedir, mp, r_fn); ret = system(cmd); @@ -203,12 +218,64 @@ int strip_media(const char *fn) code = WEXITSTATUS(ret); if (code == 127) - srv_log(xs_fmt("strip_media: error stripping %s. '%s' not found (exit 127). Set 'mogrify_path' in server.json.", fn, mp)); + srv_log(xs_fmt("strip_media: error stripping %s. '%s' not found (exit 127). Set 'mogrify_path' in server.json.", r_fn, mp)); else - srv_log(xs_fmt("strip_media: error stripping %s %d", fn, ret)); + srv_log(xs_fmt("strip_media: error stripping %s %d", r_fn, ret)); } else - srv_debug(1, xs_fmt("strip_media: stripped %s", fn)); + srv_debug(1, xs_fmt("strip_media: stripped %s", r_fn)); + } + else + /* check video extensions */ + if (xs_endswith(l_fn, ".mp4") || xs_endswith(l_fn, ".m4v") || + xs_endswith(l_fn, ".mov") || xs_endswith(l_fn, ".webm") || + xs_endswith(l_fn, ".mkv") || xs_endswith(l_fn, ".avi")) { + + const char *fp = xs_dict_get(srv_config, "ffmpeg_path"); + if (fp == NULL) + fp = "ffmpeg"; + + /* ffmpeg cannot modify in-place, so we need a temp file */ + /* we must preserve valid extension for ffmpeg to guess the format */ + const char *ext = strrchr(r_fn, '.'); + if (ext == NULL) ext = ""; + xs *tmp_fn = xs_fmt("%s.tmp%s", r_fn, ext); + + /* -map_metadata -1 strips all global metadata */ + /* -c copy copies input streams without re-encoding */ + /* we don't silence stderr so we can debug issues */ + /* we explicitly cd to srv_basedir to ensure relative paths work */ + xs *cmd = xs_fmt("cd \"%s\" && %s -y -i \"%s\" -map_metadata -1 -c copy \"%s\"", srv_basedir, fp, r_fn, tmp_fn); + + ret = system(cmd); + + if (ret != 0) { + int code = 0; + if (WIFEXITED(ret)) + code = WEXITSTATUS(ret); + + if (code == 127) + srv_log(xs_fmt("strip_media: error stripping %s. '%s' not found (exit 127). Set 'ffmpeg_path' in server.json.", r_fn, fp)); + else { + srv_log(xs_fmt("strip_media: error stripping %s %d", r_fn, ret)); + srv_log(xs_fmt("strip_media: command was: %s", cmd)); + } + + /* try to cleanup, just in case */ + /* unlink needs full path too if we are not in basedir */ + xs *full_tmp_fn = xs_fmt("%s/%s", srv_basedir, tmp_fn); + unlink(full_tmp_fn); + } + else { + /* rename tmp file to original */ + /* use full path for source because it was created relative to basedir */ + xs *full_tmp_fn = xs_fmt("%s/%s", srv_basedir, tmp_fn); + + if (rename(full_tmp_fn, fn) == 0) + srv_debug(1, xs_fmt("strip_media: stripped %s", fn)); + else + srv_log(xs_fmt("strip_media: error renaming %s to %s", full_tmp_fn, fn)); + } } } @@ -222,14 +289,33 @@ int check_strip_tool(void) int ret = 1; if (xs_type(v) == XSTYPE_TRUE) { - const char *mp = xs_dict_get(srv_config, "mogrify_path"); - if (mp == NULL) - mp = "mogrify"; + /* check mogrify */ + { + const char *mp = xs_dict_get(srv_config, "mogrify_path"); + if (mp == NULL) + mp = "mogrify"; - xs *cmd = xs_fmt("%s -version 2>/dev/null >/dev/null", mp); - - if (system(cmd) != 0) - ret = 0; + xs *cmd = xs_fmt("%s -version 2>/dev/null >/dev/null", mp); + + if (system(cmd) != 0) { + srv_log(xs_fmt("check_strip_tool: '%s' not working", mp)); + ret = 0; + } + } + + /* check ffmpeg */ + if (ret) { + const char *fp = xs_dict_get(srv_config, "ffmpeg_path"); + if (fp == NULL) + fp = "ffmpeg"; + + xs *cmd = xs_fmt("%s -version 2>/dev/null >/dev/null", fp); + + if (system(cmd) != 0) { + srv_log(xs_fmt("check_strip_tool: '%s' not working", fp)); + ret = 0; + } + } } return ret; -- cgit v1.2.3 From 6c876107aba84d2c066b62929ab094bf6d92ef71 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 6 Jan 2026 14:26:57 +0100 Subject: Hide EmojiReacts from muted actors and blocked instances. --- html.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/html.c b/html.c index ef8816d..d5a59d8 100644 --- a/html.c +++ b/html.c @@ -2460,6 +2460,10 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *content = xs_dict_get(m, "content"); const char *actor = xs_dict_get(m, "actor"); const xs_list *contentl = xs_dict_get(sfrl, content); + + if (is_muted(user, actor) || is_instance_blocked(actor)) + continue; + xs *actors = xs_list_new(); actors = xs_list_append(actors, actor); char me = actor && user && strcmp(actor, user->actor) == 0; -- cgit v1.2.3 From b6414bd2c48dd54699f3bfbdae10bb0209841f0c Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 6 Jan 2026 15:00:45 +0100 Subject: mastoapi: hide EmojiReacts from muted actors and block instances. --- mastoapi.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mastoapi.c b/mastoapi.c index 0cadf2c..52aca08 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1171,6 +1171,10 @@ xs_dict *mastoapi_status(snac *snac, const xs_dict *msg) const char *content = xs_dict_get(msg, "content"); const char *actor = xs_dict_get(msg, "actor"); const xs_list *contentl = xs_dict_get(sfrl, content); + + if ((snac && is_muted(snac, actor)) || is_instance_blocked(actor)) + continue; + /* NOTE: idk when there are no actor, but i encountered that bug. * Probably because of one of my previous attempts. * Keeping this just in case, can remove later */ -- cgit v1.2.3 From 347b2d8e03c69f1a00c621318cf60d36952131a1 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 6 Jan 2026 15:04:07 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4680262..2719f69 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## 2.87 + +Hide EmojiReacts from muted actors and blocked instances. + ## 2.86 Truncate RSS titles at UTF-8 character boundaries (contributed by lxo). -- cgit v1.2.3 From c2b050cf5389e25bb3d149452ee432116b9cc1cd Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 6 Jan 2026 15:04:34 +0100 Subject: Version 2.87 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 8a7dad6..2364f72 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ -#define VERSION "2.86" +#define VERSION "2.87" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From a01e4b148fd32a015167478171443047507c168d Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 6 Jan 2026 18:53:38 +0100 Subject: Fixed crash. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index d5a59d8..4299396 100644 --- a/html.c +++ b/html.c @@ -2461,7 +2461,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *actor = xs_dict_get(m, "actor"); const xs_list *contentl = xs_dict_get(sfrl, content); - if (is_muted(user, actor) || is_instance_blocked(actor)) + if ((user && is_muted(user, actor)) || is_instance_blocked(actor)) continue; xs *actors = xs_list_new(); -- cgit v1.2.3 From 6a2b4bbcecaadab41fd89d5219f328f3e5916ceb Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 08:40:18 +0100 Subject: If disable_emojireact is set to true in server.json, EmojiReacts are dropped on input. --- activitypub.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/activitypub.c b/activitypub.c index 617fd30..5e55b8a 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2578,6 +2578,11 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) return -1; } + if (strcmp(type, "EmojiReact") == 0 && xs_is_true(xs_dict_get(srv_config, "disable_emojireact"))) { + srv_log(xs_fmt("Dropping EmojiReact from %s due to admin configuration", actor)); + return -1; + } + const char *object, *utype; object = xs_dict_get(msg, "object"); -- cgit v1.2.3 From c6642e958b628426f2c7b0d71b427a7960cf063c Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 08:43:50 +0100 Subject: Don't show any EmojiReactions if they are disabled. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index 4299396..c41d7f4 100644 --- a/html.c +++ b/html.c @@ -2447,7 +2447,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, /* add all emoji reacts */ int is_emoji = 0; - { + if (!xs_is_true(xs_dict_get(srv_config, "disable_emojireact"))) { int c = 0; const xs_dict *k; xs *ls = xs_list_new(); -- cgit v1.2.3 From 5ef0483ab34892d7ea773a690a7c17e3d102cf46 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 08:47:57 +0100 Subject: Don't show the EmojiReact dropdown if disabled. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index c41d7f4..f26ac4d 100644 --- a/html.c +++ b/html.c @@ -2103,7 +2103,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, xs_html_tag("p", NULL)); } - { /** emoji react **/ + if (!xs_is_true(xs_dict_get(srv_config, "disable_emojireact"))) { /** emoji react **/ /* the post textarea */ xs *div_id = xs_fmt("%s_reply", md5); xs *form_id = xs_fmt("%s_reply_form", md5); -- cgit v1.2.3 From f69228fc46575e184e576d090066c4fac50e4c15 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 08:49:22 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 2719f69..0dc7fc1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## UNRELEASED + +If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From cef1d7a176b7603491dfec3f394c1b34bf765f2c Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 08:51:04 +0100 Subject: Updated documentation. --- doc/snac.8 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/snac.8 b/doc/snac.8 index b8a75fa..6f98648 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -296,6 +296,8 @@ outgoing messages (default: 15). Anyway, whenever any incoming activity from a failed instance is detected, this counter is reset for it. .It Ic vkey Public vapid key. Used for notification on some client. +.It Ic disable_emojireact +If set to true, all EmojiReact support (for input and output) is disabled. .El .Pp You must restart the server to make effective these changes. -- cgit v1.2.3 From a8cbbeeb3fdc8ec660270b9112b50d2dee71e55d Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 8 Jan 2026 09:05:53 +0100 Subject: Also disable EmojiReact notifications, if so configured. --- html.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/html.c b/html.c index f26ac4d..d5294cb 100644 --- a/html.c +++ b/html.c @@ -4030,6 +4030,9 @@ xs_str *html_notifications(snac *user, int skip, int show) if (xs_is_string(id2) && xs_set_add(&rep, id2) != 1) continue; + if (strcmp(type, "EmojiReact") == 0 && xs_is_true(xs_dict_get(srv_config, "disable_emojireact"))) + continue; + object_get(id, &obj); const char *msg_id = NULL; -- cgit v1.2.3 From fdd2217be47799d93fe7505faffd7c948d69ecdb Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 10 Jan 2026 20:40:13 +0100 Subject: New file xs_list_tools.h. --- snac.c | 1 + xs_list_tools.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ xs_version.h | 2 +- 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 xs_list_tools.h diff --git a/snac.c b/snac.c index 965edbb..41db86d 100644 --- a/snac.c +++ b/snac.c @@ -27,6 +27,7 @@ #include "xs_html.h" #include "xs_po.h" #include "xs_webmention.h" +#include "xs_list_tools.h" #include "snac.h" diff --git a/xs_list_tools.h b/xs_list_tools.h new file mode 100644 index 0000000..33d4b87 --- /dev/null +++ b/xs_list_tools.h @@ -0,0 +1,169 @@ +/* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ + +#ifndef _XS_LIST_TOOLS_H + +#define _XS_LIST_TOOLS_H + + xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv); + xs_list *xs_list_reverse(const xs_list *l); + xs_val **xs_list_to_array(const xs_list *l, int *len); + int xs_list_sort_cmp(const void *p1, const void *p2); + int xs_list_sort_inv_cmp(const void *p1, const void *p2); + int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2); + xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *)); + xs_list *xs_list_shuffle(const xs_list *l); + +#ifdef XS_IMPLEMENTATION + +#include "xs_random.h" + +xs_list *xs_list_insert_sorted(xs_list *list, const xs_val *nv) +/* inserts a string in the list in its ordered position */ +{ + XS_ASSERT_TYPE(list, XSTYPE_LIST); + + int offset = xs_size(list); + + const xs_val *v; + xs_list_foreach(list, v) { + /* if this element is greater or equal, insert here */ + if (xs_cmp(v, nv) >= 0) { + offset = v - list; + break; + } + } + + return _xs_list_write_litem(list, offset - 1, nv, xs_size(nv)); +} + + +xs_list *xs_list_reverse(const xs_list *l) +/* creates a new list as a reverse version of l */ +{ + xs_list *n = xs_dup(l); + const xs_val *v; + + /* move to one byte before the EOM */ + char *p = n + xs_size(n) - 1; + + xs_list_foreach(l, v) { + /* size of v, plus the LITEM */ + int z = xs_size(v) + 1; + + p -= z; + + /* copy v, including its LITEM */ + memcpy(p, v - 1, z); + } + + return n; +} + + +xs_val **xs_list_to_array(const xs_list *l, int *len) +/* converts a list to an array of values */ +/* must be freed after use */ +{ + *len = xs_list_len(l); + xs_val **a = xs_realloc(NULL, *len * sizeof(xs_val *)); + const xs_val *v; + int n = 0; + + xs_list_foreach(l, v) + a[n++] = (xs_val *)v; + + return a; +} + + +int xs_list_sort_cmp(const void *p1, const void *p2) +/* default list sorting function */ +{ + const xs_val *v1 = *(xs_val **)p1; + const xs_val *v2 = *(xs_val **)p2; + + return xs_cmp(v1, v2); +} + + +int xs_list_sort_inv_cmp(const void *p1, const void *p2) +/* default list inverse sorting function */ +{ + const xs_val *v1 = *(xs_val **)p1; + const xs_val *v2 = *(xs_val **)p2; + + return xs_cmp(v2, v1); +} + + +int xs_list_sort_dict_cmp(const char *field, const void *p1, const void *p2) +/* compare sorting function for a field an array of dicts */ +{ + const xs_dict *d1 = *(xs_val **)p1; + const xs_dict *d2 = *(xs_val **)p2; + + if (xs_type(d1) != XSTYPE_DICT || xs_type(d2) != XSTYPE_DICT) + return 0; + + return xs_cmp(xs_dict_get_def(d1, field, ""), + xs_dict_get_def(d2, field, "")); +} + + +xs_list *xs_list_sort(const xs_list *l, int (*cmp)(const void *, const void *)) +/* returns a sorted copy of l. cmp can be null for standard sorting */ +{ + int sz; + xs_val **a = xs_list_to_array(l, &sz); + xs_list *nl = xs_dup(l); + char *p = nl + 1 + _XS_TYPE_SIZE; + + /* sort the array */ + qsort(a, sz, sizeof(xs_val *), cmp ? cmp : xs_list_sort_cmp); + + /* transfer the sorted list over the copy */ + for (int n = 0; n < sz; n++) { + /* get the litem */ + const char *e = a[n] - 1; + int z = xs_size(e); + + memcpy(p, e, z); + p += z; + } + + xs_free(a); + + return nl; +} + + +xs_list *xs_list_shuffle(const xs_list *l) +/* returns a shuffled list */ +{ + int sz; + xs_val **a = xs_list_to_array(l, &sz); + xs_list *nl = xs_list_new(); + unsigned int seed = 0; + + xs_rnd_buf(&seed, sizeof(seed)); + + /* shuffle */ + for (int n = sz - 1; n > 0; n--) { + int m = xs_rnd_int32_d(&seed) % n; + void *p = a[n]; + a[n] = a[m]; + a[m] = p; + } + + for (int n = 0; n < sz; n++) + nl = xs_list_append(nl, a[n]); + + xs_free(a); + + return nl; +} + + +#endif /* XS_IMPLEMENTATION */ + +#endif /* XS_LIST_TOOLS_H */ diff --git a/xs_version.h b/xs_version.h index 598c72e..92a865e 100644 --- a/xs_version.h +++ b/xs_version.h @@ -1 +1 @@ -/* ad74258be9b1585840a5366cdb4b6ef707c0e95a 2026-01-01T16:58:39+01:00 */ +/* 270f9376eabd4f8e0ed3ae22a1f8eb6e06ea8b8b 2026-01-10T20:39:12+01:00 */ -- cgit v1.2.3 From 99375a7b664750c1288558f1d5c02b833a2e083c Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 10 Jan 2026 21:29:32 +0100 Subject: New command-line option top_ten. --- Makefile | 8 +++---- Makefile.NetBSD | 8 +++---- main.c | 21 ++++++++++++++++- snac.h | 2 ++ utils.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index ffeac1a..5614388 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ update-po: xgettext --omit-header -j -o $$a --language=C --keyword=L --from-code=utf-8 *.c ; \ done -activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \ +activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_url.h xs_mime.h \ xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \ xs_webmention.h xs_http.h xs_http_codes.h snac.h data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \ @@ -68,16 +68,16 @@ mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \ xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \ xs_unicode.h xs_http.h xs_http_codes.h snac.h rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h xs_match.h xs_curl.h \ - xs_openssl.h xs_json.h xs_http.h xs_http_codes.h snac.h + xs_openssl.h xs_json.h xs_http.h xs_http_codes.h xs_unicode.h snac.h sandbox.o: sandbox.c xs.h snac.h snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \ xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \ xs_http.h xs_http_codes.h xs_httpd.h xs_mime.h xs_regex.h xs_set.h \ xs_time.h xs_glob.h xs_random.h xs_match.h xs_fcgi.h xs_html.h xs_po.h \ - xs_webmention.h snac.h + xs_webmention.h xs_list_tools.h snac.h upgrade.o: upgrade.c xs.h xs_io.h xs_json.h xs_glob.h snac.h utils.o: utils.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h \ xs_random.h xs_glob.h xs_curl.h xs_regex.h xs_http.h xs_http_codes.h \ - snac.h + xs_list_tools.h xs_set.h snac.h webfinger.o: webfinger.c xs.h xs_json.h xs_curl.h xs_mime.h xs_http.h \ xs_http_codes.h snac.h diff --git a/Makefile.NetBSD b/Makefile.NetBSD index b5005ee..e752910 100644 --- a/Makefile.NetBSD +++ b/Makefile.NetBSD @@ -35,7 +35,7 @@ uninstall: rm $(PREFIX_MAN)/man5/snac.5 rm $(PREFIX_MAN)/man8/snac.8 -activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_mime.h \ +activitypub.o: activitypub.c xs.h xs_json.h xs_curl.h xs_url.h xs_mime.h \ xs_openssl.h xs_regex.h xs_time.h xs_set.h xs_match.h xs_unicode.h \ xs_webmention.h xs_http.h xs_http_codes.h snac.h data.o: data.c xs.h xs_hex.h xs_io.h xs_json.h xs_openssl.h xs_glob.h \ @@ -57,16 +57,16 @@ mastoapi.o: mastoapi.c xs.h xs_hex.h xs_openssl.h xs_json.h xs_io.h \ xs_time.h xs_glob.h xs_set.h xs_random.h xs_url.h xs_mime.h xs_match.h \ xs_unicode.h xs_http.h xs_http_codes.h snac.h rss.o: rss.c xs.h xs_html.h xs_regex.h xs_time.h xs_match.h xs_curl.h \ - xs_openssl.h xs_json.h xs_http.h xs_http_codes.h snac.h + xs_openssl.h xs_json.h xs_http.h xs_http_codes.h xs_unicode.h snac.h sandbox.o: sandbox.c xs.h snac.h snac.o: snac.c xs.h xs_hex.h xs_io.h xs_unicode_tbl.h xs_unicode.h \ xs_json.h xs_curl.h xs_openssl.h xs_socket.h xs_unix_socket.h xs_url.h \ xs_http.h xs_http_codes.h xs_httpd.h xs_mime.h xs_regex.h xs_set.h \ xs_time.h xs_glob.h xs_random.h xs_match.h xs_fcgi.h xs_html.h xs_po.h \ - xs_webmention.h snac.h + xs_webmention.h xs_list_tools.h snac.h upgrade.o: upgrade.c xs.h xs_io.h xs_json.h xs_glob.h snac.h utils.o: utils.c xs.h xs_io.h xs_json.h xs_time.h xs_openssl.h \ xs_random.h xs_glob.h xs_curl.h xs_regex.h xs_http.h xs_http_codes.h \ - snac.h + xs_list_tools.h xs_set.h snac.h webfinger.o: webfinger.c xs.h xs_json.h xs_curl.h xs_mime.h xs_http.h \ xs_http_codes.h snac.h diff --git a/main.c b/main.c index 29a8a51..4ba9796 100644 --- a/main.c +++ b/main.c @@ -76,7 +76,8 @@ int usage(const char *cmd) "list_create {basedir} {uid} {name} Creates a new list\n" "list_remove {basedir} {uid} {name} Removes an existing list\n" "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" - "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n"; + "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n" + "top_ten {basedir} {uid} [{N}] Prints the most popular posts\n"; if (cmd == NULL) printf("%s", cmds); @@ -350,6 +351,24 @@ int main(int argc, char *argv[]) return 0; } + if (strcmp(cmd, "top_ten") == 0) { /** **/ + int count = 10; + const char *n = GET_ARGV(); + if (xs_is_string(n)) + count = atoi(n); + + xs *l = user_top_ten(&snac, count); + const xs_list *i; + + xs_list_foreach(l, i) { + printf("%s %ld★ %ld↺\n", xs_list_get(i, 0), + xs_number_get_l(xs_list_get(i, 1)), + xs_number_get_l(xs_list_get(i, 2))); + } + + return 0; + } + if ((url = GET_ARGV()) == NULL) return usage(cmd); diff --git a/snac.h b/snac.h index 2364f72..e5efc0b 100644 --- a/snac.h +++ b/snac.h @@ -494,3 +494,5 @@ void rss_to_timeline(snac *user, const char *url); void rss_poll_hashtags(void); void data_fsck(void); + +xs_list *user_top_ten(snac *user, int count); diff --git a/utils.c b/utils.c index 4bdbaaf..fd077f6 100644 --- a/utils.c +++ b/utils.c @@ -11,6 +11,8 @@ #include "xs_curl.h" #include "xs_regex.h" #include "xs_http.h" +#include "xs_list_tools.h" +#include "xs_set.h" #include "snac.h" @@ -1002,6 +1004,76 @@ void import_csv(snac *user) snac_log(user, xs_fmt("Cannot open file %s", fn)); } + +static int top_ten_sort(const void *v1, const void *v2) +{ + const xs_list *l1 = *(const xs_list **)v1; + const xs_list *l2 = *(const xs_list **)v2; + + const char *c1 = xs_list_get(l1, 3); + const char *c2 = xs_list_get(l2, 3); + + return xs_cmp(c2, c1); +} + + +xs_list *user_top_ten(snac *user, int count) +/* returns the top ten more popular posts by a user */ +{ + xs *idx = xs_fmt("%s/private.idx", user->basedir); + xs *list = index_list(idx, XS_ALL); + xs *u_list = xs_list_new(); + xs_set u; + + xs_set_init(&u); + + const char *md5; + + xs_list_foreach(list, md5) { + xs *obj = NULL; + + if (!valid_status(object_get_by_md5(md5, &obj))) + continue; + + const char *id = xs_dict_get_def(obj, "id", "-"); + + if (!is_msg_mine(user, id)) + continue; + + if (xs_set_add(&u, id) != 1) + continue; + + /* get metrics */ + int ls = object_likes_len(id); + int as = object_announces_len(id); + + /* build the entry and convert to list */ + xs *s = xs_fmt("%s\t%d\t%d\t%010d", id, ls, as, ls + as); + xs *l = xs_split(s, "\t"); + + u_list = xs_list_append(u_list, l); + } + + /* sort by the sum of likes and boosts */ + xs *s_list = xs_list_sort(u_list, top_ten_sort); + + xs_list *r = xs_list_new(); + const xs_list *i; + + xs_list_foreach(s_list, i) { + r = xs_list_append(r, i); + + if (--count <= 0) + break; + } + + xs_set_free(&u); + + return r; +} + + + static const struct { const char *proto; unsigned short default_port; -- cgit v1.2.3 From 512481e6f8d92a1485b69bd00cec22fa7b8fc073 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 10 Jan 2026 21:32:14 +0100 Subject: Updated documentation. --- doc/snac.1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/snac.1 b/doc/snac.1 index cabd623..eb27fe5 100644 --- a/doc/snac.1 +++ b/doc/snac.1 @@ -405,6 +405,9 @@ Removes an existing list. Adds an account (by its @name@host handle or actor URL) to a list. .It Cm list_del Ar basedir Ar uid Ar name Ar actor_url Deletes an actor (by its actor URL) from a list. +.It Cm top_ten Ar basedir Ar uid Op N +Returns the ids of the top ten (or top N) most popular posts (considering the +sum of likes and boosts). .El .Ss Migrating an account to/from Mastodon See -- cgit v1.2.3 From 493a09a0e70aba454347b73fd725e90656ec6598 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 10 Jan 2026 21:34:38 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0dc7fc1..70591d9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,8 @@ If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. +New command-line option `top_ten`, that returns the top ten most popular posts by a user (ordered by the sum of likes and boosts) (contributed by aov). + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From 6ad2365a41dd84ee925d7921a1c5756499d6fb17 Mon Sep 17 00:00:00 2001 From: byte Date: Mon, 12 Jan 2026 01:25:49 +0100 Subject: user-specified word mutes and matching --- activitypub.c | 2 +- html.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/activitypub.c b/activitypub.c index 5e55b8a..829f6d5 100644 --- a/activitypub.c +++ b/activitypub.c @@ -2958,7 +2958,7 @@ int process_input_message(snac *snac, const xs_dict *msg, const xs_dict *req) if (xs_is_null(object)) snac_log(snac, xs_fmt("malformed message: no 'id' field")); else - if (timeline_admire(snac, object, actor, 1, xs_dup(msg)) == HTTP_STATUS_CREATED) + if (timeline_admire(snac, object, actor, 1, msg) == HTTP_STATUS_CREATED) snac_log(snac, xs_fmt("new '%s' %s %s", type, actor, object)); else snac_log(snac, xs_fmt("repeated '%s' from %s to %s", type, actor, object)); diff --git a/html.c b/html.c index d5294cb..ebd9331 100644 --- a/html.c +++ b/html.c @@ -16,6 +16,7 @@ #include "xs_url.h" #include "xs_random.h" #include "xs_http.h" +#include "xs_list_tools.h" #include "snac.h" @@ -1864,6 +1865,38 @@ xs_html *html_top_controls(snac *user) xs_html_attr("class", "button"), xs_html_attr("value", L("Update hashtags"))))))); + xs *muted_words_action = xs_fmt("%s/admin/muted-words", user->actor); + xs *muted_words = xs_join(xs_dict_get_def(user->config, + "muted_words", xs_stock(XSTYPE_LIST)), "\n"); + + xs_html_add(top_controls, + xs_html_tag("details", + xs_html_tag("summary", + xs_html_text(L("Muted words..."))), + xs_html_tag("p", + xs_html_text(L("One word per line, partial matches count"))), + xs_html_tag("div", + xs_html_attr("class", "snac-muted-words"), + xs_html_tag("form", + xs_html_attr("autocomplete", "off"), + xs_html_attr("method", "post"), + xs_html_attr("action", muted_words_action), + xs_html_attr("enctype", "multipart/form-data"), + + xs_html_tag("textarea", + xs_html_attr("name", "muted_words"), + xs_html_attr("cols", "40"), + xs_html_attr("rows", "4"), + xs_html_attr("placeholder", "nascar\nsuperbowl\nFIFA"), + xs_html_text(muted_words)), + + xs_html_tag("br", NULL), + + xs_html_sctag("input", + xs_html_attr("type", "submit"), + xs_html_attr("class", "button"), + xs_html_attr("value", L("Update muted words"))))))); + return top_controls; } @@ -2144,6 +2177,30 @@ xs_html *html_entry_controls(snac *user, const char *actor, } +static const xs_str* words_in_content(const xs_list *words, const xs_val *content) +/* returns a word that matches any of the words in content */ +{ + if (!xs_is_list(words) || !xs_is_string(content)) { + return NULL; + } + xs *c = xs_split(content, " "); + xs *sc = xs_list_sort(c, NULL); + + const xs_str *wv; + const xs_str *cv; + xs_list_foreach(words, wv) { + xs_list_foreach(sc, cv) { + xs_tolower_i((xs_str*)cv); + if(xs_str_in(cv, wv) != -1){ + return wv; + } + } + } + + return NULL; +} + + xs_html *html_entry(snac *user, xs_dict *msg, int read_only, int level, const char *md5, int hide_children) { @@ -2438,6 +2495,17 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_text(v), xs_html_text(L(" [SENSITIVE CONTENT]")))); } + else + if (user && + /* muted_words is all lowercase and sorted for performance */ + (v = words_in_content(xs_dict_get(user->config, "muted_words"), + xs_dict_get(msg, "content"))) != NULL) { + snac_debug(user, 1, xs_fmt("word %s muted by user preferences: %s", v, id)); + snac_content = xs_html_tag("details", + xs_html_tag("summary", + xs_html_text(L("Muted: ")), + xs_html_text(v))); + } else { snac_content = xs_html_tag("div", NULL); } @@ -5813,6 +5881,33 @@ int html_post_handler(const xs_dict *req, const char *q_path, status = HTTP_STATUS_SEE_OTHER; } + else + if (p_path && strcmp(p_path, "admin/muted-words") == 0) { + const char *words = xs_dict_get(p_vars, "muted_words"); + + if (xs_is_string(words)) { + xs *new_words = xs_list_new(); + xs *l = xs_split(words, "\n"); + const char *v; + + xs_list_foreach(l, v) { + xs *s1 = xs_strip_i(xs_dup(v)); + s1 = xs_replace_i(s1, " ", ""); + + if (*s1 == '\0') + continue; + + xs *s2 = xs_utf8_to_lower(s1); + + new_words = xs_list_insert_sorted(new_words, s2); + } + + snac.config = xs_dict_set(snac.config, "muted_words", new_words); + user_persist(&snac, 0); + } + + status = HTTP_STATUS_SEE_OTHER; + } if (status == HTTP_STATUS_SEE_OTHER) { const char *hard_redir = xs_dict_get(p_vars, "hard-redir"); -- cgit v1.2.3 From fdc10b0659450e6781e94e119aed1021b0863ed6 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:03:55 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 70591d9..98a86a8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,8 @@ If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming New command-line option `top_ten`, that returns the top ten most popular posts by a user (ordered by the sum of likes and boosts) (contributed by aov). +Added a new set of per-user muted words; if a post contains any of them, it's hidden behind a dropdown (contributed by byte). + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From f5ad346f7d819a1fe71ac6f1bc98e16fe1aead01 Mon Sep 17 00:00:00 2001 From: violette Date: Mon, 12 Jan 2026 05:09:21 +0100 Subject: Use the metadata pronouns. --- doc/style.css | 1 + html.c | 38 ++++++++++++++++++++++++++++++++++++++ utils.c | 1 + 3 files changed, 40 insertions(+) diff --git a/doc/style.css b/doc/style.css index 2981926..9c8764a 100644 --- a/doc/style.css +++ b/doc/style.css @@ -40,3 +40,4 @@ blockquote { font-style: italic; } a { color: #7799dd } a:visited { color: #aa99dd } } +select { max-width: 40%; } diff --git a/html.c b/html.c index ebd9331..9aaaa50 100644 --- a/html.c +++ b/html.c @@ -162,6 +162,31 @@ xs_str *actor_name(xs_dict *actor, const char *proxy) } +xs_str *actor_pronouns(xs_dict *actor) +/* gets the actor name */ +{ + const xs_list *attachment; + const xs_dict *d; + const char *pronouns = ""; + char *ret; + + if (!xs_is_null((attachment = xs_dict_get(actor, "attachment")))) { + xs_list_foreach(attachment, d) { + char *prop = xs_utf8_to_lower(xs_dict_get(d, "name")); + /* make sure that we are reading the correct metadata */ + if (strlen(prop) == 8 && strcmp(prop, "pronouns") == 0) + pronouns = xs_dict_get(d, "value"); + } + } + + /*

breaks page, cannot nest them */ + ret = xs_replace_i(xs_dup(pronouns), "

", ""); + ret = xs_replace_i(ret, "

", ""); + + return ret; +} + + xs_str *format_text_with_emoji(snac *user, const char *text, int ems, const char *proxy) /* needed when we have local text with no tags attached */ { @@ -195,6 +220,10 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, int fwer = 0; xs *name = actor_name(actor, proxy); + xs *pronouns = actor_pronouns(actor); + char pronouns_c = 0; + if (*pronouns != '\0') + pronouns_c = 1; /* get the avatar */ if ((v = xs_dict_get(actor, "icon")) != NULL) { @@ -251,6 +280,15 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs_html_text("»"))); } + if (pronouns_c > 0) + xs_html_add(actor_icon, + xs_html_text(" "), + xs_html_tag("span", + xs_html_attr("class", "snac-pronouns"), + xs_html_attr("title", "user's pronouns"), + xs_html_raw(pronouns))); + + if (strcmp(xs_dict_get(actor, "type"), "Service") == 0) { xs_html_add(actor_icon, xs_html_text(" "), diff --git a/utils.c b/utils.c index fd077f6..9f4e1b7 100644 --- a/utils.c +++ b/utils.c @@ -88,6 +88,7 @@ static const char * const default_css = " a { color: #7799dd }\n" " a:visited { color: #aa99dd }\n" "}\n" + "select { max-width: 40%; }\n" ; const char *snac_blurb = -- cgit v1.2.3 From b1612de2102d9c30bf42402f38ffdc52ab482674 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:11:45 +0100 Subject: Minor tweak. --- html.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/html.c b/html.c index 9aaaa50..9e96108 100644 --- a/html.c +++ b/html.c @@ -168,14 +168,16 @@ xs_str *actor_pronouns(xs_dict *actor) const xs_list *attachment; const xs_dict *d; const char *pronouns = ""; - char *ret; + xs_str *ret; - if (!xs_is_null((attachment = xs_dict_get(actor, "attachment")))) { + if (xs_is_list((attachment = xs_dict_get(actor, "attachment")))) { xs_list_foreach(attachment, d) { - char *prop = xs_utf8_to_lower(xs_dict_get(d, "name")); + xs *prop = xs_utf8_to_lower(xs_dict_get(d, "name")); /* make sure that we are reading the correct metadata */ - if (strlen(prop) == 8 && strcmp(prop, "pronouns") == 0) + if (strlen(prop) == 8 && strcmp(prop, "pronouns") == 0) { pronouns = xs_dict_get(d, "value"); + break; + } } } -- cgit v1.2.3 From 026c1951b8beab8e7e4bd39d9a06c613209f4892 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:13:11 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 98a86a8..a44d0ea 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -8,6 +8,8 @@ New command-line option `top_ten`, that returns the top ten most popular posts b Added a new set of per-user muted words; if a post contains any of them, it's hidden behind a dropdown (contributed by byte). +If an account has a metadata named `pronouns`, it's shown by the name (contributed by violette). + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From 7fe8761ed7992762603c01610a115fde199dcaaf Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:20:52 +0100 Subject: Strip all HTML tags from pronouns. --- html.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/html.c b/html.c index 9e96108..2107609 100644 --- a/html.c +++ b/html.c @@ -181,9 +181,8 @@ xs_str *actor_pronouns(xs_dict *actor) } } - /*

breaks page, cannot nest them */ - ret = xs_replace_i(xs_dup(pronouns), "

", ""); - ret = xs_replace_i(ret, "

", ""); + /* strip all HTML tags */ + ret = xs_regex_replace(pronouns, "]+>", ""); return ret; } -- cgit v1.2.3 From 54bb1626d2c6b55b4c331946606a9986ba963225 Mon Sep 17 00:00:00 2001 From: violette Date: Mon, 12 Jan 2026 05:33:48 +0100 Subject: mastoapi: also return children of children. --- mastoapi.c | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/mastoapi.c b/mastoapi.c index 52aca08..8187115 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -1809,6 +1809,37 @@ xs_list *mastoapi_account_lists(snac *user, const char *uid) } +xs_list *build_childrens(const xs_dict *msg, snac *snac1) { + xs_list *ret = xs_list_new(); + xs *children = object_children(xs_dict_get(msg, "id")); + char *p = children; + const xs_str *v; + + while (xs_list_iter(&p, &v)) { + xs *m2 = NULL; + + if (valid_status(timeline_get_by_md5(snac1, v, &m2))) { + if (xs_is_null(xs_dict_get(m2, "name"))) { + xs *st = mastoapi_status(snac1, m2); + + if (st) { + /* childrens children */ + xs *childs = build_childrens(m2, snac1); + ret = xs_list_append(ret, st); + if (xs_list_len(childs)) { + char *p2 = childs; + while (xs_list_iter(&p2, &v)) + ret = xs_list_append(ret, v); + + } + } + } + } + } + return ret; +} + + int mastoapi_get_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype, xs_str **link) { @@ -2821,8 +2852,6 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, /* return ancestors and children */ xs *anc = xs_list_new(); xs *des = xs_list_new(); - xs_list *p; - const xs_str *v; char pid[MD5_HEX_SIZE]; /* build the [grand]parent list, moving up */ @@ -2842,21 +2871,9 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, } /* build the children list */ - xs *children = object_children(xs_dict_get(msg, "id")); - p = children; - - while (xs_list_iter(&p, &v)) { - xs *m2 = NULL; - - if (valid_status(timeline_get_by_md5(&snac1, v, &m2))) { - if (xs_is_null(xs_dict_get(m2, "name"))) { - xs *st = mastoapi_status(&snac1, m2); - - if (st) - des = xs_list_append(des, st); - } - } - } + xs *childs = build_childrens(msg, &snac1); + if (xs_list_len(childs) > 0) + des = xs_list_cat(des, childs); out = xs_dict_new(); out = xs_dict_append(out, "ancestors", anc); -- cgit v1.2.3 From 39da12904dd53a75c4100453098c7914d8821927 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:35:08 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a44d0ea..3f22b73 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,6 +10,8 @@ Added a new set of per-user muted words; if a post contains any of them, it's hi If an account has a metadata named `pronouns`, it's shown by the name (contributed by violette). +Mastodon API: children of a post are returned recursively, not just the first level (contributed by violette). + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From 181132331d744065b13e5c6134b39335c51940f5 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 05:43:02 +0100 Subject: Updated documentation. --- doc/snac.1 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/snac.1 b/doc/snac.1 index eb27fe5..dbf63f4 100644 --- a/doc/snac.1 +++ b/doc/snac.1 @@ -110,6 +110,9 @@ URLs to RSS feeds of ActivityPub objects are also allowed .It Blocked hashtags... Enter here the list of hashtags you want to block, one per line, with or without the # symbol. +.It Muted words... +Enter here a list of words to be silenced. If a post includes +any of this words, it's hidden behind a dropdown. .El .Pp The user setup dialog allows some user information to be @@ -218,13 +221,20 @@ also private and cannot be liked nor boosted. For each entry in the timeline, a set of reasonable actions in the form of buttons will be shown. These can be: .Bl -tag -offset indent -.It Reply +.It Reply... Unveils a text area to write your intelligent and acute comment to an uninformed fellow. This note is sent to the original author as well as to your followers. The note can include mentions in the @user@format; these people will also become recipients of the message. If you reply to a boost or like, you are really replying to the note, not to the admirer of it. +.It Emoji react... +Unveils a text area that allows a user to react with an emoji +by typing its identifier, that should match one of the emojis +defined in the +.Pa emojis.json +file. By now, only those emoji identifiers surrounded by colons +can be used. .It Like Click this if you admire this post. The poster and your followers will be informed. -- cgit v1.2.3 From de9d546d70cfcbf3b2450b70039470c9a68ecdc6 Mon Sep 17 00:00:00 2001 From: violette Date: Mon, 12 Jan 2026 06:03:04 +0100 Subject: Added emoji categories. --- activitypub.c | 2 +- format.c | 20 +++++++++++++++++++- mastoapi.c | 32 +++++++++++++++++++++++--------- snac.h | 1 + 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/activitypub.c b/activitypub.c index 829f6d5..1992b13 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1611,7 +1611,7 @@ xs_dict *msg_emoji_init(snac *snac, const char *mid, const char *eid_o) xs *dict = xs_dict_new(); xs *icon = xs_dict_new(); xs *accounts = xs_list_new(); - xs *emjs = emojis(); + xs *emjs = emojis_rm_categories(); /* may be a default emoji */ xs *eidd = xs_dup(eid); diff --git a/format.c b/format.c index 803e5a5..95c1b12 100644 --- a/format.c +++ b/format.c @@ -79,6 +79,24 @@ xs_dict *emojis(void) return d; } + +xs_dict *emojis_rm_categories() { + xs *emjs = emojis(); + char *res = xs_dict_new(); + const char *k, *v; + xs_dict_foreach(emjs, k, v) { + if (xs_type(v) == XSTYPE_DICT) { + const char *v2; + xs_dict_foreach(v, k, v2) + res = xs_dict_append(res, k, v2); + } + else + res = xs_dict_append(res, k, v); + } + return res; +} + + /* Non-whitespace without trailing comma, period or closing paren */ #define NOSPACE "([^[:space:],.)]+|[,.)]+[^[:space:],.)])+" @@ -405,7 +423,7 @@ xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag { /* traditional emoticons */ - xs *d = emojis(); + xs *d = emojis_rm_categories(); int c = 0; const char *k, *v; diff --git a/mastoapi.c b/mastoapi.c index 8187115..dd80abc 100644 --- a/mastoapi.c +++ b/mastoapi.c @@ -2647,19 +2647,33 @@ int mastoapi_get_handler(const xs_dict *req, const char *q_path, if (strcmp(cmd, "/v1/custom_emojis") == 0) { /** **/ xs *emo = emojis(); xs *list = xs_list_new(); - int c = 0; const xs_str *k; const xs_val *v; - while(xs_dict_next(emo, &k, &v, &c)) { + xs_dict_foreach(emo, k, v) { xs *current = xs_dict_new(); - if (xs_startswith(v, "https://") && xs_startswith((xs_mime_by_ext(v)), "image/")) { + if ((xs_startswith(v, "https://") && xs_startswith((xs_mime_by_ext(v)), "image/")) || xs_type(v) == XSTYPE_DICT) { /* remove first and last colon */ - xs *shortcode = xs_replace(k, ":", ""); - current = xs_dict_append(current, "shortcode", shortcode); - current = xs_dict_append(current, "url", v); - current = xs_dict_append(current, "static_url", v); - current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); - list = xs_list_append(list, current); + if (xs_type(v) == XSTYPE_DICT) { + const char *v2; + const char *cat = k; + xs_dict_foreach(v, k, v2) { + xs *shortcode = xs_replace(k, ":", ""); + current = xs_dict_append(current, "shortcode", shortcode); + current = xs_dict_append(current, "url", v2); + current = xs_dict_append(current, "static_url", v2); + current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); + current = xs_dict_append(current, "category", cat); + list = xs_list_append(list, current); + } + } + else { + xs *shortcode = xs_replace(k, ":", ""); + current = xs_dict_append(current, "shortcode", shortcode); + current = xs_dict_append(current, "url", v); + current = xs_dict_append(current, "static_url", v); + current = xs_dict_append(current, "visible_in_picker", xs_stock(XSTYPE_TRUE)); + list = xs_list_append(list, current); + } } } *body = xs_json_dumps(list, 0); diff --git a/snac.h b/snac.h index e5efc0b..d57391f 100644 --- a/snac.h +++ b/snac.h @@ -412,6 +412,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path, char **body, int *b_size, char **ctype); xs_dict *emojis(void); +xs_dict *emojis_rm_categories(void); xs_str *format_text_with_emoji(snac *user, const char *text, int ems, const char *proxy); xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag); xs_str *sanitize(const char *content); -- cgit v1.2.3 From a84e74e8f22e0be502d1b4b98cadaf284db5af23 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 06:14:58 +0100 Subject: Move the pronouns closer to the account name. --- html.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/html.c b/html.c index 2107609..2ff6f79 100644 --- a/html.c +++ b/html.c @@ -222,9 +222,6 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs *name = actor_name(actor, proxy); xs *pronouns = actor_pronouns(actor); - char pronouns_c = 0; - if (*pronouns != '\0') - pronouns_c = 1; /* get the avatar */ if ((v = xs_dict_get(actor, "icon")) != NULL) { @@ -259,16 +256,28 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, if (href == NULL) href = xs_dup(actor_id); + xs_html *name_link = xs_html_tag("a", + xs_html_attr("href", href), + xs_html_attr("class", "p-author h-card snac-author"), + xs_html_raw(name)); /* name is already html-escaped */ + + if (*pronouns) { + xs_html_add(name_link, + xs_html_text(" ["), + xs_html_tag("span", + xs_html_attr("class", "snac-pronouns"), + xs_html_attr("title", "user's pronouns"), + xs_html_raw(pronouns)), + xs_html_text("]")); + } + xs_html_add(actor_icon, xs_html_sctag("img", xs_html_attr("loading", "lazy"), xs_html_attr("class", "snac-avatar"), xs_html_attr("src", avatar), xs_html_attr("alt", "[?]")), - xs_html_tag("a", - xs_html_attr("href", href), - xs_html_attr("class", "p-author h-card snac-author"), - xs_html_raw(name))); /* name is already html-escaped */ + name_link); if (!xs_is_null(url)) { xs *md5 = xs_md5_hex(url, strlen(url)); @@ -281,14 +290,6 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs_html_text("»"))); } - if (pronouns_c > 0) - xs_html_add(actor_icon, - xs_html_text(" "), - xs_html_tag("span", - xs_html_attr("class", "snac-pronouns"), - xs_html_attr("title", "user's pronouns"), - xs_html_raw(pronouns))); - if (strcmp(xs_dict_get(actor, "type"), "Service") == 0) { xs_html_add(actor_icon, -- cgit v1.2.3 From 9a5f67bd30511291f7ac9a13a56fb5611b4350cf Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 14:26:43 +0100 Subject: Revert "Updated documentation." This reverts commit cef1d7a176b7603491dfec3f394c1b34bf765f2c. --- doc/snac.8 | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/snac.8 b/doc/snac.8 index 6f98648..b8a75fa 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -296,8 +296,6 @@ outgoing messages (default: 15). Anyway, whenever any incoming activity from a failed instance is detected, this counter is reset for it. .It Ic vkey Public vapid key. Used for notification on some client. -.It Ic disable_emojireact -If set to true, all EmojiReact support (for input and output) is disabled. .El .Pp You must restart the server to make effective these changes. -- cgit v1.2.3 From cf2335c3a65ace85bc49ec0db8a92617280da35a Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 14:31:42 +0100 Subject: Updated documentation. --- doc/snac.8 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/snac.8 b/doc/snac.8 index c53bb59..d961ed2 100644 --- a/doc/snac.8 +++ b/doc/snac.8 @@ -296,6 +296,8 @@ outgoing messages (default: 15). Anyway, whenever any incoming activity from a failed instance is detected, this counter is reset for it. .It Ic vkey Public vapid key. Used for notification on some client. +.It Ic disable_emojireact +If set to true, all EmojiReact support (for input and output) is disabled. .It Ic strip_exif If set to true, EXIF and other metadata will be stripped from uploaded images (jpg, png, webp, heic, avif, tiff, gif, bmp) and videos (mp4, m4v, mov, webm, mkv, avi). This requires the .Nm mogrify -- cgit v1.2.3 From 76bb42fa09dd4b1d74dda70e59dbc5d9f1681422 Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 14:35:47 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3f22b73..ff2da45 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -12,6 +12,8 @@ If an account has a metadata named `pronouns`, it's shown by the name (contribut Mastodon API: children of a post are returned recursively, not just the first level (contributed by violette). +Implemented optional metadata stripping for images and videos using external tools (contributed by Stefano Marinelli). + ## 2.87 Hide EmojiReacts from muted actors and blocked instances. -- cgit v1.2.3 From 3f3e4892ff0d0c46b49cae88e7e74ba5c6c11a3b Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 12 Jan 2026 18:08:34 +0100 Subject: Fixed typo. --- html.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/html.c b/html.c index 2ff6f79..a11b448 100644 --- a/html.c +++ b/html.c @@ -182,8 +182,7 @@ xs_str *actor_pronouns(xs_dict *actor) } /* strip all HTML tags */ - ret = xs_regex_replace(pronouns, "]+>", ""); - + ret = xs_regex_replace(pronouns, "]+>", ""); return ret; } -- cgit v1.2.3 From 5389ed2755564d943af9a4af43f447d14af596f3 Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 13 Jan 2026 09:44:18 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ff2da45..32c3b02 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.88 If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. -- cgit v1.2.3 From 5a437c0f1d1e2f590a177e0eb7e13c05958ede4d Mon Sep 17 00:00:00 2001 From: grunfink Date: Tue, 13 Jan 2026 09:44:45 +0100 Subject: Version 2.88 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index 469982d..b6e1da1 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ -#define VERSION "2.87" +#define VERSION "2.88" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From 485986dab9ab0ee59c5829f85c6b066f6bfa3d72 Mon Sep 17 00:00:00 2001 From: byte Date: Fri, 16 Jan 2026 21:11:42 +0000 Subject: simple cosmetic counters --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/html.c b/html.c index a11b448..86620fb 100644 --- a/html.c +++ b/html.c @@ -3710,7 +3710,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c xs_html *people = xs_html_tag("div", xs_html_tag("h2", xs_html_attr("class", "snac-header"), - xs_html_text(header)), + xs_html_raw(xs_fmt("%s - %d\n", header, xs_list_len(list)))), snac_posts = xs_html_tag("details", xs_html_attr("open", NULL), xs_html_tag("summary", -- cgit v1.2.3 From 1719c1fe95017faa1a75ba58c5391e05eb2e772e Mon Sep 17 00:00:00 2001 From: byte Date: Sat, 17 Jan 2026 02:45:33 +0000 Subject: doing count conditional --- html.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/html.c b/html.c index 86620fb..c834fcf 100644 --- a/html.c +++ b/html.c @@ -3704,13 +3704,19 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, } -xs_html *html_people_list(snac *user, xs_list *list, const char *header, const char *t, const char *proxy) +xs_html *html_people_list(snac *user, xs_list *list, const char *header, const char *t, const char *proxy, int do_count) { xs_html *snac_posts; + const char *header_cnt; + if (do_count) + header_cnt = xs_fmt("%s - %d\n", header, xs_list_len(list)); + else + header_cnt = xs_fmt("%s\n", header); + xs_html *people = xs_html_tag("div", xs_html_tag("h2", xs_html_attr("class", "snac-header"), - xs_html_raw(xs_fmt("%s - %d\n", header, xs_list_len(list)))), + xs_html_raw(header_cnt)), snac_posts = xs_html_tag("details", xs_html_attr("open", NULL), xs_html_tag("summary", @@ -3951,12 +3957,12 @@ xs_str *html_people(snac *user) if (xs_list_len(pending) || xs_is_true(xs_dict_get(user->config, "approve_followers"))) { xs_html_add(lists, - html_people_list(user, pending, L("Pending follow confirmations"), "p", proxy)); + html_people_list(user, pending, L("Pending follow confirmations"), "p", proxy, 1)); } xs_html_add(lists, - html_people_list(user, wing, L("People you follow"), "i", proxy), - html_people_list(user, wers, L("People that follow you"), "e", proxy)); + html_people_list(user, wing, L("People you follow"), "i", proxy, 1), + html_people_list(user, wers, L("People that follow you"), "e", proxy, 1)); xs_html *html = xs_html_tag("html", html_user_head(user, NULL, NULL), @@ -3987,7 +3993,7 @@ xs_str *html_people_one(snac *user, const char *actor, const xs_list *list, xs *foll = xs_list_append(xs_list_new(), actor); xs_html_add(lists, - html_people_list(user, foll, L("Contact's posts"), "p", proxy)); + html_people_list(user, foll, L("Contact's posts"), "p", proxy, 0)); xs_html_add(body, lists); @@ -4641,7 +4647,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *title = xs_fmt(L("Search results for account %s"), q); - page = html_people_list(&snac, l, title, "wf", NULL); + page = html_people_list(&snac, l, title, "wf", NULL, 1); } } -- cgit v1.2.3 From 84c0ee63cf4a67e7fb8484ef874b121160b63382 Mon Sep 17 00:00:00 2001 From: byte Date: Sat, 17 Jan 2026 02:49:56 +0000 Subject: segfault fix --- html.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/html.c b/html.c index a11b448..b4cb1c7 100644 --- a/html.c +++ b/html.c @@ -167,6 +167,7 @@ xs_str *actor_pronouns(xs_dict *actor) { const xs_list *attachment; const xs_dict *d; + const char *v; const char *pronouns = ""; xs_str *ret; @@ -175,7 +176,9 @@ xs_str *actor_pronouns(xs_dict *actor) xs *prop = xs_utf8_to_lower(xs_dict_get(d, "name")); /* make sure that we are reading the correct metadata */ if (strlen(prop) == 8 && strcmp(prop, "pronouns") == 0) { - pronouns = xs_dict_get(d, "value"); + /* safeguard from NULL values */ + v = xs_dict_get(d, "value"); + pronouns = v ? v : pronouns; break; } } -- cgit v1.2.3 From 0f7e97061822ba194762ac47c1c25a880e977696 Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 17 Jan 2026 05:17:45 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 32c3b02..c06c15d 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,9 @@ # Release Notes +## UNRELEASED + +Fixed crash in pronouns processing (contributed by byte). + ## 2.88 If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. -- cgit v1.2.3 From 8ce4bd725dc9c37a58a1924a2ba355c176a2dd4a Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 17 Jan 2026 05:24:50 +0100 Subject: Fixed small memory leak. --- html.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/html.c b/html.c index 1a25eaa..3f5435c 100644 --- a/html.c +++ b/html.c @@ -3710,7 +3710,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html *html_people_list(snac *user, xs_list *list, const char *header, const char *t, const char *proxy, int do_count) { xs_html *snac_posts; - const char *header_cnt; + xs *header_cnt; if (do_count) header_cnt = xs_fmt("%s - %d\n", header, xs_list_len(list)); else @@ -3719,7 +3719,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c xs_html *people = xs_html_tag("div", xs_html_tag("h2", xs_html_attr("class", "snac-header"), - xs_html_raw(header_cnt)), + xs_html_text(header_cnt)), snac_posts = xs_html_tag("details", xs_html_attr("open", NULL), xs_html_tag("summary", -- cgit v1.2.3 From 4e166a5d22402da864518455c2cd03d6ba5ab41d Mon Sep 17 00:00:00 2001 From: grunfink Date: Sat, 17 Jan 2026 05:25:35 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index c06c15d..20fc419 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,8 @@ Fixed crash in pronouns processing (contributed by byte). +Added counters in the people page (contributed by byte). + ## 2.88 If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. -- cgit v1.2.3 From d8d40acfd17dfe28654f7acfac648a896033b63b Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 19 Jan 2026 15:53:19 +0100 Subject: New command-line option 'refresh'. --- activitypub.c | 2 +- main.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/activitypub.c b/activitypub.c index 1992b13..c34e510 100644 --- a/activitypub.c +++ b/activitypub.c @@ -3395,7 +3395,7 @@ void process_user_queue_item(snac *user, xs_dict *q_item) actor_add(actor, actor_o); } else { - if (status == HTTP_STATUS_GONE) { + if (status == HTTP_STATUS_GONE || status == HTTP_STATUS_NOT_FOUND) { actor_failure(actor, 1); snac_log(user, xs_fmt("actor_refresh marking actor %s as broken %d", actor, status)); } diff --git a/main.c b/main.c index 4ba9796..e7d5b0d 100644 --- a/main.c +++ b/main.c @@ -77,7 +77,8 @@ int usage(const char *cmd) "list_remove {basedir} {uid} {name} Removes an existing list\n" "list_add {basedir} {uid} {name} {acct} Adds an account (@user@host or actor url) to a list\n" "list_del {basedir} {uid} {name} {actor} Deletes an actor URL from a list\n" - "top_ten {basedir} {uid} [{N}] Prints the most popular posts\n"; + "top_ten {basedir} {uid} [{N}] Prints the most popular posts\n" + "refresh {basedir} {uid} Refreshes all actors\n"; if (cmd == NULL) printf("%s", cmds); @@ -369,6 +370,20 @@ int main(int argc, char *argv[]) return 0; } + if (strcmp(cmd, "refresh") == 0) { /** **/ + xs *fwers = follower_list(&snac); + xs *fwing = following_list(&snac); + const char *id; + + xs_list_foreach(fwers, id) + enqueue_actor_refresh(&snac, id, 0); + + xs_list_foreach(fwing, id) + enqueue_actor_refresh(&snac, id, 0); + + return 0; + } + if ((url = GET_ARGV()) == NULL) return usage(cmd); -- cgit v1.2.3 From 75ebfd16eda4ef158b3a8cf2a3a710152f87a81f Mon Sep 17 00:00:00 2001 From: grunfink Date: Mon, 19 Jan 2026 15:54:45 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 20fc419..e3f7b89 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -6,6 +6,8 @@ Fixed crash in pronouns processing (contributed by byte). Added counters in the people page (contributed by byte). +New command-line option `refresh`, to refresh all follower and following `Actor` objects, marking them as broken if they are. + ## 2.88 If `disable_emojireact` is set to `true` in `server.json`, EmojiReacts (incoming and outgoing) are totally disabled. -- cgit v1.2.3 From 030417e9990f015047db04d6c1aa642a05305733 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 22 Jan 2026 07:04:07 +0100 Subject: Updated RELEASE_NOTES. --- RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e3f7b89..9f2ffd6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ # Release Notes -## UNRELEASED +## 2.89 Fixed crash in pronouns processing (contributed by byte). -- cgit v1.2.3 From 189ab6394eba999d4f174d629cdebfc5fdfd4bd3 Mon Sep 17 00:00:00 2001 From: grunfink Date: Thu, 22 Jan 2026 07:04:33 +0100 Subject: Version 2.89 RELEASED. --- snac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snac.h b/snac.h index b6e1da1..ef79594 100644 --- a/snac.h +++ b/snac.h @@ -1,7 +1,7 @@ /* snac - A simple, minimalistic ActivityPub instance */ /* copyright (c) 2022 - 2026 grunfink et al. / MIT license */ -#define VERSION "2.88" +#define VERSION "2.89" #define USER_AGENT "snac/" VERSION -- cgit v1.2.3 From af416f13fe6c5192b69bee44dcefa9f66b15d0c4 Mon Sep 17 00:00:00 2001 From: pmjv Date: Fri, 23 Jan 2026 18:03:32 +0100 Subject: add susie-q (qr) to artwork --- artwork/susie-q.png | Bin 0 -> 1305 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 artwork/susie-q.png diff --git a/artwork/susie-q.png b/artwork/susie-q.png new file mode 100644 index 0000000..82fd9fe Binary files /dev/null and b/artwork/susie-q.png differ -- cgit v1.2.3