R1 cleanup: collAnon and dead code gone, docs current, every peer's scenario in one sweep
Build / Build (push) Successful in 1m7s

Starts the completion program (docs/ROADMAP.md, "Owner decisions on finishing everything", 2026-10-17).

- Dead code: the commented-out collAnon blocks (discussions, seeding, admin user lists, HTTP/3, the old signature
  middleware), the empty PrivaPubWorkersConfiguration, PublicAvatarUsersService and UserPolicyType, unused helpers,
  the second IPasswordHasher registration, the PasswordGenerator package, SignUpAsync/LoginAsync's unused invitation
  parameters. "Starting PrivaPub"; a signed-in login is sent to "/", not to "/discussions".
- Stored fields nothing read: RootUser.Contacts and ResetPasswordToken*, the local Avatar.AvatarServer,
  EmailRecovery.RecoveryCode/RequestIP/CreationDate, MongoSettings.LogsDatabase, and AppConfiguration's
  upload/discussion keys, RequiresFirstTimeSetup and Version (old documents still load: MongoDB.Entities ignores extra
  elements). DmPost's indexes are no longer made. 49 collAnon keys leave FieldsNameResource in every language.
- /clientapi/data/current-version answers the build's ref. UsersIds is a list that can't throw, and the admin routes
  leave the administrator out without mutating the request.
- deploy.yml checks SecureMode on a name no persona can have, and the browser redirect on the directory's first local
  persona: @thepra is the administrator's own now.
- Town: decePub's e2e remnants (expect, client.jsonl, the decePub column) and town/tests go; the dead gaps/load
  commands too. Mobilizon no longer keeps an event for a deleted test.
- tools/pasture/sweep.sh runs every peer's scenario, batch by batch, as CLAUDE.md asks before a change to what
  PrivaPub sends.
- Docs: CLAUDE.md's repo map, route table (every frozen route) and stale lines; ROADMAP's status (setup, v1.25.0,
  v1.26.0, the program C), the 2026-10-17 decisions, and dated notes where earlier text no longer holds; FEDERATION.md's
  FEP list (7888, f228, 7628, ae0c and 8967 supported) and the deploy's persona.

Verified: dotnet build PrivaPub.sln -c Release (0 errors, no new warnings); bash -n on the touched scripts; py_compile
on the town; the pasture's gts, mastodon and lemmy scenarios on this build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-17 02:56:57 +02:00
1 parent 6727e1817a
commit ff5e635dda
71 files changed
+238 -4767

No files matched your search

+11 -4
View File
@@ -103,11 +103,18 @@ jobs:
[ "$served" = "$BUILD_COMMIT" ] || { echo "::error::served build is '$served', expected '$BUILD_COMMIT'"; exit 1; } [ "$served" = "$BUILD_COMMIT" ] || { echo "::error::served build is '$served', expected '$BUILD_COMMIT'"; exit 1; }
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/activity+json' "$PUBLIC_URL/peasants/privapub") code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/activity+json' "$PUBLIC_URL/peasants/privapub")
[ "$code" = "200" ] || { echo "::error::the instance actor answered $code"; exit 1; } [ "$code" = "200" ] || { echo "::error::the instance actor answered $code"; exit 1; }
# SecureMode (owner decision 2026-10-04): an unsigned reader gets 401 from a persona, a browser the public page # SecureMode (owner decision 2026-10-04): an unsigned reader gets 401 before any lookup, so a name no persona can have
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/activity+json' "$PUBLIC_URL/peasants/thepra") # (a hyphen is outside UserNameRegex) checks it without naming anyone; a browser asking for a persona gets its page
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: application/activity+json' "$PUBLIC_URL/peasants/no-such-persona")
[ "$code" = "401" ] || { echo "::error::an unsigned GET of a persona answered $code, not 401: SecureMode is off"; exit 1; } [ "$code" = "401" ] || { echo "::error::an unsigned GET of a persona answered $code, not 401: SecureMode is off"; exit 1; }
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: text/html' "$PUBLIC_URL/peasants/thepra") directory=$(curl -fsS "$PUBLIC_URL/api/v1/directory?local=true&limit=1") || { echo "::error::the directory did not answer"; exit 1; }
[ "$code" = "302" ] || { echo "::error::a browser asking for a persona got $code, not a redirect"; exit 1; } persona=$(echo "$directory" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d[0]['username'] if d else '')")
if [ -z "$persona" ]; then
echo "::notice::no persona in the directory: the browser redirect is not checked"
else
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'Accept: text/html' "$PUBLIC_URL/peasants/$persona")
[ "$code" = "302" ] || { echo "::error::a browser asking for @$persona got $code, not a redirect"; exit 1; }
fi
code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/.well-known/nodeinfo") code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/.well-known/nodeinfo")
[ "$code" = "200" ] || { echo "::error::nodeinfo answered $code"; exit 1; } [ "$code" = "200" ] || { echo "::error::nodeinfo answered $code"; exit 1; }
code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/swagger/index.html") code=$(curl -s -o /dev/null -w '%{http_code}' "$PUBLIC_URL/swagger/index.html")
+35 -15
View File
@@ -18,7 +18,7 @@ Its defining idea: **one private login owns several public personas.**
Root and avatar are linked only through `RootToAvatar`. Root and avatar are linked only through `RootToAvatar`.
- **Personas must stay unlinkable** to other users and servers; only the instance admin can see the link. - **Personas must stay unlinkable** to other users and servers; only the instance admin can see the link.
- **`Group` is an ActivityPub Group actor.** It has members, an invitation code and an optional password. Groups are - **`Group` is an ActivityPub Group actor.** It has members, an invitation code and an optional password. Groups are
becoming two kinds: a public **community** (FEP-1b12, Lemmy-compatible) and a private, invitation-only **circle**. of two kinds: a public **community** (FEP-1b12, Lemmy-compatible) and a private, invitation-only **circle**.
- **`DmGroup` is a direct-message conversation.** - **`DmGroup` is a direct-message conversation.**
- **`privapub` is the instance actor** (type Application). It signs fetches no persona should be tied to. - **`privapub` is the instance actor** (type Application). It signs fetches no persona should be tied to.
- **`privapub_reports` is the reporter** (type Service, `LocalActorKind.Reporter`). It carries reports to Lemmy, which - **`privapub_reports` is the reporter** (type Service, `LocalActorKind.Reporter`). It carries reports to Lemmy, which
@@ -30,9 +30,9 @@ Its defining idea: **one private login owns several public personas.**
shown as accounts. shown as accounts.
Privacy features in the model: Privacy features in the model:
- location-ranged posts (`Post.Location`, `RangeKm`), to become local-only and never federated; - location-ranged posts (`Post.Location`, `RangeKm`), local-only and never federated;
- contacts a persona can share (`Avatar.SharedPersonalContacts`); - contacts a persona can share (`Avatar.SharedPersonalContacts`) and private notes (`RootUserNote`, `PersonalNote`)
- private notes (`RootUserNote`, `PersonalNote`). exist only as model classes, with no endpoint.
The intended client is the Mastodon client API (Tusky, Elk, Phanpy, Ivory), where each avatar logs in as its own The intended client is the Mastodon client API (Tusky, Elk, Phanpy, Ivory), where each avatar logs in as its own
account. The private `/clientapi` covers what Mastodon can't express. `thepra/decePubClient` account. The private `/clientapi` covers what Mastodon can't express. `thepra/decePubClient`
@@ -56,10 +56,17 @@ actor-scoped route gets a name in the same spirit, agreed with the owner, and a
| Activities | `/peasants/{name}/grunts/{id}` (`create-{postId}` resolves) | | Activities | `/peasants/{name}/grunts/{id}` (`create-{postId}` resolves) |
| DM context | `/peasants/{name}/whispers/{id}` | | DM context | `/peasants/{name}/whispers/{id}` |
| Quote permission (FEP-044f `QuoteAuthorization`) | `/peasants/{name}/parrot-licences/{id}` | | Quote permission (FEP-044f `QuoteAuthorization`) | `/peasants/{name}/parrot-licences/{id}` |
| Featured (pinned posts) | `/peasants/{name}/trophies` |
| Featured tags | `/peasants/{name}/tattoos` |
| Wall (FEP-400e) | `/peasants/{name}/graffiti` |
| Followers synchronisation (FEP-8fcf) | `/peasants/{name}/groupies/roll-call` |
| A group's members and moderators | `/peasants/{name}/flock`, `/peasants/{name}/wardens` |
| A post's replies and thread | `/peasants/{name}/scribbles/{id}/replies`, `/peasants/{name}/scribbles/{id}/context` |
| Token refresh | `/clientapi/user/sniff/again` | | Token refresh | `/clientapi/user/sniff/again` |
Agreed for later phases: `/gossip`, `/drool`, `/echoes` (replies, likes, shares), `/trophies` (featured), `/tattoos` All of these have federated, so they are frozen. Agreed for later: `/drool` and `/echoes` (likes, shares). `/gossip` was
(featured tags), `/flock` and `/wardens` (group members and moderators). agreed for replies before they were served at `…/scribbles/{id}/replies` (2026-10-06); whether it is still wanted is
asked in the completion program's R10.
Routes other software looks up by name stay conventional: Routes other software looks up by name stay conventional:
- `/.well-known/*` and `/nodeinfo/*`; - `/.well-known/*` and `/nodeinfo/*`;
@@ -74,15 +81,21 @@ PrivaPub.sln
PrivaPub/ ASP.NET Core Web API, net10.0 PrivaPub/ ASP.NET Core Web API, net10.0
Program.cs host, Mongo init (GUIDs Standard), pipeline, /build.json Program.cs host, Mongo init (GUIDs Standard), pipeline, /build.json
Middleware/SocialPubConfigurations.cs every DI registration (auth, federation, services, swagger, CORS) Middleware/SocialPubConfigurations.cs every DI registration (auth, federation, services, swagger, CORS)
Controllers/ClientToServer/ /clientapi/*: RootUser (signup/login/invitations/recovery), PrivateAvatar, Controllers/ClientToServer/ /clientapi/*: RootUser (signup, setup, login, invitations, recovery), PrivateAvatar,
Group, Post (posts + DMs), Admin, Data Group, Post (posts + DMs), Social, Timeline, Data, PersonaArchive, Moderator (reports),
Admin (logins), DomainBlock, Statistics, Backup
Infrastructure/ Infrastructure/
Http/ FederationHttp + SafeHttpHandlerFactory + IpRangeGuard: the only way out Http/ FederationHttp + SafeHttpHandlerFactory + IpRangeGuard: the only way out
Jobs/ JobQueue (leases), JobWorker, Backoff, HostCircuitBreaker Jobs/ JobQueue (leases), JobWorker, Backoff, HostCircuitBreaker
Ids/ PrivacyIds (day-only ids for personas and groups, arrival-ordered ids for remote posts) Ids/ PrivacyIds (day-only ids for personas and groups, arrival-ordered ids for remote posts)
Data/ Indexes (created at start), EntityMaps.Warm, Migrations/_NNN_*.cs Data/ Indexes (created at start), EntityMaps.Warm, Migrations/_NNN_*.cs
Cli/ AdminCommands (`PrivaPub admin promote|demote <root>`) Cli/ AdminCommands (`PrivaPub admin promote|demote|create-root|move-persona|delete-root`,
`media audit`, `backup`, `backups`, `restore`)
Backup/ ServerBackup, ServerRestore, ProtectiveMerge, MaintenanceLock, TransferStore
Geo/ GeoLocator, GeoUpdater (DB-IP Lite), CdnCatalog, CdnUpdater
Statistics/ InteractionLedger, Rollup, TrafficMeter, StatisticsOptions
RateLimiting.cs accounts (per client address) and inbox (per sending origin) policies RateLimiting.cs accounts (per client address) and inbox (per sending origin) policies
RegistrationOptions.cs who may make a login (`Registrations:Mode`)
Federation/ Federation/
Controllers/ PeasantsController (actor, outbox, followers, following, posts, inboxes), Controllers/ PeasantsController (actor, outbox, followers, following, posts, inboxes),
WellKnownController (webfinger, nodeinfo), UsersController (redirect) WellKnownController (webfinger, nodeinfo), UsersController (redirect)
@@ -100,13 +113,17 @@ PrivaPub/ ASP.NET Core Web API, net10.0
ReplyRelay (third-party replies to a persona's posts passed on to its followers) ReplyRelay (third-party replies to a persona's posts passed on to its followers)
Outbox/ OutboxPublisher (who a post goes to), DeliveryService (queues jobs) + DeliveryJobHandler Outbox/ OutboxPublisher (who a post goes to), DeliveryService (queues jobs) + DeliveryJobHandler
Rendering/ ActivityPubRenderer (Mastodon @context, actors, notes, collections) Rendering/ ActivityPubRenderer (Mastodon @context, actors, notes, collections)
Crawler/ Crawler, PeerHosts, RobotsTxt (the opt-in crawler behind `/stargazing`)
Relays/ Relays (the instance actor's relay subscriptions)
Domain/ Domain/
Content/ ContentRenderer (Markdown or plain text → HTML with h-card mentions and hashtags) Content/ ContentRenderer (Markdown or plain text → HTML with h-card mentions and hashtags)
Social/ FollowService (local in-process, remote Follow/Accept), Notifications Social/ FollowService (local in-process, remote Follow/Accept), Notifications
Timelines/ Fanout (TimelineEntry rows, Mastodon's home rules), TimelineService Timelines/ Fanout (TimelineEntry rows, Mastodon's home rules), TimelineService
Privacy/ VisibilityPolicy (IsPublic expression, CanSee) Privacy/ VisibilityPolicy (IsPublic expression, CanSee)
Relationships/ RelationshipService (blocks, mutes, account domain blocks; Hidden), ReportService Relationships/ RelationshipService (blocks, mutes, account domain blocks; Hidden), ReportService
Media/ MediaService (libvips, ffmpeg remux, blurhash), MediaProxy, MediaJanitor Media/ MediaService (libvips, ffmpeg, blurhash), MediaProxy, MediaJanitor
Portability/ persona archives exported and imported (Mastodon's layout)
Statistics/ StatisticsQueries, PublicGeo, ServerPlaces, SelfLocation
Domain/Statuses/ StatusService: publish, edit, remove, favourite, reblog, for a persona (both client APIs use it); Domain/Statuses/ StatusService: publish, edit, remove, favourite, reblog, for a persona (both client APIs use it);
InteractionApprovals: GoToSocial's canReply/canLike/canAnnounce, judged, asked and answered; InteractionApprovals: GoToSocial's canReply/canLike/canAnnounce, judged, asked and answered;
Participations: a persona's Join and Leave of a remote event, and the organiser's answer Participations: a persona's Join and Leave of a remote event, and the organiser's answer
@@ -114,7 +131,9 @@ PrivaPub/ ASP.NET Core Web API, net10.0
Auth/ OpenIddict setup (keys in Mongo), MastodonScopes, TokenController, OAuthPruner Auth/ OpenIddict setup (keys in Mongo), MastodonScopes, TokenController, OAuthPruner
Infrastructure/ MastodonController (avatar context, scopes, errors, Link), MastodonParams, MastodonJson, Page Infrastructure/ MastodonController (avatar context, scopes, errors, Link), MastodonParams, MastodonJson, Page
Entities/ Mappers/ Mastodon entities; MastodonMapper (Account, Status), AccountSearch Entities/ Mappers/ Mastodon entities; MastodonMapper (Account, Status), AccountSearch
Controllers/ apps, instance, accounts, statuses, timelines, notifications, search, stubs Controllers/ apps, instance, accounts, statuses, timelines, notifications, search, lists, filters,
media, polls, reactions, reports, scheduled statuses, streaming, tags, trends, cdns,
provenance; the stubs are `StubsController` in `SearchController.cs`
Web/Pages/ Razor: /@{user}, /@{user}/{id} (public posts only, strict CSP, noindex); Web/Pages/ Razor: /@{user}, /@{user}/{id} (public posts only, strict CSP, noindex);
OAuth/: /oauth/login (root password), /oauth/authorize (choose persona, consent) OAuth/: /oauth/login (root password), /oauth/authorize (choose persona, consent)
Services/ RootUsersService, GroupUsersService, PostsService, AppConfigurationService, … Services/ RootUsersService, GroupUsersService, PostsService, AppConfigurationService, …
@@ -127,8 +146,8 @@ deploy/ nginx vhost, systemd units (privapub, privapub
docs/ROADMAP.md decisions + phased plan docs/ROADMAP.md decisions + phased plan
``` ```
The roadmap moves code towards `Infrastructure/`, `Federation/`, `Domain/`, `Api/{ClientApi,Mastodon}` and `Web/`, The planned move of `/clientapi` into `Api/ClientApi` was dropped (2026-10-17): it stays in `Controllers/ClientToServer/`
one pure-move commit at a time. and `Services/`.
## Commands ## Commands
@@ -607,11 +626,12 @@ Interop is checked against real servers, starting with the workstation's own pas
```bash ```bash
DOTNET=~/.dotnet/dotnet tools/pasture/run.sh up [gts mastodon ...] # podman: PrivaPub + the named peers (default gts) + Mongo, behind Caddy DOTNET=~/.dotnet/dotnet tools/pasture/run.sh up [gts mastodon ...] # podman: PrivaPub + the named peers (default gts) + Mongo, behind Caddy
tools/pasture/interop.sh [gts mastodon ...] # each peer's scenario, then what PrivaPub's statistics saw of it tools/pasture/interop.sh [gts mastodon ...] # each peer's scenario, then what PrivaPub's statistics saw of it
tools/pasture/sweep.sh [A|B|C|D ...] # every peer's scenario, batch by batch (up, interop, down); out/sweep-<batch>.log
tools/pasture/run.sh down # removes every pasture container and volume tools/pasture/run.sh down # removes every pasture container and volume
``` ```
- **A change to what PrivaPub sends** (the `@context`, an actor's properties, an activity's shape, a delivery's headers) - **A change to what PrivaPub sends** (the `@context`, an actor's properties, an activity's shape, a delivery's headers)
is run against every peer's scenario before it is committed, not only the peers it was written for. One reader is run against every peer's scenario before it is committed, not only the peers it was written for (`sweep.sh`). One reader
stricter than the rest fails on it alone: the 2026-10-06 `proof` term passed every peer but Smithereen, whose JSON-LD stricter than the rest fails on it alone: the 2026-10-06 `proof` term passed every peer but Smithereen, whose JSON-LD
1.0 reader refused every document carrying it. 1.0 reader refused every document carrying it.
- **Layout:** `lib/pasture.sh` (network, Caddy, Mongo, PrivaPub), `peers/<name>.sh` (`<name>_up`, plus `peers/shared.sh` - **Layout:** `lib/pasture.sh` (network, Caddy, Mongo, PrivaPub), `peers/<name>.sh` (`<name>_up`, plus `peers/shared.sh`
@@ -664,7 +684,7 @@ tools/pasture/run.sh down # removes e
read from its `user_relationships`. `akkoma_token <user>` signs one of its users in. 45 checks. read from its `user_relationships`. `akkoma_token <user>` signs one of its users in. 45 checks.
- **Lemmy (1.0.0-beta.2):** the backend alone on the shared Postgres, its admin made by `setup` in the generated - **Lemmy (1.0.0-beta.2):** the backend alone on the shared Postgres, its admin made by `setup` in the generated
`config.hjson`. It trusts Caddy's CA through `SSL_CERT_FILE` and reaches the network through `config.hjson`. It trusts Caddy's CA through `SSL_CERT_FILE` and reaches the network through
`DANGER_FEDERATION_ALLOW_LOCAL_IP=1`; 0.19 cannot join (its rustls trusts only its bundled roots). Its API is `DANGER_FEDERATION_ALLOW_LOCAL_IP=1`; 0.19's release can't join as it is, so it runs as its own build (`lemmy19`, below). Its API is
`/api/v4/<path>` with a bearer token (`lm` in the scenario), and `sort` values are lowercase. It logs no refused `/api/v4/<path>` with a bearer token (`lm` in the scenario), and `sort` values are lowercase. It logs no refused
activity at `warn` (`LEMMY_LOG` sets `RUST_LOG`); the reason is in the 400's body. It answers our community's echo of activity at `warn` (`LEMMY_LOG` sets `RUST_LOG`); the reason is in the 400's body. It answers our community's echo of
its own activity and every bare `Announce{object}` 400 by design, and the echo is still needed (see its own activity and every bare `Announce{object}` 400 by design, and the echo is still needed (see
+15 -6
View File
@@ -65,8 +65,8 @@ Checked both ways, where the peer has the feature:
- communities and circles; - communities and circles;
- blocks and unfollows. - blocks and unfollows.
`docs/INTEROP.md` has each peer's evidence and what is still expected to fail. The platforms not yet in the pasture are `docs/INTEROP.md` has each peer's evidence and what is still expected to fail. The platforms not in the pasture are
covered by unit tests written in their documents' shape. read from documents in their published shape (`docs/INTEROP.md` records each one); there is no test project.
## Supported FEPs ## Supported FEPs
@@ -98,10 +98,19 @@ covered by unit tests written in their documents' shape.
(sent and honoured; see "Followers synchronisation") (sent and honoured; see "Followers synchronisation")
- [FEP-5624: Per-object reply control policies](https://codeberg.org/fediverse/fep/src/branch/main/fep/5624/fep-5624.md): - [FEP-5624: Per-object reply control policies](https://codeberg.org/fediverse/fep/src/branch/main/fep/5624/fep-5624.md):
read (see "Replies its author approves") read (see "Replies its author approves")
- [FEP-7888: Demystifying the context property](https://codeberg.org/fediverse/fep/src/branch/main/fep/7888/fep-7888.md)
and [FEP-f228: Backfilling conversations](https://codeberg.org/fediverse/fep/src/branch/main/fep/f228/fep-f228.md):
a root post serves its `context` collection, and a remote thread is read from its `context` (or `contextHistory`)
before its `replies` (see "Activities")
- [FEP-7628: Move actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/7628/fep-7628.md): received; a persona's
follows move with the account (see `Move` under "Activities")
- [FEP-ae0c: Fediverse Relay Protocols](https://codeberg.org/fediverse/fep/src/branch/main/fep/ae0c/fep-ae0c.md): the
instance actor follows the relays configured, and their `Announce`s are taken as their origin vouches (see "Relays")
- [FEP-8967: Generic attachments, link previews](https://codeberg.org/fediverse/fep/src/branch/main/fep/8967/fep-8967.md):
received; a `preview` builds the card
Planned (see `docs/ROADMAP.md`, phases P7 and P8, and the per-platform notes in `docs/INTEROP.md`): FEP-9098 (custom Planned (see `docs/ROADMAP.md`, the completion program, and the per-platform notes in `docs/INTEROP.md`): FEP-9098
emoji), FEP-7888 and FEP-f228 (threads), FEP-7628 (Move), FEP-8967 (link custom emoji offered (R7) and FEP-8967 link attachments sent (R10).
attachments), FEP-ae0c (relays).
## Actors ## Actors
@@ -128,7 +137,7 @@ The names are the project's own and are stable; resolve actors through WebFinger
- The key is `{actor}#main-key`, RSA 2048, served as SPKI PEM with `owner` set to the actor. - The key is `{actor}#main-key`, RSA 2048, served as SPKI PEM with `owner` set to the actor.
- `published` on an actor is a whole day, chosen at random up to two weeks before the account was made, so two - `published` on an actor is a whole day, chosen at random up to two weeks before the account was made, so two
personas made on the same day do not share a date. `indexable` is `false` unless the persona turns it on, and personas made on the same day do not share a date. `indexable` is `false` unless the persona turns it on, and
`discoverable` is `true` unless it turns that off (the deploy's own persona, @thepra, is undiscoverable). `discoverable` is `true` unless it turns that off.
- The instance actor is `/peasants/privapub` (type `Application`). It signs every fetch PrivaPub makes, so no avatar's key - The instance actor is `/peasants/privapub` (type `Application`). It signs every fetch PrivaPub makes, so no avatar's key
is used to read another server's content. It also answers at the server's root (`/`) for a request that asks for is used to read another server's content. It also answers at the server's root (`/`) for a request that asks for
ActivityPub, as Lemmy's site actor does: PieFed sends a community's announces to the inbox of the Application at a ActivityPub, as Lemmy's site actor does: PieFed sends a community's announces to the inbox of the Application at a
@@ -60,132 +60,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to (necessary in case of password recovery).
/// </summary>
public static string _necessary_in_case_of_password_recovery_ {
get {
return ResourceManager.GetString("(necessary in case of password recovery)", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to (&lt;a class=&quot;is-underlined has-text-info&quot; tabindex=&quot;-1&quot; target=&quot;_blank&quot; href=&quot;https://keepassxc.org/&quot;&gt;password manager&lt;/a&gt; suggested).
/// </summary>
public static string _password_manager_suggested_ {
get {
return ResourceManager.GetString("(password manager suggested)", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Amount.
/// </summary>
public static string Amount {
get {
return ResourceManager.GetString("Amount", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Answer id.
/// </summary>
public static string AnswerId {
get {
return ResourceManager.GetString("AnswerId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Answer text.
/// </summary>
public static string AnswerText {
get {
return ResourceManager.GetString("AnswerText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Custom character(emoji).
/// </summary>
public static string Character {
get {
return ResourceManager.GetString("Character", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Colour.
/// </summary>
public static string ColourIndex {
get {
return ResourceManager.GetString("ColourIndex", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Comment id.
/// </summary>
public static string CommentId {
get {
return ResourceManager.GetString("CommentId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Comment text.
/// </summary>
public static string CommentText {
get {
return ResourceManager.GetString("CommentText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Confrontation.
/// </summary>
public static string Confrontation {
get {
return ResourceManager.GetString("Confrontation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Confrontation id.
/// </summary>
public static string ConfrontationId {
get {
return ResourceManager.GetString("ConfrontationId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Context.
/// </summary>
public static string Context {
get {
return ResourceManager.GetString("Context", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End date.
/// </summary>
public static string DateEnd {
get {
return ResourceManager.GetString("DateEnd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Start date.
/// </summary>
public static string DateStart {
get {
return ResourceManager.GetString("DateStart", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Description. /// Looks up a localized string similar to Description.
/// </summary> /// </summary>
@@ -195,60 +69,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Discussion.
/// </summary>
public static string Discussion {
get {
return ResourceManager.GetString("Discussion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End date.
/// </summary>
public static string DiscussionEndDate {
get {
return ResourceManager.GetString("DiscussionEndDate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End time.
/// </summary>
public static string DiscussionEndTime {
get {
return ResourceManager.GetString("DiscussionEndTime", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Discussion id.
/// </summary>
public static string DiscussionId {
get {
return ResourceManager.GetString("DiscussionId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Discussion text.
/// </summary>
public static string DiscussionText {
get {
return ResourceManager.GetString("DiscussionText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Discussion title.
/// </summary>
public static string DiscussionTitle {
get {
return ResourceManager.GetString("DiscussionTitle", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Email. /// Looks up a localized string similar to Email.
/// </summary> /// </summary>
@@ -267,42 +87,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Max amount of confrontations.
/// </summary>
public static string ExpectedMaxConfrontationsBeforeClosingAndShowing {
get {
return ResourceManager.GetString("ExpectedMaxConfrontationsBeforeClosingAndShowing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fact.
/// </summary>
public static string Fact {
get {
return ResourceManager.GetString("Fact", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Facts.
/// </summary>
public static string Facts {
get {
return ResourceManager.GetString("Facts", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File id.
/// </summary>
public static string FileId {
get {
return ResourceManager.GetString("FileId", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Groups. /// Looks up a localized string similar to Groups.
/// </summary> /// </summary>
@@ -312,15 +96,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Include the first answer in the invitation preview? (making it more engaging to join the discussion).
/// </summary>
public static string IncludeFirstAnswerInInvitation {
get {
return ResourceManager.GetString("IncludeFirstAnswerInInvitation", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Invitation code. /// Looks up a localized string similar to Invitation code.
/// </summary> /// </summary>
@@ -330,15 +105,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Invitation code or link.
/// </summary>
public static string InvitationCodeLink {
get {
return ResourceManager.GetString("InvitationCodeLink", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Invitation password. /// Looks up a localized string similar to Invitation password.
/// </summary> /// </summary>
@@ -348,42 +114,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Require password for preview.
/// </summary>
public static string IsPasswordProtectedForPreview {
get {
return ResourceManager.GetString("IsPasswordProtectedForPreview", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Require password to show the preview.
/// </summary>
public static string IsPasswordProtectedForPreviewText {
get {
return ResourceManager.GetString("IsPasswordProtectedForPreviewText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Add password protection.
/// </summary>
public static string IsPasswordProtectedText {
get {
return ResourceManager.GetString("IsPasswordProtectedText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to IsStructured.
/// </summary>
public static string IsStructured {
get {
return ResourceManager.GetString("IsStructured", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Language id. /// Looks up a localized string similar to Language id.
/// </summary> /// </summary>
@@ -426,15 +156,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Enable notifications?(useful to receive app updates).
/// </summary>
public static string NativeNotificationsEnabled {
get {
return ResourceManager.GetString("NativeNotificationsEnabled", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to New password. /// Looks up a localized string similar to New password.
/// </summary> /// </summary>
@@ -462,15 +183,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to One time only.
/// </summary>
public static string OneTime {
get {
return ResourceManager.GetString("OneTime", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Password. /// Looks up a localized string similar to Password.
/// </summary> /// </summary>
@@ -480,24 +192,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Perception.
/// </summary>
public static string Perception {
get {
return ResourceManager.GetString("Perception", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Perceptions.
/// </summary>
public static string Perceptions {
get {
return ResourceManager.GetString("Perceptions", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Prefer system theme. /// Looks up a localized string similar to Prefer system theme.
/// </summary> /// </summary>
@@ -516,96 +210,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Recurring.
/// </summary>
public static string Recurring {
get {
return ResourceManager.GetString("Recurring", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Scan for:.
/// </summary>
public static string Scan_for_ {
get {
return ResourceManager.GetString("Scan for:", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
public static string SearchText {
get {
return ResourceManager.GetString("SearchText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sharing Secret Code.
/// </summary>
public static string ShareCode {
get {
return ResourceManager.GetString("ShareCode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show donator badge.
/// </summary>
public static string ShowDonatorBadge {
get {
return ResourceManager.GetString("ShowDonatorBadge", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show the logs tab to support troubleshooting..
/// </summary>
public static string ShowLogs {
get {
return ResourceManager.GetString("ShowLogs", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Take type.
/// </summary>
public static string TakeType {
get {
return ResourceManager.GetString("TakeType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Simple.
/// </summary>
public static string TakeTypeSimple {
get {
return ResourceManager.GetString("TakeTypeSimple", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Structured.
/// </summary>
public static string TakeTypeStructured {
get {
return ResourceManager.GetString("TakeTypeStructured", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Theme image.
/// </summary>
public static string Theme_image {
get {
return ResourceManager.GetString("Theme image", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Dark mode. /// Looks up a localized string similar to Dark mode.
/// </summary> /// </summary>
@@ -615,15 +219,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Ticks.
/// </summary>
public static string Ticks {
get {
return ResourceManager.GetString("Ticks", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Title. /// Looks up a localized string similar to Title.
/// </summary> /// </summary>
@@ -633,24 +228,6 @@ namespace PrivaPub.ClientModels.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Update reason.
/// </summary>
public static string UpdateReason {
get {
return ResourceManager.GetString("UpdateReason", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Submit anonymously.
/// </summary>
public static string UpsertUserTakeIsAnonymous {
get {
return ResourceManager.GetString("UpsertUserTakeIsAnonymous", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Username. /// Looks up a localized string similar to Username.
/// </summary> /// </summary>
@@ -659,23 +236,5 @@ namespace PrivaPub.ClientModels.Resources {
return ResourceManager.GetString("Username", resourceCulture); return ResourceManager.GetString("Username", resourceCulture);
} }
} }
/// <summary>
/// Looks up a localized string similar to Username to search and add.
/// </summary>
public static string Username_to_search_and_add {
get {
return ResourceManager.GetString("Username to search and add", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Usernames to search and add.
/// </summary>
public static string Usernames_to_search_and_add {
get {
return ResourceManager.GetString("Usernames to search and add", resourceCulture);
}
}
} }
} }
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(необходимо в случай на възстановяване на парола)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;предложен мениджър на пароли&lt;/a&gt;)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Сума</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Отговор id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Текст на отговора</value>
</data>
<data name="Character" xml:space="preserve">
<value>Персонализиран символ (емотикон)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Цвят</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Коментар id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Текст на коментара</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Конфронтация</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Конфронтация id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Контекст</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Крайна дата</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Начална дата</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Описание</value> <value>Описание</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Дискусия</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Крайна дата</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Краен час</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Дискусия id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Текст за обсъждане</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Заглавие на дискусията</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Имейл</value> <value>Имейл</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Емотикони</value> <value>Емотикони</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Максимален брой конфронтации</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Факт</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Факти</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Идентификатор на файла</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Групи</value> <value>Групи</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Да включите първия отговор в предварителния преглед на поканата? (за да се включите в дискусията по-ангажиращо)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Код на поканата</value> <value>Код на поканата</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Код или връзка за покана</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Парола за покана</value> <value>Парола за покана</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Изискване на парола за предварителен преглед</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Изискване на парола за показване на предварителния преглед</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Добавяне на защита с парола</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Идентификатор на езика</value> <value>Идентификатор на езика</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Име</value> <value>Име</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Активиране на известията?(полезно за получаване на актуализации на приложението)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Нова парола</value> <value>Нова парола</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Стара парола</value> <value>Стара парола</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Само веднъж</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Парола</value> <value>Парола</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Възприемане</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Възприятия</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Предпочитайте темата на системата</value> <value>Предпочитайте темата на системата</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Код за възстановяване</value> <value>Код за възстановяване</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Повтарящи се</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Сканиране за:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Търсене</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Споделяне на тайния код</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Покажи значката на дарителя</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Покажете раздела с дневници, за да подпомогнете отстраняването на неизправности.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Вид на вземането</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Прост</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Структуриран</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Изображение на темата</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Тъмен режим</value> <value>Тъмен режим</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Кърлежи</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Заглавие</value> <value>Заглавие</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Причина за актуализиране</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Подайте анонимно</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Потребителско име</value> <value>Потребителско име</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Потребителско име за търсене и добавяне</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Потребителски имена за търсене и добавяне</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nutné v případě obnovení hesla)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;správce hesel&lt;/a&gt; navrženo)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Částka</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Odpověď id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Text odpovědi</value>
</data>
<data name="Character" xml:space="preserve">
<value>Vlastní znak(emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Barva</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Komentář id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Text komentáře</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontace</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id konfrontace</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontext</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Datum ukončení</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Datum zahájení</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Popis</value> <value>Popis</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskuse</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Datum ukončení</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Čas ukončení</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskuze id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Text k diskusi</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Název diskuse</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maximální počet konfrontací</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Identifikátor souboru</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Skupiny</value> <value>Skupiny</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Zahrnout první odpověď do náhledu pozvánky? (abyste se mohli zapojit do diskuse)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kód pozvánky</value> <value>Kód pozvánky</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Pozvánkový kód nebo odkaz</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Heslo pozvánky</value> <value>Heslo pozvánky</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Vyžadovat heslo pro náhled</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Vyžadování hesla pro zobrazení náhledu</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Přidání ochrany heslem</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Identifikace jazyka</value> <value>Identifikace jazyka</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Název</value> <value>Název</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Povolit oznámení?(užitečné pro příjem aktualizací aplikace)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nové heslo</value> <value>Nové heslo</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Staré heslo</value> <value>Staré heslo</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Pouze jednou</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Heslo</value> <value>Heslo</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Vnímání</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Vnímání</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Preferovat systémové téma</value> <value>Preferovat systémové téma</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Kód obnovy</value> <value>Kód obnovy</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Opakující se</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Vyhledat:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Vyhledávání</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Sdílení tajného kódu</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Zobrazit odznak dárce</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Zobrazit kartu protokolů pro podporu řešení problémů.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Vezměte si typ</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Jednoduché</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturovaný</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Tématický obrázek</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tmavý režim</value> <value>Tmavý režim</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Klíšťata</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Název</value> <value>Název</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Důvod aktualizace</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Anonymní odeslání</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Uživatelské jméno</value> <value>Uživatelské jméno</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Uživatelské jméno pro vyhledávání a přidávání</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Uživatelská jména pro vyhledávání a přidávání</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nødvendig i tilfælde af inddrivelse af adgangskode)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;password manager&lt;/a&gt; foreslået)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Beløb</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Svar id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Svar tekst</value>
</data>
<data name="Character" xml:space="preserve">
<value>Brugerdefineret tegn (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Farve</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Kommentar id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Kommentar tekst</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontation</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontation id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontekst</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Slutdato</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Startdato</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Beskrivelse</value> <value>Beskrivelse</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskussion</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Slutdato</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Sluttidspunkt</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskussion id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Tekst til drøftelse</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Diskussionstitel</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maksimalt antal konfrontationer</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Fil id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupper</value> <value>Grupper</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Medtage det første svar i forhåndsvisningen af invitationen? (gør det mere indbydende at deltage i diskussionen)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kode for indbydelse</value> <value>Kode for indbydelse</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Indbydelseskode eller link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Adgangskode til invitationen</value> <value>Adgangskode til invitationen</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Kræver adgangskode til visning af preview</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Kræver adgangskode for at vise forhåndsvisningen</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Tilføj adgangskodebeskyttelse</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Sprog-id</value> <value>Sprog-id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Navn</value> <value>Navn</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Aktiver notifikationer? (nyttigt for at modtage opdateringer til appen)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Ny adgangskode</value> <value>Ny adgangskode</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Gammel adgangskode</value> <value>Gammel adgangskode</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Kun én gang</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Adgangskode</value> <value>Adgangskode</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Opfattelse</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Opfattelser</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Foretrækker systemtema</value> <value>Foretrækker systemtema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Kode for inddrivelse</value> <value>Kode for inddrivelse</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Tilbagevendende</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scan efter:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Søg på</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Deling af den hemmelige kode</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Vis donator-badge</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Vis fanen Logfiler for at støtte fejlfinding.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Tag type</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Enkel</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Struktureret</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Temabillede</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Mørk tilstand</value> <value>Mørk tilstand</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Flåter</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Årsag til opdatering</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Indsend anonymt</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Brugernavn</value> <value>Brugernavn</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Brugernavn til at søge og tilføje</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Brugernavne til at søge og tilføje</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(notwendig für die Wiederherstellung des Passworts)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;Passwortmanager&lt;/a&gt; vorgeschlagen)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Betrag</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Antwort id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Antwort-Text</value>
</data>
<data name="Character" xml:space="preserve">
<value>Benutzerdefiniertes Zeichen (Emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Farbe</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Kommentar</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Text kommentieren</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontation</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontation id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontext</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Datum des Endes</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Datum des Beginns</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Beschreibung</value> <value>Beschreibung</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskussion</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Datum des Endes</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Endzeit</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskussion id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Text zur Diskussion</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titel der Diskussion</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-Mail</value> <value>E-Mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maximale Anzahl von Konfrontationen</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Tatsache</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakten</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Datei-ID</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Gruppen</value> <value>Gruppen</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Die erste Antwort in die Vorschau der Einladung aufnehmen? (um den Anreiz zur Teilnahme an der Diskussion zu erhöhen)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Einladungs-Code</value> <value>Einladungs-Code</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Einladungscode oder Link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Passwort für die Einladung</value> <value>Passwort für die Einladung</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Passwort für Vorschau erforderlich</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Passwort erforderlich, um die Vorschau anzuzeigen</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Passwortschutz hinzufügen</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Sprache id</value> <value>Sprache id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Name</value> <value>Name</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Benachrichtigungen aktivieren?(nützlich, um App-Updates zu erhalten)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Neues Passwort</value> <value>Neues Passwort</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Altes Passwort</value> <value>Altes Passwort</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Nur einmalig</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Passwort</value> <value>Passwort</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Wahrnehmung</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Wahrnehmungen</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Systemthema bevorzugen</value> <value>Systemthema bevorzugen</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Wiederherstellungscode</value> <value>Wiederherstellungscode</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Wiederkehrende</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scannen Sie nach:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Suche</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Gemeinsamer Geheimcode</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Spenderausweis anzeigen</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Zeigen Sie die Registerkarte Protokolle an, um die Fehlersuche zu unterstützen.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Typ nehmen</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Einfach</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturiert</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Thema Bild</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Dunkler Modus</value> <value>Dunkler Modus</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Zecken</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Grund für die Aktualisierung</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Anonym einreichen</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Benutzername</value> <value>Benutzername</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Benutzername zum Suchen und Hinzufügen</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Nutzernamen zum Suchen und Hinzufügen</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(απαραίτητο σε περίπτωση ανάκτησης κωδικού πρόσβασης)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;διαχειριστής κωδικών πρόσβασης&lt;/a&gt; προτείνεται)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Ποσό</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Απάντηση id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Κείμενο απάντησης</value>
</data>
<data name="Character" xml:space="preserve">
<value>Προσαρμοσμένος χαρακτήρας (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Χρώμα</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Σχόλιο id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Κείμενο σχολιασμού</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Αντιπαράθεση</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>id αντιπαράθεσης</value>
</data>
<data name="Context" xml:space="preserve">
<value>Πλαίσιο</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Ημερομηνία λήξης</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Ημερομηνία έναρξης</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Περιγραφή</value> <value>Περιγραφή</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Συζήτηση</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Ημερομηνία λήξης</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Ώρα λήξης</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Συζήτηση id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Κείμενο συζήτησης</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Τίτλος συζήτησης</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Ηλεκτρονικό ταχυδρομείο</value> <value>Ηλεκτρονικό ταχυδρομείο</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Μέγιστος αριθμός αντιπαραθέσεων</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Γεγονός</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Γεγονότα</value>
</data>
<data name="FileId" xml:space="preserve">
<value>id αρχείου</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Ομάδες</value> <value>Ομάδες</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Να συμπεριλάβετε την πρώτη απάντηση στην προεπισκόπηση της πρόσκλησης; (καθιστώντας την πιο ελκυστική για να συμμετάσχετε στη συζήτηση)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Κωδικός πρόσκλησης</value> <value>Κωδικός πρόσκλησης</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Κωδικός πρόσκλησης ή σύνδεσμος</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Κωδικός πρόσκλησης</value> <value>Κωδικός πρόσκλησης</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Απαίτηση κωδικού πρόσβασης για προεπισκόπηση</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Απαιτείται κωδικός πρόσβασης για την εμφάνιση της προεπισκόπησης</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Προσθήκη προστασίας με κωδικό πρόσβασης</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Id γλώσσας</value> <value>Id γλώσσας</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Όνομα</value> <value>Όνομα</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Ενεργοποίηση ειδοποιήσεων; (χρήσιμο για να λαμβάνετε ενημερώσεις εφαρμογών)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Νέος κωδικός πρόσβασης</value> <value>Νέος κωδικός πρόσβασης</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Παλαιός κωδικός πρόσβασης</value> <value>Παλαιός κωδικός πρόσβασης</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Μόνο μία φορά</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Κωδικός πρόσβασης</value> <value>Κωδικός πρόσβασης</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Αντίληψη</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Αντιλήψεις</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Προτιμήστε το θέμα του συστήματος</value> <value>Προτιμήστε το θέμα του συστήματος</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Κωδικός ανάκτησης</value> <value>Κωδικός ανάκτησης</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Επαναλαμβανόμενο</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Σάρωση για:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Αναζήτηση</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Κοινή χρήση μυστικού κώδικα</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Εμφάνιση σήματος δωρητή</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Εμφάνιση της καρτέλας αρχείων καταγραφής για την υποστήριξη της αντιμετώπισης προβλημάτων.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Πάρτε τον τύπο</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Απλό</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Δομημένο</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Εικόνα θέματος</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Σκοτεινή λειτουργία</value> <value>Σκοτεινή λειτουργία</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Κρότωνες</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Τίτλος</value> <value>Τίτλος</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Αιτία ενημέρωσης</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Υποβάλετε ανώνυμα</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Όνομα χρήστη</value> <value>Όνομα χρήστη</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Όνομα χρήστη για αναζήτηση και προσθήκη</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Ονόματα χρηστών για αναζήτηση και προσθήκη</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(necesario en caso de recuperación de la contraseña)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;gestor de contraseñas&lt;/a&gt; sugerido)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Importe</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Respuesta</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Texto de respuesta</value>
</data>
<data name="Character" xml:space="preserve">
<value>Carácter personalizado (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Color</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Comentario id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Texto de los comentarios</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confrontación</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Identificación de la confrontación</value>
</data>
<data name="Context" xml:space="preserve">
<value>Contexto</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Fecha de finalización</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Fecha de inicio</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Descripción</value> <value>Descripción</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discusión</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Fecha de finalización</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Hora de finalización</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Discusión</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Texto de debate</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Título del debate</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Envíe un correo electrónico a</value> <value>Envíe un correo electrónico a</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Máxima cantidad de enfrentamientos</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Datos</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Hechos</value>
</data>
<data name="FileId" xml:space="preserve">
<value>ID de archivo</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupos</value> <value>Grupos</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>¿Incluir la primera respuesta en la vista previa de la invitación? (para que sea más atractivo participar en el debate)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Código de invitación</value> <value>Código de invitación</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Código o enlace de invitación</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Contraseña de la invitación</value> <value>Contraseña de la invitación</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Requerir contraseña para la vista previa</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Requiere contraseña para mostrar la vista previa</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Añadir protección por contraseña</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Id. de idioma</value> <value>Id. de idioma</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nombre</value> <value>Nombre</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Activar las notificaciones (útiles para recibir las actualizaciones de la aplicación)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nueva contraseña</value> <value>Nueva contraseña</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Contraseña antigua</value> <value>Contraseña antigua</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Una sola vez</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Contraseña</value> <value>Contraseña</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Percepción</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Percepciones</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Prefiero el tema del sistema</value> <value>Prefiero el tema del sistema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Código de recuperación</value> <value>Código de recuperación</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Recurrente</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Busca:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Buscar en</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Compartir el código secreto</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Mostrar el distintivo de donante</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Mostrar la pestaña de registros para apoyar la resolución de problemas.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Toma de tipo</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Simple</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Estructurado</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Imagen del tema</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Modo oscuro</value> <value>Modo oscuro</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Garrapatas</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Título</value> <value>Título</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Motivo de actualización</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Presentar de forma anónima</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Nombre de usuario</value> <value>Nombre de usuario</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Nombre de usuario para buscar y añadir</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Nombres de usuario para buscar y añadir</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(vajalik parooli taastamise korral)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;Password manager&lt;/a&gt; soovitatav)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Summa</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Vastus id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Vastuse tekst</value>
</data>
<data name="Character" xml:space="preserve">
<value>Kohandatud märk (emotikoni)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Värv</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Kommentaar id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Kommentaaride tekst</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Vastasseis</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Vastasseisu id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontekst</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Lõppkuupäev</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Alguskuupäev</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Kirjeldus</value> <value>Kirjeldus</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Arutelu</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Lõppkuupäev</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Lõpuaeg</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Arutelu id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Arutelu tekst</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Arutelu pealkiri</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-post</value> <value>E-post</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Vastasseisude maksimaalne arv</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakt</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Faktid</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Faili id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Rühmad</value> <value>Rühmad</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Lisage esimene vastus kutse eelvaates? (muudab aruteluga liitumise atraktiivsemaks)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kutse kood</value> <value>Kutse kood</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Kutse kood või link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Kutse parool</value> <value>Kutse parool</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Nõuab eelvaate jaoks parooli</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Eelvaate kuvamiseks nõutakse parooli</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Lisage paroolikaitse</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Keele id</value> <value>Keele id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nimi</value> <value>Nimi</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Teavituste lubamine?(kasulik, et saada rakenduse uuendusi)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Uus parool</value> <value>Uus parool</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Vana parool</value> <value>Vana parool</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Ainult üks kord</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Parool</value> <value>Parool</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Tajumine</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Arvamused</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Eelistage süsteemi teemat</value> <value>Eelistage süsteemi teemat</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Taastamiskood</value> <value>Taastamiskood</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Korduvad</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Skaneeri:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Otsi</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Salajase koodi jagamine</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Näita doonori märki</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Näidake veaotsingu toetamiseks logide vahekaarti.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Võtke tüüp</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Lihtne</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Struktureeritud</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Teema pilt</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tume režiim</value> <value>Tume režiim</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Puugid</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Pealkiri</value> <value>Pealkiri</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Uuendamise põhjus</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Esitage anonüümselt</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Kasutajanimi</value> <value>Kasutajanimi</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Kasutajanimi otsimiseks ja lisamiseks</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Kasutajanimed otsimiseks ja lisamiseks</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(tarvitaan salasanan palautuksen yhteydessä)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;salasananhallinta&lt;/a&gt; ehdotettu)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Määrä</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Vastaa id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Vastaus teksti</value>
</data>
<data name="Character" xml:space="preserve">
<value>Mukautettu merkki (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Väri</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Kommentti id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Kommenttiteksti</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Vastakkainasettelu</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Vastakkainasettelu id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Konteksti</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Loppupäivä</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Aloituspäivä</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Kuvaus</value> <value>Kuvaus</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Keskustelu</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Loppupäivä</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Loppuaika</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Keskustelu id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Keskusteluteksti</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Keskustelun otsikko</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Sähköposti</value> <value>Sähköposti</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Vastakkainasettelujen enimmäismäärä</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Faktat</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Tiedoston id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Ryhmät</value> <value>Ryhmät</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Sisällytä ensimmäinen vastaus kutsun esikatseluun? (mikä tekee keskusteluun osallistumisesta houkuttelevampaa)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kutsun koodi</value> <value>Kutsun koodi</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Kutsukoodi tai linkki</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Kutsun salasana</value> <value>Kutsun salasana</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Vaadi salasana esikatselua varten</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Vaadi salasana esikatselun näyttämiseksi</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Lisää salasanasuojaus</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Kielitunnus</value> <value>Kielitunnus</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nimi</value> <value>Nimi</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Ota ilmoitukset käyttöön?(hyödyllinen sovelluksen päivitysten saamiseksi)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Uusi salasana</value> <value>Uusi salasana</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Vanha salasana</value> <value>Vanha salasana</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Vain kerran</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Salasana</value> <value>Salasana</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Havainto</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Käsitykset</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Suositeltava järjestelmäteema</value> <value>Suositeltava järjestelmäteema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Palautuskoodi</value> <value>Palautuskoodi</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Toistuvat</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Etsi:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Etsi</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Salaisen koodin jakaminen</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Näytä lahjoittajan merkki</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Näytä lokit-välilehti vianmäärityksen tueksi.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Ota tyyppi</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Yksinkertainen</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturoitu</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Aiheen kuva</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tumma tila</value> <value>Tumma tila</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Punkit</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Otsikko</value> <value>Otsikko</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Päivityksen syy</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Lähetä nimettömänä</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Käyttäjätunnus</value> <value>Käyttäjätunnus</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Käyttäjätunnus hakuun ja lisäämiseen</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Käyttäjätunnukset, joita voit etsiä ja lisätä</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nécessaire en cas de récupération du mot de passe)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;gestionnaire de mots de passe&lt;/a&gt; suggéré)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Montant</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Réponse id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Texte de réponse</value>
</data>
<data name="Character" xml:space="preserve">
<value>Caractère personnalisé (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Couleur</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Commentaire</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Texte du commentaire</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confrontation</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Confrontation id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Contexte</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Date de fin</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Date de début</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Description</value> <value>Description</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discussion</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Date de fin</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Heure de fin</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>ID de discussion</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Texte de discussion</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titre de la discussion</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Courriel</value> <value>Courriel</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Nombre maximal de confrontations</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fait</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Faits et chiffres</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Identifiant du fichier</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Groupes</value> <value>Groupes</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Inclure la première réponse dans l'aperçu de l'invitation ? (ce qui rend plus attrayant le fait de rejoindre la discussion)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Code d'invitation</value> <value>Code d'invitation</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Code ou lien d'invitation</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Mot de passe de l'invitation</value> <value>Mot de passe de l'invitation</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Exiger un mot de passe pour la prévisualisation</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Exiger un mot de passe pour afficher l'aperçu</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Ajouter une protection par mot de passe</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>EstStructuré</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Identifiant de langue</value> <value>Identifiant de langue</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nom</value> <value>Nom</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Activer les notifications ? (utile pour recevoir les mises à jour de l'application)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nouveau mot de passe</value> <value>Nouveau mot de passe</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Ancien mot de passe</value> <value>Ancien mot de passe</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>En une seule fois</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Mot de passe</value> <value>Mot de passe</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Perception</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Perceptions</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Préférer le thème du système</value> <value>Préférer le thème du système</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Code de récupération</value> <value>Code de récupération</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Récurrent</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scanner pour :</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Recherche</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Partage du code secret</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Afficher le badge de donateur</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Affichez l'onglet des journaux pour faciliter le dépannage.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Type de prise</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Simple</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Structuré</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Image du thème</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Mode foncé</value> <value>Mode foncé</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Tiques</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titre</value> <value>Titre</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Raison de la mise à jour</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Soumettre anonymement</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Nom d'utilisateur</value> <value>Nom d'utilisateur</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Nom d'utilisateur pour rechercher et ajouter</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Noms d'utilisateur à rechercher et à ajouter</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(jelszó helyreállítása esetén szükséges)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;jelszókezelő&lt;/a&gt; javasolt)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Összeg</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Válasz id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Válasz szöveg</value>
</data>
<data name="Character" xml:space="preserve">
<value>Egyéni karakter (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Színes</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Megjegyzés id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Megjegyzés szövege</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontáció</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontációs azonosító</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontextus</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Végdátum</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Kezdeti időpont</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Leírás</value> <value>Leírás</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Megbeszélés</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Végdátum</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Végidő</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Megbeszélés id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Megbeszélés szövege</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Vita címe</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>A konfrontációk maximális száma</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Tény</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Tények</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Fájl azonosító</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Csoportok</value> <value>Csoportok</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Az első válasz szerepeljen a meghívó előnézetében? (így vonzóbbá teszi a vitához való csatlakozást)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Meghívó kód</value> <value>Meghívó kód</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Meghívó kód vagy link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Meghívó jelszó</value> <value>Meghívó jelszó</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Jelszó megkövetelése az előnézethez</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Jelszó megkövetelése az előnézet megjelenítéséhez</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Jelszóvédelem hozzáadása</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Nyelvi azonosító</value> <value>Nyelvi azonosító</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Név</value> <value>Név</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Értesítések engedélyezése?(hasznos az alkalmazás frissítéseinek fogadásához)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Új jelszó</value> <value>Új jelszó</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Régi jelszó</value> <value>Régi jelszó</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Csak egyszeri alkalom</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Jelszó</value> <value>Jelszó</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Percepció</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Perceptions</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>A rendszer témájának előnyben részesítése</value> <value>A rendszer témájának előnyben részesítése</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Helyreállítási kód</value> <value>Helyreállítási kód</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Visszatérő</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Keresés:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Keresés</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Titkos kód megosztása</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Adományozói jelvény megjelenítése</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>A naplók lap megjelenítése a hibaelhárítás támogatására.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Vegye a típust</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Egyszerű</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturált</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Témakép</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Sötét üzemmód</value> <value>Sötét üzemmód</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Kullancsok</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Cím</value> <value>Cím</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Frissítés oka</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Névtelenül beküldeni</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Felhasználónév</value> <value>Felhasználónév</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Felhasználónév kereséshez és hozzáadáshoz</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Felhasználónevek keresése és hozzáadása</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(necessaria in caso di recupero password)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(è suggerito l'uso del &lt;a class="is-underlined has-text-info" tabindex="-1" target="_blank" href="https://keepassxc.org/"&gt;gestore password&lt;/a&gt;)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Importo</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>ID risposta</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Testo risposta</value>
</data>
<data name="Character" xml:space="preserve">
<value>Carattere personalizzato (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Colore</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>ID commento</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Testo commento</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confronto</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id confronto</value>
</data>
<data name="Context" xml:space="preserve">
<value>Contesto</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Data di fine</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Data di inizio</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Descrizione</value> <value>Descrizione</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discussione</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Data di fine</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Tempo di fine</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>ID discussione</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Testo discussione</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titolo discussione</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Email</value> <value>Email</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Quantità massima di scontri</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fatto</value>
</data>
<data name="Facts" xml:space="preserve">
<value>I fatti</value>
</data>
<data name="FileId" xml:space="preserve">
<value>ID file</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Gruppi</value> <value>Gruppi</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Includere la prima risposta nell'anteprima dell'invito? (rendendo più coinvolgente l'adesione alla discussione)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Codice d'invito</value> <value>Codice d'invito</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Collegamento o codice di invito</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Password dell'invito</value> <value>Password dell'invito</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Richiedi la password per l'anteprima</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Richiedi la password per l'anteprima della discussione</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Aggiungere la protezione con password</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>È strutturato</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>ID lingua</value> <value>ID lingua</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nome</value> <value>Nome</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Abilitare le notifiche?(utili per percepire aggiornamenti)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nuova password</value> <value>Nuova password</value>
</data> </data>
@@ -243,78 +150,24 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Attuale password</value> <value>Attuale password</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Paga una volta</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Password</value> <value>Password</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>La percezione</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Percezioni</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Preferire il tema di sistema</value> <value>Preferire il tema di sistema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Codice di recupero</value> <value>Codice di recupero</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Ricorrente</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scansione per:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Ricerca</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Condivisione del codice segreto</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Mostra il badge del donatore</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Mostra il tab dei log a supporto della risoluzione dei problemi.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Prendi il tipo</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Semplice</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strutturato</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Immagine a tema</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Modalità scura</value> <value>Modalità scura</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Zecche</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titolo</value> <value>Titolo</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Motivo dell'aggiornamento</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Invia in forma anonima</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Soprannome</value> <value>Soprannome</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Soprannome da ricercare e aggiungere</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Soprannomi da ricercare e aggiungere</value>
</data>
<data name="AvatarId" xml:space="preserve"> <data name="AvatarId" xml:space="preserve">
<value>Avatar</value> <value>Avatar</value>
</data> </data>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(パスワード復旧時に必要)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;パスワードマネージャー&lt;/a&gt;の提案)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>金額</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>回答ID</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>回答テキスト</value>
</data>
<data name="Character" xml:space="preserve">
<value>カスタムキャラクター(絵文字)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>カラー</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>コメントID</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>コメント文</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>対決</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>コンフロンティアID</value>
</data>
<data name="Context" xml:space="preserve">
<value>コンテキスト</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>終了日</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>開始日</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>商品説明</value> <value>商品説明</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>ディスカッション</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>終了日</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>終了時間</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>ディスカッションID</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>ディスカッションテキスト</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>議論のタイトル</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>電子メール</value> <value>電子メール</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>絵文字</value> <value>絵文字</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>対決の最大量</value>
</data>
<data name="Fact" xml:space="preserve">
<value>事実</value>
</data>
<data name="Facts" xml:space="preserve">
<value>事実</value>
</data>
<data name="FileId" xml:space="preserve">
<value>ファイルID</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>グループ</value> <value>グループ</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>招待状のプレビューに最初の回答を含める?(議論への参加をより魅力的にするために)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>招待状コード</value> <value>招待状コード</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>招待コードまたはリンク</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>招待状のパスワード</value> <value>招待状のパスワード</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>プレビューにパスワードが必要</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>プレビューを表示するにはパスワードが必要です</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>パスワード保護機能の追加</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>言語ID</value> <value>言語ID</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>名前</value> <value>名前</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>通知を有効にしますか?(アプリの更新情報を受け取るのに便利です)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>新しいパスワード</value> <value>新しいパスワード</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>古いパスワード</value> <value>古いパスワード</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>1回限り</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>パスワード</value> <value>パスワード</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>パーセプション</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>認知度</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>システムテーマを優先する</value> <value>システムテーマを優先する</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>リカバリーコード</value> <value>リカバリーコード</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>リカーリング</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>スキャンしてください:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>検索</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>秘密の暗号を共有する</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>寄付者バッジを表示する</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>トラブルシューティングをサポートするために、ログタブを表示します。</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>テイクタイプ</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>シンプル</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>構造化</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>テーマイメージ</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>ダークモード</value> <value>ダークモード</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>ダニ</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>タイトル</value> <value>タイトル</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>更新理由</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>匿名で投稿する</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>ユーザー名</value> <value>ユーザー名</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>検索して追加するユーザー名</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>検索して追加するユーザー名</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(būtina slaptažodžio atkūrimo atveju)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;paslapčių tvarkyklė&lt;/a&gt; siūloma)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Suma</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Atsakymas id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Atsakymo tekstas</value>
</data>
<data name="Character" xml:space="preserve">
<value>Pasirinktinis simbolis (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Spalva</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Komentaras id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Komentaro tekstas</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontacija</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontacijos id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontekstas</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Galutinė data</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Pradžios data</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Aprašymas</value> <value>Aprašymas</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskusija</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Galutinė data</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Pabaigos laikas</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskusijos id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Diskusijos tekstas</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Diskusijos pavadinimas</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>El. paštas</value> <value>El. paštas</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Didžiausias konfrontacijų skaičius</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Faktas</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Faktai</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Failo ID</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupės</value> <value>Grupės</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Įtraukti pirmąjį atsakymą į kvietimo peržiūrą? (kad būtų patraukliau prisijungti prie diskusijos)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kvietimo kodas</value> <value>Kvietimo kodas</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Kvietimo kodas arba nuoroda</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Kvietimo slaptažodis</value> <value>Kvietimo slaptažodis</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Reikalauti slaptažodžio peržiūrai</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Reikalauti slaptažodžio, kad būtų rodoma peržiūra</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Pridėti apsaugą slaptažodžiu</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Kalbos ID</value> <value>Kalbos ID</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Pavadinimas</value> <value>Pavadinimas</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Įjungti pranešimus? (naudinga norint gauti programėlės atnaujinimus)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Naujas slaptažodis</value> <value>Naujas slaptažodis</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Senasis slaptažodis</value> <value>Senasis slaptažodis</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Tik vieną kartą</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Slaptažodis</value> <value>Slaptažodis</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Suvokimas</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Suvokimas</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Pirmenybė sistemos temai</value> <value>Pirmenybė sistemos temai</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Atkūrimo kodas</value> <value>Atkūrimo kodas</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Pasikartojantis</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Ieškoti:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Paieška</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Dalijimasis slaptuoju kodu</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Rodyti rėmėjo ženklelį</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Parodykite skirtuką "Žurnalai", kad galėtumėte padėti šalinti trikdžius.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Paimkite tipą</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Paprastas</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Struktūrinis</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Temos vaizdas</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tamsus režimas</value> <value>Tamsus režimas</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Erkės</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Pavadinimas</value> <value>Pavadinimas</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Atnaujinimo priežastis</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Pateikti anonimiškai</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Vartotojo vardas</value> <value>Vartotojo vardas</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Vartotojo vardas paieškai ir pridėjimui</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Vartotojų vardų paieška ir pridėjimas</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nepieciešams paroles atjaunošanas gadījumā)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;vārdu pārvaldnieks&lt;/a&gt; ierosināts)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Summa</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Atbilde id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Atbildes teksts</value>
</data>
<data name="Character" xml:space="preserve">
<value>Pielāgots raksturs (emodži)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Krāsa</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Komentārs id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Komentāru teksts</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontācija</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontācijas id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Konteksts</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Beigu datums</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Sākuma datums</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Apraksts</value> <value>Apraksts</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskusija</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Beigu datums</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Beigu laiks</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskusijas id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Diskusijas teksts</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Diskusijas nosaukums</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-pasts</value> <value>E-pasts</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emocijas</value> <value>Emocijas</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maksimālais konfrontāciju skaits</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakti</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakti</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Faila id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupas</value> <value>Grupas</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Iekļaut pirmo atbildi uzaicinājuma priekšskatījumā? (lai iesaistīšanās diskusijā būtu saistošāka)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Uzaicinājuma kods</value> <value>Uzaicinājuma kods</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Uzaicinājuma kods vai saite</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Uzaicinājuma parole</value> <value>Uzaicinājuma parole</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Pieprasīt paroli priekšskatīšanai</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Pieprasīt paroli, lai parādītu priekšskatījumu</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Pievienojiet paroles aizsardzību</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Valodas identifikators</value> <value>Valodas identifikators</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nosaukums</value> <value>Nosaukums</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Ieslēgt paziņojumus?(noderīgi, lai saņemtu lietotnes atjauninājumus)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Jauna parole</value> <value>Jauna parole</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Vecā parole</value> <value>Vecā parole</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Tikai vienu reizi</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Parole</value> <value>Parole</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Uztvere</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Uzskati</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Dodiet priekšroku sistēmas tēmai</value> <value>Dodiet priekšroku sistēmas tēmai</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Atgūšanas kods</value> <value>Atgūšanas kods</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Atkārtoti</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Skenēt, lai atrastu:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Meklēšana</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Koplietošanas slepenais kods</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Rādīt ziedotāja nozīmīti</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Parādiet cilni žurnāli, lai atbalstītu problēmu novēršanu.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Veikt veidu</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Vienkāršs</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturēts</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Tēmas attēls</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tumšais režīms</value> <value>Tumšais režīms</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Ērces</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Nosaukums</value> <value>Nosaukums</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Atjaunināšanas iemesls</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Iesniedziet anonīmi</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Lietotājvārds</value> <value>Lietotājvārds</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Lietotājvārds, lai meklētu un pievienotu</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Meklēšanas un pievienošanas lietotājvārdi</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nodig in geval van wachtwoordherstel)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;wachtwoord manager&lt;/a&gt; voorgesteld)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Bedrag</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Antwoord id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Antwoord tekst</value>
</data>
<data name="Character" xml:space="preserve">
<value>Aangepast karakter (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Kleur</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Commentaar id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Commentaar tekst</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confrontatie</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Confrontatie id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Context</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Einddatum</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Startdatum</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Beschrijving</value> <value>Beschrijving</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discussie</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Einddatum</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Eindtijd</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Discussie id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Besprekingstekst</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titel van de discussie</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maximum aantal confrontaties</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Feit</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Feiten</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Bestand id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Groepen</value> <value>Groepen</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Het eerste antwoord opnemen in de preview van de uitnodiging? (maakt het aantrekkelijker om deel te nemen aan de discussie)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Uitnodiging code</value> <value>Uitnodiging code</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Uitnodigingscode of link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Uitnodiging wachtwoord</value> <value>Uitnodiging wachtwoord</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Wachtwoord nodig voor preview</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Wachtwoord vereist om de preview te tonen</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Wachtwoordbeveiliging toevoegen</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Taal id</value> <value>Taal id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Naam</value> <value>Naam</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Meldingen inschakelen?(handig om app updates te ontvangen)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nieuw wachtwoord</value> <value>Nieuw wachtwoord</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Oud wachtwoord</value> <value>Oud wachtwoord</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Eenmalig</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Wachtwoord</value> <value>Wachtwoord</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Perceptie</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Percepties</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Voorkeur systeemthema</value> <value>Voorkeur systeemthema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Herstelcode</value> <value>Herstelcode</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Terugkerend</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scan voor:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Zoeken op</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Het delen van de geheime code</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Toon donateur badge</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Toon de logs tab ter ondersteuning van troubleshooting.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Neem type</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Eenvoudig</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Gestructureerd</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Thema-afbeelding</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Donkere modus</value> <value>Donkere modus</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Teken</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Update reden</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Anoniem indienen</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Gebruikersnaam</value> <value>Gebruikersnaam</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Gebruikersnaam om te zoeken en toe te voegen</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Gebruikersnamen om te zoeken en toe te voegen</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(konieczne w przypadku odzyskiwania hasła)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;password manager&lt;/a&gt; sugerowane)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Kwota</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Odpowiedź</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Odpowiedź</value>
</data>
<data name="Character" xml:space="preserve">
<value>Znak niestandardowy (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Kolor</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Komentarz id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Tekst komentarza</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontacja</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontacja id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontekst</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Data końcowa</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Data rozpoczęcia</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Opis</value> <value>Opis</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Dyskusja</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Data końcowa</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Czas zakończenia</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Dyskusja id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Tekst do dyskusji</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Tytuł dyskusji</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maksymalna ilość konfrontacji</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakt</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakty</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Id pliku</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupy</value> <value>Grupy</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Zamieścić pierwszą odpowiedź w podglądzie zaproszenia? (sprawia, że dołączenie do dyskusji jest bardziej zachęcające)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kod zaproszenia</value> <value>Kod zaproszenia</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Kod lub link do zaproszenia</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Hasło do zaproszenia</value> <value>Hasło do zaproszenia</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Wymagaj hasła do podglądu</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Wymagaj hasła, aby wyświetlić podgląd</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Dodaj ochronę hasłem</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Język id</value> <value>Język id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nazwa</value> <value>Nazwa</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Włączyć powiadomienia? (przydatne do otrzymywania aktualizacji aplikacji)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nowe hasło</value> <value>Nowe hasło</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Stare hasło</value> <value>Stare hasło</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Tylko jeden raz</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Hasło</value> <value>Hasło</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Percepcja</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Spostrzeżenia</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Preferowany motyw systemowy</value> <value>Preferowany motyw systemowy</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Kod odzyskiwania</value> <value>Kod odzyskiwania</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Powtarzające się</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Skanuj dla:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Szukaj</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Dzielenie się tajnym kodem</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Pokaż odznakę darczyńcy</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Pokaż kartę logów, aby ułatwić rozwiązywanie problemów.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Rodzaj ujęcia</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Proste</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturalne</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Obrazek tematyczny</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tryb ciemny</value> <value>Tryb ciemny</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Kleszcze</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Tytuł</value> <value>Tytuł</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Powód aktualizacji</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Zgłoś się anonimowo</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Nazwa użytkownika</value> <value>Nazwa użytkownika</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Nazwa użytkownika do wyszukiwania i dodawania</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Nazwy użytkowników do wyszukiwania i dodawania</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(necessário em caso de recuperação de senha)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;gerenciador de palavras-passe&lt;/a&gt; sugerido)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Montante</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Responder id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Responder texto</value>
</data>
<data name="Character" xml:space="preserve">
<value>Personalidade(emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Cor</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Comentar id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Comentar texto</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confrontação</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id de confronto</value>
</data>
<data name="Context" xml:space="preserve">
<value>Contexto</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Data final</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Data de início</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Descrição</value> <value>Descrição</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discussão</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Data final</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Tempo final</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Id de discussão</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Texto para discussão</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Título do debate</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Email</value> <value>Email</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Quantidade máxima de confrontos</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Facto</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fatos</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Identificação do arquivo</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupos</value> <value>Grupos</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Incluir a primeira resposta na pré-visualização do convite? (tornando-a mais envolvente para participar da discussão)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Código de convite</value> <value>Código de convite</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Código do convite ou link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Senha do convite</value> <value>Senha do convite</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Exigir senha para visualização</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Exigir senha para mostrar a visualização</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Adicionar proteção por senha</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Identificação do idioma</value> <value>Identificação do idioma</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nome</value> <value>Nome</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Habilitar notificações?(útil para receber atualizações de aplicativos)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nova senha</value> <value>Nova senha</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Senha antiga</value> <value>Senha antiga</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Só uma vez</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Senha</value> <value>Senha</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Percepção</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Percepções</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Tema do sistema de preferências</value> <value>Tema do sistema de preferências</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Código de recuperação</value> <value>Código de recuperação</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Recurrente</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Procura por:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Pesquisa</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Partilha do Código Secreto</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Mostrar crachá do doador</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Mostrar o separador de registos para suportar a resolução de problemas.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Tirar tipo</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Simples</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Estruturado</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Imagem temática</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Modo escuro</value> <value>Modo escuro</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Carraças</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Título</value> <value>Título</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Motivo da actualização</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Submeter de forma anónima</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Nome de usuário</value> <value>Nome de usuário</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Nome de usuário para pesquisar e adicionar</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Nomes de usuário para pesquisar e adicionar</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(necessary in case of password recovery)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="_blank" href="https://keepassxc.org/"&gt;password manager&lt;/a&gt; suggested)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Amount</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Answer id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Answer text</value>
</data>
<data name="Character" xml:space="preserve">
<value>Custom character(emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Colour</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Comment id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Comment text</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confrontation</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Confrontation id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Context</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>End date</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Start date</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Description</value> <value>Description</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discussion</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>End date</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>End time</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Discussion id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Discussion text</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Discussion title</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Email</value> <value>Email</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Max amount of confrontations</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fact</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Facts</value>
</data>
<data name="FileId" xml:space="preserve">
<value>File id</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Groups</value> <value>Groups</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Include the first answer in the invitation preview? (making it more engaging to join the discussion)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Invitation code</value> <value>Invitation code</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Invitation code or link</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Invitation password</value> <value>Invitation password</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Require password for preview</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Require password to show the preview</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Add password protection</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Language id</value> <value>Language id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Name</value> <value>Name</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Enable notifications?(useful to receive app updates)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>New password</value> <value>New password</value>
</data> </data>
@@ -243,78 +150,24 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Old password</value> <value>Old password</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>One time only</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Password</value> <value>Password</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Perception</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Perceptions</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Prefer system theme</value> <value>Prefer system theme</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Recovery code</value> <value>Recovery code</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Recurring</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scan for:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Search</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Sharing Secret Code</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Show donator badge</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Show the logs tab to support troubleshooting.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Take type</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Simple</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Structured</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Theme image</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Dark mode</value> <value>Dark mode</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Ticks</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Title</value> <value>Title</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Update reason</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Submit anonymously</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Username</value> <value>Username</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Username to search and add</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Usernames to search and add</value>
</data>
<data name="AvatarId" xml:space="preserve"> <data name="AvatarId" xml:space="preserve">
<value>Avatar</value> <value>Avatar</value>
</data> </data>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(necesar în cazul recuperării parolei)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;manager de parole&lt;/a&gt; sugerat)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Suma</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Răspuns id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Text de răspuns</value>
</data>
<data name="Character" xml:space="preserve">
<value>Caracter personalizat (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Culoare</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Comentariu id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Comentariu text</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Confruntare</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id de confruntare</value>
</data>
<data name="Context" xml:space="preserve">
<value>Context</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Data de încheiere</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Data de începere</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Descriere</value> <value>Descriere</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Discuție</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Data de încheiere</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Ora de sfârșit</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Discuție id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Text de discuție</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titlul discuției</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Email</value> <value>Email</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Numărul maxim de confruntări</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fapt</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fapte</value>
</data>
<data name="FileId" xml:space="preserve">
<value>ID fișier</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupuri</value> <value>Grupuri</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Includeți primul răspuns în previzualizarea invitației? (pentru a face mai atractivă participarea la discuție)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Codul de invitație</value> <value>Codul de invitație</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Cod sau link de invitație</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Parola de invitație</value> <value>Parola de invitație</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Necesită o parolă pentru previzualizare</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Necesită o parolă pentru a afișa previzualizarea</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Adăugați protecție prin parolă</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>ID-ul limbii</value> <value>ID-ul limbii</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Nume</value> <value>Nume</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Activați notificările?(util pentru a primi actualizări ale aplicației)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Parolă nouă</value> <value>Parolă nouă</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Parolă veche</value> <value>Parolă veche</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>O singură dată</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Parola</value> <value>Parola</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Percepție</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Percepții</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Preferați tema de sistem</value> <value>Preferați tema de sistem</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Cod de recuperare</value> <value>Cod de recuperare</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Recurent</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Scanează pentru:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Căutare</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Partajarea codului secret</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Arată insigna de donator</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Afișați fila jurnale pentru a sprijini depanarea.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Tipul de luare</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Simplu</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Structurat</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Imagine tematică</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Mod întunecat</value> <value>Mod întunecat</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Căpușe</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titlu</value> <value>Titlu</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Motivul actualizării</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Trimiteți în mod anonim</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Nume utilizator</value> <value>Nume utilizator</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Nume de utilizator pentru a căuta și adăuga</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Nume de utilizator pentru căutare și adăugare</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(необходимо в случае восстановления пароля)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(Предлагается &lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;password manager&lt;/a&gt;)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Сумма</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Идентификатор ответа</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Текст ответа</value>
</data>
<data name="Character" xml:space="preserve">
<value>Пользовательский символ (эмодзи)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Цвет</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Идентификатор комментария</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Текст комментария</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Противостояние</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Идентификатор противостояния</value>
</data>
<data name="Context" xml:space="preserve">
<value>Контекст</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Дата окончания</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Дата начала</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Описание</value> <value>Описание</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Обсуждение</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Дата окончания</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Время окончания</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Обсуждаемый иди</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Текст для обсуждения</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Название дискуссии</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>Электронная почта</value> <value>Электронная почта</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Максимальное количество противостояний</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Факт</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Факты</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Идентификатор файла</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Группы</value> <value>Группы</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Включить первый ответ в предварительный просмотр приглашения? (что делает его более привлекательным для участия в обсуждении)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Код приглашения</value> <value>Код приглашения</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Код приглашения или ссылка</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Пароль приглашения</value> <value>Пароль приглашения</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Требуется пароль для предварительного просмотра</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Требуется пароль для показа предварительного просмотра</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Добавить защиту паролем</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Языковой идентификатор</value> <value>Языковой идентификатор</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Имя</value> <value>Имя</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Включить уведомления? (полезно для получения обновлений приложения)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Новый пароль</value> <value>Новый пароль</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Старый пароль</value> <value>Старый пароль</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Только один раз</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Пароль</value> <value>Пароль</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Восприятие</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Восприятие</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Предпочитайте системную тему</value> <value>Предпочитайте системную тему</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Код восстановления</value> <value>Код восстановления</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Повторяющийся</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Сканирование для:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Поиск</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Обмен секретным кодом</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Показать значок жертвователя</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Покажите вкладку журналов для поддержки поиска и устранения неисправностей.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Возьмите тип</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Простой</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Структурированный</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Тематическое изображение</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Темный режим</value> <value>Темный режим</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Клещи</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Название</value> <value>Название</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Причина обновления</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Подавать анонимно</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Имя пользователя</value> <value>Имя пользователя</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Имя пользователя для поиска и добавления</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Имена пользователей для поиска и добавления</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(potrebné v prípade obnovenia hesla)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;správca hesiel&lt;/a&gt; navrhnuté)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Suma</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Odpoveď id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Text odpovede</value>
</data>
<data name="Character" xml:space="preserve">
<value>Vlastný znak (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Farba</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Komentár id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Text komentára</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontácia</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id konfrontácie</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontext</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Dátum ukončenia</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Dátum začiatku</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Popis</value> <value>Popis</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskusia</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Dátum ukončenia</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Čas ukončenia</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskusia id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Text diskusie</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Názov diskusie</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Maximálny počet konfrontácií</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Skutočnosť</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakty</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Identifikátor súboru</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Skupiny</value> <value>Skupiny</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Zahrnúť prvú odpoveď do náhľadu pozvánky? (aby bolo zapojenie do diskusie pútavejšie)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Pozývací kód</value> <value>Pozývací kód</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Pozývací kód alebo odkaz</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Heslo pozvánky</value> <value>Heslo pozvánky</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Vyžadovať heslo pre náhľad</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Vyžadovať heslo na zobrazenie náhľadu</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Pridanie ochrany heslom</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Identifikátor jazyka</value> <value>Identifikátor jazyka</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Názov</value> <value>Názov</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Povolenie oznámení?(užitočné na prijímanie aktualizácií aplikácie)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nové heslo</value> <value>Nové heslo</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Staré heslo</value> <value>Staré heslo</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Iba jedenkrát</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Heslo</value> <value>Heslo</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Vnímanie</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Vnímanie</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Uprednostniť tému systému</value> <value>Uprednostniť tému systému</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Kód obnovy</value> <value>Kód obnovy</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Opakujúce sa</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Vyhľadávanie:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Vyhľadávanie</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Zdieľanie tajného kódu</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Zobraziť odznak darcu</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Zobrazenie karty protokolov na podporu riešenia problémov.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Vezmite si typ</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Jednoduché</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Štruktúrované</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Obrázok témy</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Tmavý režim</value> <value>Tmavý režim</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Kliešte</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Názov</value> <value>Názov</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Dôvod aktualizácie</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Odoslať anonymne</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Používateľské meno</value> <value>Používateľské meno</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Používateľské meno na vyhľadávanie a pridávanie</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Používateľské mená na vyhľadávanie a pridávanie</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(potrebno v primeru obnovitve gesla)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;predlagani upravitelj gesel&lt;/a&gt;)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Znesek</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Odgovor id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Besedilo odgovora</value>
</data>
<data name="Character" xml:space="preserve">
<value>Znak po meri (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Barva</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Id komentarja</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Besedilo komentarja</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontacija</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Id konfrontacije</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontekst</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Končni datum</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Datum začetka</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Opis</value> <value>Opis</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Razprava</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Končni datum</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Končni čas</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Razprava id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Besedilo za razpravo</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Naslov razprave</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-pošta</value> <value>E-pošta</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Največje število soočenj</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Dejstva</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Dejstva</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Id datoteke</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Skupine</value> <value>Skupine</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Vključiti prvi odgovor v predogled vabila? (da bo vključitev v razpravo bolj privlačna)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Koda vabila</value> <value>Koda vabila</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Koda vabila ali povezava</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Geslo za povabilo</value> <value>Geslo za povabilo</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Zahtevajte geslo za predogled</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Zahtevajte geslo za prikaz predogleda</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Dodajanje zaščite z geslom</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Id jezika</value> <value>Id jezika</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Ime</value> <value>Ime</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Omogočite obvestila? (koristno za prejemanje posodobitev aplikacije)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Novo geslo</value> <value>Novo geslo</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Staro geslo</value> <value>Staro geslo</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Samo enkrat</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Geslo</value> <value>Geslo</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Zaznavanje</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Dojemanje</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Prednost sistemske teme</value> <value>Prednost sistemske teme</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Koda za obnovitev</value> <value>Koda za obnovitev</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Ponavljajoče se</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Iskanje za:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Iskanje</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Deljenje skrivne kode</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Prikaži značko donatorja</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Prikažite zavihek dnevniki za podporo pri odpravljanju težav.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Vrsta posnetka</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Enostavno</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturiran</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Slika teme</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Temni način</value> <value>Temni način</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Klopi</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Naslov</value> <value>Naslov</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Razlog za posodobitev</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Pošlji anonimno</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Uporabniško ime</value> <value>Uporabniško ime</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Uporabniško ime za iskanje in dodajanje</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Uporabniška imena za iskanje in dodajanje</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(nödvändig vid återställning av lösenord)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;password manager&lt;/a&gt; föreslås)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>Belopp</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>Svar id</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>Svarstext</value>
</data>
<data name="Character" xml:space="preserve">
<value>Anpassat tecken (emoji)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>Färg</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>Kommentar id</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>Kommentar</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>Konfrontation</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>Konfrontation id</value>
</data>
<data name="Context" xml:space="preserve">
<value>Kontext</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>Slutdatum</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>Startdatum</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>Beskrivning</value> <value>Beskrivning</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>Diskussion</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>Slutdatum</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>Sluttid</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>Diskussion id</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>Diskussionstext</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>Titel på diskussionen</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>E-post</value> <value>E-post</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>Emoji</value> <value>Emoji</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>Max antal konfrontationer</value>
</data>
<data name="Fact" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="Facts" xml:space="preserve">
<value>Fakta</value>
</data>
<data name="FileId" xml:space="preserve">
<value>Filid</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>Grupper</value> <value>Grupper</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>Inkludera det första svaret i förhandsgranskningen av inbjudan? (för att göra det mer lockande att delta i diskussionen)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>Kod för inbjudan</value> <value>Kod för inbjudan</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>Inbjudningskod eller länk</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>Lösenord för inbjudan</value> <value>Lösenord för inbjudan</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>Kräver lösenord för förhandsgranskning</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>Kräver lösenord för att visa förhandsgranskningen</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>Lägg till lösenordsskydd</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>IsStructured</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>Språk-id</value> <value>Språk-id</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>Namn</value> <value>Namn</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>Aktivera meddelanden (användbart för att få uppdateringar av appen)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>Nytt lösenord</value> <value>Nytt lösenord</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>Gammalt lösenord</value> <value>Gammalt lösenord</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>Endast en gång</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>Lösenord</value> <value>Lösenord</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>Uppfattning</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>Uppfattningar</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>Föredrar systemtema</value> <value>Föredrar systemtema</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>Kod för återvinning</value> <value>Kod för återvinning</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>Återkommande</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>Skanna efter:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>Sök på</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>Att dela med sig av den hemliga koden</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>Visa donatormärket</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>Visa fliken Loggar för att underlätta felsökning.</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>Typ av tagning</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>Enkelt</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>Strukturerad</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>Tema bild</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>Mörkt läge</value> <value>Mörkt läge</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>Fästingar</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>Titel</value> <value>Titel</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>Orsak till uppdatering</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>Skicka in anonymt</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>Användarnamn</value> <value>Användarnamn</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>Användarnamn för att söka och lägga till</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>Användarnamn att söka och lägga till</value>
</data>
</root> </root>
@@ -117,123 +117,30 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="(necessary in case of password recovery)" xml:space="preserve">
<value>(在恢复密码的情况下是必要的)</value>
</data>
<data name="(password manager suggested)" xml:space="preserve">
<value>(&lt;a class="is-underlined has-text-info" tabindex="-1" target="blank" href="https://keepassxc.org/"&gt;密码管理器&lt;/a&gt;建议)</value>
</data>
<data name="Amount" xml:space="preserve">
<value>数量</value>
</data>
<data name="AnswerId" xml:space="preserve">
<value>答案是</value>
</data>
<data name="AnswerText" xml:space="preserve">
<value>回答文本</value>
</data>
<data name="Character" xml:space="preserve">
<value>自定义字符(表情符号)</value>
</data>
<data name="ColourIndex" xml:space="preserve">
<value>颜色</value>
</data>
<data name="CommentId" xml:space="preserve">
<value>评论编号</value>
</data>
<data name="CommentText" xml:space="preserve">
<value>评论文本</value>
</data>
<data name="Confrontation" xml:space="preserve">
<value>对抗</value>
</data>
<data name="ConfrontationId" xml:space="preserve">
<value>对抗的身份</value>
</data>
<data name="Context" xml:space="preserve">
<value>背景介绍</value>
</data>
<data name="DateEnd" xml:space="preserve">
<value>结束日期</value>
</data>
<data name="DateStart" xml:space="preserve">
<value>开始日期</value>
</data>
<data name="Description" xml:space="preserve"> <data name="Description" xml:space="preserve">
<value>描述</value> <value>描述</value>
</data> </data>
<data name="Discussion" xml:space="preserve">
<value>讨论</value>
</data>
<data name="DiscussionEndDate" xml:space="preserve">
<value>结束日期</value>
</data>
<data name="DiscussionEndTime" xml:space="preserve">
<value>结束时间</value>
</data>
<data name="DiscussionId" xml:space="preserve">
<value>讨论的内容</value>
</data>
<data name="DiscussionText" xml:space="preserve">
<value>讨论文本</value>
</data>
<data name="DiscussionTitle" xml:space="preserve">
<value>讨论题目</value>
</data>
<data name="Email" xml:space="preserve"> <data name="Email" xml:space="preserve">
<value>电子邮件</value> <value>电子邮件</value>
</data> </data>
<data name="Emoji" xml:space="preserve"> <data name="Emoji" xml:space="preserve">
<value>表情符号</value> <value>表情符号</value>
</data> </data>
<data name="ExpectedMaxConfrontationsBeforeClosingAndShowing" xml:space="preserve">
<value>对抗的最大数量</value>
</data>
<data name="Fact" xml:space="preserve">
<value>事实</value>
</data>
<data name="Facts" xml:space="preserve">
<value>事实</value>
</data>
<data name="FileId" xml:space="preserve">
<value>文件编号</value>
</data>
<data name="Groups" xml:space="preserve"> <data name="Groups" xml:space="preserve">
<value>群体</value> <value>群体</value>
</data> </data>
<data name="IncludeFirstAnswerInInvitation" xml:space="preserve">
<value>在邀请预览中包括第一个答案?(使其更加吸引人加入讨论)</value>
</data>
<data name="InvitationCode" xml:space="preserve"> <data name="InvitationCode" xml:space="preserve">
<value>邀请函代码</value> <value>邀请函代码</value>
</data> </data>
<data name="InvitationCodeLink" xml:space="preserve">
<value>邀请函代码或链接</value>
</data>
<data name="InvitationPassword" xml:space="preserve"> <data name="InvitationPassword" xml:space="preserve">
<value>邀请函密码</value> <value>邀请函密码</value>
</data> </data>
<data name="IsPasswordProtectedForPreview" xml:space="preserve">
<value>预览时需要密码</value>
</data>
<data name="IsPasswordProtectedForPreviewText" xml:space="preserve">
<value>需要密码才能显示预览</value>
</data>
<data name="IsPasswordProtectedText" xml:space="preserve">
<value>添加密码保护</value>
</data>
<data name="IsStructured" xml:space="preserve">
<value>是结构化的</value>
</data>
<data name="LanguageId" xml:space="preserve"> <data name="LanguageId" xml:space="preserve">
<value>语言标识</value> <value>语言标识</value>
</data> </data>
<data name="Name" xml:space="preserve"> <data name="Name" xml:space="preserve">
<value>命名</value> <value>命名</value>
</data> </data>
<data name="NativeNotificationsEnabled" xml:space="preserve">
<value>启用通知?(对接收应用程序的更新很有用)</value>
</data>
<data name="NewPassword" xml:space="preserve"> <data name="NewPassword" xml:space="preserve">
<value>新密码</value> <value>新密码</value>
</data> </data>
@@ -243,76 +150,22 @@
<data name="OldPassword" xml:space="preserve"> <data name="OldPassword" xml:space="preserve">
<value>旧密码</value> <value>旧密码</value>
</data> </data>
<data name="OneTime" xml:space="preserve">
<value>仅限一次</value>
</data>
<data name="Password" xml:space="preserve"> <data name="Password" xml:space="preserve">
<value>密码</value> <value>密码</value>
</data> </data>
<data name="Perception" xml:space="preserve">
<value>感知</value>
</data>
<data name="Perceptions" xml:space="preserve">
<value>观念</value>
</data>
<data name="PreferSystemTheming" xml:space="preserve"> <data name="PreferSystemTheming" xml:space="preserve">
<value>倾向于系统主题</value> <value>倾向于系统主题</value>
</data> </data>
<data name="RecoveryCode" xml:space="preserve"> <data name="RecoveryCode" xml:space="preserve">
<value>恢复代码</value> <value>恢复代码</value>
</data> </data>
<data name="Recurring" xml:space="preserve">
<value>经常性的</value>
</data>
<data name="Scan for:" xml:space="preserve">
<value>进行扫描:</value>
</data>
<data name="SearchText" xml:space="preserve">
<value>搜索</value>
</data>
<data name="ShareCode" xml:space="preserve">
<value>分享秘密代码</value>
</data>
<data name="ShowDonatorBadge" xml:space="preserve">
<value>显示捐赠者徽章</value>
</data>
<data name="ShowLogs" xml:space="preserve">
<value>显示日志标签以支持故障排除。</value>
</data>
<data name="TakeType" xml:space="preserve">
<value>采取类型</value>
</data>
<data name="TakeTypeSimple" xml:space="preserve">
<value>简单</value>
</data>
<data name="TakeTypeStructured" xml:space="preserve">
<value>结构化</value>
</data>
<data name="Theme image" xml:space="preserve">
<value>主题图片</value>
</data>
<data name="ThemeIsDarkMode" xml:space="preserve"> <data name="ThemeIsDarkMode" xml:space="preserve">
<value>黑暗模式</value> <value>黑暗模式</value>
</data> </data>
<data name="Ticks" xml:space="preserve">
<value>蜱虫</value>
</data>
<data name="Title" xml:space="preserve"> <data name="Title" xml:space="preserve">
<value>标题</value> <value>标题</value>
</data> </data>
<data name="UpdateReason" xml:space="preserve">
<value>更新原因</value>
</data>
<data name="UpsertUserTakeIsAnonymous" xml:space="preserve">
<value>匿名提交</value>
</data>
<data name="Username" xml:space="preserve"> <data name="Username" xml:space="preserve">
<value>帐号</value> <value>帐号</value>
</data> </data>
<data name="Username to search and add" xml:space="preserve">
<value>搜索和添加的用户名</value>
</data>
<data name="Usernames to search and add" xml:space="preserve">
<value>搜索和添加的用户名</value>
</data>
</root> </root>
+1 -1
View File
@@ -2,6 +2,6 @@
{ {
public class UsersIds public class UsersIds
{ {
public IList<string> UserIdList { get; set; } = Array.Empty<string>(); public List<string> UserIdList { get; set; } = [];
} }
} }
@@ -29,14 +29,20 @@ namespace PrivaPub.Controllers.ClientToServer
RootUsersService = rootUsersService; RootUsersService = rootUsersService;
} }
// an administrator never removes, bans or unbans itself; the request's own list is left as it came
UsersIds Others(UsersIds usersIds)
{
var selfId = User.GetUserId();
return new UsersIds { UserIdList = usersIds.UserIdList.Where(id => id != selfId).ToList() };
}
[HttpDelete, Route("/clientapi/admin/remove/users"), Authorize(Policy = Policies.IsAdmin)] [HttpDelete, Route("/clientapi/admin/remove/users"), Authorize(Policy = Policies.IsAdmin)]
public async Task<IActionResult> RemoveUsers([Required] UsersIds usersIds) public async Task<IActionResult> RemoveUsers([Required] UsersIds usersIds)
{ {
var result = new WebResult(); var result = new WebResult();
try try
{ {
usersIds.UserIdList.Remove(User.GetUserId()); result = await RootUsersService.RemoveUserAsync(Others(usersIds));
result = await RootUsersService.RemoveUserAsync(usersIds);
if (!result.IsValid) if (!result.IsValid)
return StatusCode(result.StatusCode, result); return StatusCode(result.StatusCode, result);
@@ -57,13 +63,7 @@ namespace PrivaPub.Controllers.ClientToServer
var result = new WebResult(); var result = new WebResult();
try try
{ {
//var isUserResult = await UsersService.UserIsAdminAsync(User.GetUserId()); result = await RootUsersService.BanUserAsync(Others(usersIds));
//if (isUserResult.IsValid && !(bool)isUserResult.Data)
//if (isUserResult is { IsValid: true } and not { Data: bool })
// return Unauthorized();
usersIds.UserIdList.Remove(User.GetUserId());
result = await RootUsersService.BanUserAsync(usersIds);
if (!result.IsValid) if (!result.IsValid)
return StatusCode(result.StatusCode, result); return StatusCode(result.StatusCode, result);
@@ -85,12 +85,7 @@ namespace PrivaPub.Controllers.ClientToServer
var result = new WebResult(); var result = new WebResult();
try try
{ {
//var isUserResult = await UsersService.UserIsAdminAsync(User.GetUserId()); result = await RootUsersService.UnbanUserAsync(Others(usersIds));
//if (isUserResult.IsValid && !(bool)isUserResult.Data)
// return Unauthorized();
usersIds.UserIdList.Remove(User.GetUserId());
result = await RootUsersService.UnbanUserAsync(usersIds);
if (!result.IsValid) if (!result.IsValid)
return StatusCode(result.StatusCode, result); return StatusCode(result.StatusCode, result);
@@ -102,28 +97,5 @@ namespace PrivaPub.Controllers.ClientToServer
return BadRequest(result.Invalidate(Localizer["Something went wrong."])); return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
} }
} }
//[HttpGet, Authorize(Policy = Policies.IsAdmin)]
//public async Task<IActionResult> GetUsers()
//{
// var result = new WebResult();
// try
// {
// var isUserResult = await UsersService.UserIsAdminAsync(User.GetUserId());
// if (isUserResult.IsValid && !(bool)isUserResult.Data)
// return Unauthorized();
// result = await UsersService.GetUsersAsync();
// if (!result.IsValid)
// return StatusCode(result.StatusCode, result);
// return Ok(result.Data);
// }
// catch (Exception ex)
// {
// Logger.LogError(ex, $"{nameof(User)}.{nameof(GetUsers)}()");
// return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
// }
//}
} }
} }
@@ -92,7 +92,7 @@ namespace PrivaPub.Controllers.ClientToServer
[HttpPost, Route("/clientapi/user/login"), EnableRateLimiting(RateLimiting.Accounts), Authorize(Policy = Policies.IsUser), AllowAnonymous] [HttpPost, Route("/clientapi/user/login"), EnableRateLimiting(RateLimiting.Accounts), Authorize(Policy = Policies.IsUser), AllowAnonymous]
public async Task<IActionResult> Login(LoginForm loginForm) public async Task<IActionResult> Login(LoginForm loginForm)
{ {
if (User.Identity?.IsAuthenticated ?? false) return Redirect("/discussions"); if (User.Identity?.IsAuthenticated ?? false) return Redirect("/");
var result = new WebResult(); var result = new WebResult();
if (!ModelState.IsValid) if (!ModelState.IsValid)
return BadRequest(result.Invalidate(Localizer["Invalid model."])); return BadRequest(result.Invalidate(Localizer["Invalid model."]));
@@ -132,7 +132,7 @@ namespace PrivaPub.Controllers.ClientToServer
if (personaProblem != default) if (personaProblem != default)
return BadRequest(result.Invalidate(personaProblem)); return BadRequest(result.Invalidate(personaProblem));
result = await UsersService.SignUpAsync(signUpForm, signUpForm.InvitationCode); result = await UsersService.SignUpAsync(signUpForm);
if (!result.IsValid) if (!result.IsValid)
return StatusCode(result.StatusCode, result); return StatusCode(result.StatusCode, result);
var (user, userSettings) = ((RootUser, ViewUserSettings))result.Data; var (user, userSettings) = ((RootUser, ViewUserSettings))result.Data;
@@ -171,7 +171,7 @@ namespace PrivaPub.Controllers.ClientToServer
if (!invitation.IsValid) if (!invitation.IsValid)
return StatusCode(invitation.StatusCode, invitation); return StatusCode(invitation.StatusCode, invitation);
result = await UsersService.LoginAsync(loginForm, loginForm.InvitationCode); result = await UsersService.LoginAsync(loginForm);
if (!result.IsValid) if (!result.IsValid)
return StatusCode(result.StatusCode, result); return StatusCode(result.StatusCode, result);
var (user, userSettings) = ((RootUser, ViewUserSettings))result.Data; var (user, userSettings) = ((RootUser, ViewUserSettings))result.Data;
@@ -370,25 +370,6 @@ namespace PrivaPub.Controllers.ClientToServer
} }
} }
//[HttpGet, Authorize(Policy = Policies.IsUser)]
//public async Task<IActionResult> GetUser()
//{
// var result = new WebResult();
// try
// {
// result = await UsersService.GetUserAsync(User.GetUserId());
// if (!result.IsValid)
// return StatusCode(result.StatusCode, result);
// return Ok(result.Data);
// }
// catch (Exception ex)
// {
// Logger.LogError(ex, $"{nameof(User)}.{nameof(GetUser)}()");
// return BadRequest(result.Invalidate(Localizer["Something went wrong."]));
// }
//}
// what the login's media take, every persona's, and its quota when the server sets one // what the login's media take, every persona's, and its quota when the server sets one
[HttpGet, Route("/clientapi/user/storage"), Authorize(Policy = Policies.IsUser)] [HttpGet, Route("/clientapi/user/storage"), Authorize(Policy = Policies.IsUser)]
public async Task<IActionResult> GetStorage([FromServices] Microsoft.Extensions.Options.IOptionsMonitor<Domain.Media.MediaOptions> media, CancellationToken token) public async Task<IActionResult> GetStorage([FromServices] Microsoft.Extensions.Options.IOptionsMonitor<Domain.Media.MediaOptions> media, CancellationToken token)
+1 -109
View File
@@ -10,68 +10,12 @@ namespace PrivaPub.Data
{ {
public static class InitDb public static class InitDb
{ {
public static async Task Init(this DbEntities dbClient, IPasswordHasher passwordHasher) public static async Task Init(this DbEntities dbClient)
{ {
await SyncLanguages(dbClient); await SyncLanguages(dbClient);
await UpdateNewLanguages(dbClient); await UpdateNewLanguages(dbClient);
//await SyncUserSettings(dbClient);
//await ClearUsers(dbClient);
//var botsInsertionAwaiter = InsertBots(dbClient, passwordHasher);
//var updateAnswersAwaiter = UpdateAnswersLikes(dbClient);
//Task.WaitAll(botsInsertionAwaiter);
//await SyncShareDiscussions(dbClient);
} }
//static async Task UpdateAnswersLikes(DbCollections dbClient)
//{
// if (await dbClient.AnswersLikes.Find(al => al.AnswerId != null).AnyAsync()) return;
// foreach (var answerLikes in await dbClient.AnswersLikes.Find(al => true).ToListAsync())
// {
// answerLikes.AnswerId = answerLikes.Id;
// answerLikes.Id = ObjectId.GenerateNewId();
// await dbClient.AnswersLikes.InsertOneAsync(answerLikes);
// _ = await dbClient.AnswersLikes.DeleteOneAsync(al => al.Id == answerLikes.AnswerId);
// }
//}
//static async Task ClearUsers(DbColl dbClient)
//{
// await dbClient.Users.DeleteManyAsync(u => true);
// await dbClient.UsersSettings.DeleteManyAsync(u => true);
// await dbClient.Answers.DeleteManyAsync(u => true);
// await dbClient.AnswersLikes.DeleteManyAsync(u => true);
// await dbClient.Comments.DeleteManyAsync(u => true);
// await dbClient.EmailRecoveries.DeleteManyAsync(u => true);
// await dbClient.Threads.DeleteManyAsync(u => true);
// await dbClient.EDiscussions.DeleteManyAsync(u => true);
// await dbClient.Logs.DeleteManyAsync(u => true);
// await dbClient.ShareDiscussions.De(u => true);
// await dbClient.DiscussionFiles.DeleteManyAsync(u => true);
// await dbClient.UsersGroups.DeleteManyAsync(u => true);
//}
// static async Task SyncShareDiscussions(DbColl dbClient)
// {
// var anyThread = await dbClient.Discussions.Match(t => true).ExecuteAnyAsync();
// var anyShareDiscussion = await dbClient.ShareDiscussions.Match(st => true).ExecuteAnyAsync();
//
// if (anyThread == anyShareDiscussion) return;
//
// var discussions = await dbClient.Discussions.ManyAsync(t => true);
//
// foreach (var discussion in discussions)
// {
// var newShareDiscussion = new ShareDiscussion
// {
// DiscussionId = discussion.ID,
// InvitationCode = $"{Guid.NewGuid():N}{Guid.NewGuid():N}"
// };
// await newShareDiscussion.SaveAsync();
// }
// }
static async Task SyncLanguages(DbEntities dbClient) static async Task SyncLanguages(DbEntities dbClient)
{ {
if (await dbClient.Languages.ExecuteAnyAsync()) return; if (await dbClient.Languages.ExecuteAnyAsync()) return;
@@ -157,57 +101,5 @@ namespace PrivaPub.Data
await DB.Default.SaveAsync(bgLang); await DB.Default.SaveAsync(bgLang);
} }
} }
// static async Task SyncUserSettings(DbColl dbClient)
// {
// if (!await dbClient.Users.ExecuteAnyAsync()) return;
//
// var users = await dbClient.Users.ManyAsync(u => true);
// var usersId = users.Select(u => u.ID).ToList();
// var usersSettings = await dbClient.UsersSettings
// .ManyAsync(us => true);
//
// var usersWithoutSettings = users.Where(u => !usersSettings.Any(us => us.UserId == u.ID)).Select(u => u.ID).ToList();
// if (usersWithoutSettings.Count == 0) return;
//
// var defaultLanguage = await dbClient.Languages
// .Match(l => l.International2Code == "en")
// .ExecuteFirstAsync();
// foreach (var userId in usersWithoutSettings)
// await DB.SaveAsync(new UserSettings
// {
// UserId = userId,
// LanguageId = defaultLanguage.International2Code
// });
// }
//static async Task InsertBots(DbEntities dbClient, IPasswordHasher passwordHasher)
//{
// if (await dbClient.Users.Match(u => u.UserName == "bot0").ExecuteAnyAsync()) return;
// var newBots = new List<User>();
// var newBotsUserSettings = new List<UserSettings>();
// for (int i = 0; i < 100; i++)
// newBots.Add(new User
// {
// HashedPassword = passwordHasher.Hash("Asdfmov13!!!"),
// UserName = $"bot{i}"
// });
// await newBots.SaveAsync();
// var defaultLanguage = await dbClient.Languages
// .Match(l => l.International2Code == "en")
// .ExecuteFirstAsync();
// foreach (var newBot in newBots)
// newBotsUserSettings.Add(new()
// {
// UserId = newBot.ID,
// LanguageId = defaultLanguage.International2Code,
// });
// await newBotsUserSettings.SaveAsync();
//}
} }
} }
-21
View File
@@ -1,11 +1,7 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using PrivaPub.ClientModels; using PrivaPub.ClientModels;
using PrivaPub.Models.User;
using System.Security.Claims;
namespace PrivaPub.Extensions namespace PrivaPub.Extensions
{ {
public static class Extensions public static class Extensions
@@ -27,22 +23,5 @@ namespace PrivaPub.Extensions
.RequireClaim(Policies.IsUser, true.ToString().ToLower()) .RequireClaim(Policies.IsUser, true.ToString().ToLower())
.RequireClaim(Policies.IsModerator, true.ToString().ToLower()) .RequireClaim(Policies.IsModerator, true.ToString().ToLower())
.Build(); .Build();
public static string GetHostWithPath(this HttpContext httpContext) =>
$"https://{httpContext.Request.Host}{httpContext.Request.Path}";
public static string GetHost(this HttpContext httpContext) =>
$"https://{httpContext.Request.Host}";
public static UserPolicyType GetHighestPolicy(this ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.FindFirstValue(Policies.IsAdmin) == "true")
return UserPolicyType.IsAdmin;
if (claimsPrincipal.FindFirstValue(Policies.IsModerator) == "true")
return UserPolicyType.IsModerator;
return UserPolicyType.IsUser;
}
} }
} }
+1 -25
View File
@@ -1,6 +1,4 @@
using PrivaPub.ClientModels; using System.Security.Claims;
using System.Security.Claims;
namespace PrivaPub.Extensions namespace PrivaPub.Extensions
{ {
@@ -10,27 +8,5 @@ namespace PrivaPub.Extensions
{ {
return claimsPrincipal?.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.UserData)?.Value; return claimsPrincipal?.Claims?.FirstOrDefault(c => c.Type == ClaimTypes.UserData)?.Value;
} }
public static string GetUserName(this ClaimsPrincipal claimsPrincipal)
{
var userId = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
return string.IsNullOrEmpty(userId) ? default : userId;
}
public static List<string> GetUserPolicies(this ClaimsPrincipal claimsPrincipal)
{
var policies = new List<string>();
if (claimsPrincipal.Claims.Any(c => c.Type == Policies.IsAdmin && bool.Parse(c.Value)))
policies.Add(Policies.IsAdmin);
if (claimsPrincipal.Claims.Any(c => c.Type == Policies.IsUser && bool.Parse(c.Value)))
policies.Add(Policies.IsUser);
if (claimsPrincipal.Claims.Any(c => c.Type == Policies.IsModerator && bool.Parse(c.Value)))
policies.Add(Policies.IsModerator);
return policies;
}
} }
} }
@@ -75,7 +75,7 @@ namespace PrivaPub.Infrastructure.Backup
continue; continue;
} }
await roots.UpdateOneAsync(Id(root["_id"]), Copy(root, "HashedPassword", "Email", "IsEmailValidated", "IsBanned", "Policies", await roots.UpdateOneAsync(Id(root["_id"]), Copy(root, "HashedPassword", "Email", "IsEmailValidated", "IsBanned", "Policies",
"CredentialsChangedAt", "ResetPasswordToken", "ResetPasswordTokenSentAt"), cancellationToken: token); "CredentialsChangedAt"), cancellationToken: token);
} }
var avatars = database.GetCollection<BsonDocument>("Avatar"); var avatars = database.GetCollection<BsonDocument>("Avatar");
-3
View File
@@ -49,9 +49,6 @@ namespace PrivaPub.Infrastructure.Data
await Plain<Models.Media.MediaAttachment>(token, m => m.ProfileOfAvatarId); await Plain<Models.Media.MediaAttachment>(token, m => m.ProfileOfAvatarId);
await Plain<Models.Media.MediaAttachment>(token, m => m.TrashedAt); await Plain<Models.Media.MediaAttachment>(token, m => m.TrashedAt);
await Unique<DmPost>(p => p.ObjectURI, Builders<DmPost>.Filter.Gt(p => p.ObjectURI, ""), token);
await Plain<DmPost>(token, p => p.GroupId, p => p.ID);
await Unique<ForeignAvatar>(a => a.ActorURI, Builders<ForeignAvatar>.Filter.Gt(a => a.ActorURI, ""), token); await Unique<ForeignAvatar>(a => a.ActorURI, Builders<ForeignAvatar>.Filter.Gt(a => a.ActorURI, ""), token);
await Plain<ForeignAvatar>(token, a => a.PublicKeyId); await Plain<ForeignAvatar>(token, a => a.PublicKeyId);
+1 -10
View File
@@ -44,13 +44,6 @@ namespace PrivaPub.Middleware
.Configure<AppConfiguration>(configuration.GetSection(nameof(AppConfiguration))) .Configure<AppConfiguration>(configuration.GetSection(nameof(AppConfiguration)))
.Configure<PrivaPub.Infrastructure.RegistrationOptions>(configuration.GetSection("Registrations")); .Configure<PrivaPub.Infrastructure.RegistrationOptions>(configuration.GetSection("Registrations"));
} }
public static IServiceCollection PrivaPubWorkersConfiguration(this IServiceCollection service)
{
return service;
//.AddHostedService<DiscussionsWorker>()
//.AddHostedService<GroupsCleanerWorker>()
//.AddHostedService<PoliciesCleanerWorker>();
}
public static IServiceCollection PrivaPubFederationConfiguration(this IServiceCollection service, IConfiguration configuration) public static IServiceCollection PrivaPubFederationConfiguration(this IServiceCollection service, IConfiguration configuration)
{ {
service.Configure<FederationOptions>(configuration.GetSection("Federation")); service.Configure<FederationOptions>(configuration.GetSection("Federation"));
@@ -228,7 +221,6 @@ namespace PrivaPub.Middleware
.AddTransient<IRootUsersService, RootUsersService>() .AddTransient<IRootUsersService, RootUsersService>()
.AddScoped<IRootSessions, RootSessions>() .AddScoped<IRootSessions, RootSessions>()
.AddScoped<IRootRemoval, RootRemoval>() .AddScoped<IRootRemoval, RootRemoval>()
.AddTransient<IPublicAvatarUsersService, PublicAvatarUsersService>()
.AddTransient<IPrivateAvatarUsersService, PrivateAvatarUsersService>() .AddTransient<IPrivateAvatarUsersService, PrivateAvatarUsersService>()
.AddTransient<IGroupUsersService, GroupUsersService>() .AddTransient<IGroupUsersService, GroupUsersService>()
.AddTransient<IPostsService, PostsService>() .AddTransient<IPostsService, PostsService>()
@@ -240,8 +232,7 @@ namespace PrivaPub.Middleware
.AddTransient<ITimelineService, TimelineService>() .AddTransient<ITimelineService, TimelineService>()
.AddSingleton<AppConfigurationService>() .AddSingleton<AppConfigurationService>()
.AddHttpContextAccessor() .AddHttpContextAccessor()
.AddMemoryCache() .AddMemoryCache();
.AddSingleton<IPasswordHasher, PasswordHasher>();
} }
public static IServiceCollection PrivaPubMiddlewareConfiguration(this IServiceCollection service) public static IServiceCollection PrivaPubMiddlewareConfiguration(this IServiceCollection service)
-5
View File
@@ -7,11 +7,6 @@ namespace PrivaPub.Models
{ {
public class AppConfiguration : Entity public class AppConfiguration : Entity
{ {
public bool RequiresFirstTimeSetup { get; set; } = true;
public string Version { get; set; }
public int MaxAllowedUploadFiles { get; set; }
public int MaxAllowedFileSize { get; set; }
public string ValidDiscussionFilesTypes { get; set; }
public List<string> SupportedLanguages { get; set; } = new(); public List<string> SupportedLanguages { get; set; } = new();
public string BackendBaseAddress { get; set; } public string BackendBaseAddress { get; set; }
public string FrontendBaseAddress { get; set; } public string FrontendBaseAddress { get; set; }
-1
View File
@@ -3,7 +3,6 @@
public class MongoSettings public class MongoSettings
{ {
public string Database { get; set; } public string Database { get; set; }
public string LogsDatabase { get; set; }
public string ConnectionString { get; set; } public string ConnectionString { get; set; }
} }
} }
-1
View File
@@ -29,7 +29,6 @@ namespace PrivaPub.Models.User
public string PictureURL { get; set; }//icon public string PictureURL { get; set; }//icon
public string ThumbnailURL { get; set; }//image public string ThumbnailURL { get; set; }//image
public AvatarType AvatarType { get; set; } = AvatarType.Person; public AvatarType AvatarType { get; set; } = AvatarType.Person;
public AvatarServer AvatarServer { get; set; } = AvatarServer.PrivaPub;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
-3
View File
@@ -5,10 +5,7 @@ namespace PrivaPub.Models.User
public class EmailRecovery : Entity public class EmailRecovery : Entity
{ {
public string RootUserId { get; set; } public string RootUserId { get; set; }
public string RecoveryCode { get; set; }//plaintext codes before 2026-10-04; migration _011 removed them, never written now
public string CodeHash { get; set; }//sha-256 of the code, hex; the code itself exists only in the email public string CodeHash { get; set; }//sha-256 of the code, hex; the code itself exists only in the email
public DateTime ExpiresAt { get; set; } public DateTime ExpiresAt { get; set; }
public string RequestIP { get; set; }
public DateTime CreationDate { get; set; } = DateTime.UtcNow;
} }
} }
-12
View File
@@ -14,12 +14,8 @@ namespace PrivaPub.Models.User
public bool IsBanned { get; set; } = false; public bool IsBanned { get; set; } = false;
public string HashedPassword { get; set; } public string HashedPassword { get; set; }
public List<string> Policies { get; set; } = new() { ClientModels.Policies.IsUser }; public List<string> Policies { get; set; } = new() { ClientModels.Policies.IsUser };
public List<ContactItem> Contacts { get; set; } = new();
public RootUserSettings Settings { get; set; } = new(); public RootUserSettings Settings { get; set; } = new();
public string ResetPasswordToken { get; set; }
public DateTime? ResetPasswordTokenSentAt { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public DateTime? DeletedAt { get; set; } public DateTime? DeletedAt { get; set; }
@@ -38,14 +34,6 @@ namespace PrivaPub.Models.User
} }
} }
public class ContactItem
{
public string Type { get; set; }
public string Contact { get; set; }
public string Note { get; set; }
public DateTime CreationDate { get; set; } = DateTime.UtcNow;
}
public class RootUserSettings public class RootUserSettings
{ {
public string LanguageCode { get; set; } = "en-GB"; public string LanguageCode { get; set; } = "en-GB";
-9
View File
@@ -1,9 +0,0 @@
namespace PrivaPub.Models.User
{
public enum UserPolicyType
{
IsUser,
IsModerator,
IsAdmin
}
}
-1
View File
@@ -19,7 +19,6 @@
<PackageReference Include="NetVips.Native.linux-x64" Version="8.18.7" /> <PackageReference Include="NetVips.Native.linux-x64" Version="8.18.7" />
<PackageReference Include="OpenIddict.AspNetCore" Version="7.7.1" /> <PackageReference Include="OpenIddict.AspNetCore" Version="7.7.1" />
<PackageReference Include="OpenIddict.MongoDb" Version="7.7.1" /> <PackageReference Include="OpenIddict.MongoDb" Version="7.7.1" />
<PackageReference Include="PasswordGenerator" Version="3.0.0" />
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" /> <PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
<PackageReference Include="Serilog.Sinks.MongoDB" Version="7.3.0" /> <PackageReference Include="Serilog.Sinks.MongoDB" Version="7.3.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
+3 -14
View File
@@ -32,12 +32,7 @@ try
{ {
if (builder.Environment.IsProduction()) if (builder.Environment.IsProduction())
{ {
serverOptions.ListenLocalhost(6970 serverOptions.ListenLocalhost(6970);
//, options =>
//{
// options.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
//}
);
serverOptions.UseSystemd(); serverOptions.UseSystemd();
serverOptions.AddServerHeader = false; serverOptions.AddServerHeader = false;
} }
@@ -50,7 +45,6 @@ try
try try
{ {
builder.Services.PrivaPubAppSettingsConfiguration(builder.Configuration) builder.Services.PrivaPubAppSettingsConfiguration(builder.Configuration)
.PrivaPubWorkersConfiguration()
.PrivaPubAuthServicesConfiguration(builder.Configuration) .PrivaPubAuthServicesConfiguration(builder.Configuration)
.PrivaPubInternalizationConfiguration(builder.Configuration) .PrivaPubInternalizationConfiguration(builder.Configuration)
.PrivaPubOptimizationConfiguration() .PrivaPubOptimizationConfiguration()
@@ -206,9 +200,6 @@ try
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
//app.UseWhen(context => context.Request.Path.StartsWithSegments("/peasants") ||
// context.Request.Path.StartsWithSegments("/users"),
// app => app.UseSignatureVerification().UseDigestVerification());
app.MapGet("/build.json", () => Results.Json(new app.MapGet("/build.json", () => Results.Json(new
{ {
@@ -218,7 +209,6 @@ try
})); }));
app.MapControllers(); app.MapControllers();
app.MapRazorPages(); app.MapRazorPages();
//app.MapFallbackToFile("index.html");
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -226,12 +216,11 @@ try
throw; throw;
} }
Log.ForContext<Program>().Information($"Starting collAnon at {nameof(Program)}()"); Log.ForContext<Program>().Information($"Starting PrivaPub at {nameof(Program)}()");
try try
{ {
var dbClient = app.Services.GetService(typeof(DbEntities)) as DbEntities; var dbClient = app.Services.GetService(typeof(DbEntities)) as DbEntities;
var passwordHasher = app.Services.GetService(typeof(IPasswordHasher)) as IPasswordHasher; await dbClient.Init();
await dbClient.Init(passwordHasher);
await app.Services.GetRequiredService<PrivaPub.Federation.Moderation.IDomainBlocks>().Reload(CancellationToken.None); await app.Services.GetRequiredService<PrivaPub.Federation.Moderation.IDomainBlocks>().Reload(CancellationToken.None);
await PrivaPub.Api.Mastodon.Auth.PersonaExchange.EnsureFirstPartyClient(app.Services, CancellationToken.None); await PrivaPub.Api.Mastodon.Auth.PersonaExchange.EnsureFirstPartyClient(app.Services, CancellationToken.None);
} }
@@ -14,8 +14,9 @@ namespace PrivaPub.Services.ClientToServer.Public
AppConfigurationService = appConfigurationService; AppConfigurationService = appConfigurationService;
} }
// the build's ref (its tag, or the branch a manual deploy ran from), as /build.json and NodeInfo name it
public string GetCurrentVersion() => public string GetCurrentVersion() =>
AppConfigurationService.AppConfiguration.Version; string.IsNullOrEmpty(BuildInfo.Ref) ? BuildInfo.Commit : BuildInfo.Ref;
public async Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken) public async Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken)
{ {
@@ -23,15 +24,5 @@ namespace PrivaPub.Services.ClientToServer.Public
.Match(l => AppConfigurationService.AppConfiguration.SupportedLanguages.Contains(l.International2Code)) .Match(l => AppConfigurationService.AppConfiguration.SupportedLanguages.Contains(l.International2Code))
.ExecuteAsync(cancellationToken)).OrderBy(l => l.NativeName).ToArray(); .ExecuteAsync(cancellationToken)).OrderBy(l => l.NativeName).ToArray();
} }
public async Task<bool> IsValidLanguageId(string languageId)
{
var anyLanguageWithId = await DbEntities.Languages.Match(l => l.ID == languageId).ExecuteAnyAsync();
if (!anyLanguageWithId)
return false;
var language2Code = (await DbEntities.Languages
.Match(l => l.ID == languageId).ExecuteFirstAsync())?.International2Code;
return AppConfigurationService.AppConfiguration.SupportedLanguages.Contains(language2Code);
}
} }
} }
@@ -7,7 +7,5 @@ namespace PrivaPub.Services.ClientToServer.Public
string GetCurrentVersion(); string GetCurrentVersion();
Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken); Task<IEnumerable<Language>> GetLanguages(CancellationToken cancellationToken);
Task<bool> IsValidLanguageId(string languageId);
} }
} }
@@ -1,174 +0,0 @@
using Microsoft.Extensions.Localization;
using PrivaPub.ClientModels;
using PrivaPub.Models.User;
using PrivaPub.Resources;
using PrivaPub.StaticServices;
namespace PrivaPub.Services.ClientToServer.Public
{
public interface IPublicAvatarUsersService
{
Task<WebResult> GetLocalAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token);
Task<IEnumerable<Avatar>> GetLocalAvatars(UserPolicyType userPolicyType, CancellationToken token);
Task<WebResult> GetForeignAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token);
Task<IEnumerable<ForeignAvatar>> GetForeignAvatars(UserPolicyType userPolicyType, CancellationToken token);
Task<IEnumerable<Avatar>> GetRootAvatars(string rootUserId, CancellationToken token);
}
public class PublicAvatarUsersService : IPublicAvatarUsersService
{
readonly DbEntities _dbEntities;
readonly IStringLocalizer<GenericRes> _localizer;
readonly ILogger<PublicAvatarUsersService> _logger;
public PublicAvatarUsersService(DbEntities dbEntities,
IStringLocalizer<GenericRes> localizer,
ILogger<PublicAvatarUsersService> logger)
{
_dbEntities = dbEntities;
_localizer = localizer;
_logger = logger;
}
public async Task<WebResult> GetLocalAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token)
{
var result = new WebResult();
try
{
var query = _dbEntities.Avatars;
switch (userPolicyType)
{
case UserPolicyType.IsUser:
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
break;
case UserPolicyType.IsModerator:
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
break;
case UserPolicyType.IsAdmin:
query.Match(a => a.UserName == actor);
break;
}
var avatar = await query.ExecuteFirstAsync(token);
if (avatar == default)
return result.Invalidate(_localizer["User '{0}' not found.", actor], StatusCodes.Status404NotFound);
result.Data = avatar;
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetLocalAvatar)}");
return result.Invalidate(_localizer["Error: {0}", ex.ToString()], exception: ex);
}
}
public async Task<IEnumerable<Avatar>> GetLocalAvatars(UserPolicyType userPolicyType, CancellationToken token)
{
try
{
var query = _dbEntities.Avatars;
switch (userPolicyType)
{
case UserPolicyType.IsUser:
query.Match(a => !a.DeletionAt.HasValue);
break;
case UserPolicyType.IsModerator:
query.Match(a => !a.DeletionAt.HasValue);
break;
case UserPolicyType.IsAdmin:
break;
}
var avatars = await query.ExecuteAsync(token);
return avatars;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetLocalAvatars)}");
return Enumerable.Empty<Avatar>();
}
}
public async Task<WebResult> GetForeignAvatar(UserPolicyType userPolicyType, string actor, CancellationToken token)
{
var result = new WebResult();
try
{
var query = _dbEntities.ForeignAvatars;
switch (userPolicyType)
{
case UserPolicyType.IsUser:
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
break;
case UserPolicyType.IsModerator:
query.Match(a => !a.DeletionAt.HasValue && a.UserName == actor);
break;
case UserPolicyType.IsAdmin:
query.Match(a => a.UserName == actor);
break;
}
var avatar = await query.ExecuteFirstAsync(token);
if (avatar == default)
return result.Invalidate(_localizer["User '{0}' not found.", actor], StatusCodes.Status404NotFound);
result.Data = avatar;
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetForeignAvatar)}");
return result.Invalidate(_localizer["Error: {0}", ex.ToString()], exception: ex);
}
}
public async Task<IEnumerable<ForeignAvatar>> GetForeignAvatars(UserPolicyType userPolicyType, CancellationToken token)
{
try
{
var query = _dbEntities.ForeignAvatars;
switch (userPolicyType)
{
case UserPolicyType.IsUser:
query.Match(a => !a.DeletionAt.HasValue);
break;
case UserPolicyType.IsModerator:
query.Match(a => !a.DeletionAt.HasValue);
break;
case UserPolicyType.IsAdmin:
break;
}
var foreignAvatars = await query.ExecuteAsync(token);
return foreignAvatars;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetForeignAvatars)}");
return Enumerable.Empty<ForeignAvatar>();
}
}
public async Task<IEnumerable<Avatar>> GetRootAvatars(string rootUserId, CancellationToken token)
{
try
{
var rootUser = await _dbEntities.RootUsers.MatchID(rootUserId).ExecuteFirstAsync(token);
if (rootUser == default)
return Enumerable.Empty<Avatar>();
var rootToAvatars = await _dbEntities.RootToAvatars.Match(ra => ra.RootId == rootUserId).ExecuteAsync(token);
if (rootToAvatars.Count == 0)
return Enumerable.Empty<Avatar>();
var avatarIds = rootToAvatars.Select(ra => ra.AvatarId).ToArray();
var avatars = await _dbEntities.Avatars
.Match(a => avatarIds.Contains(a.ID))
.ProjectExcluding(a => a.Settings)
.ExecuteAsync(token);
return avatars;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(PublicAvatarUsersService)}.{nameof(GetRootAvatars)}");
return Enumerable.Empty<Avatar>();
}
}
}
}
-22
View File
@@ -18,7 +18,6 @@ namespace PrivaPub.Services
{ {
public interface IGroupUsersService public interface IGroupUsersService
{ {
Task<WebResult> GetGroup(string actor, CancellationToken token);
Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token); Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token);
Task<WebResult> InsertGroup(string rootUserId, InsertGroupForm form, CancellationToken token); Task<WebResult> InsertGroup(string rootUserId, InsertGroupForm form, CancellationToken token);
Task<WebResult> UpdateGroup(string rootUserId, UpdateGroupForm form, CancellationToken token); Task<WebResult> UpdateGroup(string rootUserId, UpdateGroupForm form, CancellationToken token);
@@ -58,27 +57,6 @@ namespace PrivaPub.Services
_logger = logger; _logger = logger;
} }
public async Task<WebResult> GetGroup(string actor, CancellationToken token)
{
var result = new WebResult();
try
{
var userName = actor?.ToLowerInvariant();
var group = await _dbEntities.Groups
.Match(g => g.UserName == userName && !g.DeletionAt.HasValue)
.ExecuteFirstAsync(token);
if (group == default)
return result.Invalidate(_localizer["Group '{0}' not found.", actor], StatusCodes.Status404NotFound);
result.Data = group;
return result;
}
catch (Exception ex)
{
_logger.LogError(ex, $"{nameof(GroupUsersService)}.{nameof(GetGroup)}");
return result.Invalidate(_localizer["Something went wrong."], exception: ex);
}
}
public async Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token) public async Task<WebResult> GetGroups(string rootUserId, string avatarId, CancellationToken token)
{ {
var result = new WebResult(); var result = new WebResult();
+2 -2
View File
@@ -7,9 +7,9 @@ namespace PrivaPub.Services
{ {
public interface IRootUsersService public interface IRootUsersService
{ {
Task<WebResult> LoginAsync(LoginForm loginForm, string invitationCode = default, bool isPasswordRequired = false); Task<WebResult> LoginAsync(LoginForm loginForm);
Task<WebResult> SignUpAsync(LoginForm signUpForm, string invitationCode = default, bool isPasswordRequired = false); Task<WebResult> SignUpAsync(LoginForm signUpForm);
Task<WebResult> BanUserAsync(UsersIds usersIds); Task<WebResult> BanUserAsync(UsersIds usersIds);
+3 -48
View File
@@ -1,14 +1,8 @@
using MailKit.Net.Smtp;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using MimeKit;
using MongoDB.Driver; using MongoDB.Driver;
using MongoDB.Entities; using MongoDB.Entities;
using PasswordGenerator;
using PrivaPub.ClientModels; using PrivaPub.ClientModels;
using PrivaPub.ClientModels.User; using PrivaPub.ClientModels.User;
using PrivaPub.Models; using PrivaPub.Models;
@@ -33,7 +27,6 @@ namespace PrivaPub.Services
readonly IStringLocalizer Localizer; readonly IStringLocalizer Localizer;
readonly ILogger<RootUsersService> Logger; readonly ILogger<RootUsersService> Logger;
readonly AppConfigurationService AppConfigurationService; readonly AppConfigurationService AppConfigurationService;
readonly AuthTokenManager AuthTokenManager;
readonly IJobQueue Jobs; readonly IJobQueue Jobs;
readonly IRootSessions Sessions; readonly IRootSessions Sessions;
readonly IRootRemoval Removal; readonly IRootRemoval Removal;
@@ -46,14 +39,12 @@ namespace PrivaPub.Services
ILogger<RootUsersService> logger, ILogger<RootUsersService> logger,
IPasswordHasher passwordHasher, IPasswordHasher passwordHasher,
DbEntities dbEntities, DbEntities dbEntities,
AppConfigurationService appConfigurationService, AppConfigurationService appConfigurationService)
AuthTokenManager authTokenManager)
{ {
Jobs = jobs; Jobs = jobs;
Sessions = sessions; Sessions = sessions;
Removal = removal; Removal = removal;
DbEntities = dbEntities; DbEntities = dbEntities;
AuthTokenManager = authTokenManager;
PasswordHasher = passwordHasher; PasswordHasher = passwordHasher;
Localizer = localizer; Localizer = localizer;
Logger = logger; Logger = logger;
@@ -66,8 +57,7 @@ namespace PrivaPub.Services
// a hash nobody's password matches, so an unknown login costs the same hashing as a wrong password // a hash nobody's password matches, so an unknown login costs the same hashing as a wrong password
string Decoy => _decoy ??= PasswordHasher.Hash(Convert.ToHexString(System.Security.Cryptography.RandomNumberGenerator.GetBytes(16))); string Decoy => _decoy ??= PasswordHasher.Hash(Convert.ToHexString(System.Security.Cryptography.RandomNumberGenerator.GetBytes(16)));
public async Task<WebResult> SignUpAsync(LoginForm signUpForm, string invitationCode = default, public async Task<WebResult> SignUpAsync(LoginForm signUpForm)
bool isPasswordRequired = false)
{ {
var result = new WebResult(); var result = new WebResult();
try try
@@ -98,23 +88,6 @@ namespace PrivaPub.Services
}; };
await DB.Default.SaveAsync(newUser); await DB.Default.SaveAsync(newUser);
//if (!string.IsNullOrEmpty(invitationCode))
//{
// if (isPasswordRequired)
// result = await DiscussionService.InviteUserToDiscussion(new PwDiscussionPreviewForm
// {
// InvitationCode = invitationCode,
// Password = signUpForm.InvitationPassword
// }, newUser.ID);
// else
// result = await DiscussionService.InviteUserToDiscussion(new NoPwDiscussionPreviewForm
// {
// InvitationCode = invitationCode,
// }, newUser.ID);
// if (!result.IsValid)
// return result;
//}
result.Data = (newUser, ToViewSettings(newUser.Settings)); result.Data = (newUser, ToViewSettings(newUser.Settings));
return result; return result;
@@ -126,8 +99,7 @@ namespace PrivaPub.Services
} }
} }
public async Task<WebResult> LoginAsync(LoginForm loginForm, string invitationCode = default, public async Task<WebResult> LoginAsync(LoginForm loginForm)
bool isPasswordRequired = false)
{ {
var result = new WebResult(); var result = new WebResult();
try try
@@ -148,23 +120,6 @@ namespace PrivaPub.Services
var userSettingsResult = await GetUserSettingsAsync(user.ID, loginForm); var userSettingsResult = await GetUserSettingsAsync(user.ID, loginForm);
var userSettings = (ViewUserSettings)userSettingsResult.Data; var userSettings = (ViewUserSettings)userSettingsResult.Data;
//if (!string.IsNullOrEmpty(invitationCode))
//{
// if (isPasswordRequired)
// result = await DiscussionService.InviteUserToDiscussion(new PwDiscussionPreviewForm
// {
// InvitationCode = invitationCode,
// Password = loginForm.InvitationPassword
// }, user.ID);
// else
// result = await DiscussionService.InviteUserToDiscussion(new NoPwDiscussionPreviewForm
// {
// InvitationCode = invitationCode,
// }, user.ID);
// if (!result.IsValid)
// return result;
//}
result.Data = (user, userSettings); result.Data = (user, userSettings);
return result; return result;
+1 -7
View File
@@ -1,18 +1,12 @@
{ {
"MongoSettings": { "MongoSettings": {
"Database": "PrivaPub", "Database": "PrivaPub",
"LogsDatabase": "logs",
"ConnectionString": "mongodb://localhost:27017" "ConnectionString": "mongodb://localhost:27017"
}, },
"Backups": { "Backups": {
"Nightly": false "Nightly": false
}, },
"AppConfiguration": { "AppConfiguration": {
"RequiresFirstTimeSetup": null,
"Version": "0.0.0",
"MaxAllowedUploadFiles": 3,
"MaxAllowedFileSize": 2097152,
"ValidDiscussionFilesTypes": ".odt,.docx,.pdf,.xlsx,.ods,.odp,.pptx,.png,.jpg,.jpeg",
"SupportedLanguages": [ "SupportedLanguages": [
"en", "en",
"it", "it",
@@ -83,7 +77,7 @@
"Name": "MongoDBCapped", "Name": "MongoDBCapped",
"Args": { "Args": {
"databaseUrl": "mongodb://localhost:27017/logs", "databaseUrl": "mongodb://localhost:27017/logs",
"collectionName": "collanonquick", "collectionName": "PrivaPub",
"cappedMaxSizeMb": "1024", "cappedMaxSizeMb": "1024",
"cappedMaxDocuments": "10000" "cappedMaxDocuments": "10000"
} }
-5
View File
@@ -30,16 +30,11 @@
}, },
"MongoSettings": { "MongoSettings": {
"Database": "PrivaPub", "Database": "PrivaPub",
"LogsDatabase": "logs",
"ConnectionString": "mongodb://127.0.0.1:27022/?directConnection=true" "ConnectionString": "mongodb://127.0.0.1:27022/?directConnection=true"
}, },
"AppConfiguration": { "AppConfiguration": {
"Version": "0.0.0",
"BackendBaseAddress": "https://privapub.thepra.dev", "BackendBaseAddress": "https://privapub.thepra.dev",
"FrontendBaseAddress": "https://decepub.thepra.dev", "FrontendBaseAddress": "https://decepub.thepra.dev",
"MaxAllowedUploadFiles": 3,
"MaxAllowedFileSize": 2097152,
"ValidDiscussionFilesTypes": ".odt,.docx,.pdf,.xlsx,.ods,.odp,.pptx,.png,.jpg,.jpeg",
"SupportedLanguages": [ "SupportedLanguages": [
"en", "it", "de", "fr", "es", "ja", "ru", "zh", "bg", "cs", "da", "nl", "et", "fi", "el", "hu", "lv", "lt", "pl", "pt", "ro", "sk", "sl", "sv" "en", "it", "de", "fr", "es", "ja", "ru", "zh", "bg", "cs", "da", "nl", "et", "fi", "el", "hu", "lv", "lt", "pl", "pt", "ro", "sk", "sl", "sv"
], ],
+1 -1
View File
@@ -535,7 +535,7 @@ on a Page: pins live in `featured`, locks in `Lock`.
| Gap | P | Client surface | | Gap | P | Client surface |
|---|---|---| |---|---|---|
| `Dislike` and its `Undo`: a vote ledger per object (actor, ±1, activity, relaying group, time) | P1 | `favourites_count` = upvotes; own `privapub.vote{score, up, down, mine}`, `POST …/vote` | | `Dislike` and its `Undo`: a vote ledger per object (actor, ±1, activity, relaying group, time) | P1 | `favourites_count` = upvotes; own `privapub.vote{score, up, down, mine}`, `POST …/vote` |
| Announces of activities other than Create (votes, moderation): trust the inner activity when the object's own group signed the Announce; refetching every vote does not scale. Keep the origin refetch for Create and Update. Votes and their undoing **done** 2026-10-04 (`AnnounceHandler.Relayed`: trusted from the community's own server or on its own posts, otherwise fetched from the voter's origin); moderation still open | P1 | — | | Announces of activities other than Create (votes, moderation): trust the inner activity when the object's own group signed the Announce; refetching every vote does not scale. Keep the origin refetch for Create and Update. Votes and their undoing **done** 2026-10-04 (`AnnounceHandler.Relayed`: trusted from the community's own server or on its own posts, otherwise fetched from the voter's origin); relayed locks and bans **done** 2026-10-05 (G-0006) | P1 | — |
| Moderation state: removals (reason, by, at, cascade), locks, bans with `endTime`/`removeData`, featured, moderators, `Update{Group}` by a moderator | P1 | removed posts hidden plus `privapub.removed`; `privapub.locked` (replying answers 422); pins as `pinned=true` | | Moderation state: removals (reason, by, at, cascade), locks, bans with `endTime`/`removeData`, featured, moderators, `Update{Group}` by a moderator | P1 | removed posts hidden plus `privapub.removed`; `privapub.locked` (replying answers 422); pins as `pinned=true` |
| Link posts: keep `Link.href`, the thumbnail `image` and alt text; build the card (Lemmy sends no title or description for the link) | P1 | `Status.card` | | Link posts: keep `Link.href`, the thumbnail `image` and alt text; build the card (Lemmy sends no title or description for the link) | P1 | `Status.card` |
| `ChatMessage` in and out (out to someone who writes to us that way, and to Lemmy 0.19 and Mbin by NodeInfo, done 2026-10-05) | P1 | `visibility: direct` | | `ChatMessage` in and out (out to someone who writes to us that way, and to Lemmy 0.19 and Mbin by NodeInfo, done 2026-10-05) | P1 | `visibility: direct` |
+57 -25
View File
@@ -9,10 +9,10 @@ Written 2026-10-01 from the original 2023 code, the decePubClient UI, a federati
- [x] P1.2 Social graph and timelines: v1.3.0, deployed and verified 2026-10-01 - [x] P1.2 Social graph and timelines: v1.3.0, deployed and verified 2026-10-01
- [x] P2 Mastodon client API: v1.4.0, deployed 2026-10-01; OAuth and the anonymous API verified on production, the signed-in API verified locally (no real-client login on production yet) - [x] P2 Mastodon client API: v1.4.0, deployed 2026-10-01; OAuth and the anonymous API verified on production, the signed-in API verified locally (no real-client login on production yet)
- [x] P3 Social features: v1.5.0, deployed 2026-10-01; media, proxy, blocks, mutes, bookmarks, pins and reports verified by tests and locally (no upload on production yet) - [x] P3 Social features: v1.5.0, deployed 2026-10-01; media, proxy, blocks, mutes, bookmarks, pins and reports verified by tests and locally (no upload on production yet)
- [x] P4 Groups and privacy features: v1.6.0, deployed 2026-10-01; communities, circles and local-only located posts verified by tests. v1.6.1 adds the pasture (`tools/pasture/`): live interop with GoToSocial 0.22.1 passes all 25 checks, three runs in a row. Lemmy and a live Mastodon circle member are not run yet; the pasture has GoToSocial only - [x] P4 Groups and privacy features: v1.6.0, deployed 2026-10-01; communities, circles and local-only located posts verified by tests. v1.6.1 adds the pasture (`tools/pasture/`): live interop with GoToSocial 0.22.1 passes all 25 checks, three runs in a row. Lemmy and a live Mastodon circle member are not run yet; the pasture has GoToSocial only (both run since: T/M and v1.19.1)
- [x] P5 Lose nothing: v1.7.0 to v1.9.1, deployed 2026-10-01; parsing, typed details, provenance, downvotes, tombstones, federated blocks, all checked live against GoToSocial. Book reviews and forum threads keep their raw form only (typed in P7 and P8) - [x] P5 Lose nothing: v1.7.0 to v1.9.1, deployed 2026-10-01; parsing, typed details, provenance, downvotes, tombstones, federated blocks, all checked live against GoToSocial. Book reviews and forum threads keep their raw form only (typed in P7 and P8)
- [x] P6 Emoji, polls, quotes, reactions, cards, players: v1.10.0 to v1.15.0, deployed 2026-10-01; polls, link cards, ranged video streaming and quote policies checked live against GoToSocial - [x] P6 Emoji, polls, quotes, reactions, cards, players: v1.10.0 to v1.15.0, deployed 2026-10-01; polls, link cards, ranged video streaming and quote policies checked live against GoToSocial
- [ ] T/M Test sweep, the full pasture and the interaction ledger (see "Sweep and statistics" below). T1–T4: v1.15.1, deployed and verified 2026-10-03 (CI runs all tests on a throwaway mongod; nothing answers 500). M1–M6: v1.16.0, deployed and verified 2026-10-03 (the interaction ledger records every inbox answer, handler verdict, delivery attempt and outbound request; the GoToSocial pasture passes 33/33 with no names in the statistics). T5–T9, T11 and M7–M11: v1.17.0, 2026-10-03: - [x] T/M Test sweep, the full pasture and the interaction ledger (see "Sweep and statistics" below). T1–T4: v1.15.1, deployed and verified 2026-10-03 (CI runs all tests on a throwaway mongod; nothing answers 500). M1–M6: v1.16.0, deployed and verified 2026-10-03 (the interaction ledger records every inbox answer, handler verdict, delivery attempt and outbound request; the GoToSocial pasture passes 33/33 with no names in the statistics). T5–T9, T11 and M7–M11: v1.17.0, 2026-10-03:
- 639 tests, now over HTTP too; - 639 tests, now over HTTP too;
- daily rollups, every touched server described and located, the admin statistics API, the opt-in crawler and `/stargazing`; - daily rollups, every touched server described and located, the admin statistics API, the opt-in crawler and `/stargazing`;
- the pasture as plugins: GoToSocial 37/37, Mastodon 49 plus 2 expected failures. - the pasture as plugins: GoToSocial 37/37, Mastodon 49 plus 2 expected failures.
@@ -30,7 +30,7 @@ Written 2026-10-01 from the original 2023 code, the decePubClient UI, a federati
- Akkoma's open polls showed as ended and refused votes. - Akkoma's open polls showed as ended and refused votes.
Both open items were closed without a root step (owner decisions, 2026-10-04): the server fetches its geolocation Both open items were closed without a root step (owner decisions, 2026-10-04): the server fetches its geolocation
databases itself, and the deploy makes and signs in as @thepra. databases itself, and the deploy makes and signs in as @thepra (that signed-in check was dropped on 2026-10-17).
- [x] Everything on in production (owner decisions 2026-10-04): - [x] Everything on in production (owner decisions 2026-10-04):
- v1.18.0, deployed and verified 2026-10-04: geolocation that updates itself (DB-IP Lite 2026-10 loaded), the deploy - v1.18.0, deployed and verified 2026-10-04: geolocation that updates itself (DB-IP Lite 2026-10 loaded), the deploy
signing in as @thepra (undiscoverable), the crawler on (1010 servers known within the hour), sign-up by invitation signing in as @thepra (undiscoverable), the crawler on (1010 servers known within the hour), sign-up by invitation
@@ -55,7 +55,8 @@ Written 2026-10-01 from the original 2023 code, the decePubClient UI, a federati
gap it finds fixed. Runs alongside P7, P8 and P9. Done so far: gap it finds fixed. Runs alongside P7, P8 and P9. Done so far:
- the town toolkit (`tools/pasture/town/`): drivers for PrivaPub and the six peers, the seeded `village` (23 accounts, - the town toolkit (`tools/pasture/town/`): drivers for PrivaPub and the six peers, the seeded `village` (23 accounts,
205 objects, 970 steps), the coherence sweep with known gaps (`gaps.json`), the report and `docs/INTEROP-BACKLOG.md`; 205 objects, 970 steps), the coherence sweep with known gaps (`gaps.json`), the report and `docs/INTEROP-BACKLOG.md`;
- decePubClient's end-to-end tests against the pasture (`decePubClient/tests/e2e`, Playwright for .NET); - decePubClient's end-to-end tests against the pasture (`decePubClient/tests/e2e`, Playwright for .NET; removed with the
test projects on 2026-10-17);
- three bugs the first village found, fixed: likes, reactions, votes and downvotes from followers on followers-only - three bugs the first village found, fixed: likes, reactions, votes and downvotes from followers on followers-only
posts and from circle members were dropped (G-0001); a Follow refused with Mastodon's first-contact 422 was lost for posts and from circle members were dropped (G-0001); a Follow refused with Mastodon's first-contact 422 was lost for
good; a persona addressed without being named could not see the post (silent mentions). good; a persona addressed without being named could not see the post (silent mentions).
@@ -108,6 +109,14 @@ Written 2026-10-01 from the original 2023 code, the decePubClient UI, a federati
- [x] Status search by words, scoped as Mastodon scopes it: what the persona wrote, boosted, favourited, bookmarked or - [x] Status search by words, scoped as Mastodon scopes it: what the persona wrote, boosted, favourited, bookmarked or
was named in, and public posts of authors who let themselves be indexed (off by default); newest first, through a was named in, and public posts of authors who let themselves be indexed (off by default); newest first, through a
text index over the posts' words in every language alike. text index over the posts' words in every language alike.
- [x] First-time setup and invitations (2026-10-16/17): PrivaPub v1.25.0, the first login made from the client while no
administrator exists, then setup sealed for good; decePub v1.6.0, `/setup` and `/join?code=`; PrivaPub v1.26.0,
`admin move-persona` and `admin delete-root`, and the deploy no longer signs in (@thepra is the administrator's). The
test projects were deleted the same day.
- [ ] C The completion program (owner decisions 2026-10-17, below): everything unfinished, in sixteen releases. Cleanup;
accounts (email, recovery, sessions, TOTP); the client catching up; the server's own settings; moderation; custom
emoji; the Mastodon API made real; Web Push; P7's communities; P8's signatures; the long tail with HEIC/HEIF;
hosting events; town drivers for every peer; public `/stargazing` and Bluesky bridging; the close-out.
## Intent ## Intent
@@ -244,7 +253,7 @@ and circles (see Owner decisions).
| Question | Decision | | Question | Decision |
|---|---| |---|---|
| What runs in production | **Everything that is built is on and checked by the deploy**, and nothing waits on a person running a command. | | What runs in production | **Everything that is built is on and checked by the deploy's anonymous checks** (nothing signs in since 2026-10-17), and nothing waits on a person running a command. |
| Geolocation | **The server fetches DB-IP Lite itself** (`GeoUpdater`): it checks daily, installs a new month's databases once they are published, refuses a file that does not open as the right kind of database, and keeps the old one when anything fails. No timer and no root step. The deploy fails if the databases are missing or more than 40 days old. | | Geolocation | **The server fetches DB-IP Lite itself** (`GeoUpdater`): it checks daily, installs a new month's databases once they are published, refuses a file that does not open as the right kind of database, and keeps the old one when anything fails. No timer and no root step. The deploy fails if the databases are missing or more than 40 days old. |
| Crawler | **On in production**, seeded with a handful of large servers of different kinds (`appsettings.Production.json`); the deploy fails if `/stargazing` does not say it is on. | | Crawler | **On in production**, seeded with a handful of large servers of different kinds (`appsettings.Production.json`); the deploy fails if `/stargazing` does not say it is on. |
| Sign-up | **Closed: invitations only.** A group invitation creates an account; open sign-up answers 403. NodeInfo, `/api/v1/instance` and `/api/v2/instance` read the same switch (`Registrations:Mode`), and the deploy fails if they disagree. The first login on a server is made from the client's setup page while no administrator exists (2026-10-16: first come, first served, no setup code); it becomes the administrator with its first persona, and setup closes for good (`ServerSetup`, kept across restores). `PrivaPub admin create-root` remains the way in from the box. | | Sign-up | **Closed: invitations only.** A group invitation creates an account; open sign-up answers 403. NodeInfo, `/api/v1/instance` and `/api/v2/instance` read the same switch (`Registrations:Mode`), and the deploy fails if they disagree. The first login on a server is made from the client's setup page while no administrator exists (2026-10-16: first come, first served, no setup code); it becomes the administrator with its first persona, and setup closes for good (`ServerSetup`, kept across restores). `PrivaPub admin create-root` remains the way in from the box. |
@@ -253,7 +262,7 @@ and circles (see Owner decisions).
| Signed fetches (SecureMode) | **On in production** once the pasture passes with it on (Phase 2 of the 2026-10-04 plan). | | Signed fetches (SecureMode) | **On in production** once the pasture passes with it on (Phase 2 of the 2026-10-04 plan). |
| Circles on Mastodon and GoToSocial | **Each member's copy names that member** in `cc`; a member's refetch names the member, an instance actor's refetch the members on its server. Nothing new is revealed to anyone outside the circle. | | Circles on Mastodon and GoToSocial | **Each member's copy names that member** in `cc`; a member's refetch names the member, an instance actor's refetch the members on its server. Nothing new is revealed to anyone outside the circle. |
| What circles and located posts reveal | **Unchanged**: circles still answer WebFinger, and circle and located posts still count in a persona's post count, "a good balance for the fediverse to work". | | What circles and located posts reveal | **Unchanged**: circles still answer WebFinger, and circle and located posts still count in a persona's post count, "a good balance for the fediverse to work". |
| Public `/stargazing` statistics | **Later**, as decided on 2026-10-03; the crawler and the admin API keep collecting meanwhile. | | Public `/stargazing` statistics | **Approved 2026-10-17** (C, release R15), built from public counters only. Until then the crawler and the admin API keep collecting. |
### Owner decisions on decePubClient (2026-10-04) ### Owner decisions on decePubClient (2026-10-04)
@@ -269,10 +278,10 @@ and circles (see Owner decisions).
| Question | Decision | | Question | Decision |
|---|---| |---|---|
| Scope | **Every self-hostable fediverse platform** in the pasture, accounts of every kind, a fake community across them, and coherence of state between all of them and PrivaPub, checked from both the servers and decePubClient. What the town finds is fixed until PrivaPub is the best federating server and decePubClient the best client for the fediverse at volume. | | Scope | **Every self-hostable fediverse platform** in the pasture, accounts of every kind, a fake community across them, and coherence of state between all of them and PrivaPub, checked from both the servers and decePubClient. What the town finds is fixed until PrivaPub is the best federating server and decePubClient the best client for the fediverse at volume. |
| The "Cut" list | **Lists, server-side filters, scheduled posts, followed hashtags, trends and a directory come back** (P9). The directory lists only discoverable personas; trends count only public posts PrivaPub already holds. Translation, local custom emoji, the Mastodon admin API, API registration, S3 and JSON-LD processing stay cut. | | The "Cut" list | **Lists, server-side filters, scheduled posts, followed hashtags, trends and a directory come back** (P9). The directory lists only discoverable personas; trends count only public posts PrivaPub already holds. Translation, local custom emoji, the Mastodon admin API, API registration, S3 and JSON-LD processing stay cut. *Local custom emoji came back on 2026-10-17 (C, R7).* |
| decePubClient tests | **Playwright for .NET**, against the pasture, never in CI. | | decePubClient tests | **Removed 2026-10-17.** They were Playwright for .NET against the pasture, never in CI. |
| How work lands | Commits on master in both repositories; nothing is pushed, tagged or deployed without asking. | | How work lands | Commits on master in both repositories; nothing is pushed, tagged or deployed without asking. *For the completion program (2026-10-17): each release is pushed to master, and the owner tags.* |
| Still asked first | Anything new that tells another server something about a persona, Web Push (traffic to push services), any admin endpoint in production, and anything acting from production or the owner's accounts. | | Still asked first | Anything new that tells another server something about a persona, Web Push (traffic to push services), any admin endpoint in production, and anything acting from production or the owner's accounts. *2026-10-17: Web Push, admin endpoints in production, public statistics and per-persona Bluesky bridging are approved; the rest still asks.* |
### Owner decisions on events and threads (2026-10-05) ### Owner decisions on events and threads (2026-10-05)
@@ -321,6 +330,26 @@ directory; the nginx locations), then v1.23.0, whose own pre-deploy backup was v
which held statistics salts, were deleted (owner's go-ahead); a salt-free dump taken just before the replica-set which held statistics salts, were deleted (owner's go-ahead); a salt-free dump taken just before the replica-set
conversion is kept in `/var/backups/privapub.thepra.dev/`. conversion is kept in `/var/backups/privapub.thepra.dev/`.
### Owner decisions on finishing everything (2026-10-17)
The owner found decePubClient's Administration page mostly placeholders and asked for every unfinished thing, there
and elsewhere, to be finished end to end. The plan is sixteen releases (Status, C): R1 cleanup, R2 accounts, R3 TOTP,
R4 the client catching up, R5 the server's own settings, R6 moderation, R7 custom emoji, R8 the Mastodon API, R9 Web
Push, R10 communities (P7), R11 signatures (P8), R12 the long tail, R13 hosting events, R14 town drivers, R15 public
statistics and Bluesky bridging, R16 the close-out.
| Question | Decision |
|---|---|
| Scope | **Everything, in waves**: the product (administration, accounts, the client, the Mastodon API, Web Push), then P7 and P8, then the long tail. |
| Administration | **Users and personas, instance and rules, relays and media limits, custom emoji** become real. The other Pleroma-era placeholders (Authentication, Frontend, Link formatter) go. |
| Secrets | **Stay committed**, by the existing convention; only code-level security is fixed. |
| Approved | **Web Push, the public `/stargazing` statistics, per-persona Bluesky bridging, email recovery in the client, local custom emoji, admin endpoints in production.** |
| Built after all | **Hosting events, HEIC/HEIF uploads, town drivers for every peer.** Discourse, NeoDB and Loops peers stay out. |
| Two-factor | **TOTP, right after email recovery** (R3). |
| A suspended local persona | **Tells other servers nothing new**: its posts and collections answer 404 and nothing is delivered from it; the actor stays as it is, so lifting the suspension is clean. |
| Releases | **Pushed to master, not tagged**: the owner tags when they choose. |
| Cut | FASP; rewriting HLS playlists; `Announce(object)` per peer; cross-post detection, PieFed's genAI flag, accepted answers and batched Announces; Ed25519 inbound RFC 9421; typed book reviews; the `Api/ClientApi` folder move; Pleroma `Listen` and `acceptsChatMessages` out; Owncast live state; a dislikes collection; Lemmy's `removeData`; translation; the Mastodon admin API; `POST /api/v1/accounts`; S3. |
## Libraries (researched; no maintained .NET ActivityPub library exists, so Letterbook and Iceshrimp.NET both wrote their own) ## Libraries (researched; no maintained .NET ActivityPub library exists, so Letterbook and Iceshrimp.NET both wrote their own)
| Area | Choice | | Area | Choice |
@@ -332,14 +361,14 @@ conversion is kept in `/var/backups/privapub.thepra.dev/`.
| Media | **NetVips** (+NetVips.Native) for images: autorotate, strip EXIF/GPS, thumbnails. **Blurhash.Core**, **FFMpegCore** for video. Own `IMediaStore` (local disk now). Not ImageSharp 4, whose license key is enforced at build. | | Media | **NetVips** (+NetVips.Native) for images: autorotate, strip EXIF/GPS, thumbnails. **Blurhash.Core**, **FFMpegCore** for video. Own `IMediaStore` (local disk now). Not ImageSharp 4, whose license key is enforced at build. |
| OAuth | **OpenIddict 7.7 + OpenIddict.MongoDb**: authorization code with PKCE, client_credentials, `oob` redirect, dynamic apps from `POST /api/v1/apps`, reference tokens | | OAuth | **OpenIddict 7.7 + OpenIddict.MongoDb**: authorization code with PKCE, client_credentials, `oob` redirect, dynamic apps from `POST /api/v1/apps`, reference tokens |
| Jobs | Own Mongo job collection for both inbox processing and delivery: `FindOneAndUpdate` leases, a `Channel` wake-up, per-host circuit breaker, Mastodon's backoff (`n⁴+15+jitter`, 16 tries). No MassTransit (commercial from v9, no Mongo transport). | | Jobs | Own Mongo job collection for both inbox processing and delivery: `FindOneAndUpdate` leases, a `Channel` wake-up, per-host circuit breaker, Mastodon's backoff (`n⁴+15+jitter`, 16 tries). No MassTransit (commercial from v9, no Mongo transport). |
| Tests | New xUnit project with fixture JSON captured from Mastodon, GoToSocial, Misskey, Lemmy and Akkoma; interop checked with Fediverse Pasture, verify.funfedi.dev and activitypub.academy | | Tests | *Removed 2026-10-17 (owner decision): there is no test project.* Interop is checked with the pasture, verify.funfedi.dev and activitypub.academy |
**FEPs, now:** FEP-f1d5 (NodeInfo 2.0 and 2.1), FEP-67ff (FEDERATION.md), FEP-8fcf, FEP-5feb `indexable`, **FEPs, now:** FEP-f1d5 (NodeInfo 2.0 and 2.1), FEP-67ff (FEDERATION.md), FEP-8fcf, FEP-5feb `indexable`,
FEP-7628 Move, FEP-2c59, FEP-044f quotes (parse, plus `interactionPolicy`), FEP-1b12 groups. FEP-7628 Move, FEP-2c59, FEP-044f quotes (parse, plus `interactionPolicy`), FEP-1b12 groups.
**FEPs, later:** FEP-521a, FEP-8b32, FEP-e232, relays (FEP-ae0c). **FEPs, later:** FEP-521a, FEP-8b32, FEP-e232, relays (FEP-ae0c); all done since.
**FEPs, skipped:** FEP-c390, FEP-ef61, FEP-fb2a, FEP-844e. **FEPs, skipped:** FEP-c390, FEP-ef61, FEP-fb2a. (FEP-844e was implemented after all, 2026-10-06.)
## Route names (deliberate; part of the project's character) ## Route names (deliberate; part of the project's character)
@@ -434,9 +463,10 @@ The first refactor commit is a pure move with namespaces only. Logic changes fol
- Plain: `PublicKeyId`, `(GroupUserId, _id)`, `(GroupId, _id)`. - Plain: `PublicKeyId`, `(GroupUserId, _id)`, `(GroupId, _id)`.
- **Rate limiting** on login, signup, invitation and inbox (per key host). - **Rate limiting** on login, signup, invitation and inbox (per key host).
- **Cleanup:** delete `Services/ActivityPubClient.cs` and `Models/Post/PostBoost.cs`. - **Cleanup:** delete `Services/ActivityPubClient.cs` and `Models/Post/PostBoost.cs`.
- **New `PrivaPub.Tests`** (xUnit v3): IpRangeGuard table, signature fixtures (a real Mastodon request plus tampering - **New `PrivaPub.Tests`** (xUnit v3; removed 2026-10-17): IpRangeGuard table, signature fixtures (a real Mastodon request plus tampering
cases), key-poisoning, origin rules, XSS corpus, DM injection. cases), key-poisoning, origin rules, XSS corpus, DM injection.
- **CI:** `build.yml` runs the tests. `deploy.yml` runs the tests and a `mongodump` before swapping. - **CI:** `build.yml` runs the tests. `deploy.yml` runs the tests and a `mongodump` before swapping. *Since then the server's
own pre-deploy backup replaced the mongodump, and on 2026-10-17 the tests went.*
### P1 Interop foundations (two deploys) ### P1 Interop foundations (two deploys)
@@ -573,7 +603,7 @@ The first refactor commit is a pure move with namespaces only. Logic changes fol
- **Bookmarks and pins:** pins are served as the `featured` collection at `/peasants/{name}/trophies`, with featured - **Bookmarks and pins:** pins are served as the `featured` collection at `/peasants/{name}/trophies`, with featured
tags at `/tattoos`. tags at `/tattoos`.
- **Blocks and mutes:** per avatar. **Block is not federated**: it sends Reject or Undo Follow instead and drops the - **Blocks and mutes:** per avatar. **Block is not federated**: it sends Reject or Undo Follow instead and drops the
blocked actor's traffic. Domain blocks per account as well. blocked actor's traffic. *Superseded: blocks federate (owner decision, "Blocks").* Domain blocks per account as well.
- **Reports:** inbound Flag becomes a `Report`. Outbound Flag is **sent by the instance actor**, or for a post in a - **Reports:** inbound Flag becomes a `Report`. Outbound Flag is **sent by the instance actor**, or for a post in a
community on Lemmy, PieFed or Mbin by the reporter `privapub_reports` (2026-10-06), so the reporting persona isn't community on Lemmy, PieFed or Mbin by the reporter `privapub_reports` (2026-10-06), so the reporting persona isn't
revealed. Moderator endpoints on `/clientapi`. revealed. Moderator endpoints on `/clientapi`.
@@ -759,8 +789,8 @@ it, raw where it doesn't.
- `implements` (FEP-844e): **done 2026-10-06** (RFC 9421, on the instance actor and as every actor's `generator`). - `implements` (FEP-844e): **done 2026-10-06** (RFC 9421, on the instance actor and as every actor's `generator`).
- **Mastodon API:** ~~streaming WebSocket~~ (done 2026-10-05: `/api/v1/streaming` as a WebSocket and as server-sent - **Mastodon API:** ~~streaming WebSocket~~ (done 2026-10-05: `/api/v1/streaming` as a WebSocket and as server-sent
events, user, notification, public, hashtag and list streams, each event mapped for its persona; a deletion reaches events, user, notification, public, hashtag and list streams, each event mapped for its persona; a deletion reaches
only the streams that showed the post), Web Push (gated: outbound traffic to push services), grouped notifications. only the streams that showed the post), Web Push (gated: outbound traffic to push services; approved 2026-10-17, C R9), grouped
Then advertise an honest version. notifications. Then advertise an honest version.
- **Backfill:** an author's outbox after following them: **done 2026-10-05** (`OutboxBackfill`, the first page's - **Backfill:** an author's outbox after following them: **done 2026-10-05** (`OutboxBackfill`, the first page's
public posts, twenty at most, once a day; checked live against Mastodon). public posts, twenty at most, once a day; checked live against Mastodon).
- **Long tail:** - **Long tail:**
@@ -793,25 +823,27 @@ buckets and only for servers reporting at least 10 users; the owner never intend
### Cut or deferred (deliberately) ### Cut or deferred (deliberately)
- **Cut:** - **Cut:**
- Link-preview cards *fetched from the linked page* by default. Cards built from the object, or from FEP-8967 - Link-preview cards *fetched from the linked page* by default. Cards built from the object, or from FEP-8967
`preview` data, are in P6; fetching the page is an owner decision (INTEROP §6.1). `preview` data, are in P6; fetching the page is an owner decision (INTEROP §6.1). *The owner decided to fetch ("Link
previews"); shipped in P6.*
- Translation. (Trends, the directory, lists, filters and scheduled posts were cut too, until the owner brought them - Translation. (Trends, the directory, lists, filters and scheduled posts were cut too, until the owner brought them
back on 2026-10-04: P9.) back on 2026-10-04: P9.)
- The Mastodon admin API: moderation stays on `/clientapi`. - The Mastodon admin API: moderation stays on `/clientapi`.
- `POST /api/v1/accounts` registration: avatars are created through `/clientapi`. - `POST /api/v1/accounts` registration: avatars are created through `/clientapi`.
- Local custom emoji. - Local custom emoji. *Back on 2026-10-17 (C, R7).*
- S3 storage. - S3 storage.
- JSON-LD and LD-signature processing. FEP-8b32 proofs need neither (JCS), so they are in P8. - JSON-LD and LD-signature processing. FEP-8b32 proofs need neither (JCS), so they are in P8.
- **Deferred:** video transcoding (remux only for now). - **Deferred:** video transcoding (remux only for now). *Done since: video is transcoded (CLAUDE.md, Media invariants).*
## Verification (per phase) ## Verification (per phase)
- **Unit tests** (`PrivaPub.Tests`) on every phase. Fixture JSON is captured per peer into - **Unit tests** (`PrivaPub.Tests`) on every phase. *Removed 2026-10-17: no test project remains.* Fixture JSON is captured per peer into
`Fixtures/{mastodon,gotosocial,misskey,akkoma,lemmy}/`. Renderers are checked against golden JSON. Inbound `Fixtures/{mastodon,gotosocial,misskey,akkoma,lemmy}/`. Renderers are checked against golden JSON. Inbound
scenarios run as integration tests on a throwaway mongod. scenarios run as integration tests on a throwaway mongod.
- **Interop:** **Fediverse Pasture** runs on the workstation with podman: Mastodon, GoToSocial, Misskey/Sharkey, - **Interop:** **Fediverse Pasture** runs on the workstation with podman: Mastodon, GoToSocial, Misskey/Sharkey,
Akkoma, plus Lemmy for P4. As built, `tools/pasture/run.sh` runs PrivaPub and GoToSocial behind one Caddy on a Akkoma, plus Lemmy for P4. As built, `tools/pasture/run.sh` runs PrivaPub and GoToSocial behind one Caddy on a
podman network, with `AllowPrivateNetworks`, `AllowPlainHttp` and `AcceptAnyCertificate`; startup refuses all three in podman network, with `AllowPrivateNetworks`, `AllowPlainHttp` and `AcceptAnyCertificate`; startup refuses all three in
Production. `tools/pasture/interop.sh` drives the matrix for GoToSocial; the other peers are still to be added. The Production. `tools/pasture/interop.sh` drives the matrix for GoToSocial; the other peers are still to be added. *(Since added: the
pasture runs every peer in `tools/pasture/peers/`, and `tools/pasture/sweep.sh` runs them all.)* The
matrix, per peer: matrix, per peer:
- follow both ways; - follow both ways;
- public, unlisted, followers-only and direct posts both ways; - public, unlisted, followers-only and direct posts both ways;
@@ -829,7 +861,7 @@ buckets and only for servers reporting at least 10 users; the owner never intend
- **P2:** Tusky, Elk, Phanpy and Ivory each log in with two avatars of one root as separate accounts. Home paginates - **P2:** Tusky, Elk, Phanpy and Ivory each log in with two avatars of one root as separate accounts. Home paginates
both ways; post, reply, DM, follow-by-search, notifications, CW, and edit or delete-and-redraft all work. both ways; post, reply, DM, follow-by-search, notifications, CW, and edit or delete-and-redraft all work.
`tools/smoke/mastodon-api.sh` runs after every deploy. A test asserts that no response for avatar A contains avatar `tools/smoke/mastodon-api.sh` runs after every deploy. A test asserts that no response for avatar A contains avatar
B's id. B's id. *(That test went with the test projects.)*
- **P3:** - **P3:**
- `exiftool` shows no GPS data on an uploaded original. - `exiftool` shows no GPS data on an uploaded original.
- Elk renders the blurhash. - Elk renders the blurhash.
@@ -845,7 +877,7 @@ buckets and only for servers reporting at least 10 users; the owner never intend
## Risks and sequencing ## Risks and sequencing
- Unique indexes fail on existing duplicates, so the dedupe migration runs first. Run a `mongodump` before every - Unique indexes fail on existing duplicates, so the dedupe migration runs first. Run a `mongodump` before every
tagged deploy from P0 on. tagged deploy from P0 on. *(The server's own pre-deploy backup does this now.)*
- Merge DmPost into Post and register `PrivacyIdGenerator` **before P2** exposes ids to clients. - Merge DmPost into Post and register `PrivacyIdGenerator` **before P2** exposes ids to clients.
- The publish grows by about 20 MB (OpenIddict, NetVips.Native, FFMpegCore). Keep `deploy.yml`'s asserted file list - The publish grows by about 20 MB (OpenIddict, NetVips.Native, FFMpegCore). Keep `deploy.yml`'s asserted file list
current, and add ffmpeg in `deploy/max/setup.sh`. current, and add ffmpeg in `deploy/max/setup.sh`.
-4
View File
@@ -1,13 +1,9 @@
{ {
"MongoSettings": { "MongoSettings": {
"Database": "PrivaPub", "Database": "PrivaPub",
"LogsDatabase": "logs",
"ConnectionString": "mongodb://mongo:27017/?directConnection=true" "ConnectionString": "mongodb://mongo:27017/?directConnection=true"
}, },
"AppConfiguration": { "AppConfiguration": {
"Version": "0.0.0",
"MaxAllowedUploadFiles": 3,
"MaxAllowedFileSize": 2097152,
"SupportedLanguages": [ "en" ], "SupportedLanguages": [ "en" ],
"BackendBaseAddress": "https://privapub.test", "BackendBaseAddress": "https://privapub.test",
"FrontendBaseAddress": "https://privapub.test", "FrontendBaseAddress": "https://privapub.test",
+3 -2
View File
@@ -1,8 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Drives PrivaPub and each peer (started by run.sh) through each other's federation, as their users would, then checks # Drives PrivaPub and each peer (started by run.sh) through each other's federation, as their users would, then checks
# that PrivaPub's statistics saw it all without naming anyone. # that PrivaPub's statistics saw it all without naming anyone.
# usage: tools/pasture/interop.sh [peer...] peers: gts (default), mastodon, misskey, sharkey, akkoma, lemmy, # usage: tools/pasture/interop.sh [scenario...] gts (default), and every other file in scenarios/: a peer's (with
# peertube, crawler # that peer up) or one across peers (threads, relay, restore, ...)
# tools/pasture/sweep.sh [A|B|C|D ...] every peer's scenario, a batch of peers at a time
set -uo pipefail set -uo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "$here/lib/interop.sh" . "$here/lib/interop.sh"
+1
View File
@@ -5,6 +5,7 @@
# usage: tools/pasture/run.sh up [peer...] | add <peer...> | down [--purge] | logs <name> | ps | stats # usage: tools/pasture/run.sh up [peer...] | add <peer...> | down [--purge] | logs <name> | ps | stats
# up starts everything afresh (PrivaPub republished, Mongo empty); add starts more peers next to a running pasture. # up starts everything afresh (PrivaPub republished, Mongo empty); add starts more peers next to a running pasture.
# peers: gts (default), mastodon, misskey, sharkey, akkoma, lemmy, decepub, and every other file in peers/ # peers: gts (default), mastodon, misskey, sharkey, akkoma, lemmy, decepub, and every other file in peers/
# tools/pasture/sweep.sh runs every peer's scenario, a batch of peers at a time (up, interop.sh, down).
set -euo pipefail set -euo pipefail
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/pasture.sh" . "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/pasture.sh"
+2 -1
View File
@@ -192,7 +192,8 @@ curl -s -o /dev/null -X POST -H "$LH" "$P/api/v1/follow_requests/$requester/auth
until_true 20 '[ "$(gcurl -s -H "$GH" "$G/api/v1/accounts/relationships?id[]=$locked_on_gts" | j "print(d[0][\"following\"])")" = "True" ]' && ok "an authorized request makes gtsuser a follower" || ko "authorization not applied on GoToSocial" until_true 20 '[ "$(gcurl -s -H "$GH" "$G/api/v1/accounts/relationships?id[]=$locked_on_gts" | j "print(d[0][\"following\"])")" = "True" ]' && ok "an authorized request makes gtsuser a follower" || ko "authorization not applied on GoToSocial"
echo "smoke" echo "smoke"
"$here/../smoke/mastodon-api.sh" "$P" "$PT" >/dev/null 2>&1 && ok "the deploy's Mastodon smoke check passes, signed in" || ko "the Mastodon smoke check fails" # tools/smoke/mastodon-api.sh: the deploy runs it anonymously; here a persona's token adds its signed-in checks
"$here/../smoke/mastodon-api.sh" "$P" "$PT" >/dev/null 2>&1 && ok "the Mastodon smoke check passes, anonymously and with a persona's token" || ko "the Mastodon smoke check fails"
echo "interaction policies" echo "interaction policies"
# gtsuser's post asks before anyone but its author replies or likes, and lets nobody else boost it: PrivaPub shows the # gtsuser's post asks before anyone but its author replies or likes, and lets nobody else boost it: PrivaPub shows the
+3 -13
View File
@@ -1,8 +1,8 @@
# Mobilizon 5.2.4: a group and its events. alice_mobilizon follows the group, which announces the events its members # Mobilizon 5.2.4: a group and its events. alice_mobilizon follows the group, which announces the events its members
# organise; an event arrives as an Event with its dates and place; she joins it and leaves; comments both ways; an edit # organise; an event arrives as an Event with its dates and place; she joins it and leaves; comments both ways; an edit
# and comments closed; deletes; a group post; an event kept for decePubClient's e2e; the unfollow. An event made through its API without options has its comments closed # and comments closed; deletes; a group post; the unfollow. An event made through its API without options has its
# (`commentsEnabled: false`), which PrivaPub honours, so this one opens them. Mobilizon's API is GraphQL (/api), signed in by its login mutation; what it holds is read from # comments closed (`commentsEnabled: false`), which PrivaPub honours, so this one opens them. Mobilizon's API is GraphQL
# its PostGIS (database mobilizon). # (/api), signed in by its login mutation; what it holds is read from its PostGIS (database mobilizon).
MZ=https://mobilizon.test:6443 MZ=https://mobilizon.test:6443
mz_sql() { podman exec pasture-postgis psql -U pasture -d mobilizon -tAc "$1" 2>/dev/null; } mz_sql() { podman exec pasture-postgis psql -U pasture -d mobilizon -tAc "$1" 2>/dev/null; }
# mz <query> [variables as JSON]: a GraphQL request as mzuser, its JSON answer # mz <query> [variables as JSON]: a GraphQL request as mzuser, its JSON answer
@@ -91,16 +91,6 @@ mz 'mutation($g:ID!,$t:String!){createPost(attributedToId:$g,title:$t,body:"<p>t
"{\"g\":\"$group\",\"t\":\"$post_title\"}" >/dev/null "{\"g\":\"$group\",\"t\":\"$post_title\"}" >/dev/null
until_true 60 '[ -n "$(p_home_has "$post_title")" ]' && ok "the group's post reaches alice_mobilizon's home, with its title" || ko "the group's post never arrived" until_true 60 '[ -n "$(p_home_has "$post_title")" ]' && ok "the group's post reaches alice_mobilizon's home, with its title" || ko "the group's post never arrived"
echo " an event kept for decePub's tests"
# decePubClient's e2e joins it from its card (tests/e2e/Actions/EventTests.cs); the one a run before this one kept goes
kept="$here/.state/mobilizon-kept-event.json"
[ -s "$kept" ] && mz 'mutation($e:ID!){deleteEvent(eventId:$e){id}}' "{\"e\":\"$(j "print(d['id'])" < "$kept")\"}" >/dev/null
kept_title="A concert kept for decePub $(date +%s)"
kept_begins=$(date -u -d '+10 days' +%Y-%m-%dT19:00:00Z); kept_ends=$(date -u -d '+10 days' +%Y-%m-%dT22:00:00Z)
mz 'mutation($t:String!,$b:DateTime!,$e:DateTime!,$o:ID!,$g:ID){createEvent(title:$t,description:"<p>come and listen</p>",beginsOn:$b,endsOn:$e,organizerActorId:$o,attributedToId:$g,visibility:PUBLIC,joinOptions:FREE,options:{commentModeration:ALLOW_ALL},physicalAddress:{description:"Piazza del Popolo",locality:"Roma",country:"Italia",geom:"12.4763;41.9109"}){id url}}' \
"{\"t\":\"$kept_title\",\"b\":\"$kept_begins\",\"e\":\"$kept_ends\",\"o\":\"$me\",\"g\":\"$group\"}" | j "print(json.dumps(d['data']['createEvent']))" > "$kept"
until_true 60 '[ -n "$(p_home_has "$kept_title")" ]' && ok "an event kept for decePub's tests reaches PrivaPub" || ko "the kept event never arrived"
echo " unfollow" echo " unfollow"
curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$group_on_p/unfollow" curl -s -o /dev/null -X POST -H "$PH" "$P/api/v1/accounts/$group_on_p/unfollow"
until_true 45 '[ "$(mz_sql "select count(*) from followers f join actors a on a.id = f.actor_id where a.url like '"'%alice_mobilizon%'"'")" = "0" ]' \ until_true 45 '[ "$(mz_sql "select count(*) from followers f join actors a on a.id = f.actor_id where a.url like '"'%alice_mobilizon%'"'")" = "0" ]' \
+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env bash
# Every peer's scenario, a batch of peers at a time: a change to what PrivaPub sends (the @context, an actor's
# properties, an activity's shape, a delivery's headers) runs against all of them before it is committed, since one
# reader stricter than the rest fails on it alone. Each batch starts its own pasture afresh (run.sh up), runs its
# scenarios (interop.sh) and takes the pasture down (run.sh down), and the next batch runs whatever the one before did.
# PrivaPub runs with SecureMode on, as in production, unless PRIVAPUB_ENV says otherwise; DOTNET and PASTURE_PORT reach
# run.sh as they are. Each batch's output is kept in out/sweep-<batch>.log.
# usage: tools/pasture/sweep.sh [A|B|C|D ...] (default: every batch, in that order)
# A gts mastodon misskey sharkey akkoma, with relay and aoderelay; scenarios: those five, threads followsync pins
# moves relay (relay's covers both relays)
# B lemmy lemmy19 piefed mbin nodebb
# C peertube pixelfed vernissage wordpress ghost writefreely owncast castopod funkwhale
# D friendica mobilizon gancio bookwyrm smithereen mitra snac ktistec forte hubzilla
# Not swept: restore (run it alone: it restores the whole server), crawler (it needs the crawler's own settings) and
# persona-archive; hollo, iceshrimp, pleroma, flood and decepub have no scenario of their own.
set -uo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export PRIVAPUB_ENV=${PRIVAPUB_ENV:-Federation__SecureMode=true}
batch_peers() {
case "$1" in
A) echo "gts mastodon misskey sharkey akkoma relay aoderelay" ;;
B) echo "lemmy lemmy19 piefed mbin nodebb" ;;
C) echo "peertube pixelfed vernissage wordpress ghost writefreely owncast castopod funkwhale" ;;
D) echo "friendica mobilizon gancio bookwyrm smithereen mitra snac ktistec forte hubzilla" ;;
esac
}
batch_scenarios() {
case "$1" in
A) echo "gts mastodon misskey sharkey akkoma threads followsync pins moves relay" ;;
*) batch_peers "$1" ;;
esac
}
[ $# -gt 0 ] || set -- A B C D
for batch in "$@"; do
[ -n "$(batch_peers "$batch")" ] || { echo "no such batch: $batch (A, B, C or D)" >&2; exit 2; }
for peer in $(batch_peers "$batch"); do
[ -f "$here/peers/$peer.sh" ] || { echo "batch $batch: no such peer: $peer" >&2; exit 2; }
done
for scenario in $(batch_scenarios "$batch"); do
[ -f "$here/scenarios/$scenario.sh" ] || { echo "batch $batch: no scenario for $scenario" >&2; exit 2; }
done
done
mkdir -p "$here/out"
summary=(); bad=0
for batch in "$@"; do
log="$here/out/sweep-$batch.log"
echo "== batch $batch: $(batch_peers "$batch")"
# shellcheck disable=SC2046
if ! "$here/run.sh" up $(batch_peers "$batch") 2>&1 | tee "$log"; then
summary+=("$batch the pasture did not start (out/sweep-$batch.log)"); bad=1
"$here/run.sh" down || true
continue
fi
# shellcheck disable=SC2046
"$here/interop.sh" $(batch_scenarios "$batch") 2>&1 | tee -a "$log"
status=${PIPESTATUS[0]}
"$here/run.sh" down || true
passed=$(grep -c '^ ok ' "$log"); failed=$(grep -c '^ FAIL ' "$log"); xfailed=$(grep -c '^ xf ' "$log")
line="$batch ok $passed ko $failed xf $xfailed ($(batch_scenarios "$batch"))"
if ! grep -qE '^[0-9]+ passed, [0-9]+ failed, [0-9]+ expected failures$' "$log"; then
line="$line stopped before its end (exit $status)"; bad=1
fi
[ "$failed" = 0 ] || bad=1
summary+=("$line")
done
echo; echo "sweep:"
printf ' %s\n' "${summary[@]}"
[ "$bad" = 0 ]
+1 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# The town: a fake community seeded across every pasture peer, then checked for coherence (see town/town.py). # The town: a fake community seeded across every pasture peer, then checked for coherence (see town/town.py).
# usage: tools/pasture/town.sh <command> [args] commands: selftest, seed, check, report, backlog, gaps, drive, stored, seen, # usage: tools/pasture/town.sh <command> [args] commands: selftest, seed, check, report, backlog, drive, stored, seen,
# renew <peer> (its accounts signed in again) # renew <peer> (its accounts signed in again)
exec python3 "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/town/town.py" "$@" exec python3 "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/town/town.py" "$@"
+3 -4
View File
@@ -1,5 +1,5 @@
"""docs/INTEROP-BACKLOG.md from the latest town results, the bash scenarios and decePub's e2e cells: new failures (to fix """docs/INTEROP-BACKLOG.md from the latest town results and the bash scenarios: new failures (to fix or to record in
or to record in gaps.json), known gaps by phase, known gaps now passing (close them), and the scenarios' failures. gaps.json), known gaps by phase, known gaps now passing (close them), and the scenarios' failures.
town.sh backlog [run] [--write]""" town.sh backlog [run] [--write]"""
import json import json
@@ -27,9 +27,8 @@ def main(args):
with open(os.path.join(run_dir, "results.json")) as f: with open(os.path.join(run_dir, "results.json")) as f:
result = json.load(f) result = json.load(f)
gaps = {g["id"]: g for g in check.load_gaps()} gaps = {g["id"]: g for g in check.load_gaps()}
client = check.classify(check.latest_client([dict(c) for c in load_jsonl(os.path.join(seed.OUT, "client.jsonl"))]), list(gaps.values()))
scenarios = load_jsonl(os.path.join(seed.OUT, "scenarios.jsonl")) scenarios = load_jsonl(os.path.join(seed.OUT, "scenarios.jsonl"))
checks = result["checks"] + client checks = result["checks"]
new = defaultdict(list) new = defaultdict(list)
known = defaultdict(list) known = defaultdict(list)
-15
View File
@@ -478,21 +478,6 @@ def canary_hits(platform, canaries):
return sorted(c for c in canaries if c in dump) return sorted(c for c in canaries if c in dump)
def latest_client(lines):
"""decePub's e2e cells (out/client.jsonl, appended by every run) as each cell's latest run left them: the rows from
within an hour of the cell's newest, the newest per test. A run that picked other accounts leaves no stale failure."""
from datetime import datetime, timedelta
at = lambda c: datetime.fromisoformat(c["t"].replace("Z", "+00:00"))
newest = {}
for c in lines:
newest[c["cell"]] = max(newest.get(c["cell"], at(c)), at(c))
latest = {}
for c in sorted(lines, key=at):
if at(c) >= newest[c["cell"]] - timedelta(hours=1):
latest[(c["cell"], c.get("ref"))] = c
return list(latest.values())
def load_gaps(): def load_gaps():
try: try:
with open(os.path.join(HERE, "gaps.json")) as f: with open(os.path.join(HERE, "gaps.json")) as f:
-63
View File
@@ -1,63 +0,0 @@
"""What the town's objects should look like to a reader, for decePub's e2e tests: for every object PrivaPub holds and some
town persona may see, its ref, URI, PrivaPub id, origin, kind, visibility, the text marker, content warning, media alt
texts, poll options, quoted and parent URIs, and the personas that may see it.
town.sh expect [run] [--persona <username>]"""
import json
import sys
import check
import seed
from dialects import driver
def edited_cw(world, ref, args):
"""The warning an object shows now: an edit made before plans kept warnings replaced the post without one."""
edit = next((s for s in world.planner.steps if s["verb"] == "edit" and s["args"]["target"] == ref), None)
if edit is None or ref not in world.edited:
return args.get("cw")
return edit["args"].get("cw")
def objects(world):
steps = {s["ref"]: s for s in world.planner.steps if s.get("ref") and s["verb"] == "post"}
held = driver("privapub").stored([o["uri"] for o in world.objects.values()])
personas = [k for k in world.planner.accounts if k.startswith("privapub/")]
out = []
for ref, o in sorted(world.objects.items(), key=lambda kv: int(kv[0][1:])):
row = held.get(o["uri"])
if not row or not row.exists or row.deleted or ref in world.deleted:
continue
recipients = world.recipients(o)
readers = [p.split("/")[1] for p in personas
if p == o["author"] or p in recipients or o["visibility"] in ("public", "unlisted", "community")]
if not readers:
continue
args = steps[ref]["args"]
out.append({
"ref": ref, "uri": o["uri"], "id": row.local_id, "origin": o["origin"], "author": o["author"],
"kind": o["kind"], "visibility": o["visibility"], "marker": f"({ref})", "cw": edited_cw(world, ref, args),
"alts": [m["alt"] for m in args.get("media", [])], "poll": (args.get("poll") or {}).get("options"),
"quote": world.objects.get(o.get("quote") or "", {}).get("uri"),
"parent": world.objects.get(o.get("parent") or "", {}).get("uri"),
"edited": ref in world.edited, "title": args.get("title"), "readers": readers,
"followers_of_author": sorted(p.split("/")[1] for p in world.follows.get(o["author"], set()) if p.startswith("privapub/")),
})
return out
def main(args):
name = next((a for a in args if not a.startswith("--") and not a.startswith("privapub/")), "village")
persona = None
if "--persona" in args:
persona = args[args.index("--persona") + 1].split("/")[-1]
world = check.World(seed.run_dir(name))
items = objects(world)
if persona:
items = [i for i in items if persona in i["readers"]]
print(json.dumps(items, ensure_ascii=False))
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))
+1 -1
View File
@@ -75,7 +75,7 @@
"code": "misskey-dev/misskey packages/backend/src/core/NoteDeleteService.ts: only repliesCount is decremented on delete", "code": "misskey-dev/misskey packages/backend/src/core/NoteDeleteService.ts: only repliesCount is decremented on delete",
"opened": "2026-10-05", "opened": "2026-10-05",
"status": "open", "status": "open",
"note": "the renote row is gone after our Undo (checked in its database); renoteCount stays up. Sharkey decrements it." "note": "the renote row is gone after our Undo (checked in its database); renoteCount stays up. Sharkey decrements it. Its match named decePub's e2e cells (client.action.boost), deleted 2026-10-17, so it matches nothing until a town cell checks Misskey's renote count."
}, },
{ {
"id": "G-0006", "id": "G-0006",
+1 -1
View File
@@ -1,4 +1,4 @@
"""The plan: a fake community drawn from a spec and its seed, the same on every run (tests/test_gen.py pins its hash). """The plan: a fake community drawn from a spec and its seed, the same on every run.
A plan is a list of steps, each {n, phase, round, actor, verb, args, ref}. Accounts are named "<platform>/<username>", A plan is a list of steps, each {n, phase, round, actor, verb, args, ref}. Accounts are named "<platform>/<username>",
objects by a ref ("p12"); the seeder turns refs into URIs as it goes. Phases run in order: objects by a ref ("p12"); the seeder turns refs into URIs as it goes. Phases run in order:
+2 -15
View File
@@ -12,7 +12,7 @@ import gen
DIRS = ["in", "out", "via", "control", "local"] DIRS = ["in", "out", "via", "control", "local"]
DIR_LABEL = {"in": "into PrivaPub", "out": "from PrivaPub", "via": "through PrivaPub", "control": "peer to peer", DIR_LABEL = {"in": "into PrivaPub", "out": "from PrivaPub", "via": "through PrivaPub", "control": "peer to peer",
"local": "on its own server"} "local": "on its own server"}
GROUPS = [("client", "decePub"), ("deliver", "Delivery"), ("relay", "Replies passed on"), ("confine", "Confinement"), GROUPS = [("deliver", "Delivery"), ("relay", "Replies passed on"), ("confine", "Confinement"),
("see", "Seen by the audience"), ("hide", "Hidden from outsiders"), ("count", "Counts"), ("thread", "Threads"), ("see", "Seen by the audience"), ("hide", "Hidden from outsiders"), ("count", "Counts"), ("thread", "Threads"),
("edit", "Edits"), ("delete", "Deletes"), ("graph", "Follows"), ("privacy", "Privacy")] ("edit", "Edits"), ("delete", "Deletes"), ("graph", "Follows"), ("privacy", "Privacy")]
STATUS_ORDER = ["fail", "xpass", "xfail", "pass"] STATUS_ORDER = ["fail", "xpass", "xfail", "pass"]
@@ -84,7 +84,7 @@ def render(result, scenarios, title):
cells = result["cells"] cells = result["cells"]
totals = Counter(result["totals"]) totals = Counter(result["totals"])
observers = [p for p in gen.HOSTS if any(k.split("|")[2] == p for k in cells)] + \ observers = [p for p in gen.HOSTS if any(k.split("|")[2] == p for k in cells)] + \
[o for o in ("*", "decepub") if any(k.split("|")[2] == o for k in cells)] [o for o in ("*",) if any(k.split("|")[2] == o for k in cells)]
features = sorted({k.split("|")[0] for k in cells}) features = sorted({k.split("|")[0] for k in cells})
out = [f"<title>{html.escape(title)}</title>", out = [f"<title>{html.escape(title)}</title>",
'<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600&display=swap">', '<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600&display=swap">',
@@ -169,19 +169,6 @@ def main(args):
if os.path.exists(path): if os.path.exists(path):
with open(path) as f: with open(path) as f:
scenarios = [json.loads(line) for line in f if line.strip()] scenarios = [json.loads(line) for line in f if line.strip()]
# a client's cells, when any, join the servers' in the same matrix, under the observer "decepub"
client = os.path.join(seed.OUT, "client.jsonl")
if os.path.exists(client):
import check
with open(client) as f:
lines = [json.loads(line) for line in f if line.strip()]
checks = check.classify(check.latest_client(lines), check.load_gaps())
for cell, v in check.summarise(checks).items():
result["cells"][cell] = v
from collections import Counter
totals = Counter(result["totals"])
totals.update(Counter(c["status"] for c in checks))
result["totals"] = totals
page = render(result, scenarios, "PrivaPub Town Matrix") page = render(result, scenarios, "PrivaPub Town Matrix")
target = os.path.join(run_dir, "report.html") target = os.path.join(run_dir, "report.html")
with open(target, "w") as f: with open(target, "w") as f:
Whitespace-only changes.
-79
View File
@@ -1,79 +0,0 @@
"""The town's own logic, with no pasture: python3 -m unittest discover -s tools/pasture/town/tests"""
import os
import sys
import unittest
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import check # noqa: E402
import gen # noqa: E402
from core.rng import Rng # noqa: E402
class RngTests(unittest.TestCase):
def test_the_same_seed_and_name_give_the_same_stream(self):
a, b = Rng(7, "x"), Rng(7, "x")
self.assertEqual([a.next64() for _ in range(5)], [b.next64() for _ in range(5)])
def test_substreams_do_not_disturb_each_other(self):
root = Rng(7)
before = Rng(7).sub("graph").next64()
root.sub("content").next64()
self.assertEqual(before, root.sub("graph").next64())
def test_below_stays_in_range(self):
r = Rng(1)
self.assertTrue(all(0 <= r.below(3) < 3 for _ in range(1000)))
class PlanTests(unittest.TestCase):
def test_a_spec_always_plans_the_same(self):
spec = gen.load("village")
self.assertEqual(gen.digest(gen.plan(spec)), gen.digest(gen.plan(spec)))
def test_every_post_names_its_marker_and_every_reply_a_parent_planned_before_it(self):
planner = gen.Planner(gen.load("village"))
steps = planner.plan()
made = set()
for s in steps:
if s["verb"] != "post":
continue
self.assertIn(f"({s['ref']})", s["args"]["text"])
if s["args"].get("reply_to"):
self.assertIn(s["args"]["reply_to"], made)
made.add(s["ref"])
def test_lemmy_accounts_never_follow_people_and_platforms_get_only_what_they_can_do(self):
steps = gen.plan(gen.load("village"))
for s in steps:
platform = s["actor"].split("/")[0]
if s["verb"] == "follow":
self.assertNotEqual("lemmy", platform)
if s["verb"] in ("react", "edit", "vote", "boost"):
self.assertIn({"react": "react", "edit": "edit", "vote": "vote", "boost": "boost"}[s["verb"]], gen.CAPS[platform])
def test_a_stored_plan_rebuilds_the_same_world(self):
planner = gen.Planner(gen.load("village"))
planner.plan()
stored = gen.Stored(gen.snapshot(planner))
self.assertEqual(planner.objects.keys(), stored.objects.keys())
self.assertEqual(planner.objects["p1"]["mentions"], stored.objects["p1"]["mentions"])
class GapTests(unittest.TestCase):
def test_a_known_gap_turns_failures_into_xfail_and_passes_into_xpass(self):
gaps = [{"id": "G-9", "match": {"feature": r"count\.like\..*", "observer": "privapub"}, "status": "open"}]
checks = check.classify([
{"feature": "count.like.followers", "observer": "privapub", "ok": False},
{"feature": "count.like.public", "observer": "privapub", "ok": True},
{"feature": "count.like.public", "observer": "gts", "ok": False},
], gaps)
self.assertEqual(["xfail", "xpass", "fail"], [c["status"] for c in checks])
def test_a_closed_gap_matches_nothing(self):
gaps = [{"id": "G-9", "match": {"feature": ".*"}, "status": "closed"}]
self.assertEqual("fail", check.classify([{"feature": "x", "ok": False}], gaps)[0]["status"])
if __name__ == "__main__":
unittest.main()
+1 -1
View File
@@ -59,7 +59,7 @@ def main(argv):
s = state.session(args[0], args[1]) s = state.session(args[0], args[1])
print(json.dumps(driver(args[0]).seen(s, args[2:]))) print(json.dumps(driver(args[0]).seen(s, args[2:])))
return 0 return 0
if cmd in ("plan", "seed", "check", "report", "backlog", "gaps", "expect", "load"): if cmd in ("plan", "seed", "check", "report", "backlog"):
module = __import__(cmd if cmd not in ("plan",) else "gen") module = __import__(cmd if cmd not in ("plan",) else "gen")
return module.main(args) return module.main(args)
print(f"unknown command {cmd}", file=sys.stderr) print(f"unknown command {cmd}", file=sys.stderr)