Merge remote-tracking branch 'origin/develop' into shigusegubu
* origin/develop: (115 commits) Change test case wording Use `duration` param for mute expiration duration Emoji: apply recommended tail call changes Extract translatable strings Emoji: split qualification variation into a module Add authorized_fetch_mode to description.exs EmojiReactValidator: use new qualification method Emoji: implement full-qualifier using combinations EmojiReactValidator: fix emoji qualification Revert "Merge branch 'fix/emoji-react-qualification' into 'develop'" Translated using Weblate (French) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) Translated using Weblate (Chinese (Simplified)) ...
This commit is contained in:
commit
550693111e
108 changed files with 24053 additions and 658 deletions
|
|
@ -34,7 +34,8 @@ after_script:
|
|||
build:
|
||||
stage: build
|
||||
only:
|
||||
changes:
|
||||
changes: &build_changes_policy
|
||||
- ".gitlab-ci.yml"
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
|
|
@ -45,6 +46,7 @@ spec-build:
|
|||
stage: test
|
||||
only:
|
||||
changes:
|
||||
- ".gitlab-ci.yml"
|
||||
- "lib/pleroma/web/api_spec/**/*.ex"
|
||||
- "lib/pleroma/web/api_spec.ex"
|
||||
artifacts:
|
||||
|
|
@ -59,7 +61,7 @@ benchmark:
|
|||
variables:
|
||||
MIX_ENV: benchmark
|
||||
services:
|
||||
- name: postgres:9.6
|
||||
- name: postgres:9.6-alpine
|
||||
alias: postgres
|
||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||
script:
|
||||
|
|
@ -70,16 +72,13 @@ benchmark:
|
|||
unit-testing:
|
||||
stage: test
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: &testing_cache_policy
|
||||
<<: *global_cache_policy
|
||||
policy: pull
|
||||
|
||||
services:
|
||||
- name: postgres:13
|
||||
- name: postgres:13-alpine
|
||||
alias: postgres
|
||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||
script:
|
||||
|
|
@ -92,16 +91,13 @@ unit-testing-erratic:
|
|||
retry: 2
|
||||
allow_failure: true
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: &testing_cache_policy
|
||||
<<: *global_cache_policy
|
||||
policy: pull
|
||||
|
||||
services:
|
||||
- name: postgres:13
|
||||
- name: postgres:13-alpine
|
||||
alias: postgres
|
||||
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
|
||||
script:
|
||||
|
|
@ -128,10 +124,7 @@ unit-testing-erratic:
|
|||
unit-testing-rum:
|
||||
stage: test
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
services:
|
||||
- name: minibikini/postgres-with-rum:12
|
||||
|
|
@ -147,15 +140,14 @@ unit-testing-rum:
|
|||
- mix test --preload-modules
|
||||
|
||||
lint:
|
||||
image: elixir:1.12
|
||||
image: ¤t_elixir elixir:1.12-alpine
|
||||
stage: test
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
before_script:
|
||||
before_script: ¤t_bfr_script
|
||||
- apk update
|
||||
- apk add build-base cmake file-dev git openssl
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
|
|
@ -165,29 +157,18 @@ lint:
|
|||
analysis:
|
||||
stage: test
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: *testing_cache_policy
|
||||
script:
|
||||
- mix credo --strict --only=warnings,todo,fixme,consistency,readability
|
||||
|
||||
cycles:
|
||||
image: *current_elixir
|
||||
stage: test
|
||||
image: elixir:1.11
|
||||
only:
|
||||
changes:
|
||||
- "**/*.ex"
|
||||
- "**/*.exs"
|
||||
- "mix.lock"
|
||||
changes: *build_changes_policy
|
||||
cache: {}
|
||||
before_script:
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
- mix deps.get
|
||||
- apt-get update
|
||||
- apt-get install cmake libmagic-dev -y
|
||||
before_script: *current_bfr_script
|
||||
script:
|
||||
- mix compile
|
||||
- mix xref graph --format cycles --label compile | awk '{print $0} END{exit ($0 != "No cycles found")}'
|
||||
|
|
@ -308,7 +289,7 @@ amd64-musl:
|
|||
cache: *release-cache
|
||||
variables: *release-variables
|
||||
before_script: &before-release-musl
|
||||
- apk add git gcc g++ musl-dev make cmake file-dev
|
||||
- apk add git build-base cmake file-dev openssl
|
||||
- echo "import Mix.Config" > config/prod.secret.exs
|
||||
- mix local.hex --force
|
||||
- mix local.rebar --force
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
### Changed
|
||||
- Allow users to remove their emails if instance does not need email to register
|
||||
- Uploadfilter `Pleroma.Upload.Filter.Exiftool` has been renamed to `Pleroma.Upload.Filter.Exiftool.StripLocation`
|
||||
|
||||
### Added
|
||||
- `activeMonth` and `activeHalfyear` fields in NodeInfo usage.users object
|
||||
|
|
@ -30,6 +31,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
- Configuration: Add `birthday_required` and `birthday_min_age` settings to provide a way to require users to enter their birth date.
|
||||
- PleromaAPI: Add `GET /api/v1/pleroma/birthdays` API endpoint
|
||||
- Make backend-rendered pages translatable. This includes emails. Pages returned as a HTTP response are translated using the language specified in the `userLanguage` cookie, or the `Accept-Language` header. Emails are translated using the `language` field when registering. This language can be changed by `PATCH /api/v1/accounts/update_credentials` with the `language` field.
|
||||
- Uploadfilter `Pleroma.Upload.Filter.Exiftool.ReadDescription` returns description values to the FE so they can pre fill the image description field
|
||||
- Added move account API
|
||||
|
||||
### Fixed
|
||||
- Subscription(Bell) Notifications: Don't create from Pipeline Ingested replies
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ config :pleroma, :instance,
|
|||
email: "pleroma@hjkos.com",
|
||||
notify_email: "pleroma@hjkos.com",
|
||||
description: "SigSegV, a pleroma instance",
|
||||
short_description: "HJ's semi-personal instance",
|
||||
background_image: "/images/city.jpg",
|
||||
instance_thumbnail: "/instance/thumbnail.jpeg",
|
||||
limit: 5_000,
|
||||
|
|
|
|||
|
|
@ -536,6 +536,15 @@ config :pleroma, :config_description, [
|
|||
"Very cool instance"
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: :short_description,
|
||||
type: :string,
|
||||
description:
|
||||
"Shorter version of instance description. It can be seen on `/api/v1/instance`",
|
||||
suggestions: [
|
||||
"Cool instance"
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: :limit,
|
||||
type: :integer,
|
||||
|
|
@ -1720,6 +1729,11 @@ config :pleroma, :config_description, [
|
|||
type: :boolean,
|
||||
description: "Sign object fetches with HTTP signatures"
|
||||
},
|
||||
%{
|
||||
key: :authorized_fetch_mode,
|
||||
type: :boolean,
|
||||
description: "Require HTTP signatures for AP fetches"
|
||||
},
|
||||
%{
|
||||
key: :note_replies_output_limit,
|
||||
type: :integer,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ If any of the options are left unspecified, you will be prompted interactively.
|
|||
- `--static-dir <path>` - the directory custom public files should be read from (custom emojis, frontend bundle overrides, robots.txt, etc.)
|
||||
- `--listen-ip <ip>` - the ip the app should listen to, defaults to 127.0.0.1
|
||||
- `--listen-port <port>` - the port the app should listen to, defaults to 4000
|
||||
- `--strip-uploads <Y|N>` - use ExifTool to strip uploads of sensitive location data
|
||||
- `--strip-uploads-location <Y|N>` - use ExifTool to strip uploads of sensitive location data
|
||||
- `--read-uploads-description <Y|N>` - use ExifTool to read image descriptions from uploads
|
||||
- `--anonymize-uploads <Y|N>` - randomize uploaded filenames
|
||||
- `--dedupe-uploads <Y|N>` - store files based on their hash to reduce data storage requirements if duplicates are uploaded with different filenames
|
||||
- `--skip-release-env` - skip generation the release environment file
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ To add configuration to your config file, you can copy it from the base config.
|
|||
* `email`: Email used to reach an Administrator/Moderator of the instance.
|
||||
* `notify_email`: Email used for notifications.
|
||||
* `description`: The instance’s description, can be seen in nodeinfo and ``/api/v1/instance``.
|
||||
* `short_description`: Shorter version of instance description, can be seen on ``/api/v1/instance``.
|
||||
* `limit`: Posts character limit (CW/Subject included in the counter).
|
||||
* `description_limit`: The character limit for image descriptions.
|
||||
* `remote_limit`: Hard character limit beyond which remote posts will be dropped.
|
||||
|
|
@ -627,12 +628,18 @@ This filter replaces the filename (not the path) of an upload. For complete obfu
|
|||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.Exiftool
|
||||
#### Pleroma.Upload.Filter.Exiftool.StripLocation
|
||||
|
||||
This filter only strips the GPS and location metadata with Exiftool leaving color profiles and attributes intact.
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.Exiftool.ReadDescription
|
||||
|
||||
This filter reads the ImageDescription and iptc:Caption-Abstract fields with Exiftool so clients can prefill the media description field.
|
||||
|
||||
No specific configuration.
|
||||
|
||||
#### Pleroma.Upload.Filter.Mogrify
|
||||
|
||||
* `args`: List of actions for the `mogrify` command like `"strip"` or `["strip", "auto-orient", {"implode", "1"}]`.
|
||||
|
|
|
|||
|
|
@ -1636,3 +1636,117 @@ Returns the content of the document
|
|||
"error": "Could not install frontend"
|
||||
}
|
||||
```
|
||||
|
||||
## `GET /api/v1/pleroma/admin/announcements`
|
||||
|
||||
### List announcements
|
||||
|
||||
- Params: `offset`, `limit`
|
||||
|
||||
- Response: JSON, list of announcements
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "AHDp0GBdRn1EPN5HN2",
|
||||
"content": "some content",
|
||||
"starts_at": null,
|
||||
"ends_at": null,
|
||||
"all_day": false,
|
||||
"published_at": "2022-03-09T02:13:05",
|
||||
"reactions": [],
|
||||
"statuses": [],
|
||||
"tags": [],
|
||||
"emojis": [],
|
||||
"updated_at": "2022-03-09T02:13:05"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Note that this differs from the Mastodon API variant: Mastodon API only returns *active* announcements, while this returns all.
|
||||
|
||||
## `GET /api/v1/pleroma/admin/announcements/:id`
|
||||
|
||||
### Display one announcement
|
||||
|
||||
- Response: JSON, one announcement
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "AHDp0GBdRn1EPN5HN2",
|
||||
"content": "some content",
|
||||
"starts_at": null,
|
||||
"ends_at": null,
|
||||
"all_day": false,
|
||||
"published_at": "2022-03-09T02:13:05",
|
||||
"reactions": [],
|
||||
"statuses": [],
|
||||
"tags": [],
|
||||
"emojis": [],
|
||||
"updated_at": "2022-03-09T02:13:05"
|
||||
}
|
||||
```
|
||||
|
||||
## `POST /api/v1/pleroma/admin/announcements`
|
||||
|
||||
### Create an announcement
|
||||
|
||||
- Params:
|
||||
- `content`: string, required, announcement content
|
||||
- `starts_at`: datetime, optional, default to null, the time when the announcement will become active (displayed to users); if it is null, the announcement will be active immediately
|
||||
- `ends_at`: datetime, optional, default to null, the time when the announcement will become inactive (no longer displayed to users); if it is null, the announcement will be active until an admin deletes it
|
||||
- `all_day`: boolean, optional, default to false, tells the client whether to only display dates for `starts_at` and `ends_at`
|
||||
|
||||
- Response: JSON, created announcement
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "AHDp0GBdRn1EPN5HN2",
|
||||
"content": "some content",
|
||||
"starts_at": null,
|
||||
"ends_at": null,
|
||||
"all_day": false,
|
||||
"published_at": "2022-03-09T02:13:05",
|
||||
"reactions": [],
|
||||
"statuses": [],
|
||||
"tags": [],
|
||||
"emojis": [],
|
||||
"updated_at": "2022-03-09T02:13:05"
|
||||
}
|
||||
```
|
||||
|
||||
## `PATCH /api/v1/pleroma/admin/announcements/:id`
|
||||
|
||||
### Change an announcement
|
||||
|
||||
- Params: same as `POST /api/v1/pleroma/admin/announcements`, except no param is required.
|
||||
|
||||
- Updates the announcement according to params. Missing params are kept as-is.
|
||||
|
||||
- Response: JSON, updated announcement
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "AHDp0GBdRn1EPN5HN2",
|
||||
"content": "some content",
|
||||
"starts_at": null,
|
||||
"ends_at": null,
|
||||
"all_day": false,
|
||||
"published_at": "2022-03-09T02:13:05",
|
||||
"reactions": [],
|
||||
"statuses": [],
|
||||
"tags": [],
|
||||
"emojis": [],
|
||||
"updated_at": "2022-03-09T02:13:05"
|
||||
}
|
||||
```
|
||||
|
||||
## `DELETE /api/v1/pleroma/admin/announcements/:id`
|
||||
|
||||
### Delete an announcement
|
||||
|
||||
- Response: JSON, empty object
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -342,6 +342,36 @@ See [Admin-API](admin_api.md)
|
|||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
||||
* Note: Currently, Mastodon has no API for changing email. If they add it in future it might be incompatible with Pleroma.
|
||||
|
||||
## `/api/pleroma/move_account`
|
||||
### Move account
|
||||
* Method `POST`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
* `password`: user's password
|
||||
* `target_account`: the nickname of the target account (e.g. `foo@example.org`)
|
||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
||||
* Note: This endpoint emits a `Move` activity to all followers of the current account. Some remote servers will automatically unfollow the current account and follow the target account upon seeing this, but this depends on the remote server implementation and cannot be guaranteed. For local followers , they will automatically unfollow and follow if and only if they have set the `allow_following_move` preference ("Allow auto-follow when following account moves").
|
||||
|
||||
## `/api/pleroma/aliases`
|
||||
### Get aliases of the current account
|
||||
* Method `GET`
|
||||
* Authentication: required
|
||||
* Response: JSON. Returns `{"aliases": [alias, ...]}`, where `alias` is the nickname of an alias, e.g. `foo@example.org`.
|
||||
|
||||
### Add alias to the current account
|
||||
* Method `PUT`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
* `alias`: the nickname of the alias to add, e.g. `foo@example.org`.
|
||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
||||
|
||||
### Delete alias from the current account
|
||||
* Method `DELETE`
|
||||
* Authentication: required
|
||||
* Params:
|
||||
* `alias`: the nickname of the alias to delete, e.g. `foo@example.org`.
|
||||
* Response: JSON. Returns `{"status": "success"}` if the change was successful, `{"error": "[error message]"}` otherwise
|
||||
|
||||
# Pleroma Conversations
|
||||
|
||||
Pleroma Conversations have the same general structure that Mastodon Conversations have. The behavior differs in the following ways when using these endpoints:
|
||||
|
|
|
|||
9
docs/development/setting_up_a_gitlab_runner.md
Normal file
9
docs/development/setting_up_a_gitlab_runner.md
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Setting up a Gitlab-runner
|
||||
|
||||
When you push changes, a pipeline will start some automated jobs. These are done with so called [runners](https://docs.gitlab.com/runner/), services that run somewhere on a server and run these automated jobs. These jobs typically run tests and should pass. If not, you probably need to fix something.
|
||||
|
||||
Generally, Pleroma provides a runner, so you don't need to set up your own. However, if for whatever reason you want to set up your own, here's some high level instructions.
|
||||
|
||||
1. We use docker to run the jobs, so you should install that. For Debian, you need to allow non-free packages in the [source list](https://wiki.debian.org/SourcesList). Then you can install docker with `apt install docker-compose`.
|
||||
2. You can [install](https://docs.gitlab.com/runner/install/index.html) and [configure](https://docs.gitlab.com/runner/register/index.html) a Gitlab-runner. It's probably easiest to install from the packages, but there are other options as well.
|
||||
3. When registering the runner, you'll need some values. You can find them in the project under your own name. Choose "Settings", "CI/CD", and then expand "Runners". For executor you can choose "docker". For default image, you can use the image used in <https://git.pleroma.social/pleroma/pleroma/-/blob/develop/.gitlab-ci.yml#L1> (although it shouldn't matter much).
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
# Optional software packages needed for specific functionality
|
||||
|
||||
For specific Pleroma functionality (which is disabled by default) some or all of the below packages are required:
|
||||
* `ImageMagic`
|
||||
* `ffmpeg`
|
||||
* `exiftool`
|
||||
* `ImageMagic`
|
||||
* `ffmpeg`
|
||||
* `exiftool`
|
||||
|
||||
Please refer to documentation in `docs/installation` on how to install them on specific OS.
|
||||
|
||||
|
|
@ -14,19 +14,20 @@ Note: the packages are not required with the current default settings of Pleroma
|
|||
`ImageMagick` is a set of tools to create, edit, compose, or convert bitmap images.
|
||||
|
||||
It is required for the following Pleroma features:
|
||||
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||
* `Pleroma.Upload.Filters.Mogrify`, `Pleroma.Upload.Filters.Mogrifun` upload filters (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||
* Media preview proxy for still images (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||
|
||||
## `ffmpeg`
|
||||
|
||||
`ffmpeg` is software to record, convert and stream audio and video.
|
||||
|
||||
It is required for the following Pleroma features:
|
||||
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||
* Media preview proxy for videos (related config: `media_preview_proxy/enabled` in `config/config.exs`)
|
||||
|
||||
## `exiftool`
|
||||
|
||||
`exiftool` is media files metadata reader/writer.
|
||||
|
||||
It is required for the following Pleroma features:
|
||||
* `Pleroma.Upload.Filters.Exiftool` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||
* `Pleroma.Upload.Filters.Exiftool.StripLocation` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||
* `Pleroma.Upload.Filters.Exiftool.ReadDescription` upload filter (related config: `Plaroma.Upload/filters` in `config/config.exs`)
|
||||
|
|
|
|||
|
|
@ -81,6 +81,19 @@ server {
|
|||
proxy_pass http://phoenix;
|
||||
}
|
||||
|
||||
# Uncomment this if you want notice compatibility routes for frontends like Soapbox.
|
||||
# location ~ ^/@[^/]+/([^/]+)$ {
|
||||
# proxy_pass http://phoenix/notice/$1;
|
||||
# }
|
||||
#
|
||||
# location ~ ^/@[^/]+/posts/([^/]+)$ {
|
||||
# proxy_pass http://phoenix/notice/$1;
|
||||
# }
|
||||
#
|
||||
# location ~ ^/[^/]+/status/([^/]+)$ {
|
||||
# proxy_pass http://phoenix/notice/$1;
|
||||
# }
|
||||
|
||||
location ~ ^/(media|proxy) {
|
||||
proxy_cache pleroma_media_cache;
|
||||
slice 1m;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
|||
static_dir: :string,
|
||||
listen_ip: :string,
|
||||
listen_port: :string,
|
||||
strip_uploads: :string,
|
||||
strip_uploads_location: :string,
|
||||
read_uploads_description: :string,
|
||||
anonymize_uploads: :string,
|
||||
dedupe_uploads: :string
|
||||
],
|
||||
|
|
@ -161,7 +162,7 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
|||
)
|
||||
|> Path.expand()
|
||||
|
||||
{strip_uploads_message, strip_uploads_default} =
|
||||
{strip_uploads_location_message, strip_uploads_location_default} =
|
||||
if Pleroma.Utils.command_available?("exiftool") do
|
||||
{"Do you want to strip location (GPS) data from uploaded images? This requires exiftool, it was detected as installed. (y/n)",
|
||||
"y"}
|
||||
|
|
@ -170,12 +171,29 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
|||
"n"}
|
||||
end
|
||||
|
||||
strip_uploads =
|
||||
strip_uploads_location =
|
||||
get_option(
|
||||
options,
|
||||
:strip_uploads,
|
||||
strip_uploads_message,
|
||||
strip_uploads_default
|
||||
:strip_uploads_location,
|
||||
strip_uploads_location_message,
|
||||
strip_uploads_location_default
|
||||
) === "y"
|
||||
|
||||
{read_uploads_description_message, read_uploads_description_default} =
|
||||
if Pleroma.Utils.command_available?("exiftool") do
|
||||
{"Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as installed. (y/n)",
|
||||
"y"}
|
||||
else
|
||||
{"Do you want to read data from uploaded files so clients can use it to prefill fields like image description? This requires exiftool, it was detected as not installed, please install it if you answer yes. (y/n)",
|
||||
"n"}
|
||||
end
|
||||
|
||||
read_uploads_description =
|
||||
get_option(
|
||||
options,
|
||||
:read_uploads_description,
|
||||
read_uploads_description_message,
|
||||
read_uploads_description_default
|
||||
) === "y"
|
||||
|
||||
anonymize_uploads =
|
||||
|
|
@ -229,7 +247,8 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
|||
listen_port: listen_port,
|
||||
upload_filters:
|
||||
upload_filters(%{
|
||||
strip: strip_uploads,
|
||||
strip_location: strip_uploads_location,
|
||||
read_description: read_uploads_description,
|
||||
anonymize: anonymize_uploads,
|
||||
dedupe: dedupe_uploads
|
||||
})
|
||||
|
|
@ -297,12 +316,19 @@ defmodule Mix.Tasks.Pleroma.Instance do
|
|||
|
||||
defp upload_filters(filters) when is_map(filters) do
|
||||
enabled_filters =
|
||||
if filters.strip do
|
||||
[Pleroma.Upload.Filter.Exiftool]
|
||||
if filters.strip_location do
|
||||
[Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
enabled_filters =
|
||||
if filters.read_description do
|
||||
enabled_filters ++ [Pleroma.Upload.Filter.Exiftool.ReadDescription]
|
||||
else
|
||||
enabled_filters
|
||||
end
|
||||
|
||||
enabled_filters =
|
||||
if filters.anonymize do
|
||||
enabled_filters ++ [Pleroma.Upload.Filter.AnonymizeFilename]
|
||||
|
|
|
|||
160
lib/pleroma/announcement.ex
Normal file
160
lib/pleroma/announcement.ex
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Announcement do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset, only: [cast: 3, validate_required: 2]
|
||||
import Ecto.Query
|
||||
|
||||
alias Pleroma.AnnouncementReadRelationship
|
||||
alias Pleroma.Repo
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
@primary_key {:id, FlakeId.Ecto.CompatType, autogenerate: true}
|
||||
|
||||
schema "announcements" do
|
||||
field(:data, :map)
|
||||
field(:starts_at, :utc_datetime)
|
||||
field(:ends_at, :utc_datetime)
|
||||
field(:rendered, :map)
|
||||
|
||||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
def change(struct, params \\ %{}) do
|
||||
struct
|
||||
|> cast(validate_params(struct, params), [:data, :starts_at, :ends_at, :rendered])
|
||||
|> validate_required([:data])
|
||||
end
|
||||
|
||||
defp validate_params(struct, params) do
|
||||
base_data =
|
||||
%{
|
||||
"content" => "",
|
||||
"all_day" => false
|
||||
}
|
||||
|> Map.merge((struct && struct.data) || %{})
|
||||
|
||||
merged_data =
|
||||
Map.merge(base_data, params.data)
|
||||
|> Map.take(["content", "all_day"])
|
||||
|
||||
params
|
||||
|> Map.merge(%{data: merged_data})
|
||||
|> add_rendered_properties()
|
||||
end
|
||||
|
||||
def add_rendered_properties(params) do
|
||||
{content_html, _, _} =
|
||||
Pleroma.Web.CommonAPI.Utils.format_input(params.data["content"], "text/plain",
|
||||
mentions_format: :full
|
||||
)
|
||||
|
||||
rendered = %{
|
||||
"content" => content_html
|
||||
}
|
||||
|
||||
params
|
||||
|> Map.put(:rendered, rendered)
|
||||
end
|
||||
|
||||
def add(params) do
|
||||
changeset = change(%__MODULE__{}, params)
|
||||
|
||||
Repo.insert(changeset)
|
||||
end
|
||||
|
||||
def update(announcement, params) do
|
||||
changeset = change(announcement, params)
|
||||
|
||||
Repo.update(changeset)
|
||||
end
|
||||
|
||||
def list_all do
|
||||
__MODULE__
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def list_paginated(%{limit: limited_number, offset: offset_number}) do
|
||||
__MODULE__
|
||||
|> limit(^limited_number)
|
||||
|> offset(^offset_number)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def get_by_id(id) do
|
||||
Repo.get_by(__MODULE__, id: id)
|
||||
end
|
||||
|
||||
def delete_by_id(id) do
|
||||
with announcement when not is_nil(announcement) <- get_by_id(id),
|
||||
{:ok, _} <- Repo.delete(announcement) do
|
||||
:ok
|
||||
else
|
||||
_ ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
def read_by?(announcement, user) do
|
||||
AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
|
||||
def mark_read_by(announcement, user) do
|
||||
AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
end
|
||||
|
||||
def render_json(announcement, opts \\ []) do
|
||||
extra_params =
|
||||
case Keyword.fetch(opts, :for) do
|
||||
{:ok, user} when not is_nil(user) ->
|
||||
%{read: read_by?(announcement, user)}
|
||||
|
||||
_ ->
|
||||
%{}
|
||||
end
|
||||
|
||||
admin_extra_params =
|
||||
case Keyword.fetch(opts, :admin) do
|
||||
{:ok, true} ->
|
||||
%{pleroma: %{raw_content: announcement.data["content"]}}
|
||||
|
||||
_ ->
|
||||
%{}
|
||||
end
|
||||
|
||||
base = %{
|
||||
id: announcement.id,
|
||||
content: announcement.rendered["content"],
|
||||
starts_at: announcement.starts_at,
|
||||
ends_at: announcement.ends_at,
|
||||
all_day: announcement.data["all_day"],
|
||||
published_at: announcement.inserted_at,
|
||||
updated_at: announcement.updated_at,
|
||||
mentions: [],
|
||||
statuses: [],
|
||||
tags: [],
|
||||
emojis: [],
|
||||
reactions: []
|
||||
}
|
||||
|
||||
base
|
||||
|> Map.merge(extra_params)
|
||||
|> Map.merge(admin_extra_params)
|
||||
end
|
||||
|
||||
# "visible" means:
|
||||
# starts_at < time < ends_at
|
||||
def list_all_visible_when(time) do
|
||||
__MODULE__
|
||||
|> where([a], is_nil(a.starts_at) or a.starts_at < ^time)
|
||||
|> where([a], is_nil(a.ends_at) or a.ends_at > ^time)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def list_all_visible do
|
||||
list_all_visible_when(DateTime.now("Etc/UTC") |> elem(1))
|
||||
end
|
||||
end
|
||||
55
lib/pleroma/announcement_read_relationship.ex
Normal file
55
lib/pleroma/announcement_read_relationship.ex
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.AnnouncementReadRelationship do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
||||
|
||||
alias FlakeId.Ecto.CompatType
|
||||
alias Pleroma.Announcement
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
|
||||
@type t :: %__MODULE__{}
|
||||
|
||||
schema "announcement_read_relationships" do
|
||||
belongs_to(:user, User, type: CompatType)
|
||||
belongs_to(:announcement, Announcement, type: CompatType)
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
def mark_read(user, announcement) do
|
||||
%__MODULE__{}
|
||||
|> cast(%{user_id: user.id, announcement_id: announcement.id}, [:user_id, :announcement_id])
|
||||
|> validate_required([:user_id, :announcement_id])
|
||||
|> foreign_key_constraint(:user_id)
|
||||
|> foreign_key_constraint(:announcement_id)
|
||||
|> unique_constraint([:user_id, :announcement_id])
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
def mark_unread(user, announcement) do
|
||||
with relationship <- get(user, announcement),
|
||||
{:exists, true} <- {:exists, not is_nil(relationship)},
|
||||
{:ok, _} <- Repo.delete(relationship) do
|
||||
:ok
|
||||
else
|
||||
{:exists, false} ->
|
||||
:ok
|
||||
|
||||
_ ->
|
||||
:error
|
||||
end
|
||||
end
|
||||
|
||||
def get(user, announcement) do
|
||||
Repo.get_by(__MODULE__, user_id: user.id, announcement_id: announcement.id)
|
||||
end
|
||||
|
||||
def exists?(user, announcement) do
|
||||
not is_nil(get(user, announcement))
|
||||
end
|
||||
end
|
||||
|
|
@ -164,7 +164,8 @@ defmodule Pleroma.ApplicationRequirements do
|
|||
|
||||
defp check_system_commands!(:ok) do
|
||||
filter_commands_statuses = [
|
||||
check_filter(Pleroma.Upload.Filter.Exiftool, "exiftool"),
|
||||
check_filter(Pleroma.Upload.Filter.Exiftool.StripLocation, "exiftool"),
|
||||
check_filter(Pleroma.Upload.Filter.Exiftool.ReadDescription, "exiftool"),
|
||||
check_filter(Pleroma.Upload.Filter.Mogrify, "mogrify"),
|
||||
check_filter(Pleroma.Upload.Filter.Mogrifun, "mogrify"),
|
||||
check_filter(Pleroma.Upload.Filter.AnalyzeMetadata, "mogrify"),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,43 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
|||
"\n* `config :pleroma, :instance, mrf_transparency_exclusions` is now `config :pleroma, :mrf, transparency_exclusions`"}
|
||||
]
|
||||
|
||||
def check_exiftool_filter do
|
||||
filters = Config.get([Pleroma.Upload]) |> Keyword.get(:filters, [])
|
||||
|
||||
if Pleroma.Upload.Filter.Exiftool in filters do
|
||||
Logger.warn("""
|
||||
!!!DEPRECATION WARNING!!!
|
||||
Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later:
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool]
|
||||
```
|
||||
|
||||
Is now
|
||||
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
```
|
||||
""")
|
||||
|
||||
new_config =
|
||||
filters
|
||||
|> Enum.map(fn
|
||||
Pleroma.Upload.Filter.Exiftool -> Pleroma.Upload.Filter.Exiftool.StripLocation
|
||||
filter -> filter
|
||||
end)
|
||||
|
||||
Config.put([Pleroma.Upload, :filters], new_config)
|
||||
|
||||
:error
|
||||
else
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
def check_simple_policy_tuples do
|
||||
has_strings =
|
||||
Config.get([:mrf_simple])
|
||||
|
|
@ -180,7 +217,8 @@ defmodule Pleroma.Config.DeprecationWarnings do
|
|||
check_old_chat_shoutbox(),
|
||||
check_quarantined_instances_tuples(),
|
||||
check_transparency_exclusions_tuples(),
|
||||
check_simple_policy_tuples()
|
||||
check_simple_policy_tuples(),
|
||||
check_exiftool_filter()
|
||||
]
|
||||
|> Enum.reduce(:ok, fn
|
||||
:ok, :ok -> :ok
|
||||
|
|
|
|||
|
|
@ -27,4 +27,10 @@ defmodule Pleroma.Constants do
|
|||
do:
|
||||
~w(index.html robots.txt static static-fe finmoji emoji packs sounds images instance sw.js sw-pleroma.js favicon.png schemas doc embed.js embed.css)
|
||||
)
|
||||
|
||||
# basic regex, just there to weed out potential mistakes
|
||||
# https://datatracker.ietf.org/doc/html/rfc2045#section-5.1
|
||||
const(mime_regex,
|
||||
do: ~r/^[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+\/[^[:cntrl:] ()<>@,;:\\"\/\[\]?=]+(; .*)?$/
|
||||
)
|
||||
end
|
||||
|
|
|
|||
10
lib/pleroma/docs/translator.ex
Normal file
10
lib/pleroma/docs/translator.ex
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Docs.Translator do
|
||||
require Pleroma.Docs.Translator.Compiler
|
||||
require Pleroma.Web.Gettext
|
||||
|
||||
@before_compile Pleroma.Docs.Translator.Compiler
|
||||
end
|
||||
119
lib/pleroma/docs/translator/compiler.ex
Normal file
119
lib/pleroma/docs/translator/compiler.ex
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Docs.Translator.Compiler do
|
||||
@external_resource "config/description.exs"
|
||||
@raw_config Pleroma.Config.Loader.read("config/description.exs")
|
||||
@raw_descriptions @raw_config[:pleroma][:config_description]
|
||||
|
||||
defmacro __before_compile__(_env) do
|
||||
strings =
|
||||
__MODULE__.descriptions()
|
||||
|> __MODULE__.extract_strings()
|
||||
|
||||
quote do
|
||||
def placeholder do
|
||||
unquote do
|
||||
Enum.map(
|
||||
strings,
|
||||
fn {path, type, string} ->
|
||||
ctxt = msgctxt_for(path, type)
|
||||
|
||||
quote do
|
||||
Pleroma.Web.Gettext.dpgettext_noop(
|
||||
"config_descriptions",
|
||||
unquote(ctxt),
|
||||
unquote(string)
|
||||
)
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def descriptions do
|
||||
Pleroma.Web.ActivityPub.MRF.config_descriptions()
|
||||
|> Enum.reduce(@raw_descriptions, fn description, acc -> [description | acc] end)
|
||||
|> Pleroma.Docs.Generator.convert_to_strings()
|
||||
end
|
||||
|
||||
def extract_strings(descriptions) do
|
||||
descriptions
|
||||
|> Enum.reduce(%{strings: [], path: []}, &process_item/2)
|
||||
|> Map.get(:strings)
|
||||
end
|
||||
|
||||
defp process_item(entity, acc) do
|
||||
current_level =
|
||||
acc
|
||||
|> process_desc(entity)
|
||||
|> process_label(entity)
|
||||
|
||||
process_children(entity, current_level)
|
||||
end
|
||||
|
||||
defp process_desc(acc, %{description: desc} = item) do
|
||||
%{
|
||||
strings: [{acc.path ++ [key_for(item)], "description", desc} | acc.strings],
|
||||
path: acc.path
|
||||
}
|
||||
end
|
||||
|
||||
defp process_desc(acc, _) do
|
||||
acc
|
||||
end
|
||||
|
||||
defp process_label(acc, %{label: label} = item) do
|
||||
%{
|
||||
strings: [{acc.path ++ [key_for(item)], "label", label} | acc.strings],
|
||||
path: acc.path
|
||||
}
|
||||
end
|
||||
|
||||
defp process_label(acc, _) do
|
||||
acc
|
||||
end
|
||||
|
||||
defp process_children(%{children: children} = item, acc) do
|
||||
current_level = Map.put(acc, :path, acc.path ++ [key_for(item)])
|
||||
|
||||
children
|
||||
|> Enum.reduce(current_level, &process_item/2)
|
||||
|> Map.put(:path, acc.path)
|
||||
end
|
||||
|
||||
defp process_children(_, acc) do
|
||||
acc
|
||||
end
|
||||
|
||||
def msgctxt_for(path, type) do
|
||||
"config #{type} at #{Enum.join(path, " > ")}"
|
||||
end
|
||||
|
||||
defp convert_group({_, group}) do
|
||||
group
|
||||
end
|
||||
|
||||
defp convert_group(group) do
|
||||
group
|
||||
end
|
||||
|
||||
def key_for(%{group: group, key: key}) do
|
||||
"#{convert_group(group)}-#{key}"
|
||||
end
|
||||
|
||||
def key_for(%{group: group}) do
|
||||
convert_group(group)
|
||||
end
|
||||
|
||||
def key_for(%{key: key}) do
|
||||
key
|
||||
end
|
||||
|
||||
def key_for(_) do
|
||||
nil
|
||||
end
|
||||
end
|
||||
25
lib/pleroma/ecto_type/activity_pub/object_validators/mime.ex
Normal file
25
lib/pleroma/ecto_type/activity_pub/object_validators/mime.ex
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.EctoType.ActivityPub.ObjectValidators.MIME do
|
||||
use Ecto.Type
|
||||
|
||||
require Pleroma.Constants
|
||||
|
||||
def type, do: :string
|
||||
|
||||
def cast(mime) when is_binary(mime) do
|
||||
if mime =~ Pleroma.Constants.mime_regex() do
|
||||
{:ok, mime}
|
||||
else
|
||||
{:ok, "application/octet-stream"}
|
||||
end
|
||||
end
|
||||
|
||||
def cast(_), do: :error
|
||||
|
||||
def dump(data), do: {:ok, data}
|
||||
|
||||
def load(data), do: {:ok, data}
|
||||
end
|
||||
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Emoji do
|
|||
"""
|
||||
use GenServer
|
||||
|
||||
alias Pleroma.Emoji.Combinations
|
||||
alias Pleroma.Emoji.Loader
|
||||
|
||||
require Logger
|
||||
|
|
@ -137,4 +138,17 @@ defmodule Pleroma.Emoji do
|
|||
end
|
||||
|
||||
def is_unicode_emoji?(_), do: false
|
||||
|
||||
emoji_qualification_map =
|
||||
emojis
|
||||
|> Enum.filter(&String.contains?(&1, "\uFE0F"))
|
||||
|> Combinations.variate_emoji_qualification()
|
||||
|
||||
for {qualified, unqualified_list} <- emoji_qualification_map do
|
||||
for unqualified <- unqualified_list do
|
||||
def fully_qualify_emoji(unquote(unqualified)), do: unquote(qualified)
|
||||
end
|
||||
end
|
||||
|
||||
def fully_qualify_emoji(emoji), do: emoji
|
||||
end
|
||||
|
|
|
|||
45
lib/pleroma/emoji/combinations.ex
Normal file
45
lib/pleroma/emoji/combinations.ex
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Emoji.Combinations do
|
||||
# FE0F is the emoji variation sequence. It is used for fully-qualifying
|
||||
# emoji, and that includes emoji combinations.
|
||||
# This code generates combinations per emoji: for each FE0F, all possible
|
||||
# combinations of the character being removed or staying will be generated.
|
||||
# This is made as an attempt to find all partially-qualified and unqualified
|
||||
# versions of a fully-qualified emoji.
|
||||
# I have found *no cases* for which this would be a problem, after browsing
|
||||
# the entire emoji list in emoji-test.txt. This is safe, and, sadly, most
|
||||
# likely sane too.
|
||||
|
||||
defp qualification_combinations(codepoints) do
|
||||
qualification_combinations([[]], codepoints)
|
||||
end
|
||||
|
||||
defp qualification_combinations(acc, []), do: acc
|
||||
|
||||
defp qualification_combinations(acc, ["\uFE0F" | tail]) do
|
||||
acc
|
||||
|> Enum.flat_map(fn x -> [x, x ++ ["\uFE0F"]] end)
|
||||
|> qualification_combinations(tail)
|
||||
end
|
||||
|
||||
defp qualification_combinations(acc, [codepoint | tail]) do
|
||||
acc
|
||||
|> Enum.map(&Kernel.++(&1, [codepoint]))
|
||||
|> qualification_combinations(tail)
|
||||
end
|
||||
|
||||
def variate_emoji_qualification(emoji) when is_binary(emoji) do
|
||||
emoji
|
||||
|> String.codepoints()
|
||||
|> qualification_combinations()
|
||||
|> Enum.map(&List.to_string/1)
|
||||
end
|
||||
|
||||
def variate_emoji_qualification(emoji) when is_list(emoji) do
|
||||
emoji
|
||||
|> Enum.map(fn emoji -> {emoji, variate_emoji_qualification(emoji)} end)
|
||||
end
|
||||
end
|
||||
|
|
@ -194,12 +194,13 @@ defmodule Pleroma.FollowingRelationship do
|
|||
|> join(:inner, [r], f in assoc(r, :follower))
|
||||
|> where(following_id: ^origin.id)
|
||||
|> where([r, f], f.allow_following_move == true)
|
||||
|> where([r, f], f.local == true)
|
||||
|> limit(50)
|
||||
|> preload([:follower])
|
||||
|> Repo.all()
|
||||
|> Enum.map(fn following_relationship ->
|
||||
Repo.delete(following_relationship)
|
||||
Pleroma.Web.CommonAPI.follow(following_relationship.follower, target)
|
||||
Pleroma.Web.CommonAPI.unfollow(following_relationship.follower, origin)
|
||||
end)
|
||||
|> case do
|
||||
[] ->
|
||||
|
|
|
|||
|
|
@ -60,12 +60,23 @@ defmodule Pleroma.Upload do
|
|||
width: integer(),
|
||||
height: integer(),
|
||||
blurhash: String.t(),
|
||||
description: String.t(),
|
||||
path: String.t()
|
||||
}
|
||||
defstruct [:id, :name, :tempfile, :content_type, :width, :height, :blurhash, :path]
|
||||
defstruct [
|
||||
:id,
|
||||
:name,
|
||||
:tempfile,
|
||||
:content_type,
|
||||
:width,
|
||||
:height,
|
||||
:blurhash,
|
||||
:description,
|
||||
:path
|
||||
]
|
||||
|
||||
defp get_description(opts, upload) do
|
||||
case {opts[:description], Pleroma.Config.get([Pleroma.Upload, :default_description])} do
|
||||
defp get_description(upload) do
|
||||
case {upload.description, Pleroma.Config.get([Pleroma.Upload, :default_description])} do
|
||||
{description, _} when is_binary(description) -> description
|
||||
{_, :filename} -> upload.name
|
||||
{_, str} when is_binary(str) -> str
|
||||
|
|
@ -81,7 +92,7 @@ defmodule Pleroma.Upload do
|
|||
with {:ok, upload} <- prepare_upload(upload, opts),
|
||||
upload = %__MODULE__{upload | path: upload.path || "#{upload.id}/#{upload.name}"},
|
||||
{:ok, upload} <- Pleroma.Upload.Filter.filter(opts.filters, upload),
|
||||
description = get_description(opts, upload),
|
||||
description = get_description(upload),
|
||||
{_, true} <-
|
||||
{:description_limit,
|
||||
String.length(description) <= Pleroma.Config.get([:instance, :description_limit])},
|
||||
|
|
@ -152,7 +163,8 @@ defmodule Pleroma.Upload do
|
|||
id: UUID.generate(),
|
||||
name: file.filename,
|
||||
tempfile: file.path,
|
||||
content_type: file.content_type
|
||||
content_type: file.content_type,
|
||||
description: opts.description
|
||||
}}
|
||||
end
|
||||
end
|
||||
|
|
@ -172,7 +184,8 @@ defmodule Pleroma.Upload do
|
|||
id: UUID.generate(),
|
||||
name: hash <> "." <> ext,
|
||||
tempfile: tmp_path,
|
||||
content_type: content_type
|
||||
content_type: content_type,
|
||||
description: opts.description
|
||||
}}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
49
lib/pleroma/upload/filter/exiftool/read_description.ex
Normal file
49
lib/pleroma/upload/filter/exiftool/read_description.ex
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.ReadDescription do
|
||||
@moduledoc """
|
||||
Gets a valid description from the related EXIF tags and provides them in the response if no description is provided yet.
|
||||
It will first check ImageDescription, when that doesn't probide a valid description, it will check iptc:Caption-Abstract.
|
||||
A valid description means the fields are filled in and not too long (see `:instance, :description_limit`).
|
||||
"""
|
||||
@behaviour Pleroma.Upload.Filter
|
||||
|
||||
@spec filter(Pleroma.Upload.t()) :: {:ok, any()} | {:error, String.t()}
|
||||
|
||||
def filter(%Pleroma.Upload{description: description})
|
||||
when is_binary(description),
|
||||
do: {:ok, :noop}
|
||||
|
||||
def filter(%Pleroma.Upload{tempfile: file} = upload),
|
||||
do: {:ok, :filtered, upload |> Map.put(:description, read_description_from_exif_data(file))}
|
||||
|
||||
def filter(_, _), do: {:ok, :noop}
|
||||
|
||||
defp read_description_from_exif_data(file) do
|
||||
nil
|
||||
|> read_when_empty(file, "-ImageDescription")
|
||||
|> read_when_empty(file, "-iptc:Caption-Abstract")
|
||||
end
|
||||
|
||||
defp read_when_empty(current_description, _, _) when is_binary(current_description),
|
||||
do: current_description
|
||||
|
||||
defp read_when_empty(_, file, tag) do
|
||||
try do
|
||||
{tag_content, 0} =
|
||||
System.cmd("exiftool", ["-b", "-s3", tag, file], stderr_to_stdout: true, parallelism: true)
|
||||
|
||||
tag_content = String.trim(tag_content)
|
||||
|
||||
if tag_content != "" and
|
||||
String.length(tag_content) <=
|
||||
Pleroma.Config.get([:instance, :description_limit]),
|
||||
do: tag_content,
|
||||
else: nil
|
||||
rescue
|
||||
_ in ErlangError -> nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.Exiftool do
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.StripLocation do
|
||||
@moduledoc """
|
||||
Strips GPS related EXIF tags and overwrites the file in place.
|
||||
Also strips or replaces filesystem metadata e.g., timestamps.
|
||||
|
|
@ -706,7 +706,7 @@ defmodule Pleroma.User do
|
|||
])
|
||||
|> validate_required([:name, :nickname])
|
||||
|> unique_constraint(:nickname)
|
||||
|> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
|
||||
|> validate_not_restricted_nickname(:nickname)
|
||||
|> validate_format(:nickname, local_nickname_regex())
|
||||
|> put_ap_id()
|
||||
|> unique_constraint(:ap_id)
|
||||
|
|
@ -754,17 +754,9 @@ defmodule Pleroma.User do
|
|||
|> validate_confirmation(:password)
|
||||
|> unique_constraint(:email)
|
||||
|> validate_format(:email, @email_regex)
|
||||
|> validate_change(:email, fn :email, email ->
|
||||
valid? =
|
||||
Config.get([User, :email_blacklist])
|
||||
|> Enum.all?(fn blacklisted_domain ->
|
||||
!String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain])
|
||||
end)
|
||||
|
||||
if valid?, do: [], else: [email: "Invalid email"]
|
||||
end)
|
||||
|> validate_email_not_in_blacklisted_domain(:email)
|
||||
|> unique_constraint(:nickname)
|
||||
|> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames]))
|
||||
|> validate_not_restricted_nickname(:nickname)
|
||||
|> validate_format(:nickname, local_nickname_regex())
|
||||
|> validate_length(:bio, max: bio_limit)
|
||||
|> validate_length(:name, min: 1, max: name_limit)
|
||||
|
|
@ -778,6 +770,35 @@ defmodule Pleroma.User do
|
|||
|> put_following_and_follower_and_featured_address()
|
||||
end
|
||||
|
||||
def validate_not_restricted_nickname(changeset, field) do
|
||||
validate_change(changeset, field, fn _, value ->
|
||||
valid? =
|
||||
Config.get([User, :restricted_nicknames])
|
||||
|> Enum.all?(fn restricted_nickname ->
|
||||
String.downcase(value) != String.downcase(restricted_nickname)
|
||||
end)
|
||||
|
||||
if valid?, do: [], else: [nickname: "Invalid nickname"]
|
||||
end)
|
||||
end
|
||||
|
||||
def validate_email_not_in_blacklisted_domain(changeset, field) do
|
||||
validate_change(changeset, field, fn _, value ->
|
||||
valid? =
|
||||
Config.get([User, :email_blacklist])
|
||||
|> Enum.all?(fn blacklisted_domain ->
|
||||
blacklisted_domain_downcase = String.downcase(blacklisted_domain)
|
||||
|
||||
!String.ends_with?(String.downcase(value), [
|
||||
"@" <> blacklisted_domain_downcase,
|
||||
"." <> blacklisted_domain_downcase
|
||||
])
|
||||
end)
|
||||
|
||||
if valid?, do: [], else: [email: "Invalid email"]
|
||||
end)
|
||||
end
|
||||
|
||||
def maybe_validate_required_email(changeset, true), do: changeset
|
||||
|
||||
def maybe_validate_required_email(changeset, _) do
|
||||
|
|
@ -1459,17 +1480,30 @@ defmodule Pleroma.User do
|
|||
{:ok, list(UserRelationship.t())} | {:error, String.t()}
|
||||
def mute(%User{} = muter, %User{} = mutee, params \\ %{}) do
|
||||
notifications? = Map.get(params, :notifications, true)
|
||||
expires_in = Map.get(params, :expires_in, 0)
|
||||
duration = Map.get(params, :duration, 0)
|
||||
|
||||
with {:ok, user_mute} <- UserRelationship.create_mute(muter, mutee),
|
||||
expires_at =
|
||||
if duration > 0 do
|
||||
DateTime.utc_now()
|
||||
|> DateTime.add(duration)
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
||||
with {:ok, user_mute} <- UserRelationship.create_mute(muter, mutee, expires_at),
|
||||
{:ok, user_notification_mute} <-
|
||||
(notifications? && UserRelationship.create_notification_mute(muter, mutee)) ||
|
||||
(notifications? &&
|
||||
UserRelationship.create_notification_mute(
|
||||
muter,
|
||||
mutee,
|
||||
expires_at
|
||||
)) ||
|
||||
{:ok, nil} do
|
||||
if expires_in > 0 do
|
||||
if duration > 0 do
|
||||
Pleroma.Workers.MuteExpireWorker.enqueue(
|
||||
"unmute_user",
|
||||
%{"muter_id" => muter.id, "mutee_id" => mutee.id},
|
||||
schedule_in: expires_in
|
||||
scheduled_at: expires_at
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -2364,6 +2398,38 @@ defmodule Pleroma.User do
|
|||
|> update_and_set_cache()
|
||||
end
|
||||
|
||||
def alias_users(user) do
|
||||
user.also_known_as
|
||||
|> Enum.map(&User.get_cached_by_ap_id/1)
|
||||
|> Enum.filter(fn user -> user != nil end)
|
||||
end
|
||||
|
||||
def add_alias(user, new_alias_user) do
|
||||
current_aliases = user.also_known_as || []
|
||||
new_alias_ap_id = new_alias_user.ap_id
|
||||
|
||||
if new_alias_ap_id in current_aliases do
|
||||
{:ok, user}
|
||||
else
|
||||
user
|
||||
|> cast(%{also_known_as: current_aliases ++ [new_alias_ap_id]}, [:also_known_as])
|
||||
|> update_and_set_cache()
|
||||
end
|
||||
end
|
||||
|
||||
def delete_alias(user, alias_user) do
|
||||
current_aliases = user.also_known_as || []
|
||||
alias_ap_id = alias_user.ap_id
|
||||
|
||||
if alias_ap_id in current_aliases do
|
||||
user
|
||||
|> cast(%{also_known_as: current_aliases -- [alias_ap_id]}, [:also_known_as])
|
||||
|> update_and_set_cache()
|
||||
else
|
||||
{:error, :no_such_alias}
|
||||
end
|
||||
end
|
||||
|
||||
# Internal function; public one is `deactivate/2`
|
||||
defp set_activation_status(user, status) do
|
||||
user
|
||||
|
|
|
|||
|
|
@ -18,16 +18,17 @@ defmodule Pleroma.UserRelationship do
|
|||
belongs_to(:source, User, type: FlakeId.Ecto.CompatType)
|
||||
belongs_to(:target, User, type: FlakeId.Ecto.CompatType)
|
||||
field(:relationship_type, Pleroma.UserRelationship.Type)
|
||||
field(:expires_at, :utc_datetime)
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
for relationship_type <- Keyword.keys(Pleroma.UserRelationship.Type.__enum_map__()) do
|
||||
# `def create_block/2`, `def create_mute/2`, `def create_reblog_mute/2`,
|
||||
# `def create_notification_mute/2`, `def create_inverse_subscription/2`,
|
||||
# `def endorsement/2`
|
||||
def unquote(:"create_#{relationship_type}")(source, target),
|
||||
do: create(unquote(relationship_type), source, target)
|
||||
# `def create_block/3`, `def create_mute/3`, `def create_reblog_mute/3`,
|
||||
# `def create_notification_mute/3`, `def create_inverse_subscription/3`,
|
||||
# `def endorsement/3`
|
||||
def unquote(:"create_#{relationship_type}")(source, target, expires_at \\ nil),
|
||||
do: create(unquote(relationship_type), source, target, expires_at)
|
||||
|
||||
# `def delete_block/2`, `def delete_mute/2`, `def delete_reblog_mute/2`,
|
||||
# `def delete_notification_mute/2`, `def delete_inverse_subscription/2`,
|
||||
|
|
@ -37,9 +38,15 @@ defmodule Pleroma.UserRelationship do
|
|||
|
||||
# `def block_exists?/2`, `def mute_exists?/2`, `def reblog_mute_exists?/2`,
|
||||
# `def notification_mute_exists?/2`, `def inverse_subscription_exists?/2`,
|
||||
# `def inverse_endorsement?/2`
|
||||
# `def inverse_endorsement_exists?/2`
|
||||
def unquote(:"#{relationship_type}_exists?")(source, target),
|
||||
do: exists?(unquote(relationship_type), source, target)
|
||||
|
||||
# `def get_block_expire_date/2`, `def get_mute_expire_date/2`,
|
||||
# `def get_reblog_mute_expire_date/2`, `def get_notification_mute_exists?/2`,
|
||||
# `def get_inverse_subscription_expire_date/2`, `def get_inverse_endorsement_expire_date/2`
|
||||
def unquote(:"get_#{relationship_type}_expire_date")(source, target),
|
||||
do: get_expire_date(unquote(relationship_type), source, target)
|
||||
end
|
||||
|
||||
def user_relationship_types, do: Keyword.keys(user_relationship_mappings())
|
||||
|
|
@ -48,7 +55,7 @@ defmodule Pleroma.UserRelationship do
|
|||
|
||||
def changeset(%UserRelationship{} = user_relationship, params \\ %{}) do
|
||||
user_relationship
|
||||
|> cast(params, [:relationship_type, :source_id, :target_id])
|
||||
|> cast(params, [:relationship_type, :source_id, :target_id, :expires_at])
|
||||
|> validate_required([:relationship_type, :source_id, :target_id])
|
||||
|> unique_constraint(:relationship_type,
|
||||
name: :user_relationships_source_id_relationship_type_target_id_index
|
||||
|
|
@ -62,12 +69,26 @@ defmodule Pleroma.UserRelationship do
|
|||
|> Repo.exists?()
|
||||
end
|
||||
|
||||
def create(relationship_type, %User{} = source, %User{} = target) do
|
||||
def get_expire_date(relationship_type, %User{} = source, %User{} = target) do
|
||||
%UserRelationship{expires_at: expires_at} =
|
||||
UserRelationship
|
||||
|> where(
|
||||
relationship_type: ^relationship_type,
|
||||
source_id: ^source.id,
|
||||
target_id: ^target.id
|
||||
)
|
||||
|> Repo.one!()
|
||||
|
||||
expires_at
|
||||
end
|
||||
|
||||
def create(relationship_type, %User{} = source, %User{} = target, expires_at \\ nil) do
|
||||
%UserRelationship{}
|
||||
|> changeset(%{
|
||||
relationship_type: relationship_type,
|
||||
source_id: source.id,
|
||||
target_id: target.id
|
||||
target_id: target.id,
|
||||
expires_at: expires_at
|
||||
})
|
||||
|> Repo.insert(
|
||||
on_conflict: {:replace_all_except, [:id]},
|
||||
|
|
|
|||
|
|
@ -413,7 +413,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
"type" => "Move",
|
||||
"actor" => origin.ap_id,
|
||||
"object" => origin.ap_id,
|
||||
"target" => target.ap_id
|
||||
"target" => target.ap_id,
|
||||
"to" => [origin.follower_address]
|
||||
}
|
||||
|
||||
with true <- origin.ap_id in target.also_known_as,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|
|||
|
||||
defp fix_replies(data), do: data
|
||||
|
||||
def fix_attachments(%{"attachment" => attachment} = data) when is_map(attachment),
|
||||
do: Map.put(data, "attachment", [attachment])
|
||||
|
||||
def fix_attachments(data), do: data
|
||||
|
||||
defp fix(data) do
|
||||
data
|
||||
|> CommonFixes.fix_actor()
|
||||
|
|
@ -72,6 +77,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidator do
|
|||
|> fix_url()
|
||||
|> fix_tag()
|
||||
|> fix_replies()
|
||||
|> fix_attachments()
|
||||
|> Transmogrifier.fix_emoji()
|
||||
|> Transmogrifier.fix_content_map()
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
|
|||
@primary_key false
|
||||
embedded_schema do
|
||||
field(:type, :string)
|
||||
field(:mediaType, :string, default: "application/octet-stream")
|
||||
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
|
||||
field(:name, :string)
|
||||
field(:blurhash, :string)
|
||||
|
||||
embeds_many :url, UrlObjectValidator, primary_key: false do
|
||||
field(:type, :string)
|
||||
field(:href, ObjectValidators.Uri)
|
||||
field(:mediaType, :string, default: "application/octet-stream")
|
||||
field(:mediaType, ObjectValidators.MIME, default: "application/octet-stream")
|
||||
field(:width, :integer)
|
||||
field(:height, :integer)
|
||||
end
|
||||
|
|
@ -59,13 +59,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidator do
|
|||
end
|
||||
|
||||
def fix_media_type(data) do
|
||||
data = Map.put_new(data, "mediaType", data["mimeType"])
|
||||
|
||||
if is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] do
|
||||
data
|
||||
else
|
||||
Map.put(data, "mediaType", "application/octet-stream")
|
||||
end
|
||||
Map.put_new(data, "mediaType", data["mimeType"] || "application/octet-stream")
|
||||
end
|
||||
|
||||
defp handle_href(href, mediaType, data) do
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|
|||
defp fix(data) do
|
||||
data =
|
||||
data
|
||||
|> fix_emoji_qualification()
|
||||
|> CommonFixes.fix_actor()
|
||||
|> CommonFixes.fix_activity_addressing()
|
||||
|
||||
|
|
@ -61,6 +62,23 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.EmojiReactValidator do
|
|||
end
|
||||
end
|
||||
|
||||
defp fix_emoji_qualification(%{"content" => emoji} = data) do
|
||||
new_emoji = Pleroma.Emoji.fully_qualify_emoji(emoji)
|
||||
|
||||
cond do
|
||||
Pleroma.Emoji.is_unicode_emoji?(emoji) ->
|
||||
data
|
||||
|
||||
Pleroma.Emoji.is_unicode_emoji?(new_emoji) ->
|
||||
data |> Map.put("content", new_emoji)
|
||||
|
||||
true ->
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
defp fix_emoji_qualification(data), do: data
|
||||
|
||||
defp validate_emoji(cng) do
|
||||
content = get_field(cng, :content)
|
||||
|
||||
|
|
|
|||
|
|
@ -203,13 +203,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
media_type =
|
||||
cond do
|
||||
is_map(url) && MIME.extensions(url["mediaType"]) != [] ->
|
||||
is_map(url) && url =~ Pleroma.Constants.mime_regex() ->
|
||||
url["mediaType"]
|
||||
|
||||
is_bitstring(data["mediaType"]) && MIME.extensions(data["mediaType"]) != [] ->
|
||||
is_bitstring(data["mediaType"]) && data["mediaType"] =~ Pleroma.Constants.mime_regex() ->
|
||||
data["mediaType"]
|
||||
|
||||
is_bitstring(data["mimeType"]) && MIME.extensions(data["mimeType"]) != [] ->
|
||||
is_bitstring(data["mimeType"]) && data["mimeType"] =~ Pleroma.Constants.mime_regex() ->
|
||||
data["mimeType"]
|
||||
|
||||
true ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.AnnouncementController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
alias Pleroma.Announcement
|
||||
alias Pleroma.Web.ControllerHelper
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:create, :delete, :change])
|
||||
plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action in [:index, :show])
|
||||
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.AnnouncementOperation
|
||||
|
||||
defp default_limit, do: 20
|
||||
|
||||
def index(conn, params) do
|
||||
limit = Map.get(params, :limit, default_limit())
|
||||
offset = Map.get(params, :offset, 0)
|
||||
|
||||
announcements = Announcement.list_paginated(%{limit: limit, offset: offset})
|
||||
|
||||
render(conn, "index.json", announcements: announcements)
|
||||
end
|
||||
|
||||
def show(conn, %{id: id} = _params) do
|
||||
announcement = Announcement.get_by_id(id)
|
||||
|
||||
if is_nil(announcement) do
|
||||
{:error, :not_found}
|
||||
else
|
||||
render(conn, "show.json", announcement: announcement)
|
||||
end
|
||||
end
|
||||
|
||||
def create(%{body_params: params} = conn, _params) do
|
||||
with {:ok, announcement} <- Announcement.add(change_params(params)) do
|
||||
render(conn, "show.json", announcement: announcement)
|
||||
else
|
||||
_ ->
|
||||
{:error, 400}
|
||||
end
|
||||
end
|
||||
|
||||
def change_params(orig_params) do
|
||||
data =
|
||||
%{}
|
||||
|> Pleroma.Maps.put_if_present("content", orig_params, &Map.fetch(&1, :content))
|
||||
|> Pleroma.Maps.put_if_present("all_day", orig_params, &Map.fetch(&1, :all_day))
|
||||
|
||||
orig_params
|
||||
|> Map.merge(%{data: data})
|
||||
end
|
||||
|
||||
def change(%{body_params: params} = conn, %{id: id} = _params) do
|
||||
with announcement <- Announcement.get_by_id(id),
|
||||
{:exists, true} <- {:exists, not is_nil(announcement)},
|
||||
{:ok, announcement} <- Announcement.update(announcement, change_params(params)) do
|
||||
render(conn, "show.json", announcement: announcement)
|
||||
else
|
||||
{:exists, false} ->
|
||||
{:error, :not_found}
|
||||
|
||||
_ ->
|
||||
{:error, 400}
|
||||
end
|
||||
end
|
||||
|
||||
def delete(conn, %{id: id} = _params) do
|
||||
case Announcement.delete_by_id(id) do
|
||||
:ok ->
|
||||
conn
|
||||
|> ControllerHelper.json_response(:ok, %{})
|
||||
|
||||
_ ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -22,10 +22,58 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
|
|||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ConfigOperation
|
||||
|
||||
defp translate_descriptions(descriptions, path \\ []) do
|
||||
Enum.map(descriptions, fn desc -> translate_item(desc, path) end)
|
||||
end
|
||||
|
||||
defp translate_string(str, path, type) do
|
||||
Gettext.dpgettext(
|
||||
Pleroma.Web.Gettext,
|
||||
"config_descriptions",
|
||||
Pleroma.Docs.Translator.Compiler.msgctxt_for(path, type),
|
||||
str
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_put_translated(item, key, path) do
|
||||
if item[key] do
|
||||
Map.put(
|
||||
item,
|
||||
key,
|
||||
translate_string(
|
||||
item[key],
|
||||
path ++ [Pleroma.Docs.Translator.Compiler.key_for(item)],
|
||||
to_string(key)
|
||||
)
|
||||
)
|
||||
else
|
||||
item
|
||||
end
|
||||
end
|
||||
|
||||
defp translate_item(item, path) do
|
||||
item
|
||||
|> maybe_put_translated(:label, path)
|
||||
|> maybe_put_translated(:description, path)
|
||||
|> translate_children(path)
|
||||
end
|
||||
|
||||
defp translate_children(%{children: children} = item, path) when is_list(children) do
|
||||
item
|
||||
|> Map.put(
|
||||
:children,
|
||||
translate_descriptions(children, path ++ [Pleroma.Docs.Translator.Compiler.key_for(item)])
|
||||
)
|
||||
end
|
||||
|
||||
defp translate_children(item, _path) do
|
||||
item
|
||||
end
|
||||
|
||||
def descriptions(conn, _params) do
|
||||
descriptions = Enum.filter(Pleroma.Docs.JSON.compiled_descriptions(), &whitelisted_config?/1)
|
||||
|
||||
json(conn, descriptions)
|
||||
json(conn, translate_descriptions(descriptions))
|
||||
end
|
||||
|
||||
def show(conn, %{only_db: true}) do
|
||||
|
|
|
|||
15
lib/pleroma/web/admin_api/views/announcement_view.ex
Normal file
15
lib/pleroma/web/admin_api/views/announcement_view.ex
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.AnnouncementView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
def render("index.json", %{announcements: announcements}) do
|
||||
render_many(announcements, __MODULE__, "show.json")
|
||||
end
|
||||
|
||||
def render("show.json", %{announcement: announcement}) do
|
||||
Pleroma.Announcement.render_json(announcement, admin: true)
|
||||
end
|
||||
end
|
||||
|
|
@ -278,11 +278,17 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
%Schema{allOf: [BooleanLike], default: true},
|
||||
"Mute notifications in addition to statuses? Defaults to `true`."
|
||||
),
|
||||
Operation.parameter(
|
||||
:duration,
|
||||
:query,
|
||||
%Schema{type: :integer},
|
||||
"Expire the mute in `duration` seconds. Default 0 for infinity"
|
||||
),
|
||||
Operation.parameter(
|
||||
:expires_in,
|
||||
:query,
|
||||
%Schema{type: :integer, default: 0},
|
||||
"Expire the mute in `expires_in` seconds. Default 0 for infinity"
|
||||
"Deprecated, use `duration` instead"
|
||||
)
|
||||
],
|
||||
responses: %{
|
||||
|
|
@ -545,10 +551,18 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
description: "Invite token required when the registrations aren't public"
|
||||
},
|
||||
birthday: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "User's birthday",
|
||||
format: :date
|
||||
anyOf: [
|
||||
%Schema{
|
||||
type: :string,
|
||||
format: :date
|
||||
},
|
||||
%Schema{
|
||||
type: :string,
|
||||
maxLength: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
language: %Schema{
|
||||
type: :string,
|
||||
|
|
@ -733,10 +747,18 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
},
|
||||
actor_type: ActorType,
|
||||
birthday: %Schema{
|
||||
type: :string,
|
||||
nullable: true,
|
||||
description: "User's birthday",
|
||||
format: :date
|
||||
anyOf: [
|
||||
%Schema{
|
||||
type: :string,
|
||||
format: :date
|
||||
},
|
||||
%Schema{
|
||||
type: :string,
|
||||
maxLength: 0
|
||||
}
|
||||
]
|
||||
},
|
||||
show_birthday: %Schema{
|
||||
allOf: [BooleanLike],
|
||||
|
|
@ -861,10 +883,15 @@ defmodule Pleroma.Web.ApiSpec.AccountOperation do
|
|||
description: "Mute notifications in addition to statuses? Defaults to true.",
|
||||
default: true
|
||||
},
|
||||
duration: %Schema{
|
||||
type: :integer,
|
||||
nullable: true,
|
||||
description: "Expire the mute in `expires_in` seconds. Default 0 for infinity"
|
||||
},
|
||||
expires_in: %Schema{
|
||||
type: :integer,
|
||||
nullable: true,
|
||||
description: "Expire the mute in `expires_in` seconds. Default 0 for infinity",
|
||||
description: "Deprecated, use `duration` instead",
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Admin.AnnouncementOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Announcement
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
|
||||
import Pleroma.Web.ApiSpec.Helpers
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def index_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement managment"],
|
||||
summary: "Retrieve a list of announcements",
|
||||
operationId: "AdminAPI.AnnouncementController.index",
|
||||
security: [%{"oAuth" => ["admin:read"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:limit,
|
||||
:query,
|
||||
%Schema{type: :integer, minimum: 1},
|
||||
"the maximum number of announcements to return"
|
||||
),
|
||||
Operation.parameter(
|
||||
:offset,
|
||||
:query,
|
||||
%Schema{type: :integer, minimum: 0},
|
||||
"the offset of the first announcement to return"
|
||||
)
|
||||
| admin_api_params()
|
||||
],
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", list_of_announcements()),
|
||||
400 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def show_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement managment"],
|
||||
summary: "Display one announcement",
|
||||
operationId: "AdminAPI.AnnouncementController.show",
|
||||
security: [%{"oAuth" => ["admin:read"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:id,
|
||||
:path,
|
||||
:string,
|
||||
"announcement id"
|
||||
)
|
||||
| admin_api_params()
|
||||
],
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", Announcement),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def delete_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement managment"],
|
||||
summary: "Delete one announcement",
|
||||
operationId: "AdminAPI.AnnouncementController.delete",
|
||||
security: [%{"oAuth" => ["admin:write"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:id,
|
||||
:path,
|
||||
:string,
|
||||
"announcement id"
|
||||
)
|
||||
| admin_api_params()
|
||||
],
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", %Schema{type: :object}),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def create_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement managment"],
|
||||
summary: "Create one announcement",
|
||||
operationId: "AdminAPI.AnnouncementController.create",
|
||||
security: [%{"oAuth" => ["admin:write"]}],
|
||||
requestBody: request_body("Parameters", create_request(), required: true),
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", Announcement),
|
||||
400 => Operation.response("Bad Request", "application/json", ApiError),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def change_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement managment"],
|
||||
summary: "Change one announcement",
|
||||
operationId: "AdminAPI.AnnouncementController.change",
|
||||
security: [%{"oAuth" => ["admin:write"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:id,
|
||||
:path,
|
||||
:string,
|
||||
"announcement id"
|
||||
)
|
||||
| admin_api_params()
|
||||
],
|
||||
requestBody: request_body("Parameters", change_request(), required: true),
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", Announcement),
|
||||
400 => Operation.response("Bad Request", "application/json", ApiError),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp create_or_change_props do
|
||||
%{
|
||||
content: %Schema{type: :string},
|
||||
starts_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
ends_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
all_day: %Schema{type: :boolean}
|
||||
}
|
||||
end
|
||||
|
||||
def create_request do
|
||||
%Schema{
|
||||
title: "AnnouncementCreateRequest",
|
||||
type: :object,
|
||||
required: [:content],
|
||||
properties: create_or_change_props()
|
||||
}
|
||||
end
|
||||
|
||||
def change_request do
|
||||
%Schema{
|
||||
title: "AnnouncementChangeRequest",
|
||||
type: :object,
|
||||
properties: create_or_change_props()
|
||||
}
|
||||
end
|
||||
|
||||
def list_of_announcements do
|
||||
%Schema{
|
||||
type: :array,
|
||||
items: Announcement
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.AnnouncementOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Announcement
|
||||
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
def index_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement"],
|
||||
summary: "Retrieve a list of announcements",
|
||||
operationId: "MastodonAPI.AnnouncementController.index",
|
||||
security: [%{"oAuth" => []}],
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", list_of_announcements()),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def mark_read_operation do
|
||||
%Operation{
|
||||
tags: ["Announcement"],
|
||||
summary: "Mark one announcement as read",
|
||||
operationId: "MastodonAPI.AnnouncementController.mark_read",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
parameters: [
|
||||
Operation.parameter(
|
||||
:id,
|
||||
:path,
|
||||
:string,
|
||||
"announcement id"
|
||||
)
|
||||
],
|
||||
responses: %{
|
||||
200 => Operation.response("Response", "application/json", %Schema{type: :object}),
|
||||
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def list_of_announcements do
|
||||
%Schema{
|
||||
type: :array,
|
||||
items: Announcement
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -51,6 +51,12 @@ defmodule Pleroma.Web.ApiSpec.NotificationOperation do
|
|||
:include_types,
|
||||
:query,
|
||||
%Schema{type: :array, items: notification_type()},
|
||||
"Deprecated, use `types` instead"
|
||||
),
|
||||
Operation.parameter(
|
||||
:types,
|
||||
:query,
|
||||
%Schema{type: :array, items: notification_type()},
|
||||
"Include the notifications for activities with the given types"
|
||||
),
|
||||
Operation.parameter(
|
||||
|
|
|
|||
|
|
@ -214,6 +214,146 @@ defmodule Pleroma.Web.ApiSpec.TwitterUtilOperation do
|
|||
}
|
||||
end
|
||||
|
||||
def move_account_operation do
|
||||
%Operation{
|
||||
tags: ["Account credentials"],
|
||||
summary: "Move account",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
operationId: "UtilController.move_account",
|
||||
requestBody: request_body("Parameters", move_account_request(), required: true),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Success", "application/json", %Schema{
|
||||
type: :object,
|
||||
properties: %{status: %Schema{type: :string, example: "success"}}
|
||||
}),
|
||||
400 => Operation.response("Error", "application/json", ApiError),
|
||||
403 => Operation.response("Error", "application/json", ApiError),
|
||||
404 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp move_account_request do
|
||||
%Schema{
|
||||
title: "MoveAccountRequest",
|
||||
description: "POST body for moving the account",
|
||||
type: :object,
|
||||
required: [:password, :target_account],
|
||||
properties: %{
|
||||
password: %Schema{type: :string, description: "Current password"},
|
||||
target_account: %Schema{
|
||||
type: :string,
|
||||
description: "The nickname of the target account to move to"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def list_aliases_operation do
|
||||
%Operation{
|
||||
tags: ["Account credentials"],
|
||||
summary: "List account aliases",
|
||||
security: [%{"oAuth" => ["read:accounts"]}],
|
||||
operationId: "UtilController.list_aliases",
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Success", "application/json", %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
aliases: %Schema{
|
||||
type: :array,
|
||||
items: %Schema{type: :string},
|
||||
example: ["foo@example.org"]
|
||||
}
|
||||
}
|
||||
}),
|
||||
400 => Operation.response("Error", "application/json", ApiError),
|
||||
403 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def add_alias_operation do
|
||||
%Operation{
|
||||
tags: ["Account credentials"],
|
||||
summary: "Add an alias to this account",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
operationId: "UtilController.add_alias",
|
||||
requestBody: request_body("Parameters", add_alias_request(), required: true),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Success", "application/json", %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
status: %Schema{
|
||||
type: :string,
|
||||
example: "success"
|
||||
}
|
||||
}
|
||||
}),
|
||||
400 => Operation.response("Error", "application/json", ApiError),
|
||||
403 => Operation.response("Error", "application/json", ApiError),
|
||||
404 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp add_alias_request do
|
||||
%Schema{
|
||||
title: "AddAliasRequest",
|
||||
description: "PUT body for adding aliases",
|
||||
type: :object,
|
||||
required: [:alias],
|
||||
properties: %{
|
||||
alias: %Schema{
|
||||
type: :string,
|
||||
description: "The nickname of the account to add to aliases"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def delete_alias_operation do
|
||||
%Operation{
|
||||
tags: ["Account credentials"],
|
||||
summary: "Delete an alias from this account",
|
||||
security: [%{"oAuth" => ["write:accounts"]}],
|
||||
operationId: "UtilController.delete_alias",
|
||||
requestBody: request_body("Parameters", delete_alias_request(), required: true),
|
||||
responses: %{
|
||||
200 =>
|
||||
Operation.response("Success", "application/json", %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
status: %Schema{
|
||||
type: :string,
|
||||
example: "success"
|
||||
}
|
||||
}
|
||||
}),
|
||||
400 => Operation.response("Error", "application/json", ApiError),
|
||||
403 => Operation.response("Error", "application/json", ApiError),
|
||||
404 => Operation.response("Error", "application/json", ApiError)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp delete_alias_request do
|
||||
%Schema{
|
||||
title: "DeleteAliasRequest",
|
||||
description: "PUT body for deleting aliases",
|
||||
type: :object,
|
||||
required: [:alias],
|
||||
properties: %{
|
||||
alias: %Schema{
|
||||
type: :string,
|
||||
description: "The nickname of the account to delete from aliases"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def healthcheck_operation do
|
||||
%Operation{
|
||||
tags: ["Accounts"],
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Account do
|
|||
header: %Schema{type: :string, format: :uri},
|
||||
id: FlakeID,
|
||||
locked: %Schema{type: :boolean},
|
||||
mute_expires_at: %Schema{type: :string, format: "date-time", nullable: true},
|
||||
note: %Schema{type: :string, format: :html},
|
||||
statuses_count: %Schema{type: :integer},
|
||||
url: %Schema{type: :string, format: :uri},
|
||||
|
|
|
|||
45
lib/pleroma/web/api_spec/schemas/announcement.ex
Normal file
45
lib/pleroma/web/api_spec/schemas/announcement.ex
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.Schemas.Announcement do
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Schemas.FlakeID
|
||||
|
||||
require OpenApiSpex
|
||||
|
||||
OpenApiSpex.schema(%{
|
||||
title: "Announcement",
|
||||
description: "Response schema for an announcement",
|
||||
type: :object,
|
||||
properties: %{
|
||||
id: FlakeID,
|
||||
content: %Schema{type: :string},
|
||||
starts_at: %Schema{
|
||||
type: :string,
|
||||
format: "date-time",
|
||||
nullable: true
|
||||
},
|
||||
ends_at: %Schema{
|
||||
type: :string,
|
||||
format: "date-time",
|
||||
nullable: true
|
||||
},
|
||||
all_day: %Schema{type: :boolean},
|
||||
published_at: %Schema{type: :string, format: "date-time"},
|
||||
updated_at: %Schema{type: :string, format: "date-time"},
|
||||
read: %Schema{type: :boolean},
|
||||
mentions: %Schema{type: :array},
|
||||
statuses: %Schema{type: :array},
|
||||
tags: %Schema{type: :array},
|
||||
emojis: %Schema{type: :array},
|
||||
reactions: %Schema{type: :array},
|
||||
pleroma: %Schema{
|
||||
type: :object,
|
||||
properties: %{
|
||||
raw_content: %Schema{type: :string}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
|
@ -411,6 +411,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
|
||||
@doc "POST /api/v1/accounts/:id/mute"
|
||||
def mute(%{assigns: %{user: muter, account: muted}, body_params: params} = conn, _params) do
|
||||
params =
|
||||
params
|
||||
|> Map.put_new(:duration, Map.get(params, :expires_in, 0))
|
||||
|
||||
with {:ok, _user_relationships} <- User.mute(muter, muted, params) do
|
||||
render(conn, "relationship.json", user: muter, target: muted)
|
||||
else
|
||||
|
|
@ -491,7 +495,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
users =
|
||||
user
|
||||
|> User.muted_users_relation(_restrict_deactivated = true)
|
||||
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
|
||||
|> Pleroma.Pagination.fetch_paginated(params)
|
||||
|
||||
conn
|
||||
|> add_link_headers(users)
|
||||
|
|
@ -499,7 +503,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
users: users,
|
||||
for: user,
|
||||
as: :user,
|
||||
embed_relationships: embed_relationships?(params)
|
||||
embed_relationships: embed_relationships?(params),
|
||||
mutes: true
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -508,7 +513,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
|||
users =
|
||||
user
|
||||
|> User.blocked_users_relation(_restrict_deactivated = true)
|
||||
|> Pleroma.Pagination.fetch_paginated(Map.put(params, :skip_order, true))
|
||||
|> Pleroma.Pagination.fetch_paginated(params)
|
||||
|
||||
conn
|
||||
|> add_link_headers(users)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AnnouncementController do
|
||||
use Pleroma.Web, :controller
|
||||
|
||||
import Pleroma.Web.ControllerHelper,
|
||||
only: [
|
||||
json_response: 3
|
||||
]
|
||||
|
||||
alias Pleroma.Announcement
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
|
||||
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||
|
||||
# Mastodon docs say this only requires a user token, no scopes needed
|
||||
# As the op `|` requires at least one scope to be present, we use `&` here.
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: [], op: :&}
|
||||
when action in [:index]
|
||||
)
|
||||
|
||||
# Same as in MastodonAPI specs
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["write:accounts"]}
|
||||
when action in [:mark_read]
|
||||
)
|
||||
|
||||
action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
|
||||
|
||||
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.AnnouncementOperation
|
||||
|
||||
@doc "GET /api/v1/announcements"
|
||||
def index(%{assigns: %{user: user}} = conn, _params) do
|
||||
render(conn, "index.json", announcements: all_visible(), user: user)
|
||||
end
|
||||
|
||||
def index(conn, _params) do
|
||||
render(conn, "index.json", announcements: all_visible(), user: nil)
|
||||
end
|
||||
|
||||
defp all_visible do
|
||||
Announcement.list_all_visible()
|
||||
end
|
||||
|
||||
@doc "POST /api/v1/announcements/:id/dismiss"
|
||||
def mark_read(%{assigns: %{user: user}} = conn, %{id: id} = _params) do
|
||||
with announcement when not is_nil(announcement) <- Announcement.get_by_id(id),
|
||||
{:ok, _} <- Announcement.mark_read_by(announcement, user) do
|
||||
json_response(conn, :ok, %{})
|
||||
else
|
||||
_ ->
|
||||
{:error, :not_found}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -55,7 +55,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationController do
|
|||
def index(%{assigns: %{user: user}} = conn, params) do
|
||||
params =
|
||||
Map.new(params, fn {k, v} -> {to_string(k), v} end)
|
||||
|> Map.put_new("include_types", @default_notification_types)
|
||||
|> Map.put_new("types", Map.get(params, :include_types, @default_notification_types))
|
||||
|
||||
notifications = MastodonAPI.get_notifications(user, params)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
|
||||
user
|
||||
|> Notification.for_user_query(options)
|
||||
|> restrict(:include_types, options)
|
||||
|> restrict(:types, options)
|
||||
|> restrict(:exclude_types, options)
|
||||
|> restrict(:account_ap_id, options)
|
||||
|> Pagination.fetch_paginated(params)
|
||||
|
|
@ -80,7 +80,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
defp cast_params(params) do
|
||||
param_types = %{
|
||||
exclude_types: {:array, :string},
|
||||
include_types: {:array, :string},
|
||||
types: {:array, :string},
|
||||
exclude_visibilities: {:array, :string},
|
||||
reblogs: :boolean,
|
||||
with_muted: :boolean,
|
||||
|
|
@ -92,7 +92,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
|||
changeset.changes
|
||||
end
|
||||
|
||||
defp restrict(query, :include_types, %{include_types: mastodon_types = [_ | _]}) do
|
||||
defp restrict(query, :types, %{types: mastodon_types = [_ | _]}) do
|
||||
where(query, [n], n.type in ^mastodon_types)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|> maybe_put_unread_conversation_count(user, opts[:for])
|
||||
|> maybe_put_unread_notification_count(user, opts[:for])
|
||||
|> maybe_put_email_address(user, opts[:for])
|
||||
|> maybe_put_mute_expires_at(user, opts[:for], opts)
|
||||
|> maybe_show_birthday(user, opts[:for])
|
||||
end
|
||||
|
||||
|
|
@ -434,6 +435,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
|
||||
defp maybe_put_email_address(data, _, _), do: data
|
||||
|
||||
defp maybe_put_mute_expires_at(data, %User{} = user, target, %{mutes: true}) do
|
||||
Map.put(
|
||||
data,
|
||||
:mute_expires_at,
|
||||
UserRelationship.get_mute_expire_date(target, user)
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_put_mute_expires_at(data, _, _, _), do: data
|
||||
|
||||
defp maybe_show_birthday(data, %User{id: user_id} = user, %User{id: user_id}) do
|
||||
data
|
||||
|> Kernel.put_in([:pleroma, :birthday], user.birthday)
|
||||
|
|
|
|||
15
lib/pleroma/web/mastodon_api/views/announcement_view.ex
Normal file
15
lib/pleroma/web/mastodon_api/views/announcement_view.ex
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AnnouncementView do
|
||||
use Pleroma.Web, :view
|
||||
|
||||
def render("index.json", %{announcements: announcements, user: user}) do
|
||||
render_many(announcements, __MODULE__, "show.json", user: user)
|
||||
end
|
||||
|
||||
def render("show.json", %{announcement: announcement, user: user}) do
|
||||
Pleroma.Announcement.render_json(announcement, for: user)
|
||||
end
|
||||
end
|
||||
|
|
@ -17,6 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceView do
|
|||
uri: Pleroma.Web.Endpoint.url(),
|
||||
title: Keyword.get(instance, :name),
|
||||
description: Keyword.get(instance, :description),
|
||||
short_description: Keyword.get(instance, :short_description),
|
||||
version: "#{@mastodon_api_level} (compatible; #{Pleroma.Application.named_version()})",
|
||||
email: Keyword.get(instance, :email),
|
||||
urls: %{
|
||||
|
|
|
|||
|
|
@ -229,6 +229,12 @@ defmodule Pleroma.Web.Router do
|
|||
post("/frontends/install", FrontendController, :install)
|
||||
|
||||
post("/backups", AdminAPIController, :create_backup)
|
||||
|
||||
get("/announcements", AnnouncementController, :index)
|
||||
post("/announcements", AnnouncementController, :create)
|
||||
get("/announcements/:id", AnnouncementController, :show)
|
||||
patch("/announcements/:id", AnnouncementController, :change)
|
||||
delete("/announcements/:id", AnnouncementController, :delete)
|
||||
end
|
||||
|
||||
# AdminAPI: admins and mods (staff) can perform these actions (if enabled by config)
|
||||
|
|
@ -343,6 +349,11 @@ defmodule Pleroma.Web.Router do
|
|||
post("/delete_account", UtilController, :delete_account)
|
||||
put("/notification_settings", UtilController, :update_notificaton_settings)
|
||||
post("/disable_account", UtilController, :disable_account)
|
||||
post("/move_account", UtilController, :move_account)
|
||||
|
||||
put("/aliases", UtilController, :add_alias)
|
||||
get("/aliases", UtilController, :list_aliases)
|
||||
delete("/aliases", UtilController, :delete_alias)
|
||||
end
|
||||
|
||||
scope "/api/pleroma", Pleroma.Web.PleromaAPI do
|
||||
|
|
@ -575,6 +586,9 @@ defmodule Pleroma.Web.Router do
|
|||
get("/timelines/home", TimelineController, :home)
|
||||
get("/timelines/direct", TimelineController, :direct)
|
||||
get("/timelines/list/:list_id", TimelineController, :list)
|
||||
|
||||
get("/announcements", AnnouncementController, :index)
|
||||
post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
|
||||
end
|
||||
|
||||
scope "/api/v1", Pleroma.Web.MastodonAPI do
|
||||
|
|
@ -669,11 +683,6 @@ defmodule Pleroma.Web.Router do
|
|||
get("/activities/:uuid", OStatus.OStatusController, :activity)
|
||||
get("/notice/:id", OStatus.OStatusController, :notice)
|
||||
|
||||
# Notice compatibility routes for other frontends
|
||||
get("/@:nickname/:id", OStatus.OStatusController, :notice)
|
||||
get("/@:nickname/posts/:id", OStatus.OStatusController, :notice)
|
||||
get("/:nickname/status/:id", OStatus.OStatusController, :notice)
|
||||
|
||||
# Mastodon compatibility routes
|
||||
get("/users/:nickname/statuses/:id", OStatus.OStatusController, :object)
|
||||
get("/users/:nickname/statuses/:id/activity", OStatus.OStatusController, :activity)
|
||||
|
|
|
|||
|
|
@ -167,15 +167,6 @@ defmodule Pleroma.Web.StaticFE.StaticFEController do
|
|||
defp assign_id(%{path_info: ["notice", notice_id]} = conn, _opts),
|
||||
do: assign(conn, :notice_id, notice_id)
|
||||
|
||||
defp assign_id(%{path_info: ["@" <> _nickname, notice_id]} = conn, _opts),
|
||||
do: assign(conn, :notice_id, notice_id)
|
||||
|
||||
defp assign_id(%{path_info: ["@" <> _nickname, "posts", notice_id]} = conn, _opts),
|
||||
do: assign(conn, :notice_id, notice_id)
|
||||
|
||||
defp assign_id(%{path_info: [_nickname, "status", notice_id]} = conn, _opts),
|
||||
do: assign(conn, :notice_id, notice_id)
|
||||
|
||||
defp assign_id(%{path_info: ["users", user_id]} = conn, _opts),
|
||||
do: assign(conn, :username_or_id, user_id)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
alias Pleroma.Emoji
|
||||
alias Pleroma.Healthcheck
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.Web.WebFinger
|
||||
|
|
@ -26,7 +27,18 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
:change_password,
|
||||
:delete_account,
|
||||
:update_notificaton_settings,
|
||||
:disable_account
|
||||
:disable_account,
|
||||
:move_account,
|
||||
:add_alias,
|
||||
:delete_alias
|
||||
]
|
||||
)
|
||||
|
||||
plug(
|
||||
OAuthScopesPlug,
|
||||
%{scopes: ["read:accounts"]}
|
||||
when action in [
|
||||
:list_aliases
|
||||
]
|
||||
)
|
||||
|
||||
|
|
@ -158,6 +170,91 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
end
|
||||
end
|
||||
|
||||
def move_account(%{assigns: %{user: user}, body_params: body_params} = conn, %{}) do
|
||||
case CommonAPI.Utils.confirm_current_password(user, body_params.password) do
|
||||
{:ok, user} ->
|
||||
with {:ok, target_user} <- find_or_fetch_user_by_nickname(body_params.target_account),
|
||||
{:ok, _user} <- ActivityPub.move(user, target_user) do
|
||||
json(conn, %{status: "success"})
|
||||
else
|
||||
{:not_found, _} ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Target account not found."})
|
||||
|
||||
{:error, error} ->
|
||||
json(conn, %{error: error})
|
||||
end
|
||||
|
||||
{:error, msg} ->
|
||||
json(conn, %{error: msg})
|
||||
end
|
||||
end
|
||||
|
||||
def add_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do
|
||||
with {:ok, alias_user} <- find_user_by_nickname(body_params.alias),
|
||||
{:ok, _user} <- user |> User.add_alias(alias_user) do
|
||||
json(conn, %{status: "success"})
|
||||
else
|
||||
{:not_found, _} ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Target account does not exist."})
|
||||
|
||||
{:error, error} ->
|
||||
json(conn, %{error: error})
|
||||
end
|
||||
end
|
||||
|
||||
def delete_alias(%{assigns: %{user: user}, body_params: body_params} = conn, _) do
|
||||
with {:ok, alias_user} <- find_user_by_nickname(body_params.alias),
|
||||
{:ok, _user} <- user |> User.delete_alias(alias_user) do
|
||||
json(conn, %{status: "success"})
|
||||
else
|
||||
{:error, :no_such_alias} ->
|
||||
conn
|
||||
|> put_status(404)
|
||||
|> json(%{error: "Account has no such alias."})
|
||||
|
||||
{:error, error} ->
|
||||
json(conn, %{error: error})
|
||||
end
|
||||
end
|
||||
|
||||
def list_aliases(%{assigns: %{user: user}} = conn, %{}) do
|
||||
alias_nicks =
|
||||
user
|
||||
|> User.alias_users()
|
||||
|> Enum.map(&User.full_nickname/1)
|
||||
|
||||
json(conn, %{aliases: alias_nicks})
|
||||
end
|
||||
|
||||
defp find_user_by_nickname(nickname) do
|
||||
user = User.get_cached_by_nickname(nickname)
|
||||
|
||||
if user == nil do
|
||||
{:not_found, nil}
|
||||
else
|
||||
{:ok, user}
|
||||
end
|
||||
end
|
||||
|
||||
defp find_or_fetch_user_by_nickname(nickname) do
|
||||
user = User.get_by_nickname(nickname)
|
||||
|
||||
if user != nil and user.local do
|
||||
{:ok, user}
|
||||
else
|
||||
with {:ok, user} <- User.fetch_by_nickname(nickname) do
|
||||
{:ok, user}
|
||||
else
|
||||
_ ->
|
||||
{:not_found, nil}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def captcha(conn, _params) do
|
||||
json(conn, Pleroma.Captcha.new())
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,5 +7,9 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowView do
|
|||
import Phoenix.HTML.Form
|
||||
alias Pleroma.Web.Gettext
|
||||
|
||||
defdelegate avatar_url(user), to: Pleroma.User
|
||||
def avatar_url(user) do
|
||||
user
|
||||
|> Pleroma.User.avatar_url()
|
||||
|> Pleroma.Web.MediaProxy.url()
|
||||
end
|
||||
end
|
||||
|
|
|
|||
2
mix.exs
2
mix.exs
|
|
@ -194,7 +194,7 @@ defmodule Pleroma.Mixfile do
|
|||
ref: "e0f16822d578866e186a0974d65ad58cddc1e2ab"},
|
||||
{:restarter, path: "./restarter"},
|
||||
{:majic, "~> 1.0"},
|
||||
{:eblurhash, "~> 1.1.0"},
|
||||
{:eblurhash, "~> 1.2.2"},
|
||||
{:open_api_spex, "~> 3.10"},
|
||||
{:phoenix_live_dashboard, "~> 0.6.2"},
|
||||
{:ecto_psql_extras, "~> 0.6"},
|
||||
|
|
|
|||
2
mix.lock
2
mix.lock
|
|
@ -29,7 +29,7 @@
|
|||
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
|
||||
"earmark": {:hex, :earmark, "1.4.18", "618c4ff1563450d1832b7fb41dc6755e470f91a6fd4c70f350a58b14f64a7db8", [:mix], [{:earmark_parser, ">= 1.4.17", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "57ac3b6da3958ed09c669a9b159e86377fcccda56bacde8a209fa4dcdef52560"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.17", "6f3c7e94170377ba45241d394389e800fb15adc5de51d0a3cd52ae766aafd63f", [:mix], [], "hexpm", "f93ac89c9feca61c165b264b5837bf82344d13bebc634cd575cb711e2e342023"},
|
||||
"eblurhash": {:hex, :eblurhash, "1.1.0", "e10ccae762598507ebfacf0b645ed49520f2afa3e7e9943e73a91117dffce415", [:rebar3], [], "hexpm", "2e6b889d09fddd374e3c5ac57c486138768763264e99ac1074ae5fa7fc9ab51d"},
|
||||
"eblurhash": {:hex, :eblurhash, "1.2.2", "7da4255aaea984b31bb71155f673257353b0e0554d0d30dcf859547e74602582", [:rebar3], [], "hexpm", "8c20ca00904de023a835a9dcb7b7762fed32264c85a80c3cafa85288e405044c"},
|
||||
"ecto": {:hex, :ecto, "3.6.2", "efdf52acfc4ce29249bab5417415bd50abd62db7b0603b8bab0d7b996548c2bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "efad6dfb04e6f986b8a3047822b0f826d9affe8e4ebdd2aeedbfcb14fd48884e"},
|
||||
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
|
||||
"ecto_psql_extras": {:hex, :ecto_psql_extras, "0.7.4", "5d43fd088d39a158c860b17e8d210669587f63ec89ea122a4654861c8c6e2db4", [:mix], [{:ecto_sql, "~> 3.4", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:postgrex, ">= 0.15.7", [hex: :postgrex, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1.1", [hex: :table_rex, repo: "hexpm", optional: false]}], "hexpm", "311db02f1b772e3d0dc7f56a05044b5e1499d78ed6abf38885e1ca70059449e5"},
|
||||
|
|
|
|||
6023
priv/gettext/config_descriptions.pot
Normal file
6023
priv/gettext/config_descriptions.pot
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -10,175 +10,175 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:122
|
||||
msgid "%{name} - %{count} is not a multiple of %{multiple}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:131
|
||||
msgid "%{name} - %{value} is larger than exclusive maximum %{max}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:140
|
||||
msgid "%{name} - %{value} is larger than inclusive maximum %{max}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:149
|
||||
msgid "%{name} - %{value} is smaller than exclusive minimum %{min}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:158
|
||||
msgid "%{name} - %{value} is smaller than inclusive minimum %{min}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:102
|
||||
msgid "%{name} - Array items must be unique."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:114
|
||||
msgid "%{name} - Array length %{length} is larger than maxItems: %{}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:106
|
||||
msgid "%{name} - Array length %{length} is smaller than minItems: %{min}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:166
|
||||
msgid "%{name} - Invalid %{type}. Got: %{value}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:174
|
||||
msgid "%{name} - Invalid format. Expected %{format}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:51
|
||||
msgid "%{name} - Invalid schema.type. Got: %{type}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:178
|
||||
msgid "%{name} - Invalid value for enum."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:95
|
||||
msgid "%{name} - String length is larger than maxLength: %{length}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:88
|
||||
msgid "%{name} - String length is smaller than minLength: %{length}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:63
|
||||
msgid "%{name} - null value where %{type} expected."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:60
|
||||
msgid "%{name} - null value."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:182
|
||||
msgid "Failed to cast to any schema in %{polymorphic_type}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:71
|
||||
msgid "Failed to cast value as %{invalid_schema}. Value must be castable using `allOf` schemas listed."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:84
|
||||
msgid "Failed to cast value to one of: %{failed_schemas}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:78
|
||||
msgid "Failed to cast value using any of: %{failed_schemas}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:212
|
||||
msgid "Invalid value for header: %{name}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:204
|
||||
msgid "Missing field: %{name}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:208
|
||||
msgid "Missing header: %{name}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:196
|
||||
msgid "No value provided for required discriminator `%{field}`."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:216
|
||||
msgid "Object property count %{property_count} is greater than maxProperties: %{max_properties}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:224
|
||||
msgid "Object property count %{property_count} is less than minProperties: %{min_properties}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/error.html.eex:2
|
||||
msgid "Oops"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:188
|
||||
msgid "Unexpected field: %{name}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:200
|
||||
msgid "Unknown schema: %{name}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:192
|
||||
msgid "Value used as discriminator for `%{field}` matches no schemas."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:43
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:37
|
||||
msgid "announces"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:44
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:38
|
||||
msgid "likes"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:42
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:36
|
||||
msgid "replies"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:27
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:22
|
||||
msgid "sensitive media"
|
||||
|
|
|
|||
|
|
@ -89,436 +89,483 @@ msgstr ""
|
|||
msgid "must be equal to %{number}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:523
|
||||
msgid "Account not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:316
|
||||
msgid "Already voted"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:402
|
||||
msgid "Bad request"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/controller_helper.ex:97
|
||||
#: lib/pleroma/web/controller_helper.ex:103
|
||||
msgid "Can't display this activity"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:324
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:325
|
||||
msgid "Can't find user"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:80
|
||||
msgid "Can't get favorites"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:482
|
||||
msgid "Cannot post an empty status without attachments"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:441
|
||||
msgid "Comment must be up to %{max_size} characters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/config_db.ex:200
|
||||
msgid "Config with params %{params} not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:167 lib/pleroma/web/common_api.ex:171
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:167
|
||||
#: lib/pleroma/web/common_api.ex:171
|
||||
msgid "Could not delete"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:217
|
||||
msgid "Could not favorite"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:254
|
||||
msgid "Could not unfavorite"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:202
|
||||
msgid "Could not unrepeat"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:530 lib/pleroma/web/common_api.ex:539
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:530
|
||||
#: lib/pleroma/web/common_api.ex:539
|
||||
msgid "Could not update state"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:205
|
||||
msgid "Error."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:105
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:144
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:631
|
||||
msgid "Invalid credentials"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/ensure_authenticated_plug.ex:42
|
||||
msgid "Invalid credentials."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:337
|
||||
msgid "Invalid indices"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:29
|
||||
msgid "Invalid parameters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:349
|
||||
msgid "Invalid password."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:255
|
||||
msgid "Invalid request"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:102
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:108
|
||||
msgid "Kocaptcha service unavailable"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:140
|
||||
msgid "Missing parameters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:477
|
||||
msgid "No such conversation"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:171
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:197 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:239
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:197
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:239
|
||||
msgid "No such permission_group"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:504
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11 lib/pleroma/web/feed/tag_controller.ex:16
|
||||
#: lib/pleroma/web/feed/user_controller.ex:69 lib/pleroma/web/o_status/o_status_controller.ex:132
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:515
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11
|
||||
#: lib/pleroma/web/feed/tag_controller.ex:16
|
||||
#: lib/pleroma/web/feed/user_controller.ex:69
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:132
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:84
|
||||
msgid "Not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:308
|
||||
msgid "Poll's author can't vote"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:39 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:51
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:52 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:326
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:39
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:51
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:52
|
||||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:326
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
|
||||
msgid "Record not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35
|
||||
#: lib/pleroma/web/feed/user_controller.ex:78 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:42
|
||||
#: lib/pleroma/web/feed/user_controller.ex:78
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:42
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:138
|
||||
msgid "Something went wrong"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/activity_draft.ex:143
|
||||
msgid "The message visibility must be direct"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:492
|
||||
msgid "The status is over the character limit"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex:36
|
||||
msgid "This resource requires authentication."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/rate_limiter.ex:208
|
||||
msgid "Throttled"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:338
|
||||
msgid "Too many choices"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:268
|
||||
msgid "You can't revoke your own admin status."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:243
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:333
|
||||
msgid "Your account is currently disabled"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:205
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:356
|
||||
msgid "Your login is missing a confirmed e-mail address"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:392
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:403
|
||||
msgid "can't read inbox of %{nickname} as %{as_nickname}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:502
|
||||
msgid "can't update outbox of %{nickname} as %{as_nickname}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:475
|
||||
msgid "conversation is already muted"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:510
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:521
|
||||
msgid "error"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:34
|
||||
msgid "mascots can only be images"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:63
|
||||
msgid "not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:437
|
||||
msgid "Bad OAuth request."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:108
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:114
|
||||
msgid "CAPTCHA already used"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:111
|
||||
msgid "CAPTCHA expired"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:57
|
||||
msgid "Failed"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:453
|
||||
msgid "Failed to authenticate: %{message}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:484
|
||||
msgid "Failed to set up user account."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/o_auth_scopes_plug.ex:37
|
||||
msgid "Insufficient permissions: %{permissions}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:111
|
||||
msgid "Internal Error"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:22
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:29
|
||||
msgid "Invalid Username/Password"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:117
|
||||
msgid "Invalid answer data"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33
|
||||
msgid "Nodeinfo schema version not handled"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:194
|
||||
msgid "This action is outside the authorized scopes"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:14
|
||||
msgid "Unknown error, please check the details and try again."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:136
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:180
|
||||
msgid "Unlisted redirect_uri."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:433
|
||||
msgid "Unsupported OAuth provider: %{provider}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/uploaders/uploader.ex:74
|
||||
msgid "Uploader callback timeout"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/uploader_controller.ex:23
|
||||
msgid "bad request"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:96
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:102
|
||||
msgid "CAPTCHA Error"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:266
|
||||
msgid "Could not add reaction emoji"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api.ex:277
|
||||
msgid "Could not remove reaction emoji"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:128
|
||||
msgid "Invalid CAPTCHA (Missing parameter: %{name})"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:96
|
||||
msgid "List not found"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:151
|
||||
msgid "Missing parameter: %{name}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:232
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:346
|
||||
msgid "Password reset is required"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/tests/auth_test_controller.ex:9
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/chat_controller.ex:6 lib/pleroma/web/admin_api/controllers/config_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6 lib/pleroma/web/admin_api/controllers/frontend_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/instance_controller.ex:6 lib/pleroma/web/admin_api/controllers/instance_document_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/user_controller.ex:6 lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6
|
||||
#: lib/pleroma/web/fallback/redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6
|
||||
#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:6
|
||||
#: lib/pleroma/web/manifest_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:11 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/directory_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14 lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/report_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7 lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6 lib/pleroma/web/media_proxy/media_proxy_controller.ex:6
|
||||
#: lib/pleroma/web/mongoose_im/mongoose_im_controller.ex:6 lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:6 lib/pleroma/web/o_auth/mfa_controller.ex:10
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:6 lib/pleroma/web/o_status/o_status_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/app_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/backup_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5
|
||||
#: lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/instances_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/announcement_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/chat_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/frontend_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/instance_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/instance_document_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/relay_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/user_controller.ex:6
|
||||
#: lib/pleroma/web/controller_helper.ex:6
|
||||
#: lib/pleroma/web/embed_controller.ex:6
|
||||
#: lib/pleroma/web/fallback/redirect_controller.ex:6
|
||||
#: lib/pleroma/web/feed/tag_controller.ex:6
|
||||
#: lib/pleroma/web/feed/user_controller.ex:6
|
||||
#: lib/pleroma/web/mailer/subscription_controller.ex:6
|
||||
#: lib/pleroma/web/manifest_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/announcement_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:11
|
||||
#: lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/directory_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14
|
||||
#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7
|
||||
#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6
|
||||
#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6
|
||||
#: lib/pleroma/web/mongoose_im/mongoose_im_controller.ex:6
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/o_auth/mfa_controller.ex:10
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:6
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/app_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/backup_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5
|
||||
#: lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/instances_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex:6
|
||||
#: lib/pleroma/web/static_fe/static_fe_controller.ex:6 lib/pleroma/web/twitter_api/controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/uploader_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7
|
||||
#: lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex:6
|
||||
#: lib/pleroma/web/static_fe/static_fe_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10
|
||||
#: lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6
|
||||
#: lib/pleroma/web/uploader_controller.ex:6
|
||||
#: lib/pleroma/web/web_finger/web_finger_controller.ex:6
|
||||
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/ensure_authenticated_plug.ex:32
|
||||
msgid "Two-factor authentication enabled, you must use a access token."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
|
||||
msgid "Web push subscription is disabled on this Pleroma instance"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:234
|
||||
msgid "You can't revoke your own admin/moderator status."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:129
|
||||
msgid "authorization required for timeline view"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:24
|
||||
msgid "Access denied"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:321
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:322
|
||||
msgid "This API requires an authenticated user"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/ensure_staff_privileged_plug.ex:26
|
||||
#: lib/pleroma/web/plugs/user_is_admin_plug.ex:21
|
||||
msgid "User is not an admin."
|
||||
|
|
@ -531,33 +578,33 @@ msgid_plural "Last export was less than %{days} days ago"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/user/backup.ex:93
|
||||
msgid "Backups require enabled email"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:423
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:434
|
||||
msgid "Character limit (%{limit} characters) exceeded, contains %{length} characters"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/user/backup.ex:98
|
||||
msgid "Email is required"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/common_api/utils.ex:507
|
||||
msgid "Too many attachments"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/plugs/ensure_staff_privileged_plug.ex:33
|
||||
#: lib/pleroma/web/plugs/user_is_staff_plug.ex:20
|
||||
msgid "User is not a staff member."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:366
|
||||
msgid "Your account is awaiting approval."
|
||||
msgstr ""
|
||||
|
|
|
|||
6011
priv/gettext/fr/LC_MESSAGES/config_descriptions.po
Normal file
6011
priv/gettext/fr/LC_MESSAGES/config_descriptions.po
Normal file
File diff suppressed because it is too large
Load diff
212
priv/gettext/fr/LC_MESSAGES/default.po
Normal file
212
priv/gettext/fr/LC_MESSAGES/default.po
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-07-21 23:42+0300\n"
|
||||
"PO-Revision-Date: 2022-07-22 19:00+0000\n"
|
||||
"Last-Translator: Haelwenn <contact+git.pleroma.social@hacktivis.me>\n"
|
||||
"Language-Team: French <http://weblate.pleroma-dev.ebin.club/projects/pleroma/"
|
||||
"pleroma-backend-domain-default/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
## "msgid"s here are often extracted from source code.
|
||||
## Add new translations manually only if they're dynamic
|
||||
## translations that can't be statically extracted.
|
||||
##
|
||||
## Run "mix gettext.extract" to bring this file up to
|
||||
## date. Leave "msgstr"s empty as changing them here as no
|
||||
## effect: edit them in PO (.po) files instead.
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - %{count} is not a multiple of %{multiple}."
|
||||
msgstr "%{name} - %{count} n'est pas un multiple de %{multiple}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:131
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - %{value} is larger than exclusive maximum %{max}."
|
||||
msgstr "%{name} - %{value} est plus large que %{max}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:140
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - %{value} is larger than inclusive maximum %{max}."
|
||||
msgstr "%{name} - %{value} est plus large que %{max}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - %{value} is smaller than exclusive minimum %{min}."
|
||||
msgstr "%{name} - %{value} est plus petit que %{min}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - %{value} is smaller than inclusive minimum %{min}."
|
||||
msgstr "%{name} - %{value} est plus petit que %{min}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:102
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Array items must be unique."
|
||||
msgstr "%{name} - Les objects de la liste doivent être uniques."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Array length %{length} is larger than maxItems: %{}."
|
||||
msgstr ""
|
||||
"%{name} - La longueur %{length} de la liste est supérieure à maxItems : %{}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:106
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Array length %{length} is smaller than minItems: %{min}."
|
||||
msgstr ""
|
||||
"%{name} - La longueur %{length} de la liste est inférieure à minItems : "
|
||||
"%{min}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:166
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Invalid %{type}. Got: %{value}."
|
||||
msgstr "%{name} - %{type} invalide. Reçu : %{value}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:174
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Invalid format. Expected %{format}."
|
||||
msgstr "%{name} - Format invalide. Format voulu : %{format}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:51
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Invalid schema.type. Got: %{type}."
|
||||
msgstr "%{name} - schema.type invalide. Reçu : %{type}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:178
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - Invalid value for enum."
|
||||
msgstr "%{name} - valeur invalide pour enum."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - String length is larger than maxLength: %{length}."
|
||||
msgstr ""
|
||||
"%{name} - Longueur de chaine de caractères supérieure à maxLength : "
|
||||
"%{length}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - String length is smaller than minLength: %{length}."
|
||||
msgstr ""
|
||||
"%{name} - Longueur de chaine de caractères inférieure à minLength : "
|
||||
"%{length}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - null value where %{type} expected."
|
||||
msgstr "%{name} - valeur nulle quand %{type} est requis."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{name} - null value."
|
||||
msgstr "%{name} - valeur nulle."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:182
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to cast to any schema in %{polymorphic_type}"
|
||||
msgstr "Échec de transformation du schéma en %{polymorphic_type}"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:71
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to cast value as %{invalid_schema}. Value must be castable using `allOf` schemas listed."
|
||||
msgstr ""
|
||||
"Échec de transformation de la valeur en %{invalid_schema}. La valeur doit "
|
||||
"être transformable dans un des schémas `allOf` listés."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to cast value to one of: %{failed_schemas}."
|
||||
msgstr "Échec de transformation de la valeur en un des : %{failed_schemas}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Failed to cast value using any of: %{failed_schemas}."
|
||||
msgstr "Échec de transformation de la valeur en un des : %{failed_schemas}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:212
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Invalid value for header: %{name}."
|
||||
msgstr "Valeur invalide pour l'en-tête : %{name}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:204
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Missing field: %{name}."
|
||||
msgstr "Champ manquant : %{name}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:208
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Missing header: %{name}."
|
||||
msgstr "En-tête manquant : %{name}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:196
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No value provided for required discriminator `%{field}`."
|
||||
msgstr "Aucune valeur fournie pour le discriminant `%{field}`."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:216
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Object property count %{property_count} is greater than maxProperties: %{max_properties}."
|
||||
msgstr ""
|
||||
"Le nombre de propriétés, %{property_count} est supérieur à maxProperties : "
|
||||
"%{max_properties}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:224
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Object property count %{property_count} is less than minProperties: %{min_properties}"
|
||||
msgstr ""
|
||||
"Le nombre de propriétés, %{property_count} est inférieur à minProperties : "
|
||||
"%{min_properties}"
|
||||
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/error.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Oops"
|
||||
msgstr "Oups"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:188
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unexpected field: %{name}."
|
||||
msgstr "Champ inconnu : %{name}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:200
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown schema: %{name}."
|
||||
msgstr "Schéma inconnu : %{name}."
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:192
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Value used as discriminator for `%{field}` matches no schemas."
|
||||
msgstr ""
|
||||
"Valeur utilisée en discriminant de `%{field}` ne correspond à aucun schémas."
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:43
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "announces"
|
||||
msgstr "annonces"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:44
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:38
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "likes"
|
||||
msgstr "favoris"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:42
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "replies"
|
||||
msgstr "réponses"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:27
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "sensitive media"
|
||||
msgstr "contenu sensible"
|
||||
165
priv/gettext/fr/LC_MESSAGES/posix_errors.po
Normal file
165
priv/gettext/fr/LC_MESSAGES/posix_errors.po
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-07-22 02:09+0300\n"
|
||||
"PO-Revision-Date: 2022-07-21 23:35+0000\n"
|
||||
"Last-Translator: Haelwenn <contact+git.pleroma.social@hacktivis.me>\n"
|
||||
"Language-Team: French <http://weblate.pleroma-dev.ebin.club/projects/pleroma/"
|
||||
"pleroma-backend-domain-posix_errors/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
## `msgid`s here are often extracted from source code.
|
||||
## Add new translations manually only if they're dynamic
|
||||
## translations that can't be statically extracted.
|
||||
##
|
||||
## Run `mix gettext.extract` to bring this file up to
|
||||
## date. Leave `msgstr`s empty as changing them here as no
|
||||
## effect: edit them in PO (`.po`) files instead.
|
||||
msgid "eperm"
|
||||
msgstr "Opération non permise"
|
||||
|
||||
msgid "eacces"
|
||||
msgstr "Permission refusée"
|
||||
|
||||
msgid "eagain"
|
||||
msgstr "Ressource temporairement indisponible"
|
||||
|
||||
msgid "ebadf"
|
||||
msgstr "Mauvais descripteur de fichier"
|
||||
|
||||
msgid "ebadmsg"
|
||||
msgstr "Mauvais message"
|
||||
|
||||
msgid "ebusy"
|
||||
msgstr "Périphérique ou ressource occupée"
|
||||
|
||||
msgid "edeadlk"
|
||||
msgstr "Interblocage des ressources évité"
|
||||
|
||||
msgid "edeadlock"
|
||||
msgstr "Interblocage des ressources évité"
|
||||
|
||||
msgid "edquot"
|
||||
msgstr "Quota disque dépassé"
|
||||
|
||||
msgid "eexist"
|
||||
msgstr "Fichier existant"
|
||||
|
||||
msgid "efault"
|
||||
msgstr "Mauvaise addresse"
|
||||
|
||||
msgid "efbig"
|
||||
msgstr "Fichier trop gros"
|
||||
|
||||
msgid "eftype"
|
||||
msgstr "Type ou format de fichier inapproprié"
|
||||
|
||||
msgid "eintr"
|
||||
msgstr "Appel système interrompu"
|
||||
|
||||
msgid "einval"
|
||||
msgstr "Argument invalide"
|
||||
|
||||
msgid "eio"
|
||||
msgstr "Erreur entrée/sortie"
|
||||
|
||||
msgid "eisdir"
|
||||
msgstr "Opération non-permise sur un répertoire"
|
||||
|
||||
msgid "eloop"
|
||||
msgstr "Trop de niveau de liens symboliques"
|
||||
|
||||
msgid "emfile"
|
||||
msgstr "Trop de fichiers ouverts"
|
||||
|
||||
msgid "emlink"
|
||||
msgstr "Trop de liens"
|
||||
|
||||
msgid "emultihop"
|
||||
msgstr "Multi-saut essayé"
|
||||
|
||||
msgid "enametoolong"
|
||||
msgstr "Nom de fichier trop long"
|
||||
|
||||
msgid "enfile"
|
||||
msgstr "Trop de fichier ouvert dans le système"
|
||||
|
||||
msgid "enobufs"
|
||||
msgstr "Pas d'espace tampon disponible"
|
||||
|
||||
msgid "enodev"
|
||||
msgstr "Périphérique inexistant"
|
||||
|
||||
msgid "enolck"
|
||||
msgstr "Pas de verrous disponibles"
|
||||
|
||||
msgid "enolink"
|
||||
msgstr "Lien rompus"
|
||||
|
||||
msgid "enoent"
|
||||
msgstr "Fichier ou dossier non trouvé"
|
||||
|
||||
msgid "enomem"
|
||||
msgstr "Échec d'allocation mémoire"
|
||||
|
||||
msgid "enospc"
|
||||
msgstr "Plus de place disponible sur le périphérique"
|
||||
|
||||
msgid "enosr"
|
||||
msgstr "Plus de flux disponibles"
|
||||
|
||||
msgid "enostr"
|
||||
msgstr "Périphérique qui n'est pas un flux"
|
||||
|
||||
msgid "enosys"
|
||||
msgstr "Fonction non implémentée"
|
||||
|
||||
msgid "enotblk"
|
||||
msgstr "Périphérique bloc requis"
|
||||
|
||||
msgid "enotdir"
|
||||
msgstr "Pas un répertoire"
|
||||
|
||||
msgid "enotsup"
|
||||
msgstr "Opération non supportée"
|
||||
|
||||
msgid "enxio"
|
||||
msgstr "Addresse de périphérique inconnue"
|
||||
|
||||
msgid "eopnotsupp"
|
||||
msgstr "Opération non supportée"
|
||||
|
||||
msgid "eoverflow"
|
||||
msgstr "Valeur trop grande pour le type de donnée definit"
|
||||
|
||||
msgid "epipe"
|
||||
msgstr "Tuyaux rompu"
|
||||
|
||||
msgid "erange"
|
||||
msgstr "Valeur numérique hors de l'interval"
|
||||
|
||||
msgid "erofs"
|
||||
msgstr "Système de fichier en lecture-seule"
|
||||
|
||||
msgid "espipe"
|
||||
msgstr "Déplacement interdit"
|
||||
|
||||
msgid "esrch"
|
||||
msgstr "Processus inexistant"
|
||||
|
||||
msgid "estale"
|
||||
msgstr "Descripteur de fichier bouché"
|
||||
|
||||
msgid "etxtbsy"
|
||||
msgstr "Fichier texte occupé"
|
||||
|
||||
msgid "exdev"
|
||||
msgstr "Lien inter-périphérique invalide"
|
||||
564
priv/gettext/fr/LC_MESSAGES/static_pages.po
Normal file
564
priv/gettext/fr/LC_MESSAGES/static_pages.po
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-07-21 23:03+0300\n"
|
||||
"PO-Revision-Date: 2022-07-21 20:44+0000\n"
|
||||
"Last-Translator: Haelwenn <contact+git.pleroma.social@hacktivis.me>\n"
|
||||
"Language-Team: French <http://weblate.pleroma-dev.ebin.club/projects/pleroma/"
|
||||
"pleroma-backend-domain-static_pages/fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
## "msgid"s here are often extracted from source code.
|
||||
## Add new translations manually only if they're dynamic
|
||||
## translations that can't be statically extracted.
|
||||
##
|
||||
## Run "mix gettext.extract" to bring this file up to
|
||||
## date. Leave "msgstr"s empty as changing them here as no
|
||||
## effect: edit them in PO (.po) files instead.
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow authorization button"
|
||||
msgid "Authorize"
|
||||
msgstr "Autoriser"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error fetching user"
|
||||
msgstr "Erreur de requête au compte"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remote follow"
|
||||
msgstr "Suivit distant"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "placeholder text for auth code entry"
|
||||
msgid "Authentication code"
|
||||
msgstr "Code d'Authentification"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "placeholder text for password entry"
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "placeholder text for username entry"
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur·rice"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow authorization button for login"
|
||||
msgid "Authorize"
|
||||
msgstr "Autoriser"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow authorization button for mfa"
|
||||
msgid "Authorize"
|
||||
msgstr "Autoriser"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error following account"
|
||||
msgstr "Erreur de suivi du compte"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow header, need login"
|
||||
msgid "Log in to follow"
|
||||
msgstr "Authentification pour le suivit"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow mfa header"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr "Authentification à deux facteurs"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow success"
|
||||
msgid "Account followed!"
|
||||
msgstr "Utilisateur·rice suivi·e !"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "placeholder text for account id"
|
||||
msgid "Your account ID, e.g. lain@quitter.se"
|
||||
msgstr "Votre identifiant, ex. lain@quitter.se"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow authorization button for following with a remote account"
|
||||
msgid "Follow"
|
||||
msgstr "Suivre"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error: %{error}"
|
||||
msgstr "Erreur : %{error}"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remotely follow %{nickname}"
|
||||
msgstr "Suivre %{nickname} à distance"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset button"
|
||||
msgid "Reset"
|
||||
msgstr "Changer"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset failed homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr "Page d'accueil"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset failed message"
|
||||
msgid "Password reset failed"
|
||||
msgstr "Échec de changement du mot de passe"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset form confirm password prompt"
|
||||
msgid "Confirmation"
|
||||
msgstr "Confirmation"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset form password prompt"
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset invalid token message"
|
||||
msgid "Invalid Token"
|
||||
msgstr "Jeton invalide"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset successful homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr "Page d'accueil"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset successful message"
|
||||
msgid "Password changed!"
|
||||
msgstr "Mot de passe changé !"
|
||||
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.atom.eex:15
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.rss.eex:7
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "tag feed description"
|
||||
msgid "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse."
|
||||
msgstr ""
|
||||
"Ceci sont des messages publics lié à #%{tag}. Vous pouvez intéragir avec si "
|
||||
"vous avez un compte sur le Fediverse."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth authorization exists page title"
|
||||
msgid "Authorization exists"
|
||||
msgstr "Autorisation existante"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:32
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth authorize approve button"
|
||||
msgid "Approve"
|
||||
msgstr "Approuver"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth authorize cancel button"
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth authorize message"
|
||||
msgid "Application <strong>%{client_name}</strong> is requesting access to your account."
|
||||
msgstr ""
|
||||
"L'application <strong>%{client_name}</strong> demande un accès à votre "
|
||||
"compte."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth authorized page title"
|
||||
msgid "Successfully authorized"
|
||||
msgstr "Autorisé avec succès"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth external provider page title"
|
||||
msgid "Sign in with external provider"
|
||||
msgstr "Authentication externe"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth external provider sign in button"
|
||||
msgid "Sign in with %{strategy}"
|
||||
msgstr "Authentification avec %{strategy}"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth login button"
|
||||
msgid "Log In"
|
||||
msgstr "Authentification"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:51
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth login password prompt"
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth login username prompt"
|
||||
msgid "Username"
|
||||
msgstr "Nom d'utilisateur·rice"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:39
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register nickname prompt"
|
||||
msgid "Pleroma Handle"
|
||||
msgstr "Pseudo Pleroma"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register nickname unchangeable warning"
|
||||
msgid "Choose carefully! You won't be able to change this later. You will be able to change your display name, though."
|
||||
msgstr ""
|
||||
"Faites attention ! Vous ne pourrez plus le changer plus tard. Mais, vous "
|
||||
"pourrez changer votre Nom."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page email prompt"
|
||||
msgid "Email"
|
||||
msgstr "Courriel"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page fill form prompt"
|
||||
msgid "If you'd like to register a new account, please provide the details below."
|
||||
msgstr "Si vous voulez créer un compte, veuillez fournir les détails suivants."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page login button"
|
||||
msgid "Proceed as existing user"
|
||||
msgstr "Continuer avec un compte existant"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page login password prompt"
|
||||
msgid "Password"
|
||||
msgstr "Mot de passe"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page login prompt"
|
||||
msgid "Alternatively, sign in to connect to existing account."
|
||||
msgstr "Alternativement, s'authentifier avec un compte existant."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page login username prompt"
|
||||
msgid "Name or email"
|
||||
msgstr "Nom ou courriel"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page nickname prompt"
|
||||
msgid "Nickname"
|
||||
msgstr "Pseudonyme"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page register button"
|
||||
msgid "Proceed as new user"
|
||||
msgstr "Continuer avec un nouveau compte"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page title"
|
||||
msgid "Registration Details"
|
||||
msgstr "Détails d'inscriptions"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:36
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth register page title"
|
||||
msgid "This is the first time you visit! Please enter your Pleroma handle."
|
||||
msgstr "Ceci est votre première visite ! Veuillez entrer votre pseudo."
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth scopes message"
|
||||
msgid "The following permissions will be granted"
|
||||
msgstr "Les permissions suivantes seront données"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:2
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:2
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "oauth token code message"
|
||||
msgid "Token code is <br>%{token}"
|
||||
msgstr "Le jeton est <br>%{token}"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa auth code prompt"
|
||||
msgid "Authentication code"
|
||||
msgstr "Code d'authentification"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa auth page title"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr "Authentification à double-facteurs"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa auth page use recovery code link"
|
||||
msgid "Enter a two-factor recovery code"
|
||||
msgstr "Entrer un code de récupération de l'authentification à double-facteur"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa auth verify code button"
|
||||
msgid "Verify"
|
||||
msgstr "Vérifier"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa recover page title"
|
||||
msgid "Two-factor recovery"
|
||||
msgstr "Récupération du double-facteur"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa recover recovery code prompt"
|
||||
msgid "Recovery code"
|
||||
msgstr "Code de récupération"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa recover use 2fa code link"
|
||||
msgid "Enter a two-factor code"
|
||||
msgstr "Entrer un code double-facteur"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mfa recover verify recovery code button"
|
||||
msgid "Verify"
|
||||
msgstr "Vérifier"
|
||||
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "static fe profile page remote follow button"
|
||||
msgid "Remote follow"
|
||||
msgstr "Suivit distant"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:163
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email header line"
|
||||
msgid "Hey %{nickname}, here is what you've missed!"
|
||||
msgstr "Salut %{nickname}, voici ce que tu as manqué·e !"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:544
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email receiver address"
|
||||
msgid "The email address you are subscribed as is <a href='mailto:%{@user.email}' style='color: %{color};text-decoration: none;'>%{email}</a>. "
|
||||
msgstr ""
|
||||
"L'adresse que vous avez enregistré est <a href='mailto:%{@user.email}' "
|
||||
"style='color : %{color} ;text-decoration : none ;'>%{email}</a>. "
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:538
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email sending reason"
|
||||
msgid "You have received this email because you have signed up to receive digest emails from <b>%{instance}</b> Pleroma instance."
|
||||
msgstr ""
|
||||
"Vous recevez ce courriel parce-que vous avez autorisé les messages-résumés "
|
||||
"de l'instance pleroma, <b>%{instance}</b>."
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email unsubscribe action"
|
||||
msgid "To unsubscribe, please go %{here}."
|
||||
msgstr "Pour vous désinscrire, aller %{here}."
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email unsubscribe action link text"
|
||||
msgid "here"
|
||||
msgstr "ici"
|
||||
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mailer unsubscribe failed message"
|
||||
msgid "UNSUBSCRIBE FAILURE"
|
||||
msgstr "ÉCHEC DE DÉSINSCRIPTION"
|
||||
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex:1
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "mailer unsubscribe successful message"
|
||||
msgid "UNSUBSCRIBE SUCCESSFUL"
|
||||
msgstr "SUCCÈS DE LA DÉSINSCRIPTION"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:385
|
||||
#, elixir-format
|
||||
msgctxt "new followers count header"
|
||||
msgid "%{count} New Follower"
|
||||
msgid_plural "%{count} New Followers"
|
||||
msgstr[0] "%{count} nouveau suivit"
|
||||
msgstr[1] "%{count} nouveaux suivits"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:356
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "account archive email body - self-requested"
|
||||
msgid "<p>You requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
msgstr ""
|
||||
"<p>Vous avez demandé une sauvegarde complète de votre compte Pleroma. Le "
|
||||
"téléchargement est prêt :</p>\n"
|
||||
"<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:384
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "account archive email subject"
|
||||
msgid "Your account archive is ready"
|
||||
msgstr "La sauvegarde de votre compte est prête"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:188
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "approval pending email body"
|
||||
msgid "<h3>Awaiting Approval</h3>\n<p>Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>En attente d'approbation</h3>\n"
|
||||
"<p>Votre compte sur %{instance_name} est en revue par l'équipe. Vous "
|
||||
"recevrez un autre courriel quand le compte sera approuvé.</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:202
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "approval pending email subject"
|
||||
msgid "Your account is awaiting approval"
|
||||
msgstr "Votre compte est en attente d'approbation"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "confirmation email body"
|
||||
msgid "<h3>Thank you for registering on %{instance_name}</h3>\n<p>Email confirmation is required to activate the account.</p>\n<p>Please click the following link to <a href=\"%{confirmation_url}\">activate your account</a>.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>Merci de votre inscription à %{instance_name}</h3>\n"
|
||||
"<p>Une confirmation du courriel est requise.</p>\n"
|
||||
"<p>Veuillez cliquer sur <a href=\"%{confirmation_url}\">pour activer votre "
|
||||
"compte</a>.</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:174
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "confirmation email subject"
|
||||
msgid "%{instance_name} account confirmation"
|
||||
msgstr "confirmation du compte %{instance_name}"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:310
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "digest email subject"
|
||||
msgid "Your digest from %{instance_name}"
|
||||
msgstr "Votre résumé de %{instance_name}"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:81
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset email body"
|
||||
msgid "<h3>Reset your password at %{instance_name}</h3>\n<p>Someone has requested password change for your account at %{instance_name}.</p>\n<p>If it was you, visit the following link to proceed: <a href=\"%{password_reset_url}\">reset password</a>.</p>\n<p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>Changement de mot de passe à %{instance_name}</h3>\n"
|
||||
"<p>Une requête de changement de mot de passe pour votre compte à "
|
||||
"%{instance_name} à été reçue.</p>\n"
|
||||
"<p>Si c'était vous, veuillez suivre le lien suivant pour continuer : <a href="
|
||||
"\"%{password_reset_url}\">changer de mot de passe</a>.</p>\n"
|
||||
"<p>Si ça n'était pas vous, rien à craindre, vos données sont sécurisés et "
|
||||
"votre mot de passe n'a pas été changé.</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:98
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "password reset email subject"
|
||||
msgid "Password reset"
|
||||
msgstr "Changement de mot de passe"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:215
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "successful registration email body"
|
||||
msgid "<h3>Hello @%{nickname},</h3>\n<p>Your account at %{instance_name} has been registered successfully.</p>\n<p>No further action is required to activate your account.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>Bonjour @%{nickname},</h3>\n"
|
||||
"<p>Votre compte %{instance_name} à été enregistré avec succès.</p>\n"
|
||||
"<p>Aucune action suivante est requise.</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:231
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "successful registration email subject"
|
||||
msgid "Account registered on %{instance_name}"
|
||||
msgstr "Compte enregistré sur %{instance_name}"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:119
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "user invitation email body"
|
||||
msgid "<h3>You are invited to %{instance_name}</h3>\n<p>%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.</p>\n<p>Click the following link to register: <a href=\"%{registration_url}\">accept invitation</a>.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>Vous avez été invité à %{instance_name}</h3>\n"
|
||||
"<p>%{inviter_name} vous invite à rejoindre %{instance_name}, une instance de "
|
||||
"Pleroma, réseau social fédéré.</p>\n"
|
||||
"<p>Cliquer le lien suivant pour vous enregistrer : <a href=\""
|
||||
"%{registration_url}\">accepter l'invitation</a>.</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:136
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "user invitation email subject"
|
||||
msgid "Invitation to %{instance_name}"
|
||||
msgstr "Invitation à %{instance_name}"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "welcome email html body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "Bienvenu·e à %{instance_name} !"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:41
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "welcome email subject"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "Bienvenu·e à %{instance_name} !"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:65
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "welcome email text body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "Bienvenu·e à %{instance_name} !"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:368
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "account archive email body - admin requested"
|
||||
msgid "<p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
msgstr ""
|
||||
"<p>L'Admin de @%{admin_nickname} à demandé une sauvegarde complète de votre "
|
||||
"compte Pleroma. Le téléchargement est prêt:</p>\n"
|
||||
"<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
|
|
@ -10,393 +10,393 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
msgctxt "remote follow authorization button"
|
||||
msgid "Authorize"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:2
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error fetching user"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:4
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remote follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:8
|
||||
msgctxt "placeholder text for auth code entry"
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:10
|
||||
msgctxt "placeholder text for password entry"
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:8
|
||||
msgctxt "placeholder text for username entry"
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:13
|
||||
msgctxt "remote follow authorization button for login"
|
||||
msgid "Authorize"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:12
|
||||
msgctxt "remote follow authorization button for mfa"
|
||||
msgid "Authorize"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:2
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error following account"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:4
|
||||
msgctxt "remote follow header, need login"
|
||||
msgid "Log in to follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:4
|
||||
msgctxt "remote follow mfa header"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:4
|
||||
msgctxt "remote follow success"
|
||||
msgid "Account followed!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:7
|
||||
msgctxt "placeholder text for account id"
|
||||
msgid "Your account ID, e.g. lain@quitter.se"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:8
|
||||
msgctxt "remote follow authorization button for following with a remote account"
|
||||
msgid "Follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:2
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error: %{error}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:4
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remotely follow %{nickname}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:12
|
||||
msgctxt "password reset button"
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:4
|
||||
msgctxt "password reset failed homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:1
|
||||
msgctxt "password reset failed message"
|
||||
msgid "Password reset failed"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:8
|
||||
msgctxt "password reset form confirm password prompt"
|
||||
msgid "Confirmation"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:4
|
||||
msgctxt "password reset form password prompt"
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex:1
|
||||
msgctxt "password reset invalid token message"
|
||||
msgid "Invalid Token"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:2
|
||||
msgctxt "password reset successful homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:1
|
||||
msgctxt "password reset successful message"
|
||||
msgid "Password changed!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.atom.eex:15
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.rss.eex:7
|
||||
msgctxt "tag feed description"
|
||||
msgid "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:1
|
||||
msgctxt "oauth authorization exists page title"
|
||||
msgid "Authorization exists"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:32
|
||||
msgctxt "oauth authorize approve button"
|
||||
msgid "Approve"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:30
|
||||
msgctxt "oauth authorize cancel button"
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:23
|
||||
msgctxt "oauth authorize message"
|
||||
msgid "Application <strong>%{client_name}</strong> is requesting access to your account."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:1
|
||||
msgctxt "oauth authorized page title"
|
||||
msgid "Successfully authorized"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:1
|
||||
msgctxt "oauth external provider page title"
|
||||
msgid "Sign in with external provider"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:13
|
||||
msgctxt "oauth external provider sign in button"
|
||||
msgid "Sign in with %{strategy}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:54
|
||||
msgctxt "oauth login button"
|
||||
msgid "Log In"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:51
|
||||
msgctxt "oauth login password prompt"
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:47
|
||||
msgctxt "oauth login username prompt"
|
||||
msgid "Username"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:39
|
||||
msgctxt "oauth register nickname prompt"
|
||||
msgid "Pleroma Handle"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:37
|
||||
msgctxt "oauth register nickname unchangeable warning"
|
||||
msgid "Choose carefully! You won't be able to change this later. You will be able to change your display name, though."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:18
|
||||
msgctxt "oauth register page email prompt"
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:10
|
||||
msgctxt "oauth register page fill form prompt"
|
||||
msgid "If you'd like to register a new account, please provide the details below."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:35
|
||||
msgctxt "oauth register page login button"
|
||||
msgid "Proceed as existing user"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:31
|
||||
msgctxt "oauth register page login password prompt"
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:24
|
||||
msgctxt "oauth register page login prompt"
|
||||
msgid "Alternatively, sign in to connect to existing account."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:27
|
||||
msgctxt "oauth register page login username prompt"
|
||||
msgid "Name or email"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:14
|
||||
msgctxt "oauth register page nickname prompt"
|
||||
msgid "Nickname"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:22
|
||||
msgctxt "oauth register page register button"
|
||||
msgid "Proceed as new user"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:8
|
||||
msgctxt "oauth register page title"
|
||||
msgid "Registration Details"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:36
|
||||
msgctxt "oauth register page title"
|
||||
msgid "This is the first time you visit! Please enter your Pleroma handle."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex:2
|
||||
msgctxt "oauth scopes message"
|
||||
msgid "The following permissions will be granted"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:2
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:2
|
||||
msgctxt "oauth token code message"
|
||||
msgid "Token code is <br>%{token}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:12
|
||||
msgctxt "mfa auth code prompt"
|
||||
msgid "Authentication code"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:8
|
||||
msgctxt "mfa auth page title"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:23
|
||||
msgctxt "mfa auth page use recovery code link"
|
||||
msgid "Enter a two-factor recovery code"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:20
|
||||
msgctxt "mfa auth verify code button"
|
||||
msgid "Verify"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:8
|
||||
msgctxt "mfa recover page title"
|
||||
msgid "Two-factor recovery"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:12
|
||||
msgctxt "mfa recover recovery code prompt"
|
||||
msgid "Recovery code"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:23
|
||||
msgctxt "mfa recover use 2fa code link"
|
||||
msgid "Enter a two-factor code"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:20
|
||||
msgctxt "mfa recover verify recovery code button"
|
||||
msgid "Verify"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex:8
|
||||
msgctxt "static fe profile page remote follow button"
|
||||
msgid "Remote follow"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:163
|
||||
msgctxt "digest email header line"
|
||||
msgid "Hey %{nickname}, here is what you've missed!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:544
|
||||
msgctxt "digest email receiver address"
|
||||
msgid "The email address you are subscribed as is <a href='mailto:%{@user.email}' style='color: %{color};text-decoration: none;'>%{email}</a>. "
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:538
|
||||
msgctxt "digest email sending reason"
|
||||
msgid "You have received this email because you have signed up to receive digest emails from <b>%{instance}</b> Pleroma instance."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
msgctxt "digest email unsubscribe action"
|
||||
msgid "To unsubscribe, please go %{here}."
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
msgctxt "digest email unsubscribe action link text"
|
||||
msgid "here"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex:1
|
||||
msgctxt "mailer unsubscribe failed message"
|
||||
msgid "UNSUBSCRIBE FAILURE"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex:1
|
||||
msgctxt "mailer unsubscribe successful message"
|
||||
msgid "UNSUBSCRIBE SUCCESSFUL"
|
||||
|
|
@ -410,103 +410,103 @@ msgid_plural "%{count} New Followers"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:356
|
||||
msgctxt "account archive email body - self-requested"
|
||||
msgid "<p>You requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:384
|
||||
msgctxt "account archive email subject"
|
||||
msgid "Your account archive is ready"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:188
|
||||
msgctxt "approval pending email body"
|
||||
msgid "<h3>Awaiting Approval</h3>\n<p>Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:202
|
||||
msgctxt "approval pending email subject"
|
||||
msgid "Your account is awaiting approval"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:158
|
||||
msgctxt "confirmation email body"
|
||||
msgid "<h3>Thank you for registering on %{instance_name}</h3>\n<p>Email confirmation is required to activate the account.</p>\n<p>Please click the following link to <a href=\"%{confirmation_url}\">activate your account</a>.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:174
|
||||
msgctxt "confirmation email subject"
|
||||
msgid "%{instance_name} account confirmation"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:310
|
||||
msgctxt "digest email subject"
|
||||
msgid "Your digest from %{instance_name}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:81
|
||||
msgctxt "password reset email body"
|
||||
msgid "<h3>Reset your password at %{instance_name}</h3>\n<p>Someone has requested password change for your account at %{instance_name}.</p>\n<p>If it was you, visit the following link to proceed: <a href=\"%{password_reset_url}\">reset password</a>.</p>\n<p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:98
|
||||
msgctxt "password reset email subject"
|
||||
msgid "Password reset"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:215
|
||||
msgctxt "successful registration email body"
|
||||
msgid "<h3>Hello @%{nickname},</h3>\n<p>Your account at %{instance_name} has been registered successfully.</p>\n<p>No further action is required to activate your account.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:231
|
||||
msgctxt "successful registration email subject"
|
||||
msgid "Account registered on %{instance_name}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:119
|
||||
msgctxt "user invitation email body"
|
||||
msgid "<h3>You are invited to %{instance_name}</h3>\n<p>%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.</p>\n<p>Click the following link to register: <a href=\"%{registration_url}\">accept invitation</a>.</p>\n"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:136
|
||||
msgctxt "user invitation email subject"
|
||||
msgid "Invitation to %{instance_name}"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:53
|
||||
msgctxt "welcome email html body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:41
|
||||
msgctxt "welcome email subject"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:65
|
||||
msgctxt "welcome email text body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr ""
|
||||
|
||||
#, elixir-format
|
||||
#, elixir-autogen, elixir-format
|
||||
#: lib/pleroma/emails/user_email.ex:368
|
||||
msgctxt "account archive email body - admin requested"
|
||||
msgid "<p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
|
|
|
|||
6027
priv/gettext/zh_Hans/LC_MESSAGES/config_descriptions.po
Normal file
6027
priv/gettext/zh_Hans/LC_MESSAGES/config_descriptions.po
Normal file
File diff suppressed because it is too large
Load diff
193
priv/gettext/zh_Hans/LC_MESSAGES/default.po
Normal file
193
priv/gettext/zh_Hans/LC_MESSAGES/default.po
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
## "msgid"s in this file come from POT (.pot) files.
|
||||
##
|
||||
## Do not add, change, or remove "msgid"s manually here as
|
||||
## they're tied to the ones in the corresponding POT file
|
||||
## (with the same domain).
|
||||
##
|
||||
## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-07-22 19:00+0000\n"
|
||||
"Last-Translator: Yating Zhan <thestrandedvalley@protonmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://weblate.pleroma-dev.ebin.club/"
|
||||
"projects/pleroma/pleroma-backend-domain-default/zh_Hans/>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:122
|
||||
#, elixir-format
|
||||
msgid "%{name} - %{count} is not a multiple of %{multiple}."
|
||||
msgstr "%{name} - %{count} 不是 %{multiple} 的倍数。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:131
|
||||
#, elixir-format
|
||||
msgid "%{name} - %{value} is larger than exclusive maximum %{max}."
|
||||
msgstr "%{name} - %{value} 大于排除性最大值 %{max}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:140
|
||||
#, elixir-format
|
||||
msgid "%{name} - %{value} is larger than inclusive maximum %{max}."
|
||||
msgstr "%{name} - %{value} 大于包括性最大值 %{max}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:149
|
||||
#, elixir-format
|
||||
msgid "%{name} - %{value} is smaller than exclusive minimum %{min}."
|
||||
msgstr "%{name} - %{value} 小于排除性最小值 %{min}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:158
|
||||
#, elixir-format
|
||||
msgid "%{name} - %{value} is smaller than inclusive minimum %{min}."
|
||||
msgstr "%{name} - %{value} 小于包括性最小值 %{min}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:102
|
||||
#, elixir-format
|
||||
msgid "%{name} - Array items must be unique."
|
||||
msgstr "%{name} - 数组项目必须唯一。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:114
|
||||
#, elixir-format
|
||||
msgid "%{name} - Array length %{length} is larger than maxItems: %{}."
|
||||
msgstr "%{name} - 数组长度 %{length} 大于最大项目数: %{}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:106
|
||||
#, elixir-format
|
||||
msgid "%{name} - Array length %{length} is smaller than minItems: %{min}."
|
||||
msgstr "%{name} - 数组长度 %{length} 小于最小项目数: %{min}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:166
|
||||
#, elixir-format
|
||||
msgid "%{name} - Invalid %{type}. Got: %{value}."
|
||||
msgstr "%{name} - 不合法的 %{type}。得到的是:%{value}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:174
|
||||
#, elixir-format
|
||||
msgid "%{name} - Invalid format. Expected %{format}."
|
||||
msgstr "%{name} - 不合法的格式。预期是 %{format}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:51
|
||||
#, elixir-format
|
||||
msgid "%{name} - Invalid schema.type. Got: %{type}."
|
||||
msgstr "%{name} - 不合法的 schema.type。得到的是:%{type}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:178
|
||||
#, elixir-format
|
||||
msgid "%{name} - Invalid value for enum."
|
||||
msgstr "%{name} - 枚举值不合法。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:95
|
||||
#, elixir-format
|
||||
msgid "%{name} - String length is larger than maxLength: %{length}."
|
||||
msgstr "%{name} - 字串长度大于最大长度:%{length}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:88
|
||||
#, elixir-format
|
||||
msgid "%{name} - String length is smaller than minLength: %{length}."
|
||||
msgstr "%{name} - 字串长度小于最小长度:%{length}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:63
|
||||
#, elixir-format
|
||||
msgid "%{name} - null value where %{type} expected."
|
||||
msgstr "%{name} - null 值,但是预期该是 %{type}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:60
|
||||
#, elixir-format
|
||||
msgid "%{name} - null value."
|
||||
msgstr "%{name} - null 值。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:182
|
||||
#, elixir-format
|
||||
msgid "Failed to cast to any schema in %{polymorphic_type}"
|
||||
msgstr "转换到 %{polymorphic_type} 中的任一 schema 失败"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:71
|
||||
#, elixir-format
|
||||
msgid "Failed to cast value as %{invalid_schema}. Value must be castable using `allOf` schemas listed."
|
||||
msgstr "把值转换成 %{invalid_schema} 失败。值必须可以被转换成在列的「所有」schema。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:84
|
||||
#, elixir-format
|
||||
msgid "Failed to cast value to one of: %{failed_schemas}."
|
||||
msgstr "转换值为 %{failed_schemas} 中的一个失败。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:78
|
||||
#, elixir-format
|
||||
msgid "Failed to cast value using any of: %{failed_schemas}."
|
||||
msgstr "转换值为 %{failed_schemas} 中的任意一个失败。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:212
|
||||
#, elixir-format
|
||||
msgid "Invalid value for header: %{name}."
|
||||
msgstr "头 %{name} 的不合法的值。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:204
|
||||
#, elixir-format
|
||||
msgid "Missing field: %{name}."
|
||||
msgstr "缺少字段:%{name}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:208
|
||||
#, elixir-format
|
||||
msgid "Missing header: %{name}."
|
||||
msgstr "缺少头:%{name}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:196
|
||||
#, elixir-format
|
||||
msgid "No value provided for required discriminator `%{field}`."
|
||||
msgstr ""
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:216
|
||||
#, elixir-format
|
||||
msgid "Object property count %{property_count} is greater than maxProperties: %{max_properties}."
|
||||
msgstr ""
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:224
|
||||
#, elixir-format
|
||||
msgid "Object property count %{property_count} is less than minProperties: %{min_properties}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/error.html.eex:2
|
||||
#, elixir-format
|
||||
msgid "Oops"
|
||||
msgstr "嗨呀"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:188
|
||||
#, elixir-format
|
||||
msgid "Unexpected field: %{name}."
|
||||
msgstr "超出预期的字段:%{name}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:200
|
||||
#, elixir-format
|
||||
msgid "Unknown schema: %{name}."
|
||||
msgstr "未知的 schema:%{name}。"
|
||||
|
||||
#: lib/pleroma/web/api_spec/render_error.ex:192
|
||||
#, elixir-format
|
||||
msgid "Value used as discriminator for `%{field}` matches no schemas."
|
||||
msgstr ""
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:43
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:37
|
||||
#, elixir-format
|
||||
msgid "announces"
|
||||
msgstr "传播"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:44
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:38
|
||||
#, elixir-format
|
||||
msgid "likes"
|
||||
msgstr "喜欢"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:42
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:36
|
||||
#, elixir-format
|
||||
msgid "replies"
|
||||
msgstr "回复"
|
||||
|
||||
#: lib/pleroma/web/templates/embed/show.html.eex:27
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/_notice.html.eex:22
|
||||
#, elixir-format
|
||||
msgid "sensitive media"
|
||||
msgstr "敏感媒体"
|
||||
|
|
@ -3,16 +3,16 @@ msgstr ""
|
|||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-09-20 13:18+0000\n"
|
||||
"PO-Revision-Date: 2020-12-14 06:00+0000\n"
|
||||
"Last-Translator: shironeko <shironeko@tesaguri.club>\n"
|
||||
"Language-Team: Chinese (Simplified) <https://translate.pleroma.social/"
|
||||
"projects/pleroma/pleroma/zh_Hans/>\n"
|
||||
"PO-Revision-Date: 2022-07-22 19:00+0000\n"
|
||||
"Last-Translator: Yating Zhan <thestrandedvalley@protonmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://weblate.pleroma-dev.ebin.club/"
|
||||
"projects/pleroma/pleroma-backend-domain-errors/zh_Hans/>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.0.4\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
|
|
@ -65,7 +65,7 @@ msgstr[0] "应为 %{count} 个字符"
|
|||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
msgstr[0] "应有 %{item} 项"
|
||||
msgstr[0] "应有 %{count} 项"
|
||||
|
||||
msgid "should be at least %{count} character(s)"
|
||||
msgid_plural "should be at least %{count} character(s)"
|
||||
|
|
@ -99,121 +99,101 @@ msgstr "必须大于等于 %{number}"
|
|||
msgid "must be equal to %{number}"
|
||||
msgstr "必须等于 %{number}"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:505
|
||||
#: lib/pleroma/web/common_api.ex:523
|
||||
#, elixir-format
|
||||
msgid "Account not found"
|
||||
msgstr "未找到账号"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:339
|
||||
#: lib/pleroma/web/common_api.ex:316
|
||||
#, elixir-format
|
||||
msgid "Already voted"
|
||||
msgstr "已经进行了投票"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:359
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:402
|
||||
#, elixir-format
|
||||
msgid "Bad request"
|
||||
msgstr "不正确的请求"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:426
|
||||
#, elixir-format
|
||||
msgid "Can't delete object"
|
||||
msgstr "不能删除对象"
|
||||
|
||||
#: lib/pleroma/web/controller_helper.ex:105
|
||||
#: lib/pleroma/web/controller_helper.ex:111
|
||||
#: lib/pleroma/web/controller_helper.ex:97
|
||||
#: lib/pleroma/web/controller_helper.ex:103
|
||||
#, elixir-format
|
||||
msgid "Can't display this activity"
|
||||
msgstr "不能显示该活动"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:285
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:324
|
||||
#, elixir-format
|
||||
msgid "Can't find user"
|
||||
msgstr "找不到用户"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:61
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:80
|
||||
#, elixir-format
|
||||
msgid "Can't get favorites"
|
||||
msgstr "不能获取收藏"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:438
|
||||
#, elixir-format
|
||||
msgid "Can't like object"
|
||||
msgstr "不能喜欢对象"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:563
|
||||
#: lib/pleroma/web/common_api/utils.ex:482
|
||||
#, elixir-format
|
||||
msgid "Cannot post an empty status without attachments"
|
||||
msgstr "无法发送空白且不包含附件的状态"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:511
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/common_api/utils.ex:441
|
||||
#, elixir-format
|
||||
msgid "Comment must be up to %{max_size} characters"
|
||||
msgstr "评论最多可使用 %{max_size} 字符"
|
||||
|
||||
#: lib/pleroma/config/config_db.ex:191
|
||||
#: lib/pleroma/config_db.ex:200
|
||||
#, elixir-format
|
||||
msgid "Config with params %{params} not found"
|
||||
msgstr "无法找到包含参数 %{params} 的配置"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:181
|
||||
#: lib/pleroma/web/common_api/common_api.ex:185
|
||||
#: lib/pleroma/web/common_api.ex:167
|
||||
#: lib/pleroma/web/common_api.ex:171
|
||||
#, elixir-format
|
||||
msgid "Could not delete"
|
||||
msgstr "无法删除"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:231
|
||||
#: lib/pleroma/web/common_api.ex:217
|
||||
#, elixir-format
|
||||
msgid "Could not favorite"
|
||||
msgstr "无法收藏"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:453
|
||||
#, elixir-format
|
||||
msgid "Could not pin"
|
||||
msgstr "无法置顶"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:278
|
||||
#: lib/pleroma/web/common_api.ex:254
|
||||
#, elixir-format
|
||||
msgid "Could not unfavorite"
|
||||
msgstr "无法取消收藏"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:463
|
||||
#, elixir-format
|
||||
msgid "Could not unpin"
|
||||
msgstr "无法取消置顶"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:216
|
||||
#: lib/pleroma/web/common_api.ex:202
|
||||
#, elixir-format
|
||||
msgid "Could not unrepeat"
|
||||
msgstr "无法取消转发"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:512
|
||||
#: lib/pleroma/web/common_api/common_api.ex:521
|
||||
#: lib/pleroma/web/common_api.ex:530
|
||||
#: lib/pleroma/web/common_api.ex:539
|
||||
#, elixir-format
|
||||
msgid "Could not update state"
|
||||
msgstr "无法更新状态"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:207
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:205
|
||||
#, elixir-format
|
||||
msgid "Error."
|
||||
msgstr "错误。"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:106
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:99
|
||||
#, elixir-format
|
||||
msgid "Invalid CAPTCHA"
|
||||
msgstr "无效的验证码"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:116
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:568
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:144
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:631
|
||||
#, elixir-format
|
||||
msgid "Invalid credentials"
|
||||
msgstr "无效的凭据"
|
||||
|
||||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:38
|
||||
#: lib/pleroma/web/plugs/ensure_authenticated_plug.ex:42
|
||||
#, elixir-format
|
||||
msgid "Invalid credentials."
|
||||
msgstr "无效的凭据。"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:355
|
||||
#: lib/pleroma/web/common_api.ex:337
|
||||
#, elixir-format
|
||||
msgid "Invalid indices"
|
||||
msgstr "无效的索引"
|
||||
|
|
@ -223,343 +203,362 @@ msgstr "无效的索引"
|
|||
msgid "Invalid parameters"
|
||||
msgstr "无效的参数"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:414
|
||||
#: lib/pleroma/web/common_api/utils.ex:349
|
||||
#, elixir-format
|
||||
msgid "Invalid password."
|
||||
msgstr "无效的密码。"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:220
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:254
|
||||
#, elixir-format
|
||||
msgid "Invalid request"
|
||||
msgstr "无效的请求"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:109
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:102
|
||||
#, elixir-format
|
||||
msgid "Kocaptcha service unavailable"
|
||||
msgstr "Kocaptcha 服务不可用"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:112
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:140
|
||||
#, elixir-format
|
||||
msgid "Missing parameters"
|
||||
msgstr "缺少参数"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:547
|
||||
#: lib/pleroma/web/common_api/utils.ex:477
|
||||
#, elixir-format
|
||||
msgid "No such conversation"
|
||||
msgstr "没有该对话"
|
||||
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:388
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:414 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:456
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:171
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:197
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:239
|
||||
#, elixir-format
|
||||
msgid "No such permission_group"
|
||||
msgstr "没有该权限组"
|
||||
|
||||
#: lib/pleroma/plugs/uploaded_media.ex:84
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:486 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11
|
||||
#: lib/pleroma/web/feed/user_controller.ex:71 lib/pleroma/web/ostatus/ostatus_controller.ex:143
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:504
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:11
|
||||
#: lib/pleroma/web/feed/tag_controller.ex:16
|
||||
#: lib/pleroma/web/feed/user_controller.ex:69
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:132
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:84
|
||||
#, elixir-format
|
||||
msgid "Not found"
|
||||
msgstr "未找到"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:331
|
||||
#: lib/pleroma/web/common_api.ex:308
|
||||
#, elixir-format
|
||||
msgid "Poll's author can't vote"
|
||||
msgstr "投票的发起者不能投票"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:20
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:37 lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:49
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:50 lib/pleroma/web/mastodon_api/controllers/status_controller.ex:306
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:39
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:51
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:52
|
||||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:326
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:71
|
||||
#, elixir-format
|
||||
msgid "Record not found"
|
||||
msgstr "未找到该记录"
|
||||
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:35
|
||||
#: lib/pleroma/web/feed/user_controller.ex:77 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:36
|
||||
#: lib/pleroma/web/ostatus/ostatus_controller.ex:149
|
||||
#: lib/pleroma/web/feed/user_controller.ex:78
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:42
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:138
|
||||
#, elixir-format
|
||||
msgid "Something went wrong"
|
||||
msgstr "发生了一些错误"
|
||||
|
||||
#: lib/pleroma/web/common_api/activity_draft.ex:107
|
||||
#: lib/pleroma/web/common_api/activity_draft.ex:143
|
||||
#, elixir-format
|
||||
msgid "The message visibility must be direct"
|
||||
msgstr "该消息必须为私信"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:573
|
||||
#: lib/pleroma/web/common_api/utils.ex:492
|
||||
#, elixir-format
|
||||
msgid "The status is over the character limit"
|
||||
msgstr "状态超过了字符数限制"
|
||||
|
||||
#: lib/pleroma/plugs/ensure_public_or_authenticated_plug.ex:31
|
||||
#: lib/pleroma/web/plugs/ensure_public_or_authenticated_plug.ex:36
|
||||
#, elixir-format
|
||||
msgid "This resource requires authentication."
|
||||
msgstr "该资源需要认证。"
|
||||
|
||||
#: lib/pleroma/plugs/rate_limiter/rate_limiter.ex:206
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/plugs/rate_limiter.ex:208
|
||||
#, elixir-format
|
||||
msgid "Throttled"
|
||||
msgstr "节流了"
|
||||
msgstr "限流了"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:356
|
||||
#: lib/pleroma/web/common_api.ex:338
|
||||
#, elixir-format
|
||||
msgid "Too many choices"
|
||||
msgstr "太多选项"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:443
|
||||
#, elixir-format
|
||||
msgid "Unhandled activity type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:485
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:268
|
||||
#, elixir-format
|
||||
msgid "You can't revoke your own admin status."
|
||||
msgstr "您不能撤消自己的管理员权限。"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:221
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:308
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:243
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:333
|
||||
#, elixir-format
|
||||
msgid "Your account is currently disabled"
|
||||
msgstr "您的账户已被禁用"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:183
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:331
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:205
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:356
|
||||
#, elixir-format
|
||||
msgid "Your login is missing a confirmed e-mail address"
|
||||
msgstr "您的账户缺少已认证的 e-mail 地址"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:390
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:392
|
||||
#, elixir-format
|
||||
msgid "can't read inbox of %{nickname} as %{as_nickname}"
|
||||
msgstr "无法以 %{as_nickname} 读取 %{nickname} 的收件箱"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:473
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:491
|
||||
#, elixir-format
|
||||
msgid "can't update outbox of %{nickname} as %{as_nickname}"
|
||||
msgstr "无法以 %{as_nickname} 更新 %{nickname} 的出件箱"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:471
|
||||
#: lib/pleroma/web/common_api.ex:475
|
||||
#, elixir-format
|
||||
msgid "conversation is already muted"
|
||||
msgstr "对话已经被静音"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:314
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:492
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:510
|
||||
#, elixir-format
|
||||
msgid "error"
|
||||
msgstr "错误"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:32
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:34
|
||||
#, elixir-format
|
||||
msgid "mascots can only be images"
|
||||
msgstr "吉祥物只能是图片"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:62
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:63
|
||||
#, elixir-format
|
||||
msgid "not found"
|
||||
msgstr "未找到"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:394
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:437
|
||||
#, elixir-format
|
||||
msgid "Bad OAuth request."
|
||||
msgstr "错误的 OAuth 请求。"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:115
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:108
|
||||
#, elixir-format
|
||||
msgid "CAPTCHA already used"
|
||||
msgstr "验证码已被使用"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:112
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:105
|
||||
#, elixir-format
|
||||
msgid "CAPTCHA expired"
|
||||
msgstr "验证码已过期"
|
||||
|
||||
#: lib/pleroma/plugs/uploaded_media.ex:57
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:57
|
||||
#, elixir-format
|
||||
msgid "Failed"
|
||||
msgstr "失败"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:410
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:453
|
||||
#, elixir-format
|
||||
msgid "Failed to authenticate: %{message}."
|
||||
msgstr "认证失败:%{message}。"
|
||||
msgstr "鉴权失败:%{message}。"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:441
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:484
|
||||
#, elixir-format
|
||||
msgid "Failed to set up user account."
|
||||
msgstr "建立用户帐号失败。"
|
||||
|
||||
#: lib/pleroma/plugs/oauth_scopes_plug.ex:38
|
||||
#: lib/pleroma/web/plugs/o_auth_scopes_plug.ex:37
|
||||
#, elixir-format
|
||||
msgid "Insufficient permissions: %{permissions}."
|
||||
msgstr "权限不足:%{permissions}。"
|
||||
|
||||
#: lib/pleroma/plugs/uploaded_media.ex:104
|
||||
#: lib/pleroma/web/plugs/uploaded_media.ex:111
|
||||
#, elixir-format
|
||||
msgid "Internal Error"
|
||||
msgstr "内部错误"
|
||||
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:22
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:29
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:22
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:29
|
||||
#, elixir-format
|
||||
msgid "Invalid Username/Password"
|
||||
msgstr "无效的用户名/密码"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:118
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:111
|
||||
#, elixir-format
|
||||
msgid "Invalid answer data"
|
||||
msgstr "无效的回答数据"
|
||||
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:33
|
||||
#, elixir-format
|
||||
#, elixir-format, fuzzy
|
||||
msgid "Nodeinfo schema version not handled"
|
||||
msgstr ""
|
||||
msgstr "Nodeinfo schema 版本没被处理"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:172
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:194
|
||||
#, elixir-format
|
||||
msgid "This action is outside the authorized scopes"
|
||||
msgstr "此操作在许可范围以外"
|
||||
|
||||
#: lib/pleroma/web/oauth/fallback_controller.ex:14
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:14
|
||||
#, elixir-format
|
||||
msgid "Unknown error, please check the details and try again."
|
||||
msgstr "未知错误,请检查并重试。"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:119
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:158
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:136
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:180
|
||||
#, elixir-format
|
||||
msgid "Unlisted redirect_uri."
|
||||
msgstr ""
|
||||
msgstr "没被列出的重定向 URI(redirect_uri)。"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:390
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:433
|
||||
#, elixir-format
|
||||
msgid "Unsupported OAuth provider: %{provider}."
|
||||
msgstr "不支持的 OAuth 提供者:%{provider}。"
|
||||
|
||||
#: lib/pleroma/uploaders/uploader.ex:72
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/uploaders/uploader.ex:74
|
||||
#, elixir-format
|
||||
msgid "Uploader callback timeout"
|
||||
msgstr "上传回复超时"
|
||||
msgstr "上传器回调超时"
|
||||
|
||||
#: lib/pleroma/web/uploader_controller.ex:23
|
||||
#, elixir-format
|
||||
msgid "bad request"
|
||||
msgstr "错误的请求"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:103
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:96
|
||||
#, elixir-format
|
||||
msgid "CAPTCHA Error"
|
||||
msgstr "验证码错误"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:290
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/common_api.ex:266
|
||||
#, elixir-format
|
||||
msgid "Could not add reaction emoji"
|
||||
msgstr "无法添加表情反应"
|
||||
|
||||
#: lib/pleroma/web/common_api/common_api.ex:301
|
||||
#: lib/pleroma/web/common_api.ex:277
|
||||
#, elixir-format
|
||||
msgid "Could not remove reaction emoji"
|
||||
msgstr "无法移除表情反应"
|
||||
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:129
|
||||
#: lib/pleroma/web/twitter_api/twitter_api.ex:122
|
||||
#, elixir-format
|
||||
msgid "Invalid CAPTCHA (Missing parameter: %{name})"
|
||||
msgstr "无效的验证码(缺少参数:%{name})"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:92
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:96
|
||||
#, elixir-format
|
||||
msgid "List not found"
|
||||
msgstr "未找到列表"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:123
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:151
|
||||
#, elixir-format
|
||||
msgid "Missing parameter: %{name}"
|
||||
msgstr "缺少参数:%{name}"
|
||||
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:210
|
||||
#: lib/pleroma/web/oauth/oauth_controller.ex:321
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:232
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:346
|
||||
#, elixir-format
|
||||
msgid "Password reset is required"
|
||||
msgstr "需要重置密码"
|
||||
|
||||
#: lib/pleroma/tests/auth_test_controller.ex:9
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6 lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6 lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6 lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex:6 lib/pleroma/web/admin_api/controllers/relay_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6 lib/pleroma/web/admin_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/controller_helper.ex:6 lib/pleroma/web/embed_controller.ex:6
|
||||
#: lib/pleroma/web/fallback_redirect_controller.ex:6 lib/pleroma/web/feed/tag_controller.ex:6
|
||||
#: lib/pleroma/web/feed/user_controller.ex:6 lib/pleroma/web/mailer/subscription_controller.ex:2
|
||||
#: lib/pleroma/web/masto_fe_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14
|
||||
#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/report_controller.ex:8
|
||||
#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7
|
||||
#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6 lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6
|
||||
#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6 lib/pleroma/web/mongooseim/mongoose_im_controller.ex:6
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6 lib/pleroma/web/oauth/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/oauth/mfa_controller.ex:10 lib/pleroma/web/oauth/oauth_controller.ex:6
|
||||
#: lib/pleroma/web/ostatus/ostatus_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5 lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:2 lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6 lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/chat_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/config_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/frontend_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/instance_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/instance_document_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/invite_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/relay_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/admin_api/controllers/user_controller.ex:6
|
||||
#: lib/pleroma/web/controller_helper.ex:6
|
||||
#: lib/pleroma/web/embed_controller.ex:6
|
||||
#: lib/pleroma/web/fallback/redirect_controller.ex:6
|
||||
#: lib/pleroma/web/feed/tag_controller.ex:6
|
||||
#: lib/pleroma/web/feed/user_controller.ex:6
|
||||
#: lib/pleroma/web/mailer/subscription_controller.ex:6
|
||||
#: lib/pleroma/web/manifest_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/app_controller.ex:11
|
||||
#: lib/pleroma/web/mastodon_api/controllers/auth_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/conversation_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/custom_emoji_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/directory_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/filter_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/follow_request_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/instance_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/list_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/marker_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/mastodon_api_controller.ex:14
|
||||
#: lib/pleroma/web/mastodon_api/controllers/media_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/poll_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/scheduled_activity_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/search_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/status_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:7
|
||||
#: lib/pleroma/web/mastodon_api/controllers/suggestion_controller.ex:6
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:6
|
||||
#: lib/pleroma/web/media_proxy/media_proxy_controller.ex:6
|
||||
#: lib/pleroma/web/mongoose_im/mongoose_im_controller.ex:6
|
||||
#: lib/pleroma/web/nodeinfo/nodeinfo_controller.ex:6
|
||||
#: lib/pleroma/web/o_auth/fallback_controller.ex:6
|
||||
#: lib/pleroma/web/o_auth/mfa_controller.ex:10
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:6
|
||||
#: lib/pleroma/web/o_status/o_status_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/account_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/app_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/backup_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/chat_controller.ex:5
|
||||
#: lib/pleroma/web/pleroma_api/controllers/conversation_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_file_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_reaction_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/instances_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/notification_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/report_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/scrobble_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7 lib/pleroma/web/static_fe/static_fe_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10 lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6 lib/pleroma/web/twitter_api/twitter_api_controller.ex:6
|
||||
#: lib/pleroma/web/uploader_controller.ex:6 lib/pleroma/web/web_finger/web_finger_controller.ex:6
|
||||
#: lib/pleroma/web/pleroma_api/controllers/two_factor_authentication_controller.ex:7
|
||||
#: lib/pleroma/web/pleroma_api/controllers/user_import_controller.ex:6
|
||||
#: lib/pleroma/web/static_fe/static_fe_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/password_controller.ex:10
|
||||
#: lib/pleroma/web/twitter_api/controllers/remote_follow_controller.ex:6
|
||||
#: lib/pleroma/web/twitter_api/controllers/util_controller.ex:6
|
||||
#: lib/pleroma/web/uploader_controller.ex:6
|
||||
#: lib/pleroma/web/web_finger/web_finger_controller.ex:6
|
||||
#, elixir-format
|
||||
msgid "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
||||
msgstr ""
|
||||
msgstr "安全违例:OAuth 域检查既没处理也没显式跳过。"
|
||||
|
||||
#: lib/pleroma/plugs/ensure_authenticated_plug.ex:28
|
||||
#, elixir-format, fuzzy
|
||||
#: lib/pleroma/web/plugs/ensure_authenticated_plug.ex:32
|
||||
#, elixir-format
|
||||
msgid "Two-factor authentication enabled, you must use a access token."
|
||||
msgstr "已启用两因素验证,您需要使用访问令牌。"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:210
|
||||
#, elixir-format
|
||||
msgid "Unexpected error occurred while adding file to pack."
|
||||
msgstr "向表情包添加文件时发生了没有预料到的错误。"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:138
|
||||
#, elixir-format
|
||||
msgid "Unexpected error occurred while creating pack."
|
||||
msgstr "创建表情包时发生了没有预料到的错误。"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:278
|
||||
#, elixir-format
|
||||
msgid "Unexpected error occurred while removing file from pack."
|
||||
msgstr "从表情包移除文件时发生了没有预料到的错误。"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:250
|
||||
#, elixir-format
|
||||
msgid "Unexpected error occurred while updating file in pack."
|
||||
msgstr "更新表情包内的文件时发生了没有预料到的错误。"
|
||||
|
||||
#: lib/pleroma/web/pleroma_api/controllers/emoji_pack_controller.ex:179
|
||||
#, elixir-format
|
||||
msgid "Unexpected error occurred while updating pack metadata."
|
||||
msgstr "更新表情包元数据时发生了没有预料到的错误。"
|
||||
msgstr "已启用两因素鉴权,您需要使用访问令牌。"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/subscription_controller.ex:61
|
||||
#, elixir-format, fuzzy
|
||||
#, elixir-format
|
||||
msgid "Web push subscription is disabled on this Pleroma instance"
|
||||
msgstr "此 Pleroma 实例禁用了网页推送订阅"
|
||||
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:451
|
||||
#: lib/pleroma/web/admin_api/controllers/admin_api_controller.ex:234
|
||||
#, elixir-format
|
||||
msgid "You can't revoke your own admin/moderator status."
|
||||
msgstr "您不能撤消自己的管理员权限。"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:126
|
||||
#: lib/pleroma/web/mastodon_api/controllers/timeline_controller.ex:129
|
||||
#, elixir-format
|
||||
msgid "authorization required for timeline view"
|
||||
msgstr "浏览时间线需要认证"
|
||||
|
|
@ -569,12 +568,50 @@ msgstr "浏览时间线需要认证"
|
|||
msgid "Access denied"
|
||||
msgstr "拒绝访问"
|
||||
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:282
|
||||
#: lib/pleroma/web/mastodon_api/controllers/account_controller.ex:321
|
||||
#, elixir-format
|
||||
msgid "This API requires an authenticated user"
|
||||
msgstr "此 API 需要已认证的用户"
|
||||
|
||||
#: lib/pleroma/plugs/user_is_admin_plug.ex:21
|
||||
#: lib/pleroma/web/plugs/ensure_staff_privileged_plug.ex:26
|
||||
#: lib/pleroma/web/plugs/user_is_admin_plug.ex:21
|
||||
#, elixir-format
|
||||
msgid "User is not an admin."
|
||||
msgstr "该用户不是管理员。"
|
||||
|
||||
#: lib/pleroma/user/backup.ex:75
|
||||
#, elixir-format
|
||||
msgid "Last export was less than a day ago"
|
||||
msgid_plural "Last export was less than %{days} days ago"
|
||||
msgstr[0] "上次导出还不到 %{days} 天前"
|
||||
|
||||
#: lib/pleroma/user/backup.ex:93
|
||||
#, elixir-format
|
||||
msgid "Backups require enabled email"
|
||||
msgstr "备份要求开启邮件"
|
||||
|
||||
#: lib/pleroma/web/activity_pub/activity_pub_controller.ex:423
|
||||
#, elixir-format
|
||||
msgid "Character limit (%{limit} characters) exceeded, contains %{length} characters"
|
||||
msgstr "超过字符限制(%{limit} 个字符),包含了 %{length} 个字符"
|
||||
|
||||
#: lib/pleroma/user/backup.ex:98
|
||||
#, elixir-format
|
||||
msgid "Email is required"
|
||||
msgstr "需要邮箱"
|
||||
|
||||
#: lib/pleroma/web/common_api/utils.ex:507
|
||||
#, elixir-format
|
||||
msgid "Too many attachments"
|
||||
msgstr "太多附件"
|
||||
|
||||
#: lib/pleroma/web/plugs/ensure_staff_privileged_plug.ex:33
|
||||
#: lib/pleroma/web/plugs/user_is_staff_plug.ex:20
|
||||
#, elixir-format
|
||||
msgid "User is not a staff member."
|
||||
msgstr "该用户不是运营成员。"
|
||||
|
||||
#: lib/pleroma/web/o_auth/o_auth_controller.ex:366
|
||||
#, elixir-format
|
||||
msgid "Your account is awaiting approval."
|
||||
msgstr "你的账号正等待批准。"
|
||||
|
|
|
|||
160
priv/gettext/zh_Hans/LC_MESSAGES/posix_errors.po
Normal file
160
priv/gettext/zh_Hans/LC_MESSAGES/posix_errors.po
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
## "msgid"s in this file come from POT (.pot) files.
|
||||
##
|
||||
## Do not add, change, or remove "msgid"s manually here as
|
||||
## they're tied to the ones in the corresponding POT file
|
||||
## (with the same domain).
|
||||
##
|
||||
## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2022-07-22 19:00+0000\n"
|
||||
"Last-Translator: Yating Zhan <thestrandedvalley@protonmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://weblate.pleroma-dev.ebin.club/"
|
||||
"projects/pleroma/pleroma-backend-domain-posix_errors/zh_Hans/>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
msgid "eperm"
|
||||
msgstr "不允许的操作"
|
||||
|
||||
msgid "eacces"
|
||||
msgstr "权限不够"
|
||||
|
||||
msgid "eagain"
|
||||
msgstr "资源暂时不可用"
|
||||
|
||||
msgid "ebadf"
|
||||
msgstr "坏的文件描述符"
|
||||
|
||||
msgid "ebadmsg"
|
||||
msgstr "坏讯息"
|
||||
|
||||
msgid "ebusy"
|
||||
msgstr "设备或资源忙"
|
||||
|
||||
msgid "edeadlk"
|
||||
msgstr "避免了资源死锁"
|
||||
|
||||
msgid "edeadlock"
|
||||
msgstr "避免了资源死锁"
|
||||
|
||||
msgid "edquot"
|
||||
msgstr "超出了磁盘配额"
|
||||
|
||||
msgid "eexist"
|
||||
msgstr "文件存在"
|
||||
|
||||
msgid "efault"
|
||||
msgstr "坏地址"
|
||||
|
||||
msgid "efbig"
|
||||
msgstr "文件太大"
|
||||
|
||||
msgid "eftype"
|
||||
msgstr "不合适的文件类型或格式"
|
||||
|
||||
msgid "eintr"
|
||||
msgstr "系统调用被中断"
|
||||
|
||||
msgid "einval"
|
||||
msgstr "不合法的参数"
|
||||
|
||||
msgid "eio"
|
||||
msgstr "输入/输出错误"
|
||||
|
||||
msgid "eisdir"
|
||||
msgstr "在目录上非法操作"
|
||||
|
||||
msgid "eloop"
|
||||
msgstr "太多层符号链接"
|
||||
|
||||
msgid "emfile"
|
||||
msgstr "太多打开的文件"
|
||||
|
||||
msgid "emlink"
|
||||
msgstr "太多链接"
|
||||
|
||||
msgid "emultihop"
|
||||
msgstr ""
|
||||
|
||||
msgid "enametoolong"
|
||||
msgstr "文件名太长"
|
||||
|
||||
msgid "enfile"
|
||||
msgstr "系统里太多打开的文件"
|
||||
|
||||
msgid "enobufs"
|
||||
msgstr "没有可用的缓冲空间"
|
||||
|
||||
msgid "enodev"
|
||||
msgstr "没这设备"
|
||||
|
||||
msgid "enolck"
|
||||
msgstr "没有可用的锁"
|
||||
|
||||
msgid "enolink"
|
||||
msgstr "链接被切断了"
|
||||
|
||||
msgid "enoent"
|
||||
msgstr "没这文件或目录"
|
||||
|
||||
msgid "enomem"
|
||||
msgstr "不能分配内存"
|
||||
|
||||
msgid "enospc"
|
||||
msgstr "设备上没剩余空间"
|
||||
|
||||
msgid "enosr"
|
||||
msgstr ""
|
||||
|
||||
msgid "enostr"
|
||||
msgstr "设备不是流"
|
||||
|
||||
msgid "enosys"
|
||||
msgstr "功能没实现"
|
||||
|
||||
msgid "enotblk"
|
||||
msgstr ""
|
||||
|
||||
msgid "enotdir"
|
||||
msgstr ""
|
||||
|
||||
msgid "enotsup"
|
||||
msgstr "不受支持的操作"
|
||||
|
||||
msgid "enxio"
|
||||
msgstr "该设备或路径不存在"
|
||||
|
||||
msgid "eopnotsupp"
|
||||
msgstr "不受支持的操作"
|
||||
|
||||
msgid "eoverflow"
|
||||
msgstr "请为给定类型的数据指定较小的数值"
|
||||
|
||||
msgid "epipe"
|
||||
msgstr ""
|
||||
|
||||
msgid "erange"
|
||||
msgstr ""
|
||||
|
||||
msgid "erofs"
|
||||
msgstr "只读权限文件系统"
|
||||
|
||||
msgid "espipe"
|
||||
msgstr ""
|
||||
|
||||
msgid "esrch"
|
||||
msgstr "具体进程不存在"
|
||||
|
||||
msgid "estale"
|
||||
msgstr ""
|
||||
|
||||
msgid "etxtbsy"
|
||||
msgstr "文本文件忙碌"
|
||||
|
||||
msgid "exdev"
|
||||
msgstr "该多设备链接不可用"
|
||||
552
priv/gettext/zh_Hans/LC_MESSAGES/static_pages.po
Normal file
552
priv/gettext/zh_Hans/LC_MESSAGES/static_pages.po
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR Free Software Foundation, Inc.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"PO-Revision-Date: 2022-07-21 23:35+0000\n"
|
||||
"Last-Translator: tusooa <tusooa@kazv.moe>\n"
|
||||
"Language-Team: Chinese (Simplified) <http://weblate.pleroma-dev.ebin.club/"
|
||||
"projects/pleroma/pleroma-backend-domain-static_pages/zh_Hans/>\n"
|
||||
"Language: zh_Hans\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 4.13.1\n"
|
||||
|
||||
## "msgid"s in this file come from POT (.pot) files.
|
||||
##
|
||||
## Do not add, change, or remove "msgid"s manually here as
|
||||
## they're tied to the ones in the corresponding POT file
|
||||
## (with the same domain).
|
||||
##
|
||||
## Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
## to merge POT files into PO files.
|
||||
#~ msgid ""
|
||||
#~ msgstr ""
|
||||
#~ "Language: zh_Hans\n"
|
||||
#~ "Plural-Forms: nplurals=1\n"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:9
|
||||
#, elixir-format
|
||||
msgctxt "remote follow authorization button"
|
||||
msgid "Authorize"
|
||||
msgstr "授权"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error fetching user"
|
||||
msgstr "获取用户时出错"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remote follow"
|
||||
msgstr "远程关注"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "placeholder text for auth code entry"
|
||||
msgid "Authentication code"
|
||||
msgstr "授权代码"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:10
|
||||
#, elixir-format
|
||||
msgctxt "placeholder text for password entry"
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "placeholder text for username entry"
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:13
|
||||
#, elixir-format
|
||||
msgctxt "remote follow authorization button for login"
|
||||
msgid "Authorize"
|
||||
msgstr "授权"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:12
|
||||
#, elixir-format
|
||||
msgctxt "remote follow authorization button for mfa"
|
||||
msgid "Authorize"
|
||||
msgstr "授权"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error following account"
|
||||
msgstr "关注用户时出错"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_login.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "remote follow header, need login"
|
||||
msgid "Log in to follow"
|
||||
msgstr "登录以关注"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/follow_mfa.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "remote follow mfa header"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr "两步鉴权"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/remote_follow/followed.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "remote follow success"
|
||||
msgid "Account followed!"
|
||||
msgstr "已经关注了账号!"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:7
|
||||
#, elixir-format
|
||||
msgctxt "placeholder text for account id"
|
||||
msgid "Your account ID, e.g. lain@quitter.se"
|
||||
msgstr "你的账户 ID,如 lain@quitter.se"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "remote follow authorization button for following with a remote account"
|
||||
msgid "Follow"
|
||||
msgstr "关注"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "remote follow error"
|
||||
msgid "Error: %{error}"
|
||||
msgstr "错误:%{error}"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/util/subscribe.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "remote follow header"
|
||||
msgid "Remotely follow %{nickname}"
|
||||
msgstr "远程关注 %{nickname}"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:12
|
||||
#, elixir-format
|
||||
msgctxt "password reset button"
|
||||
msgid "Reset"
|
||||
msgstr "重置"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "password reset failed homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr "回主页"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_failed.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "password reset failed message"
|
||||
msgid "Password reset failed"
|
||||
msgstr "密码重置失败"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "password reset form confirm password prompt"
|
||||
msgid "Confirmation"
|
||||
msgstr "确认密码"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset.html.eex:4
|
||||
#, elixir-format
|
||||
msgctxt "password reset form password prompt"
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/invalid_token.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "password reset invalid token message"
|
||||
msgid "Invalid Token"
|
||||
msgstr "无效的令牌"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "password reset successful homepage link"
|
||||
msgid "Homepage"
|
||||
msgstr "回主页"
|
||||
|
||||
#: lib/pleroma/web/templates/twitter_api/password/reset_success.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "password reset successful message"
|
||||
msgid "Password changed!"
|
||||
msgstr "密码已经修改了!"
|
||||
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.atom.eex:15
|
||||
#: lib/pleroma/web/templates/feed/feed/tag.rss.eex:7
|
||||
#, elixir-format
|
||||
msgctxt "tag feed description"
|
||||
msgid "These are public toots tagged with #%{tag}. You can interact with them if you have an account anywhere in the fediverse."
|
||||
msgstr "这些是标了 #%{tag} 签的公开文章。你要是在联邦宇宙的任何地方有账号,就能和它们互动。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "oauth authorization exists page title"
|
||||
msgid "Authorization exists"
|
||||
msgstr "授权已经存在"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:32
|
||||
#, elixir-format
|
||||
msgctxt "oauth authorize approve button"
|
||||
msgid "Approve"
|
||||
msgstr "批准"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:30
|
||||
#, elixir-format
|
||||
msgctxt "oauth authorize cancel button"
|
||||
msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:23
|
||||
#, elixir-format
|
||||
msgctxt "oauth authorize message"
|
||||
msgid "Application <strong>%{client_name}</strong> is requesting access to your account."
|
||||
msgstr "应用程序 <strong>%{client_name}</strong> 在请求访问你的账号。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "oauth authorized page title"
|
||||
msgid "Successfully authorized"
|
||||
msgstr "成功授权"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "oauth external provider page title"
|
||||
msgid "Sign in with external provider"
|
||||
msgstr "通过外部提供者登录"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex:13
|
||||
#, elixir-format
|
||||
msgctxt "oauth external provider sign in button"
|
||||
msgid "Sign in with %{strategy}"
|
||||
msgstr "通过 %{strategy} 登录"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:54
|
||||
#, elixir-format
|
||||
msgctxt "oauth login button"
|
||||
msgid "Log In"
|
||||
msgstr "登录"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:51
|
||||
#, elixir-format
|
||||
msgctxt "oauth login password prompt"
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:47
|
||||
#, elixir-format
|
||||
msgctxt "oauth login username prompt"
|
||||
msgid "Username"
|
||||
msgstr "用户名"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:39
|
||||
#, elixir-format
|
||||
msgctxt "oauth register nickname prompt"
|
||||
msgid "Pleroma Handle"
|
||||
msgstr "Pleroma 用户名"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:37
|
||||
#, elixir-format
|
||||
msgctxt "oauth register nickname unchangeable warning"
|
||||
msgid "Choose carefully! You won't be able to change this later. You will be able to change your display name, though."
|
||||
msgstr "选仔细了!你之后就不能改它了。但是你可以改显示名。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:18
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page email prompt"
|
||||
msgid "Email"
|
||||
msgstr "邮箱"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:10
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page fill form prompt"
|
||||
msgid "If you'd like to register a new account, please provide the details below."
|
||||
msgstr "如果你想注册新账号,请提供如下信息。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:35
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page login button"
|
||||
msgid "Proceed as existing user"
|
||||
msgstr "以已有用户继续"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:31
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page login password prompt"
|
||||
msgid "Password"
|
||||
msgstr "密码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:24
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page login prompt"
|
||||
msgid "Alternatively, sign in to connect to existing account."
|
||||
msgstr "或者,登录到已有账号。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:27
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page login username prompt"
|
||||
msgid "Name or email"
|
||||
msgstr "名字或邮箱"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:14
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page nickname prompt"
|
||||
msgid "Nickname"
|
||||
msgstr "昵称"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:22
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page register button"
|
||||
msgid "Proceed as new user"
|
||||
msgstr "以新用户继续"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/register.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page title"
|
||||
msgid "Registration Details"
|
||||
msgstr "注册详情"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/show.html.eex:36
|
||||
#, elixir-format
|
||||
msgctxt "oauth register page title"
|
||||
msgid "This is the first time you visit! Please enter your Pleroma handle."
|
||||
msgstr "这是你第一次访问。请输入 Pleroma 用户名。"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/_scopes.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "oauth scopes message"
|
||||
msgid "The following permissions will be granted"
|
||||
msgstr "将要允许如下权限"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_authorization_created.html.eex:2
|
||||
#: lib/pleroma/web/templates/o_auth/o_auth/oob_token_exists.html.eex:2
|
||||
#, elixir-format
|
||||
msgctxt "oauth token code message"
|
||||
msgid "Token code is <br>%{token}"
|
||||
msgstr "令牌代码是<br>%{token}"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:12
|
||||
#, elixir-format
|
||||
msgctxt "mfa auth code prompt"
|
||||
msgid "Authentication code"
|
||||
msgstr "鉴权代码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "mfa auth page title"
|
||||
msgid "Two-factor authentication"
|
||||
msgstr "两步鉴权"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:23
|
||||
#, elixir-format
|
||||
msgctxt "mfa auth page use recovery code link"
|
||||
msgid "Enter a two-factor recovery code"
|
||||
msgstr "输入两步恢复码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/totp.html.eex:20
|
||||
#, elixir-format
|
||||
msgctxt "mfa auth verify code button"
|
||||
msgid "Verify"
|
||||
msgstr "验证"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "mfa recover page title"
|
||||
msgid "Two-factor recovery"
|
||||
msgstr "两步恢复"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:12
|
||||
#, elixir-format
|
||||
msgctxt "mfa recover recovery code prompt"
|
||||
msgid "Recovery code"
|
||||
msgstr "恢复码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:23
|
||||
#, elixir-format
|
||||
msgctxt "mfa recover use 2fa code link"
|
||||
msgid "Enter a two-factor code"
|
||||
msgstr "输入鉴权码"
|
||||
|
||||
#: lib/pleroma/web/templates/o_auth/mfa/recovery.html.eex:20
|
||||
#, elixir-format
|
||||
msgctxt "mfa recover verify recovery code button"
|
||||
msgid "Verify"
|
||||
msgstr "验证"
|
||||
|
||||
#: lib/pleroma/web/templates/static_fe/static_fe/profile.html.eex:8
|
||||
#, elixir-format
|
||||
msgctxt "static fe profile page remote follow button"
|
||||
msgid "Remote follow"
|
||||
msgstr "远程关注"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:163
|
||||
#, elixir-format
|
||||
msgctxt "digest email header line"
|
||||
msgid "Hey %{nickname}, here is what you've missed!"
|
||||
msgstr "早 %{nickname},你刚错过这些!"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:544
|
||||
#, elixir-format
|
||||
msgctxt "digest email receiver address"
|
||||
msgid "The email address you are subscribed as is <a href='mailto:%{@user.email}' style='color: %{color};text-decoration: none;'>%{email}</a>. "
|
||||
msgstr ""
|
||||
"你订阅的邮箱地址是 <a href='mailto:%{@user.email}' style='color: %{color"
|
||||
"};text-decoration: none;'>%{email}</a>。 "
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:538
|
||||
#, elixir-format
|
||||
msgctxt "digest email sending reason"
|
||||
msgid "You have received this email because you have signed up to receive digest emails from <b>%{instance}</b> Pleroma instance."
|
||||
msgstr "因为你选择了收取来自 <b>%{instance}</b> 的摘要邮件,所以你会收到这封邮件。"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
#, elixir-format
|
||||
msgctxt "digest email unsubscribe action"
|
||||
msgid "To unsubscribe, please go %{here}."
|
||||
msgstr "要取消订阅,请去%{here}。"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:547
|
||||
#, elixir-format
|
||||
msgctxt "digest email unsubscribe action link text"
|
||||
msgid "here"
|
||||
msgstr "此处"
|
||||
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_failure.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "mailer unsubscribe failed message"
|
||||
msgid "UNSUBSCRIBE FAILURE"
|
||||
msgstr "取消订阅失败"
|
||||
|
||||
#: lib/pleroma/web/templates/mailer/subscription/unsubscribe_success.html.eex:1
|
||||
#, elixir-format
|
||||
msgctxt "mailer unsubscribe successful message"
|
||||
msgid "UNSUBSCRIBE SUCCESSFUL"
|
||||
msgstr "取消订阅成功"
|
||||
|
||||
#: lib/pleroma/web/templates/email/digest.html.eex:385
|
||||
#, elixir-format
|
||||
msgctxt "new followers count header"
|
||||
msgid "%{count} New Follower"
|
||||
msgid_plural "%{count} New Followers"
|
||||
msgstr[0] "%{count} 个新关注者"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:356
|
||||
#, elixir-format
|
||||
msgctxt "account archive email body - self-requested"
|
||||
msgid "<p>You requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
msgstr ""
|
||||
"<p>你之前要了一份你的 Pleroma 账号的完整备份。现在可以下载了:</p>\n"
|
||||
"<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:384
|
||||
#, elixir-format
|
||||
msgctxt "account archive email subject"
|
||||
msgid "Your account archive is ready"
|
||||
msgstr "你的账号存档准备好了"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:188
|
||||
#, elixir-format
|
||||
msgctxt "approval pending email body"
|
||||
msgid "<h3>Awaiting Approval</h3>\n<p>Your account at %{instance_name} is being reviewed by staff. You will receive another email once your account is approved.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>等待批准</h3>\n"
|
||||
"<p>管理人员正在审核你在 %{instance_name} 的账号。等账号批准之后你会收到另一封邮件。</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:202
|
||||
#, elixir-format
|
||||
msgctxt "approval pending email subject"
|
||||
msgid "Your account is awaiting approval"
|
||||
msgstr "你的账号在等待批准"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:158
|
||||
#, elixir-format
|
||||
msgctxt "confirmation email body"
|
||||
msgid "<h3>Thank you for registering on %{instance_name}</h3>\n<p>Email confirmation is required to activate the account.</p>\n<p>Please click the following link to <a href=\"%{confirmation_url}\">activate your account</a>.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>感谢注册 %{instance_name}</h3>\n"
|
||||
"<p>要激活账号,必须验证邮箱。</p>\n"
|
||||
"<p>请点如下链接来<a href=\"%{confirmation_url}\">激活账号</a>。</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:174
|
||||
#, elixir-format
|
||||
msgctxt "confirmation email subject"
|
||||
msgid "%{instance_name} account confirmation"
|
||||
msgstr "%{instance_name} 账号激活"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:310
|
||||
#, elixir-format
|
||||
msgctxt "digest email subject"
|
||||
msgid "Your digest from %{instance_name}"
|
||||
msgstr "来自 %{instance_name} 的摘要"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:81
|
||||
#, elixir-format
|
||||
msgctxt "password reset email body"
|
||||
msgid "<h3>Reset your password at %{instance_name}</h3>\n<p>Someone has requested password change for your account at %{instance_name}.</p>\n<p>If it was you, visit the following link to proceed: <a href=\"%{password_reset_url}\">reset password</a>.</p>\n<p>If it was someone else, nothing to worry about: your data is secure and your password has not been changed.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>重置你在 %{instance_name} 的密码</h3>\n"
|
||||
"<p>有人请求了重置你在 %{instance_name} 的账号的密码。</p>\n"
|
||||
"<p>如果那是你,访问如下链接以继续:<a href=\"%{password_reset_url}\">重置密码</a>。</p>\n"
|
||||
"<p>如果是别人,不必担心:你的数据很安全,密码也没变。</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:98
|
||||
#, elixir-format
|
||||
msgctxt "password reset email subject"
|
||||
msgid "Password reset"
|
||||
msgstr "密码重置"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:215
|
||||
#, elixir-format
|
||||
msgctxt "successful registration email body"
|
||||
msgid "<h3>Hello @%{nickname},</h3>\n<p>Your account at %{instance_name} has been registered successfully.</p>\n<p>No further action is required to activate your account.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>早 @%{nickname},</h3>\n"
|
||||
"<p>你在 %{instance_name} 上的账号已经成功注册了。</p>\n"
|
||||
"<p>你的账号已经激活,无需再做任何操作。</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:231
|
||||
#, elixir-format
|
||||
msgctxt "successful registration email subject"
|
||||
msgid "Account registered on %{instance_name}"
|
||||
msgstr "在 %{instance_name} 上注册了账号"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:119
|
||||
#, elixir-format
|
||||
msgctxt "user invitation email body"
|
||||
msgid "<h3>You are invited to %{instance_name}</h3>\n<p>%{inviter_name} invites you to join %{instance_name}, an instance of Pleroma federated social networking platform.</p>\n<p>Click the following link to register: <a href=\"%{registration_url}\">accept invitation</a>.</p>\n"
|
||||
msgstr ""
|
||||
"<h3>有人邀请你去 %{instance_name}</h3>\n"
|
||||
"<p>%{inviter_name} 邀请你去 %{instance_name}。这是社交网络平台 Pleroma 的一个实例。</p>\n"
|
||||
"<p>点如下链接以注册:<a href=\"%{registration_url}\">接受邀请</a>。</p>\n"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:136
|
||||
#, elixir-format
|
||||
msgctxt "user invitation email subject"
|
||||
msgid "Invitation to %{instance_name}"
|
||||
msgstr "去 %{instance_name} 的邀请"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:53
|
||||
#, elixir-format
|
||||
msgctxt "welcome email html body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "欢迎来到 %{instance_name}!"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:41
|
||||
#, elixir-format
|
||||
msgctxt "welcome email subject"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "欢迎来到 %{instance_name}!"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:65
|
||||
#, elixir-format
|
||||
msgctxt "welcome email text body"
|
||||
msgid "Welcome to %{instance_name}!"
|
||||
msgstr "欢迎来到 %{instance_name}!"
|
||||
|
||||
#: lib/pleroma/emails/user_email.ex:368
|
||||
#, elixir-format
|
||||
msgctxt "account archive email body - admin requested"
|
||||
msgid "<p>Admin @%{admin_nickname} requested a full backup of your Pleroma account. It's ready for download:</p>\n<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
msgstr ""
|
||||
"<p>管理员 @%{admin_nickname} 之前要了一份你的 Pleroma 账号的完整备份。现在可以下载了:</p>\n"
|
||||
"<p><a href=\"%{download_url}\">%{download_url}</a></p>\n"
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
defmodule Pleroma.Repo.Migrations.UploadFilterExiftoolToExiftoolStripLocation do
|
||||
use Ecto.Migration
|
||||
|
||||
alias Pleroma.ConfigDB
|
||||
|
||||
def up,
|
||||
do:
|
||||
ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload})
|
||||
|> update_filtername(
|
||||
Pleroma.Upload.Filter.Exiftool,
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation
|
||||
)
|
||||
|
||||
def down,
|
||||
do:
|
||||
ConfigDB.get_by_params(%{group: :pleroma, key: Pleroma.Upload})
|
||||
|> update_filtername(
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation,
|
||||
Pleroma.Upload.Filter.Exiftool
|
||||
)
|
||||
|
||||
defp update_filtername(%{value: value}, from_filtername, to_filtername) do
|
||||
new_value =
|
||||
value
|
||||
|> Keyword.update(:filters, [], fn filters ->
|
||||
filters
|
||||
|> Enum.map(fn
|
||||
^from_filtername -> to_filtername
|
||||
filter -> filter
|
||||
end)
|
||||
end)
|
||||
|
||||
ConfigDB.update_or_create(%{group: :pleroma, key: Pleroma.Upload, value: new_value})
|
||||
end
|
||||
|
||||
defp update_filtername(_, _, _), do: nil
|
||||
end
|
||||
26
priv/repo/migrations/20220308012601_create_announcements.exs
Normal file
26
priv/repo/migrations/20220308012601_create_announcements.exs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
defmodule Pleroma.Repo.Migrations.CreateAnnouncements do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create_if_not_exists table(:announcements, primary_key: false) do
|
||||
add(:id, :uuid, primary_key: true)
|
||||
add(:data, :map)
|
||||
add(:starts_at, :naive_datetime)
|
||||
add(:ends_at, :naive_datetime)
|
||||
add(:rendered, :map)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
create_if_not_exists table(:announcement_read_relationships) do
|
||||
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
|
||||
add(:announcement_id, references(:announcements, type: :uuid, on_delete: :delete_all))
|
||||
|
||||
timestamps(updated_at: false)
|
||||
end
|
||||
|
||||
create_if_not_exists(
|
||||
unique_index(:announcement_read_relationships, [:user_id, :announcement_id])
|
||||
)
|
||||
end
|
||||
end
|
||||
17
priv/repo/migrations/20220506175506_add_index_hotspots.exs
Normal file
17
priv/repo/migrations/20220506175506_add_index_hotspots.exs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo.Migrations.AddIndexHotspots do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
# Stop inserts into activities from doing a full-table scan of users:
|
||||
create_if_not_exists(index(:users, [:ap_id, "COALESCE(follower_address, '')"]))
|
||||
|
||||
# Change two indexes and a filter recheck into one index scan:
|
||||
create_if_not_exists(index(:following_relationships, [:follower_id, :state]))
|
||||
|
||||
create_if_not_exists(index(:notifications, [:user_id, :seen]))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
defmodule Pleroma.Repo.Migrations.ChangeReportNotesContentToText do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
alter table(:report_notes) do
|
||||
modify(:content, :text)
|
||||
end
|
||||
end
|
||||
|
||||
# 20191203043610_create_report_notes.exs
|
||||
def down do
|
||||
alter table(:report_notes) do
|
||||
modify(:content, :string)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Repo.Migrations.AddExpiresAtToUserRelationships do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
alter table(:user_relationships) do
|
||||
add_if_not_exists(:expires_at, :utc_datetime)
|
||||
end
|
||||
end
|
||||
end
|
||||
BIN
test/fixtures/image_with_caption-abstract.jpg
vendored
Normal file
BIN
test/fixtures/image_with_caption-abstract.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 697 B |
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract.jpg
vendored
Normal file
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 823 B |
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg
vendored
Normal file
BIN
test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 785 B |
BIN
test/fixtures/image_with_no_description.jpg
vendored
Normal file
BIN
test/fixtures/image_with_no_description.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 631 B |
31
test/fixtures/owncast-note-with-attachment.json
vendored
Normal file
31
test/fixtures/owncast-note-with-attachment.json
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"attachment": {
|
||||
"content": "Live stream preview",
|
||||
"type": "Image",
|
||||
"url": "https://owncast.localhost.localdomain/preview.gif?us=KjfNX387gm"
|
||||
},
|
||||
"attributedTo": "https://owncast.localhost.localdomain/federation/user/streamer",
|
||||
"audience": "https://www.w3.org/ns/activitystreams#Public",
|
||||
"content": "<p>I've gone live!</p><p></p><p><a class=\"hashtag\" href=\"https://directory.owncast.online/tags/owncast\">#owncast</a> <a class=\"hashtag\" href=\"https://directory.owncast.online/tags/streaming\">#streaming</a></p><a href=\"https://owncast.localhost.localdomain\">https://owncast.localhost.localdomain</a>",
|
||||
"id": "https://owncast.localhost.localdomain/federation/KjBNuq8ng",
|
||||
"published": "2022-04-17T15:42:03Z",
|
||||
"tag": [
|
||||
{
|
||||
"href": "https://directory.owncast.online/tags/owncast",
|
||||
"name": "#owncast",
|
||||
"type": "Hashtag"
|
||||
},
|
||||
{
|
||||
"href": "https://directory.owncast.online/tags/streaming",
|
||||
"name": "#streaming",
|
||||
"type": "Hashtag"
|
||||
},
|
||||
{
|
||||
"href": "https://directory.owncast.online/tags/owncast",
|
||||
"name": "#owncast",
|
||||
"type": "Hashtag"
|
||||
}
|
||||
],
|
||||
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type": "Note"
|
||||
}
|
||||
1
test/fixtures/tesla_mock/https___lm.kazv.moe_users_mewmew.xml
vendored
Normal file
1
test/fixtures/tesla_mock/https___lm.kazv.moe_users_mewmew.xml
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Subject>acct:mewmew@lm.kazv.moe</Subject><Alias>https://lm.kazv.moe/users/mewmew</Alias><Alias>https://lm.kazv.moe/users/tester</Alias><Alias>https://lm.kazv.moe/users/testuser</Alias><Link href="https://lm.kazv.moe/users/mewmew" rel="http://webfinger.net/rel/profile-page" type="text/html" /><Link href="https://lm.kazv.moe/users/mewmew" rel="self" type="application/activity+json" /><Link href="https://lm.kazv.moe/users/mewmew" rel="self" type="application/ld+json; profile="https://www.w3.org/ns/activitystreams"" /><Link rel="http://ostatus.org/schema/1.0/subscribe" template="https://lm.kazv.moe/ostatus_subscribe?acct={uri}" /></XRD>
|
||||
1
test/fixtures/tesla_mock/lm.kazv.moe_host_meta
vendored
Normal file
1
test/fixtures/tesla_mock/lm.kazv.moe_host_meta
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"><Link rel="lrdd" template="https://lm.kazv.moe/.well-known/webfinger?resource={uri}" type="application/xrd+xml" /></XRD>
|
||||
1
test/fixtures/tesla_mock/mewmew@lm.kazv.moe.json
vendored
Normal file
1
test/fixtures/tesla_mock/mewmew@lm.kazv.moe.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"@context":["https://www.w3.org/ns/activitystreams","https://lm.kazv.moe/schemas/litepub-0.1.jsonld",{"@language":"und"}],"alsoKnownAs":["https://lm.kazv.moe/users/tester","https://lm.kazv.moe/users/testuser"],"attachment":[],"capabilities":{"acceptsChatMessages":true},"discoverable":false,"endpoints":{"oauthAuthorizationEndpoint":"https://lm.kazv.moe/oauth/authorize","oauthRegistrationEndpoint":"https://lm.kazv.moe/api/v1/apps","oauthTokenEndpoint":"https://lm.kazv.moe/oauth/token","sharedInbox":"https://lm.kazv.moe/inbox","uploadMedia":"https://lm.kazv.moe/api/ap/upload_media"},"featured":"https://lm.kazv.moe/users/mewmew/collections/featured","followers":"https://lm.kazv.moe/users/mewmew/followers","following":"https://lm.kazv.moe/users/mewmew/following","id":"https://lm.kazv.moe/users/mewmew","inbox":"https://lm.kazv.moe/users/mewmew/inbox","manuallyApprovesFollowers":false,"name":"mew","outbox":"https://lm.kazv.moe/users/mewmew/outbox","preferredUsername":"mewmew","publicKey":{"id":"https://lm.kazv.moe/users/mewmew#main-key","owner":"https://lm.kazv.moe/users/mewmew","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0nT3IVUwx799FSJyJEOY\n5D2c5zgtt2Z+BD9417eVLmVQF5fJlWgcKS4pbFc76zkYoBkZtV7XbzvN9KTNulpa\nUGNOM0/UdEoQLB8xbVCMm0ABUU8vbTWoMTxp93bfVHBz+33FPYdH1JHX4TCU/mJF\nX4UJMvFmMn5BFjSQm9GG6Eq2j6SAUsaTa8+Rrd8FzS6zb/dk3N/Llz0tfsZYS0sq\nEy9OYhsKOQ6eegULFJOF3Hz04vzwftmeXFsbb3aO2zKz3uAMYZglWHNBYJAePBtJ\ng362kqdJwgT14TFnZ0K2ziDPbkRULG1Kke/lsqw2rPF6Q6P4PeO1shCEDthoDoID\newIDAQAB\n-----END PUBLIC KEY-----\n\n"},"summary":"","tag":[],"type":"Person","url":"https://lm.kazv.moe/users/mewmew"}
|
||||
|
|
@ -67,7 +67,9 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
|
|||
"test/uploads",
|
||||
"--static-dir",
|
||||
"./test/../test/instance/static/",
|
||||
"--strip-uploads",
|
||||
"--strip-uploads-location",
|
||||
"y",
|
||||
"--read-uploads-description",
|
||||
"y",
|
||||
"--dedupe-uploads",
|
||||
"n",
|
||||
|
|
@ -91,7 +93,10 @@ defmodule Mix.Tasks.Pleroma.InstanceTest do
|
|||
assert generated_config =~ "password: \"dbpass\""
|
||||
assert generated_config =~ "configurable_from_database: true"
|
||||
assert generated_config =~ "http: [ip: {127, 0, 0, 1}, port: 4000]"
|
||||
assert generated_config =~ "filters: [Pleroma.Upload.Filter.Exiftool]"
|
||||
|
||||
assert generated_config =~
|
||||
"filters: [Pleroma.Upload.Filter.Exiftool.StripLocation, Pleroma.Upload.Filter.Exiftool.ReadDescription]"
|
||||
|
||||
assert File.read!(tmp_path() <> "setup.psql") == generated_setup_psql()
|
||||
assert File.exists?(Path.expand("./test/instance/static/robots.txt"))
|
||||
end
|
||||
|
|
|
|||
40
test/pleroma/announcement_read_relationship_test.exs
Normal file
40
test/pleroma/announcement_read_relationship_test.exs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.AnnouncementReadRelationshipTest do
|
||||
alias Pleroma.AnnouncementReadRelationship
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
{:ok, user: insert(:user), announcement: insert(:announcement)}
|
||||
end
|
||||
|
||||
describe "mark_read/2" do
|
||||
test "should insert relationship", %{user: user, announcement: announcement} do
|
||||
{:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
|
||||
assert AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
end
|
||||
|
||||
describe "mark_unread/2" do
|
||||
test "should delete relationship", %{user: user, announcement: announcement} do
|
||||
{:ok, _} = AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
|
||||
assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement)
|
||||
refute AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
|
||||
test "should not fail if relationship does not exist", %{
|
||||
user: user,
|
||||
announcement: announcement
|
||||
} do
|
||||
assert :ok = AnnouncementReadRelationship.mark_unread(user, announcement)
|
||||
refute AnnouncementReadRelationship.exists?(user, announcement)
|
||||
end
|
||||
end
|
||||
end
|
||||
98
test/pleroma/announcement_test.exs
Normal file
98
test/pleroma/announcement_test.exs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.AnnouncementTest do
|
||||
alias Pleroma.Announcement
|
||||
|
||||
use Pleroma.DataCase, async: true
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
describe "list_all_visible_when/1" do
|
||||
setup do: {:ok, time: NaiveDateTime.utc_now()}
|
||||
|
||||
test "with no start or end time", %{time: time} do
|
||||
_announcement = insert(:announcement)
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with start time before current", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: before_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with start time after current", %{time: time} do
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: after_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with end time after current", %{time: time} do
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{ends_at: after_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with end time before current", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{ends_at: before_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with both start and end time", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: before_now, ends_at: after_now})
|
||||
|
||||
assert [_] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
|
||||
test "with both start and end time, current not in the range", %{time: time} do
|
||||
before_now = NaiveDateTime.add(time, -10, :second)
|
||||
after_now = NaiveDateTime.add(time, 10, :second)
|
||||
|
||||
_announcement = insert(:announcement, %{starts_at: after_now, ends_at: before_now})
|
||||
|
||||
assert [] = Announcement.list_all_visible_when(time)
|
||||
end
|
||||
end
|
||||
|
||||
describe "announcements formatting" do
|
||||
test "it formats links" do
|
||||
raw = "something on https://pleroma.social ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?https://pleroma.social)
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
|
||||
test "it formats mentions" do
|
||||
user = insert(:user)
|
||||
raw = "something on @#{user.nickname} ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?#{user.nickname})
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
|
||||
test "it formats tags" do
|
||||
raw = "something on #mew ."
|
||||
announcement = insert(:announcement, %{data: %{"content" => raw}})
|
||||
|
||||
assert announcement.rendered["content"] =~ ~r(<a.+?#mew)
|
||||
assert announcement.data["content"] == raw
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -11,6 +11,62 @@ defmodule Pleroma.Config.DeprecationWarningsTest do
|
|||
alias Pleroma.Config
|
||||
alias Pleroma.Config.DeprecationWarnings
|
||||
|
||||
describe "filter exiftool" do
|
||||
test "gives warning when still used" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[Pleroma.Upload.Filter.Exiftool]
|
||||
)
|
||||
|
||||
assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) =~
|
||||
"""
|
||||
!!!DEPRECATION WARNING!!!
|
||||
Your config is using Exiftool as a filter instead of Exiftool.StripLocation. This should work for now, but you are advised to change to the new configuration to prevent possible issues later:
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool]
|
||||
```
|
||||
|
||||
Is now
|
||||
|
||||
|
||||
```
|
||||
config :pleroma, Pleroma.Upload,
|
||||
filters: [Pleroma.Upload.Filter.Exiftool.StripLocation]
|
||||
```
|
||||
"""
|
||||
end
|
||||
|
||||
test "changes setting to exiftool strip location" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[Pleroma.Upload.Filter.Exiftool, Pleroma.Upload.Filter.Exiftool.ReadDescription]
|
||||
)
|
||||
|
||||
expected_config = [
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation,
|
||||
Pleroma.Upload.Filter.Exiftool.ReadDescription
|
||||
]
|
||||
|
||||
capture_log(fn -> DeprecationWarnings.warn() end)
|
||||
|
||||
assert Config.get([Pleroma.Upload]) |> Keyword.get(:filters, []) == expected_config
|
||||
end
|
||||
|
||||
test "doesn't give a warning with correct config" do
|
||||
clear_config(
|
||||
[Pleroma.Upload, :filters],
|
||||
[
|
||||
Pleroma.Upload.Filter.Exiftool.StripLocation,
|
||||
Pleroma.Upload.Filter.Exiftool.ReadDescription
|
||||
]
|
||||
)
|
||||
|
||||
assert capture_log(fn -> DeprecationWarnings.check_exiftool_filter() end) == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "simple policy tuples" do
|
||||
test "gives warning when there are still strings" do
|
||||
clear_config([:mrf_simple],
|
||||
|
|
|
|||
90
test/pleroma/docs/translator/compiler_test.exs
Normal file
90
test/pleroma/docs/translator/compiler_test.exs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Docs.Translator.CompilerTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Pleroma.Docs.Translator.Compiler
|
||||
|
||||
@descriptions [
|
||||
%{
|
||||
key: "1",
|
||||
label: "1",
|
||||
description: "2",
|
||||
children: [
|
||||
%{
|
||||
key: "3",
|
||||
label: "3",
|
||||
description: "4"
|
||||
},
|
||||
%{
|
||||
key: "5",
|
||||
label: "5",
|
||||
description: "6"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
key: "7",
|
||||
label: "7",
|
||||
description: "8",
|
||||
children: [
|
||||
%{
|
||||
key: "9",
|
||||
description: "9",
|
||||
children: [
|
||||
%{
|
||||
key: "10",
|
||||
description: "10",
|
||||
children: [
|
||||
%{key: "11", description: "11"},
|
||||
%{description: "12"}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
label: "13"
|
||||
}
|
||||
]
|
||||
},
|
||||
%{
|
||||
group: "14",
|
||||
label: "14"
|
||||
},
|
||||
%{
|
||||
group: "15",
|
||||
key: "15",
|
||||
label: "15"
|
||||
},
|
||||
%{
|
||||
group: {":subgroup", "16"},
|
||||
label: "16"
|
||||
}
|
||||
]
|
||||
|
||||
describe "extract_strings/1" do
|
||||
test "it extracts all labels and descriptions" do
|
||||
strings = Compiler.extract_strings(@descriptions)
|
||||
assert length(strings) == 16
|
||||
|
||||
assert {["1"], "label", "1"} in strings
|
||||
assert {["1"], "description", "2"} in strings
|
||||
assert {["1", "3"], "label", "3"} in strings
|
||||
assert {["1", "3"], "description", "4"} in strings
|
||||
assert {["1", "5"], "label", "5"} in strings
|
||||
assert {["1", "5"], "description", "6"} in strings
|
||||
assert {["7"], "label", "7"} in strings
|
||||
assert {["7"], "description", "8"} in strings
|
||||
assert {["7", "9"], "description", "9"} in strings
|
||||
assert {["7", "9", "10"], "description", "10"} in strings
|
||||
assert {["7", "9", "10", "11"], "description", "11"} in strings
|
||||
assert {["7", "9", "10", nil], "description", "12"} in strings
|
||||
assert {["7", nil], "label", "13"} in strings
|
||||
assert {["14"], "label", "14"} in strings
|
||||
assert {["15-15"], "label", "15"} in strings
|
||||
assert {["16"], "label", "16"} in strings
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -13,4 +13,27 @@ defmodule Pleroma.ReportNoteTest do
|
|||
assert {:ok, note} = ReportNote.create(user.id, report.id, "naughty boy")
|
||||
assert note.content == "naughty boy"
|
||||
end
|
||||
|
||||
test "create/3 with very long content" do
|
||||
user = insert(:user)
|
||||
report = insert(:report_activity)
|
||||
|
||||
very_long_content = """
|
||||
] pwgen 25 15
|
||||
eJ9eeceiquoolei2queeLeimi aiN9ie2iokie8chush7aiph5N ulaNgaighoPiequaipuzoog8F
|
||||
Ohphei0hee6hoo0wah4Aasah9 ziel3Yo3eew4neiy3ekiesh8u ue9ShahTh7oongoPheeneijah
|
||||
ohGheeCh6aloque0Neviopou3 ush2oobohxeec4aequeich3Oo Ze3eighoowiojadohch8iCa1n
|
||||
Yu4yieBie9eengoich8fae4th chohqu6exooSiibogh3iefeez peephahtaik9quie5mohD9nee
|
||||
eeQuur3rie5mei8ieng6iesie wei1meinguv0Heidoov8Ibaed deemo2Poh6ohc3eiBeez1uox2
|
||||
] pwgen 25 15
|
||||
eJ9eeceiquoolei2queeLeimi aiN9ie2iokie8chush7aiph5N ulaNgaighoPiequaipuzoog8F
|
||||
Ohphei0hee6hoo0wah4Aasah9 ziel3Yo3eew4neiy3ekiesh8u ue9ShahTh7oongoPheeneijah
|
||||
ohGheeCh6aloque0Neviopou3 ush2oobohxeec4aequeich3Oo Ze3eighoowiojadohch8iCa1n
|
||||
Yu4yieBie9eengoich8fae4th chohqu6exooSiibogh3iefeez peephahtaik9quie5mohD9nee
|
||||
eeQuur3rie5mei8ieng6iesie wei1meinguv0Heidoov8Ibaed deemo2Poh6ohc3eiBeez1uox2
|
||||
"""
|
||||
|
||||
assert {:ok, note} = ReportNote.create(user.id, report.id, very_long_content)
|
||||
assert note.content == very_long_content
|
||||
end
|
||||
end
|
||||
|
|
|
|||
117
test/pleroma/upload/filter/exiftool/read_description_test.exs
Normal file
117
test/pleroma/upload/filter/exiftool/read_description_test.exs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.ReadDescriptionTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
@uploads %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
test "keeps description when not empty" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile:
|
||||
Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: "Some description"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :noop}
|
||||
end
|
||||
|
||||
test "otherwise returns ImageDescription when present" do
|
||||
uploads_after = %Pleroma.Upload{
|
||||
name: "image_with_imagedescription_and_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
tempfile:
|
||||
Path.absname("test/fixtures/image_with_imagedescription_and_caption-abstract.jpg"),
|
||||
description: "a descriptive white pixel"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(@uploads) ==
|
||||
{:ok, :filtered, uploads_after}
|
||||
end
|
||||
|
||||
test "otherwise returns iptc:Caption-Abstract when present" do
|
||||
upload = %Pleroma.Upload{
|
||||
name: "image_with_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
upload_after = %Pleroma.Upload{
|
||||
name: "image_with_caption-abstract.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_caption-abstract.jpg"),
|
||||
description: "an abstract white pixel"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(upload) ==
|
||||
{:ok, :filtered, upload_after}
|
||||
end
|
||||
|
||||
test "otherwise returns nil" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "image_with_no_description.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/image_with_no_description.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/image_with_no_description.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
|
||||
test "Return nil when image description from EXIF data exceeds the maximum length" do
|
||||
clear_config([:instance, :description_limit], 5)
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(@uploads) ==
|
||||
{:ok, :filtered, @uploads}
|
||||
end
|
||||
|
||||
test "Ignores content with only whitespace" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "non-existant.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg"
|
||||
),
|
||||
tempfile:
|
||||
Path.absname(
|
||||
"test/fixtures/image_with_imagedescription_and_caption-abstract_whitespaces.jpg"
|
||||
),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
|
||||
test "Return nil when image description from EXIF data can't be read" do
|
||||
uploads = %Pleroma.Upload{
|
||||
name: "non-existant.jpg",
|
||||
content_type: "image/jpeg",
|
||||
path: Path.absname("test/fixtures/non-existant.jpg"),
|
||||
tempfile: Path.absname("test/fixtures/non-existant_tmp.jpg"),
|
||||
description: nil
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.ReadDescription.filter(uploads) ==
|
||||
{:ok, :filtered, uploads}
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
||||
defmodule Pleroma.Upload.Filter.Exiftool.StripLocationTest do
|
||||
use Pleroma.DataCase, async: true
|
||||
alias Pleroma.Upload.Filter
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
|||
tempfile: Path.absname("test/fixtures/DSCN0010_tmp.jpg")
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.filter(upload) == {:ok, :filtered}
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :filtered}
|
||||
|
||||
{exif_original, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010.jpg"])
|
||||
{exif_filtered, 0} = System.cmd("exiftool", ["test/fixtures/DSCN0010_tmp.jpg"])
|
||||
|
|
@ -37,6 +37,6 @@ defmodule Pleroma.Upload.Filter.ExiftoolTest do
|
|||
content_type: "image/webp"
|
||||
}
|
||||
|
||||
assert Filter.Exiftool.filter(upload) == {:ok, :noop}
|
||||
assert Filter.Exiftool.StripLocation.filter(upload) == {:ok, :noop}
|
||||
end
|
||||
end
|
||||
|
|
@ -618,9 +618,10 @@ defmodule Pleroma.UserTest do
|
|||
end
|
||||
|
||||
test "it restricts certain nicknames" do
|
||||
clear_config([User, :restricted_nicknames], ["about"])
|
||||
[restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
|
||||
|
||||
assert is_bitstring(restricted_name)
|
||||
assert is_binary(restricted_name)
|
||||
|
||||
params =
|
||||
@full_user_data
|
||||
|
|
@ -631,6 +632,23 @@ defmodule Pleroma.UserTest do
|
|||
refute changeset.valid?
|
||||
end
|
||||
|
||||
test "it is case-insensitive when restricting nicknames" do
|
||||
clear_config([User, :restricted_nicknames], ["about"])
|
||||
[restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames])
|
||||
|
||||
assert is_binary(restricted_name)
|
||||
|
||||
restricted_upcase_name = String.upcase(restricted_name)
|
||||
|
||||
params =
|
||||
@full_user_data
|
||||
|> Map.put(:nickname, restricted_upcase_name)
|
||||
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
||||
refute changeset.valid?
|
||||
end
|
||||
|
||||
test "it blocks blacklisted email domains" do
|
||||
clear_config([User, :email_blacklist], ["trolling.world"])
|
||||
|
||||
|
|
@ -639,6 +657,11 @@ defmodule Pleroma.UserTest do
|
|||
changeset = User.register_changeset(%User{}, params)
|
||||
refute changeset.valid?
|
||||
|
||||
# Block with case-insensitive match
|
||||
params = Map.put(@full_user_data, :email, "troll@TrOlLing.wOrld")
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
refute changeset.valid?
|
||||
|
||||
# Block with subdomain match
|
||||
params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world")
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
|
@ -1123,7 +1146,7 @@ defmodule Pleroma.UserTest do
|
|||
user = insert(:user)
|
||||
muted_user = insert(:user)
|
||||
|
||||
{:ok, _user_relationships} = User.mute(user, muted_user, %{expires_in: 60})
|
||||
{:ok, _user_relationships} = User.mute(user, muted_user, %{duration: 60})
|
||||
assert User.mutes?(user, muted_user)
|
||||
|
||||
worker = Pleroma.Workers.MuteExpireWorker
|
||||
|
|
@ -2579,6 +2602,82 @@ defmodule Pleroma.UserTest do
|
|||
object_id
|
||||
end
|
||||
|
||||
describe "add_alias/2" do
|
||||
test "should add alias for another user" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user2)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 1
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
end
|
||||
|
||||
test "should add multiple aliases" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user)
|
||||
|
||||
assert {:ok, user} = user |> User.add_alias(user2)
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user3)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 2
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
assert user3.ap_id in user_updated.also_known_as
|
||||
end
|
||||
|
||||
test "should not add duplicate aliases" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
|
||||
assert {:ok, user} = user |> User.add_alias(user2)
|
||||
|
||||
assert {:ok, user_updated} = user |> User.add_alias(user2)
|
||||
|
||||
assert user_updated.also_known_as |> length() == 1
|
||||
assert user2.ap_id in user_updated.also_known_as
|
||||
end
|
||||
end
|
||||
|
||||
describe "alias_users/1" do
|
||||
test "should get aliases for a user" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
aliases = user2 |> User.alias_users()
|
||||
|
||||
assert aliases |> length() == 1
|
||||
|
||||
alias_user = aliases |> Enum.at(0)
|
||||
|
||||
assert alias_user.ap_id == user.ap_id
|
||||
end
|
||||
end
|
||||
|
||||
describe "delete_alias/2" do
|
||||
test "should delete existing alias" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
assert {:ok, user_updated} = user2 |> User.delete_alias(user)
|
||||
|
||||
assert user_updated.also_known_as == []
|
||||
end
|
||||
|
||||
test "should report error on non-existing alias" do
|
||||
user = insert(:user)
|
||||
user2 = insert(:user)
|
||||
user3 = insert(:user, also_known_as: [user.ap_id])
|
||||
|
||||
assert {:error, :no_such_alias} = user3 |> User.delete_alias(user2)
|
||||
|
||||
user3_updated = User.get_cached_by_ap_id(user3.ap_id)
|
||||
|
||||
assert user3_updated.also_known_as |> length() == 1
|
||||
assert user.ap_id in user3_updated.also_known_as
|
||||
end
|
||||
end
|
||||
|
||||
describe "account endorsements" do
|
||||
test "it pins people" do
|
||||
user = insert(:user)
|
||||
|
|
|
|||
|
|
@ -1836,9 +1836,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
"target" => ^new_ap_id,
|
||||
"type" => "Move"
|
||||
},
|
||||
local: true
|
||||
local: true,
|
||||
recipients: recipients
|
||||
} = activity
|
||||
|
||||
assert old_user.follower_address in recipients
|
||||
|
||||
params = %{
|
||||
"op" => "move_following",
|
||||
"origin_id" => old_user.id,
|
||||
|
|
@ -1869,6 +1872,42 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
|
|||
assert {:error, "Target account must have the origin in `alsoKnownAs`"} =
|
||||
ActivityPub.move(old_user, new_user)
|
||||
end
|
||||
|
||||
test "do not move remote user following relationships" do
|
||||
%{ap_id: old_ap_id} = old_user = insert(:user)
|
||||
%{ap_id: new_ap_id} = new_user = insert(:user, also_known_as: [old_ap_id])
|
||||
follower_remote = insert(:user, local: false)
|
||||
|
||||
User.follow(follower_remote, old_user)
|
||||
|
||||
assert User.following?(follower_remote, old_user)
|
||||
|
||||
assert {:ok, activity} = ActivityPub.move(old_user, new_user)
|
||||
|
||||
assert %Activity{
|
||||
actor: ^old_ap_id,
|
||||
data: %{
|
||||
"actor" => ^old_ap_id,
|
||||
"object" => ^old_ap_id,
|
||||
"target" => ^new_ap_id,
|
||||
"type" => "Move"
|
||||
},
|
||||
local: true
|
||||
} = activity
|
||||
|
||||
params = %{
|
||||
"op" => "move_following",
|
||||
"origin_id" => old_user.id,
|
||||
"target_id" => new_user.id
|
||||
}
|
||||
|
||||
assert_enqueued(worker: Pleroma.Workers.BackgroundWorker, args: params)
|
||||
|
||||
Pleroma.Workers.BackgroundWorker.perform(%Oban.Job{args: params})
|
||||
|
||||
assert User.following?(follower_remote, old_user)
|
||||
refute User.following?(follower_remote, new_user)
|
||||
end
|
||||
end
|
||||
|
||||
test "doesn't retrieve replies activities with exclude_replies" do
|
||||
|
|
|
|||
|
|
@ -43,4 +43,15 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.ArticleNotePageValidatorTest
|
|||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
|
||||
test "a note with an attachment should work", _ do
|
||||
insert(:user, %{ap_id: "https://owncast.localhost.localdomain/federation/user/streamer"})
|
||||
|
||||
note =
|
||||
"test/fixtures/owncast-note-with-attachment.json"
|
||||
|> File.read!()
|
||||
|> Jason.decode!()
|
||||
|
||||
%{valid?: true} = ArticleNotePageValidator.cast_and_validate(note)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,6 +27,46 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.AttachmentValidatorTest do
|
|||
assert attachment.mediaType == "application/octet-stream"
|
||||
end
|
||||
|
||||
test "works with an unknown but valid mime type" do
|
||||
attachment = %{
|
||||
"mediaType" => "x-custom/x-type",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "x-custom/x-type"
|
||||
end
|
||||
|
||||
test "works with invalid mime types" do
|
||||
attachment = %{
|
||||
"mediaType" => "x-customx-type",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "application/octet-stream"
|
||||
|
||||
attachment = %{
|
||||
"mediaType" => "https://example.org",
|
||||
"type" => "Document",
|
||||
"url" => "https://example.org"
|
||||
}
|
||||
|
||||
assert {:ok, attachment} =
|
||||
AttachmentValidator.cast_and_validate(attachment)
|
||||
|> Ecto.Changeset.apply_action(:insert)
|
||||
|
||||
assert attachment.mediaType == "application/octet-stream"
|
||||
end
|
||||
|
||||
test "it turns mastodon attachments into our attachments" do
|
||||
attachment = %{
|
||||
"url" =>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,37 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.EmojiReactHandlingTest do
|
|||
assert match?([["👌", _]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it works for incoming unqualified emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
{:ok, activity} = CommonAPI.post(user, %{status: "hello"})
|
||||
|
||||
# woman detective emoji, unqualified
|
||||
unqualified_emoji = [0x1F575, 0x200D, 0x2640] |> List.to_string()
|
||||
|
||||
data =
|
||||
File.read!("test/fixtures/emoji-reaction.json")
|
||||
|> Jason.decode!()
|
||||
|> Map.put("object", activity.data["object"])
|
||||
|> Map.put("actor", other_user.ap_id)
|
||||
|> Map.put("content", unqualified_emoji)
|
||||
|
||||
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
|
||||
|
||||
assert data["actor"] == other_user.ap_id
|
||||
assert data["type"] == "EmojiReact"
|
||||
assert data["id"] == "http://mastodon.example.org/users/admin#reactions/2"
|
||||
assert data["object"] == activity.data["object"]
|
||||
# woman detective emoji, fully qualified
|
||||
emoji = [0x1F575, 0xFE0F, 0x200D, 0x2640, 0xFE0F] |> List.to_string()
|
||||
assert data["content"] == emoji
|
||||
|
||||
object = Object.get_by_ap_id(data["object"])
|
||||
|
||||
assert object.data["reaction_count"] == 1
|
||||
assert match?([[emoji, _]], object.data["reactions"])
|
||||
end
|
||||
|
||||
test "it reject invalid emoji reactions" do
|
||||
user = insert(:user)
|
||||
other_user = insert(:user, local: false)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,281 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.AdminAPI.AnnouncementControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
setup do
|
||||
admin = insert(:user, is_admin: true)
|
||||
token = insert(:oauth_admin_token, user: admin)
|
||||
|
||||
conn =
|
||||
build_conn()
|
||||
|> assign(:user, admin)
|
||||
|> assign(:token, token)
|
||||
|
||||
{:ok, %{admin: admin, token: token, conn: conn}}
|
||||
end
|
||||
|
||||
describe "GET /api/v1/pleroma/admin/announcements" do
|
||||
test "it lists all announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id}] = response
|
||||
end
|
||||
|
||||
test "it paginates announcements", %{conn: conn} do
|
||||
_announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(response) == 20
|
||||
end
|
||||
|
||||
test "it paginates announcements with custom params", %{conn: conn} do
|
||||
announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: 5, offset: 7)
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert length(response) == 5
|
||||
assert Enum.at(response, 0)["id"] == Enum.at(announcements, 7).id
|
||||
end
|
||||
|
||||
test "it returns empty list with out-of-bounds offset", %{conn: conn} do
|
||||
_announcements = Enum.map(0..20, fn _ -> insert(:announcement) end)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", offset: 21)
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [] = response
|
||||
end
|
||||
|
||||
test "it rejects invalid pagination params", %{conn: conn} do
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: 0)
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", limit: -1)
|
||||
|> json_response_and_validate_schema(400)
|
||||
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements", offset: -1)
|
||||
|> json_response_and_validate_schema(400)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it displays one announcement", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"id" => ^id} = response
|
||||
end
|
||||
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> get("/api/v1/pleroma/admin/announcements/#{id}xxx")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it deletes specified announcement", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> delete("/api/v1/pleroma/admin/announcements/#{id}xxx")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
|
||||
assert %{id: ^id} = Pleroma.Announcement.get_by_id(id)
|
||||
end
|
||||
end
|
||||
|
||||
describe "PATCH /api/v1/pleroma/admin/announcements/:id" do
|
||||
test "it returns not found for non-existent id", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}xxx", %{})
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
|
||||
assert %{id: ^id} = Pleroma.Announcement.get_by_id(id)
|
||||
end
|
||||
|
||||
test "it updates a field", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: NaiveDateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert NaiveDateTime.compare(new.starts_at, starts_at) == :eq
|
||||
end
|
||||
|
||||
test "it updates with time with utc timezone", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second)
|
||||
starts_at = DateTime.add(now, -10, :second)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: DateTime.to_iso8601(starts_at)
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert DateTime.compare(new.starts_at, starts_at) == :eq
|
||||
end
|
||||
|
||||
test "it updates a data field", %{conn: conn} do
|
||||
%{id: id} = announcement = insert(:announcement, data: %{"all_day" => true})
|
||||
|
||||
assert announcement.data["all_day"] == true
|
||||
|
||||
new_content = "new content"
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
content: new_content
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["content"] == new_content
|
||||
assert response["all_day"] == true
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert new.data["content"] == new_content
|
||||
assert new.data["all_day"] == true
|
||||
end
|
||||
|
||||
test "it nullifies a nullable field", %{conn: conn} do
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
|
||||
%{id: id} = insert(:announcement, starts_at: starts_at)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> patch("/api/v1/pleroma/admin/announcements/#{id}", %{
|
||||
starts_at: nil
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert response["starts_at"] == nil
|
||||
|
||||
new = Pleroma.Announcement.get_by_id(id)
|
||||
|
||||
assert new.starts_at == nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/pleroma/admin/announcements" do
|
||||
test "it creates an announcement", %{conn: conn} do
|
||||
content = "test post announcement api"
|
||||
|
||||
now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
|
||||
starts_at = NaiveDateTime.add(now, -10, :second)
|
||||
ends_at = NaiveDateTime.add(now, 10, :second)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => NaiveDateTime.to_iso8601(starts_at),
|
||||
"ends_at" => NaiveDateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"content" => ^content, "all_day" => true} = response
|
||||
|
||||
announcement = Pleroma.Announcement.get_by_id(response["id"])
|
||||
|
||||
assert not is_nil(announcement)
|
||||
|
||||
assert NaiveDateTime.compare(announcement.starts_at, starts_at) == :eq
|
||||
assert NaiveDateTime.compare(announcement.ends_at, ends_at) == :eq
|
||||
end
|
||||
|
||||
test "creating with time with utc timezones", %{conn: conn} do
|
||||
content = "test post announcement api"
|
||||
|
||||
now = DateTime.now("Etc/UTC") |> elem(1) |> DateTime.truncate(:second)
|
||||
starts_at = DateTime.add(now, -10, :second)
|
||||
ends_at = DateTime.add(now, 10, :second)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> put_req_header("content-type", "application/json")
|
||||
|> post("/api/v1/pleroma/admin/announcements", %{
|
||||
"content" => content,
|
||||
"starts_at" => DateTime.to_iso8601(starts_at),
|
||||
"ends_at" => DateTime.to_iso8601(ends_at),
|
||||
"all_day" => true
|
||||
})
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert %{"content" => ^content, "all_day" => true} = response
|
||||
|
||||
announcement = Pleroma.Announcement.get_by_id(response["id"])
|
||||
|
||||
assert not is_nil(announcement)
|
||||
|
||||
assert DateTime.compare(announcement.starts_at, starts_at) == :eq
|
||||
assert DateTime.compare(announcement.ends_at, ends_at) == :eq
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
alias Pleroma.Repo
|
||||
alias Pleroma.Tests.ObanHelpers
|
||||
alias Pleroma.User
|
||||
alias Pleroma.UserRelationship
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.ActivityPub.InternalFetchActor
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
|
@ -1011,6 +1012,40 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
assert %{"id" => _id, "muting" => false, "muting_notifications" => false} =
|
||||
json_response_and_validate_schema(conn, 200)
|
||||
end
|
||||
|
||||
test "expiring", %{conn: conn, user: user} do
|
||||
other_user = insert(:user)
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v1/accounts/#{other_user.id}/mute", %{"duration" => "86400"})
|
||||
|
||||
assert %{"id" => _id, "muting" => true} = json_response_and_validate_schema(conn, 200)
|
||||
|
||||
mute_expires_at = UserRelationship.get_mute_expire_date(user, other_user)
|
||||
|
||||
assert DateTime.diff(
|
||||
mute_expires_at,
|
||||
DateTime.utc_now() |> DateTime.add(24 * 60 * 60)
|
||||
) in -3..3
|
||||
end
|
||||
|
||||
test "falls back to expires_in", %{conn: conn, user: user} do
|
||||
other_user = insert(:user)
|
||||
|
||||
conn
|
||||
|> put_req_header("content-type", "multipart/form-data")
|
||||
|> post("/api/v1/accounts/#{other_user.id}/mute", %{"expires_in" => "86400"})
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
mute_expires_at = UserRelationship.get_mute_expire_date(user, other_user)
|
||||
|
||||
assert DateTime.diff(
|
||||
mute_expires_at,
|
||||
DateTime.utc_now() |> DateTime.add(24 * 60 * 60)
|
||||
) in -3..3
|
||||
end
|
||||
end
|
||||
|
||||
describe "pinned statuses" do
|
||||
|
|
@ -1829,21 +1864,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/mutes")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [id1, id2, id3] == Enum.map(result, & &1["id"])
|
||||
assert [id3, id2, id1] == Enum.map(result, & &1["id"])
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/mutes?limit=1")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id1}] = result
|
||||
assert [%{"id" => ^id3}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> get("/api/v1/mutes?since_id=#{id1}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
|
||||
assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -1857,7 +1892,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/mutes?since_id=#{id1}&limit=1")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id2}] = result
|
||||
assert [%{"id" => ^id3}] = result
|
||||
end
|
||||
|
||||
test "list of mutes with with_relationships parameter" do
|
||||
|
|
@ -1876,7 +1911,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|
||||
assert [
|
||||
%{
|
||||
"id" => ^id1,
|
||||
"id" => ^id3,
|
||||
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
|
||||
},
|
||||
%{
|
||||
|
|
@ -1884,7 +1919,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
|
||||
},
|
||||
%{
|
||||
"id" => ^id3,
|
||||
"id" => ^id1,
|
||||
"pleroma" => %{"relationship" => %{"muting" => true, "followed_by" => true}}
|
||||
}
|
||||
] =
|
||||
|
|
@ -1909,7 +1944,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/blocks")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [id1, id2, id3] == Enum.map(result, & &1["id"])
|
||||
assert [id3, id2, id1] == Enum.map(result, & &1["id"])
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -1917,7 +1952,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/blocks?limit=1")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id1}] = result
|
||||
assert [%{"id" => ^id3}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -1925,7 +1960,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/blocks?since_id=#{id1}")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id2}, %{"id" => ^id3}] = result
|
||||
assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -1941,7 +1976,31 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|
|||
|> get("/api/v1/blocks?since_id=#{id1}&limit=1")
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id2}] = result
|
||||
assert [%{"id" => ^id3}] = result
|
||||
|
||||
conn_res =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get("/api/v1/blocks?limit=2")
|
||||
|
||||
next_url =
|
||||
~r{<.+?(?<link>/api[^>]+)>; rel=\"next\"}
|
||||
|> Regex.named_captures(get_resp_header(conn_res, "link") |> Enum.at(0))
|
||||
|> Map.get("link")
|
||||
|
||||
result =
|
||||
conn_res
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id3}, %{"id" => ^id2}] = result
|
||||
|
||||
result =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> get(next_url)
|
||||
|> json_response_and_validate_schema(200)
|
||||
|
||||
assert [%{"id" => ^id1}] = result
|
||||
end
|
||||
|
||||
test "account lookup", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.MastodonAPI.AnnouncementControllerTest do
|
||||
use Pleroma.Web.ConnCase
|
||||
|
||||
import Pleroma.Factory
|
||||
|
||||
alias Pleroma.Announcement
|
||||
alias Pleroma.AnnouncementReadRelationship
|
||||
|
||||
describe "GET /api/v1/announcements" do
|
||||
setup do
|
||||
%{conn: conn} = oauth_access([])
|
||||
{:ok, conn: conn}
|
||||
end
|
||||
|
||||
test "it does not allow guests", %{conn: conn} do
|
||||
_response =
|
||||
conn
|
||||
|> assign(:token, nil)
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:forbidden)
|
||||
end
|
||||
|
||||
test "it allows users with scopes" do
|
||||
%{conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
end
|
||||
|
||||
test "it lists all announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id}] = response
|
||||
end
|
||||
|
||||
test "it returns time with utc timezone", %{conn: conn} do
|
||||
start_time =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(-999_999, :second)
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
end_time =
|
||||
NaiveDateTime.utc_now()
|
||||
|> NaiveDateTime.add(999_999, :second)
|
||||
|> NaiveDateTime.truncate(:second)
|
||||
|
||||
%{id: id} = insert(:announcement, %{starts_at: start_time, ends_at: end_time})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id}] = [announcement] = response
|
||||
|
||||
assert String.ends_with?(announcement["starts_at"], "Z")
|
||||
assert String.ends_with?(announcement["ends_at"], "Z")
|
||||
end
|
||||
|
||||
test "it does not list announcements starting after current time", %{conn: conn} do
|
||||
time = NaiveDateTime.utc_now() |> NaiveDateTime.add(999_999, :second)
|
||||
insert(:announcement, starts_at: time)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [] = response
|
||||
end
|
||||
|
||||
test "it does not list announcements ending before current time", %{conn: conn} do
|
||||
time = NaiveDateTime.utc_now() |> NaiveDateTime.add(-999_999, :second)
|
||||
insert(:announcement, ends_at: time)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [] = response
|
||||
end
|
||||
|
||||
test "when authenticated, also expose read property", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id, "read" => false}] = response
|
||||
end
|
||||
|
||||
test "when authenticated and announcement is read by user" do
|
||||
%{id: id} = announcement = insert(:announcement)
|
||||
user = insert(:user)
|
||||
|
||||
AnnouncementReadRelationship.mark_read(user, announcement)
|
||||
|
||||
%{conn: conn} = oauth_access(["read:accounts"], user: user)
|
||||
|
||||
response =
|
||||
conn
|
||||
|> get("/api/v1/announcements")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert [%{"id" => ^id, "read" => true}] = response
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /api/v1/announcements/:id/dismiss" do
|
||||
setup do: oauth_access(["write:accounts"])
|
||||
|
||||
test "it requires auth", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> assign(:token, nil)
|
||||
|> post("/api/v1/announcements/#{id}/dismiss")
|
||||
|> json_response_and_validate_schema(:forbidden)
|
||||
end
|
||||
|
||||
test "it requires write:accounts oauth scope" do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
%{conn: conn} = oauth_access(["read:accounts"])
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> post("/api/v1/announcements/#{id}/dismiss")
|
||||
|> json_response_and_validate_schema(:forbidden)
|
||||
end
|
||||
|
||||
test "it gives 404 for non-existent announcements", %{conn: conn} do
|
||||
%{id: id} = insert(:announcement)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> post("/api/v1/announcements/#{id}xxx/dismiss")
|
||||
|> json_response_and_validate_schema(:not_found)
|
||||
end
|
||||
|
||||
test "it marks announcement as read", %{user: user, conn: conn} do
|
||||
%{id: id} = announcement = insert(:announcement)
|
||||
|
||||
refute Announcement.read_by?(announcement, user)
|
||||
|
||||
_response =
|
||||
conn
|
||||
|> post("/api/v1/announcements/#{id}/dismiss")
|
||||
|> json_response_and_validate_schema(:ok)
|
||||
|
||||
assert Announcement.read_by?(announcement, user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -22,6 +22,7 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do
|
|||
"uri" => _,
|
||||
"title" => _,
|
||||
"description" => _,
|
||||
"short_description" => _,
|
||||
"version" => _,
|
||||
"email" => from_config_email,
|
||||
"urls" => %{
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
test "filters notifications using include_types" do
|
||||
test "filters notifications using types" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
|
|
@ -438,21 +438,21 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
reblog_notification_id = get_notification_id_by_activity(reblog_activity)
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
|
||||
conn_res = get(conn, "/api/v1/notifications?types[]=follow")
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=mention")
|
||||
conn_res = get(conn, "/api/v1/notifications?types[]=mention")
|
||||
|
||||
assert [%{"id" => ^mention_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=favourite")
|
||||
conn_res = get(conn, "/api/v1/notifications?types[]=favourite")
|
||||
|
||||
assert [%{"id" => ^favorite_notification_id}] =
|
||||
json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=reblog")
|
||||
conn_res = get(conn, "/api/v1/notifications?types[]=reblog")
|
||||
|
||||
assert [%{"id" => ^reblog_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
|
||||
assert length(result) == 4
|
||||
|
||||
query = params_to_query(%{include_types: ["follow", "mention", "favourite", "reblog"]})
|
||||
query = params_to_query(%{types: ["follow", "mention", "favourite", "reblog"]})
|
||||
|
||||
result =
|
||||
conn
|
||||
|
|
@ -470,6 +470,23 @@ defmodule Pleroma.Web.MastodonAPI.NotificationControllerTest do
|
|||
assert length(result) == 4
|
||||
end
|
||||
|
||||
test "filtering falls back to include_types" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
||||
{:ok, _activity} = CommonAPI.post(other_user, %{status: "hey @#{user.nickname}"})
|
||||
{:ok, create_activity} = CommonAPI.post(user, %{status: "hey"})
|
||||
{:ok, _activity} = CommonAPI.favorite(other_user, create_activity.id)
|
||||
{:ok, _activity} = CommonAPI.repeat(create_activity.id, other_user)
|
||||
{:ok, _, _, follow_activity} = CommonAPI.follow(other_user, user)
|
||||
|
||||
follow_notification_id = get_notification_id_by_activity(follow_activity)
|
||||
|
||||
conn_res = get(conn, "/api/v1/notifications?include_types[]=follow")
|
||||
|
||||
assert [%{"id" => ^follow_notification_id}] = json_response_and_validate_schema(conn_res, 200)
|
||||
end
|
||||
|
||||
test "destroy multiple" do
|
||||
%{user: user, conn: conn} = oauth_access(["read:notifications", "write:notifications"])
|
||||
other_user = insert(:user)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue