feat: add support and content removal workflows
Some checks are pending
Quality / full-local-gates (push) Waiting to run
Some checks are pending
Quality / full-local-gates (push) Waiting to run
This commit is contained in:
parent
0a588182a0
commit
e2ea2252bc
|
|
@ -124,6 +124,8 @@ SMTP_TLS=never
|
|||
SMTP_SSL=false
|
||||
EMAIL_FROM_NAME="Who Need Help"
|
||||
EMAIL_FROM_ADDRESS=contact@example.com
|
||||
# Optional monitored inbox. It receives new-case alerts and is used as Reply-To.
|
||||
SUPPORT_INBOX_ADDRESS=
|
||||
|
||||
CODEX_SESSION_ID=copy-the-main-local-codex-session-id
|
||||
# Optional shared PostgreSQL-backed policies. Keep {} until product thresholds are approved.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ thank-you link; money goes directly between users outside the platform.
|
|||
- Bidirectional discovery blocks, scoped reports, account/request/category
|
||||
moderation, abuse-signal review, and audited moderator access to only the
|
||||
conversation linked by a report.
|
||||
- Separate public support and content-removal intake, including moderation
|
||||
appeals, account deletion/data requests, a URL-only TAKE IT DOWN form,
|
||||
verified-contact status links, operator alerts, and audited staff queues.
|
||||
- Optional GPS evidence derived from browser accuracy envelopes. Raw current
|
||||
positions are deleted on stop, terminal match state, or participant block.
|
||||
- PostgreSQL-backed cross-replica action-limit policies configured by the
|
||||
|
|
@ -201,7 +204,11 @@ existing file:
|
|||
|
||||
Configure the verified reverse-proxy source IP/CIDR and transactional SMTP
|
||||
provider in that file. Email registration and magic-link login are unusable for
|
||||
real recipients until that relay and its accepted sender are configured.
|
||||
real recipients until that relay and its accepted sender are configured. Set
|
||||
the optional `SUPPORT_INBOX_ADDRESS` to a monitored mailbox to receive
|
||||
metadata-only new-case alerts and make replies return to the support team; the
|
||||
database queues continue to work when it is empty. See
|
||||
[the support and content-removal runbook](docs/support-and-content-removal.md).
|
||||
Then validate the file structure and the production Compose render:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ x-app-environment: &app-environment
|
|||
SMTP_SSL: ${SMTP_SSL:?Set SMTP_SSL in .env}
|
||||
EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:?Set EMAIL_FROM_NAME in .env}
|
||||
EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:?Set EMAIL_FROM_ADDRESS in .env}
|
||||
SUPPORT_INBOX_ADDRESS: ${SUPPORT_INBOX_ADDRESS:-}
|
||||
CODEX_SESSION_ID: ${CODEX_SESSION_ID:-not-configured}
|
||||
RATE_LIMIT_POLICIES_JSON: ${RATE_LIMIT_POLICIES_JSON:-{}}
|
||||
MAP_TILE_URL: ${MAP_TILE_URL:-https://tile.openstreetmap.org/{z}/{x}/{y}.png}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ config :who_need_help, :mailer_from,
|
|||
name: "Who Need Help",
|
||||
address: "contact@example.com"
|
||||
|
||||
config :who_need_help, :support_inbox_address, nil
|
||||
|
||||
config :who_need_help, :scopes,
|
||||
user: [
|
||||
default: true,
|
||||
|
|
|
|||
|
|
@ -444,6 +444,19 @@ if config_env() == :prod do
|
|||
name: System.get_env("EMAIL_FROM_NAME", "Who Need Help"),
|
||||
address: System.get_env("EMAIL_FROM_ADDRESS", "contact@example.com")
|
||||
|
||||
support_inbox_address =
|
||||
case System.get_env("SUPPORT_INBOX_ADDRESS") do
|
||||
value when value in [nil, ""] -> nil
|
||||
value -> value
|
||||
end
|
||||
|
||||
if support_inbox_address &&
|
||||
not Regex.match?(~r/^[^@,;\s]+@[^@,;\s]+$/, support_inbox_address) do
|
||||
raise "SUPPORT_INBOX_ADDRESS must be a single email address without spaces."
|
||||
end
|
||||
|
||||
config :who_need_help, :support_inbox_address, support_inbox_address
|
||||
|
||||
config :who_need_help, WhoNeedHelp.Mailer, smtp_config
|
||||
|
||||
config :who_need_help, WhoNeedHelpWeb.Endpoint,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ app:
|
|||
# HANDOVER_SECRET, RELEASE_COOKIE, and METRICS_TOKEN. It may also contain both
|
||||
# GITHUB_OAUTH_CLIENT_ID and GITHUB_OAUTH_CLIENT_SECRET to enable verified
|
||||
# GitHub linking, and both GOOGLE_OAUTH_CLIENT_ID and
|
||||
# GOOGLE_OAUTH_CLIENT_SECRET to enable Google registration/sign-in. Push is
|
||||
# GOOGLE_OAUTH_CLIENT_SECRET to enable Google registration/sign-in. Optional
|
||||
# SUPPORT_INBOX_ADDRESS enables metadata-only operator alerts and Reply-To. Push is
|
||||
# opt-in: provide PUSH_HTTP_ENDPOINT,
|
||||
# PUSH_HTTP_BEARER_TOKEN, PUSH_HTTP_MAX_ATTEMPTS,
|
||||
# PUSH_HTTP_RECEIVE_TIMEOUT_MS, PUSH_HTTP_CONNECT_TIMEOUT_MS, and
|
||||
|
|
|
|||
|
|
@ -71,7 +71,10 @@ do not copy the temporary VPN value into an unrelated server.
|
|||
Configure the transactional SMTP relay and sender accepted by that provider.
|
||||
Provider-specific auth, TLS, ports, and credentials can be supplied to the
|
||||
initializer through the documented `PRODUCTION_SMTP_*` environment values or
|
||||
edited in the resulting ignored file. If Google registration/sign-in is
|
||||
edited in the resulting ignored file. Set optional `SUPPORT_INBOX_ADDRESS` to
|
||||
a monitored address for support/removal queue alerts and email `Reply-To`;
|
||||
leaving it empty disables operator email alerts, not the protected queues. If
|
||||
Google registration/sign-in is
|
||||
enabled, also set both Google Web client credentials and register
|
||||
`https://YOUR_PHX_HOST/auth/google/callback` as the exact authorized redirect
|
||||
URI. Leave both credentials empty to keep the feature disabled. Then run:
|
||||
|
|
|
|||
137
docs/support-and-content-removal.md
Normal file
137
docs/support-and-content-removal.md
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
# Support and content-removal operations
|
||||
|
||||
Status: implemented intake and operator workflow. This document describes the
|
||||
software behavior; it is not a legal opinion and does not establish that a
|
||||
particular law applies to the operator.
|
||||
|
||||
## Separate queues
|
||||
|
||||
Who Need Help deliberately separates three mechanisms:
|
||||
|
||||
1. An authenticated in-product report targets exactly one request, assignment,
|
||||
message, Activity, or Activity message and follows the existing audited
|
||||
trust-and-safety workflow.
|
||||
2. A support request covers account access, technical issues, safety concerns,
|
||||
moderation appeals, privacy questions, data export, and account deletion.
|
||||
3. A content-removal notice covers a precise item alleged to be illegal or to
|
||||
infringe a right. TAKE IT DOWN notices have a dedicated public form and a
|
||||
separate regime value in the removal queue.
|
||||
|
||||
The operator workspace is `/support/operations`. It is protected by the same
|
||||
database-checked moderator or administrator authorization as the existing
|
||||
moderation workspace. Every creation and decision records an audit event.
|
||||
|
||||
## Public routes
|
||||
|
||||
- `/support` — ordinary support.
|
||||
- `/account/delete` — external account-deletion request path suitable for use
|
||||
as the Google Play account-deletion web resource.
|
||||
- `/legal/content-removal` — general electronic notice-and-action intake.
|
||||
- `/legal/take-it-down` — dedicated intimate-visual-material removal intake.
|
||||
|
||||
The request and Activity screens link to the general form with the exact local
|
||||
content URL prefilled. Only same-origin relative paths can be prefilled this
|
||||
way. The server validates one complete HTTP or HTTPS URL per line and accepts
|
||||
at most 20 locations in one notice.
|
||||
|
||||
## Contact verification and status access
|
||||
|
||||
Public submissions display a reference but never expose the signed status token
|
||||
in the redirect. The private status link is sent to the contact email. Opening
|
||||
it marks that contact address as verified. An authenticated submission uses the
|
||||
confirmed account email and is verified immediately.
|
||||
|
||||
Email-link verification establishes access to the mailbox, not government
|
||||
identity, authority to act for another person, or the truth of the claim.
|
||||
Operators must perform any additional verification appropriate to the requested
|
||||
action. In particular, an account-deletion request must not be fulfilled against
|
||||
another person's account merely because an address was typed into the form.
|
||||
|
||||
Identity and contact fields may be omitted from a general report of sexual
|
||||
material involving a minor. Such a report still receives an urgent queue state,
|
||||
but no status email can be sent without a contact address.
|
||||
|
||||
## TAKE IT DOWN boundary
|
||||
|
||||
The dedicated form accepts exact URLs and textual identification only. It does
|
||||
not accept file uploads and explicitly tells the submitter not to reproduce or
|
||||
email the intimate image or video. A submitted notice is marked for urgent
|
||||
review and records a review due time 48 hours after receipt.
|
||||
|
||||
The current product does not accept user-uploaded images or videos. The presence
|
||||
of this preparedness workflow therefore does not claim that Who Need Help is a
|
||||
covered platform, that a submitted item satisfies the statutory definition, or
|
||||
that identical-copy detection exists. If media hosting is added, the operator
|
||||
must review the then-current law, implement safe media hashing and
|
||||
identical-copy handling where applicable, and test the entire removal path
|
||||
before enabling uploads.
|
||||
|
||||
The primary US text currently requires a clear and conspicuous process and, for
|
||||
a valid request to a covered platform, removal of the depiction plus reasonable
|
||||
efforts concerning known identical copies as soon as possible and no later than
|
||||
48 hours:
|
||||
|
||||
- <https://www.govinfo.gov/content/pkg/COMPS-18158/pdf/COMPS-18158.pdf>
|
||||
|
||||
## EU electronic notices
|
||||
|
||||
The general form captures the elements listed in Article 16 of Regulation (EU)
|
||||
2022/2065: a reasoned explanation, exact electronic location, submitter name and
|
||||
email subject to the child-sexual-abuse exception, and a good-faith accuracy
|
||||
statement. It sends an acknowledgement when email is available and sends the
|
||||
recorded decision after a verified-contact operator update.
|
||||
|
||||
- <https://eur-lex.europa.eu/eli/reg/2022/2065/oj/eng>
|
||||
|
||||
Product implementation alone does not determine the service's legal
|
||||
classification, establishment, target markets, applicable national law, or
|
||||
redress obligations. Those remain launch decisions requiring jurisdiction-
|
||||
specific review.
|
||||
|
||||
## Email and operator notification
|
||||
|
||||
`EMAIL_FROM_ADDRESS` remains the outbound sender. Optional
|
||||
`SUPPORT_INBOX_ADDRESS` has two separate effects:
|
||||
|
||||
- outgoing support/removal messages use it as `Reply-To`;
|
||||
- it receives a metadata-only alert containing the reference, queue type, and
|
||||
protected operator URL when a case is created.
|
||||
|
||||
The alert intentionally excludes the free-text report and reported URLs. The
|
||||
full record remains in the protected database queue. If the variable is empty,
|
||||
intake and reporter acknowledgement still work, but no operator inbox alert is
|
||||
sent. The configured inbox must be monitored operationally; the application
|
||||
cannot prove staffing or response availability.
|
||||
|
||||
## Account deletion and data export
|
||||
|
||||
The web application and Android WebView expose the account-deletion request from
|
||||
account settings, and the public `/account/delete` route remains usable after an
|
||||
app is uninstalled. The workflow verifies the contact and creates an audited
|
||||
account-lifecycle request.
|
||||
|
||||
Actual erasure/anonymization and export are not automated because the operator
|
||||
has not yet selected a jurisdiction-specific retention policy for safety,
|
||||
fraud, disputes, and legal records. An operator must not mark a request resolved
|
||||
until the applicable data action has actually been completed and communicated.
|
||||
Before public launch, legal review must define which linked records are erased,
|
||||
anonymized, or retained and for how long; only then should a destructive
|
||||
execution routine be implemented and tested against backups and relational
|
||||
constraints.
|
||||
|
||||
Google Play's current policy requires both an in-app path and an external web
|
||||
resource when an app allows account creation:
|
||||
|
||||
- <https://support.google.com/googleplay/android-developer/answer/13327111?hl=en>
|
||||
|
||||
## Abuse controls and operational limits
|
||||
|
||||
`support_request` and `content_removal_notice` are supported names in the shared
|
||||
PostgreSQL rate limiter. As with the other actions, no numeric policy is enabled
|
||||
unless the operator supplies measured values through
|
||||
`RATE_LIMIT_POLICIES_JSON`. CSRF protection, validation, exact URL limits,
|
||||
contact verification, staff authorization, and audit events apply regardless.
|
||||
|
||||
The software does not provide emergency response. Threats to life or safety are
|
||||
prioritized in the queue, while every public safety screen continues to direct
|
||||
people in immediate danger to local emergency services.
|
||||
|
|
@ -135,3 +135,10 @@ requires an explicit one-time operational bootstrap, and later role changes are
|
|||
audited; the last administrator cannot demote themselves.
|
||||
The operator must publish jurisdiction-specific emergency contacts, privacy
|
||||
notice, prohibited-items policy, and data-retention policy before public launch.
|
||||
|
||||
Public support and legal removal are separate from in-product reports. Support,
|
||||
moderation appeals, privacy/data requests, general electronic removal notices,
|
||||
and a dedicated TAKE IT DOWN intake are described in
|
||||
`docs/support-and-content-removal.md`. Public contacts are verified through an
|
||||
emailed private status link; moderator/admin decisions and access remain
|
||||
audited. The removal forms never accept intimate-media uploads.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Who Need Help — implementation verification
|
||||
|
||||
Observed through 2026-07-20 in the local workspace. This report separates observed
|
||||
Observed through 2026-07-21 in the local workspace. This report separates observed
|
||||
results from product limits and unknown production properties.
|
||||
|
||||
## Verified MVP capabilities
|
||||
|
|
@ -18,6 +18,7 @@ results from product limits and unknown production properties.
|
|||
| Reputation and anti-abuse | Implemented at MVP level | Handover codes, two-party completion, double-blind reviews, unique-counterpart ranking, optional movement/proximity evidence, reports, blocks, abuse signals, and moderator audit paths have automated tests. | The system is not bot-proof and does not claim identity verification. No punitive numeric policy is enabled without measured and approved thresholds. |
|
||||
| Account registration and sign-in | Implemented and browser-verified | Email registration sends a confirmation magic link and does not require a password. Confirmed users can keep using magic links or add a password in settings. Google OpenID Connect registration, sign-in, link, unlink, replay prevention, verified-email enforcement, and account-ownership rules are covered by the 260-test suite. A headed Chrome run completed registration, confirmation through Mailpit, password setup, logout, password login, and localized settings with zero console warnings or errors. | The local Compose environment captures email in Mailpit. A production SMTP relay and a real Google Web client are not configured or externally verified. |
|
||||
| Social profiles | Manual links implemented; optional GitHub verification implemented and automated-tested | Manual links cannot set verification fields. The optional GitHub flow uses state, PKCE, a user-bound one-time session, unique provider ownership, and an audit record. The local protocol drill also performs real HTTP token/user exchanges without returning an access token to the application. | GitHub OAuth credentials are intentionally absent and are not required for registration or the help flow. The real external provider redirect/callback remains disabled and unverified; other providers remain manual/unverified. |
|
||||
| Support and content removal | Implemented and browser-verified | Public support, account deletion, general removal, and TAKE IT DOWN forms create separate audited queues; private email status links verify public contacts; authenticated submissions use the account email; moderator-only operations can update status and notify verified contacts. TAKE IT DOWN accepts URLs/text only and records a 48-hour review due time. | The current product hosts no user media and does not claim TAKE IT DOWN coverage. Staffing, jurisdiction-specific legal classification, final retention rules, actual account erasure/export, and identical-media-copy handling remain operational/legal work. |
|
||||
| Voluntary thanks | Implemented as an external optional link | A helper can expose an optional link after completion; the UI states that the platform does not process the payment. | The platform does not provide payments, escrow, refunds, tax reporting, or payment guarantees. |
|
||||
| Android client | Local and public-staging clients implemented and emulator-verified | The native packages `org.whoneedhelp.mobile.debug` and `org.whoneedhelp.mobile.staging` launch the same authenticated LiveView app. Seven lifecycle, permission, deep-link, foreground tracking, recoverable main-page failure, notification-Stop, and Activity-destruction tests passed on each of API 30, 34, and 37. The API 37 staging smoke asserted the public home and Safety DOM over HTTPS. A run-scoped Android/browser staging test passed login, private chat in both directions, foreground tracking, live marker appearance/removal, and exact cleanup. | Production signing, Play Store publication, verified Android App Links, unattended/background-permission tracking, and iOS are not implemented. |
|
||||
| Multiple web/worker instances | Implemented and locally failure/rollout-verified | The final isolated Compose drill passed BEAM crashes and sequential replacement with 3 web/2 worker replicas: all five nodes joined, PubSub passed, and 744/744 readiness requests succeeded. The project-owned kind cluster replaced all 2 web/2 worker pod UIDs under `maxUnavailable=0`; all four replacement pods joined, PubSub passed, and 363/363 samples ultimately succeeded. | Local PostGIS is a single instance. Production database HA, backups, and recovery are operator work and are not claimed complete. |
|
||||
|
|
@ -27,6 +28,16 @@ results from product limits and unknown production properties.
|
|||
|
||||
## Reproducible checks
|
||||
|
||||
- On 2026-07-21, `./scripts/test.sh` and the Dockerized `mix precommit` each
|
||||
passed 273 tests after the support/content-removal implementation. The full
|
||||
isolated `./scripts/quality.sh` gate passed compiler, xref, Credo, Sobelow,
|
||||
Dialyzer, Hex/npm audits, Compose/Helm validation, and configured source/image
|
||||
scans. Headed Chrome over `https://whoneedhelp.imalto.site` verified public
|
||||
support acknowledgement and contact verification, general removal intake,
|
||||
the separate urgent TAKE IT DOWN form and 48-hour due time, passwordless
|
||||
account confirmation, admin-only queues, audited operator response email,
|
||||
account-deletion navigation, Russian localization, selected-status
|
||||
preservation, and zero browser-console errors or warnings.
|
||||
- On 2026-07-20, after adding Google OpenID Connect authentication,
|
||||
`./scripts/test.sh` and `mix precommit` each passed 260 tests with zero
|
||||
failures. The full isolated `./scripts/quality.sh` gate also passed format,
|
||||
|
|
@ -1115,10 +1126,12 @@ availability, or target-server capacity.
|
|||
autoscaling, and action-limit policies.
|
||||
- Publish jurisdiction-specific emergency contacts, privacy, retention,
|
||||
prohibited-items, and voluntary-payment guidance after legal review.
|
||||
- The current UI has no self-service account deletion or data-export flow.
|
||||
Decide the retention/anonymization behavior, implement the selected control,
|
||||
and verify it before promising that capability to users.
|
||||
- Establish moderation/support operations and incident response for real users.
|
||||
- The UI now has authenticated and external account-deletion/data-request
|
||||
intake, contact verification, case status, and an audited operator queue.
|
||||
Actual erasure/anonymization and export remain manual until a legally reviewed
|
||||
retention policy defines the treatment of linked safety and dispute records.
|
||||
- Staff and monitor the implemented moderation/support queues and establish an
|
||||
incident-response/on-call process for real users.
|
||||
- If verified GitHub identity is desired, create and configure its OAuth App and
|
||||
exercise the external redirect/callback. This is an optional enhancement, not
|
||||
a registration or launch blocker.
|
||||
|
|
|
|||
256
lib/who_need_help/content_removal.ex
Normal file
256
lib/who_need_help/content_removal.ex
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
defmodule WhoNeedHelp.ContentRemoval do
|
||||
@moduledoc "Separate intake and review queue for electronic content-removal notices."
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
alias WhoNeedHelp.Accounts
|
||||
alias WhoNeedHelp.Accounts.{Scope, User}
|
||||
alias WhoNeedHelp.ContentRemoval.{Notice, Notifier}
|
||||
alias WhoNeedHelp.Pagination
|
||||
alias WhoNeedHelp.Repo
|
||||
alias WhoNeedHelp.Trust
|
||||
alias WhoNeedHelp.Trust.RateLimiter
|
||||
|
||||
@access_salt "content-removal-access"
|
||||
@urgent_categories [
|
||||
:non_consensual_intimate_media,
|
||||
:child_sexual_abuse_material,
|
||||
:threat_to_life_or_safety
|
||||
]
|
||||
|
||||
def change_notice(%Notice{} = notice, attrs \\ %{}) do
|
||||
Notice.submission_changeset(notice, attrs)
|
||||
end
|
||||
|
||||
def create_notice(scope, regime, attrs) when regime in [:general, :dsa, :take_it_down] do
|
||||
user = scope_user(scope)
|
||||
attrs = normalize_keys(attrs)
|
||||
attrs = maybe_use_user_email(attrs, user)
|
||||
category = enum_value(Notice, :category, attrs["category"])
|
||||
status = if category in @urgent_categories, do: :urgent_review, else: :open
|
||||
|
||||
response_due_at =
|
||||
if regime == :take_it_down, do: DateTime.add(DateTime.utc_now(:second), 48, :hour)
|
||||
|
||||
with {:ok, _limit} <-
|
||||
RateLimiter.check(:content_removal_notice, rate_scope(user, attrs["contact_email"])) do
|
||||
Repo.transact(fn ->
|
||||
with {:ok, notice} <-
|
||||
%Notice{
|
||||
reference: unique_reference(),
|
||||
regime: regime,
|
||||
status: status,
|
||||
response_due_at: response_due_at,
|
||||
requester_id: user && user.id,
|
||||
contact_verified_at: user && DateTime.utc_now(:second)
|
||||
}
|
||||
|> Notice.submission_changeset(attrs)
|
||||
|> Repo.insert(),
|
||||
{:ok, _audit} <-
|
||||
Trust.audit(
|
||||
user && user.id,
|
||||
"content_removal_notice.created",
|
||||
"content_removal_notice",
|
||||
notice.id,
|
||||
%{
|
||||
"category" => to_string(notice.category),
|
||||
"regime" => to_string(notice.regime),
|
||||
"status" => to_string(notice.status)
|
||||
}
|
||||
) do
|
||||
{:ok, notice}
|
||||
end
|
||||
end)
|
||||
|> notify_received()
|
||||
end
|
||||
end
|
||||
|
||||
def list_for_user(%Scope{user: %User{id: user_id}}) do
|
||||
Notice
|
||||
|> where([notice], notice.requester_id == ^user_id)
|
||||
|> order_by([notice], desc: notice.inserted_at, desc: notice.id)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def get_by_access_token(id, token) when is_binary(token) do
|
||||
with {:ok, id} <- Ecto.UUID.cast(id),
|
||||
{:ok, ^id} <-
|
||||
Phoenix.Token.verify(WhoNeedHelpWeb.Endpoint, @access_salt, token, max_age: 31_536_000),
|
||||
%Notice{} = notice <- Repo.get(Notice, id) do
|
||||
verify_contact(notice)
|
||||
else
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def get_by_access_token(_id, _token), do: {:error, :not_found}
|
||||
|
||||
def access_token(%Notice{id: id}) do
|
||||
Phoenix.Token.sign(WhoNeedHelpWeb.Endpoint, @access_salt, id)
|
||||
end
|
||||
|
||||
def status_url(%Notice{} = notice) do
|
||||
token = access_token(notice)
|
||||
|
||||
WhoNeedHelpWeb.Endpoint.url() <>
|
||||
"/legal/content-removal/#{notice.id}?token=#{URI.encode_www_form(token)}"
|
||||
end
|
||||
|
||||
def paginate_for_staff(%Scope{user: user}, options \\ []) do
|
||||
if Accounts.moderator_authorized?(user) do
|
||||
limit = Pagination.limit(options)
|
||||
cursor = Pagination.cursor(options)
|
||||
|
||||
Notice
|
||||
|> maybe_regime(Keyword.get(options, :regime))
|
||||
|> before(cursor)
|
||||
|> order_by([notice], desc: notice.inserted_at, desc: notice.id)
|
||||
|> limit(^(limit + 1))
|
||||
|> preload([:requester, :reviewed_by])
|
||||
|> Repo.all()
|
||||
|> Pagination.page(limit, &{&1.inserted_at, &1.id})
|
||||
else
|
||||
%Pagination.Page{}
|
||||
end
|
||||
end
|
||||
|
||||
def moderate(%Scope{user: moderator}, id, attrs) do
|
||||
with {:ok, id} <- Ecto.UUID.cast(id),
|
||||
true <- Accounts.moderator_authorized?(moderator) do
|
||||
attrs =
|
||||
attrs
|
||||
|> normalize_keys()
|
||||
|> Map.merge(%{
|
||||
"reviewed_at" => DateTime.utc_now(:second),
|
||||
"reviewed_by_id" => moderator.id
|
||||
})
|
||||
|
||||
Repo.transact(fn ->
|
||||
notice =
|
||||
Notice
|
||||
|> where([notice], notice.id == ^id)
|
||||
|> lock("FOR UPDATE")
|
||||
|> Repo.one()
|
||||
|
||||
if notice do
|
||||
with {:ok, notice} <- notice |> Notice.moderation_changeset(attrs) |> Repo.update(),
|
||||
{:ok, _audit} <-
|
||||
Trust.audit(
|
||||
moderator.id,
|
||||
"content_removal_notice.moderated",
|
||||
"content_removal_notice",
|
||||
notice.id,
|
||||
%{
|
||||
"status" => to_string(notice.status)
|
||||
}
|
||||
) do
|
||||
{:ok, notice}
|
||||
end
|
||||
else
|
||||
{:error, :not_found}
|
||||
end
|
||||
end)
|
||||
|> notify_decision()
|
||||
else
|
||||
false -> {:error, :forbidden}
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_received({:ok, %Notice{contact_email: email} = notice}) when email in [nil, ""],
|
||||
do: notify_operator(notice)
|
||||
|
||||
defp notify_received({:ok, notice}) do
|
||||
result =
|
||||
case Notifier.deliver_received(notice, status_url(notice)) do
|
||||
{:ok, _metadata} ->
|
||||
notice
|
||||
|> Ecto.Changeset.change(acknowledgement_sent_at: DateTime.utc_now(:second))
|
||||
|> Repo.update()
|
||||
|
||||
_error ->
|
||||
{:ok, notice}
|
||||
end
|
||||
|
||||
case result do
|
||||
{:ok, current} -> notify_operator(current)
|
||||
error -> error
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_received(result), do: result
|
||||
|
||||
defp notify_operator(notice) do
|
||||
_ = Notifier.deliver_operator_alert(notice)
|
||||
{:ok, notice}
|
||||
end
|
||||
|
||||
defp notify_decision({:ok, %Notice{contact_verified_at: nil} = notice}), do: {:ok, notice}
|
||||
|
||||
defp notify_decision({:ok, notice}) do
|
||||
case Notifier.deliver_decision(notice, status_url(notice)) do
|
||||
{:ok, _metadata} ->
|
||||
notice
|
||||
|> Ecto.Changeset.change(decision_sent_at: DateTime.utc_now(:second))
|
||||
|> Repo.update()
|
||||
|
||||
_error ->
|
||||
{:ok, notice}
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_decision(result), do: result
|
||||
|
||||
defp verify_contact(%Notice{contact_verified_at: nil} = notice) do
|
||||
notice
|
||||
|> Ecto.Changeset.change(contact_verified_at: DateTime.utc_now(:second))
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
defp verify_contact(%Notice{} = notice), do: {:ok, notice}
|
||||
|
||||
defp before(query, nil), do: query
|
||||
|
||||
defp before(query, {inserted_at, id}) do
|
||||
where(
|
||||
query,
|
||||
[notice],
|
||||
notice.inserted_at < ^inserted_at or
|
||||
(notice.inserted_at == ^inserted_at and notice.id < ^id)
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_regime(query, nil), do: query
|
||||
defp maybe_regime(query, regime), do: where(query, [notice], notice.regime == ^regime)
|
||||
|
||||
defp maybe_use_user_email(attrs, %User{email: email}) do
|
||||
Map.put(attrs, "contact_email", email)
|
||||
end
|
||||
|
||||
defp maybe_use_user_email(attrs, nil), do: attrs
|
||||
|
||||
defp rate_scope(%User{id: id}, _email), do: "user:#{id}"
|
||||
|
||||
defp rate_scope(nil, email) when is_binary(email),
|
||||
do: "email:#{String.downcase(String.trim(email))}"
|
||||
|
||||
defp rate_scope(nil, _email), do: "missing-email"
|
||||
|
||||
defp scope_user(%Scope{user: %User{} = user}), do: user
|
||||
defp scope_user(_scope), do: nil
|
||||
|
||||
defp enum_value(module, field, value) do
|
||||
Ecto.Enum.cast_value(module, field, value)
|
||||
|> case do
|
||||
{:ok, enum} -> enum
|
||||
:error -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp unique_reference do
|
||||
suffix = 8 |> :crypto.strong_rand_bytes() |> Base.encode32(case: :upper, padding: false)
|
||||
"REM-#{suffix}"
|
||||
end
|
||||
|
||||
defp normalize_keys(attrs), do: Map.new(attrs, fn {key, value} -> {to_string(key), value} end)
|
||||
end
|
||||
177
lib/who_need_help/content_removal/notice.ex
Normal file
177
lib/who_need_help/content_removal/notice.ex
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
defmodule WhoNeedHelp.ContentRemoval.Notice do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
|
||||
schema "content_removal_notices" do
|
||||
field :reference, :string
|
||||
|
||||
field :regime, Ecto.Enum,
|
||||
values: [:general, :dsa, :take_it_down],
|
||||
default: :general
|
||||
|
||||
field :category, Ecto.Enum,
|
||||
values: [
|
||||
:illegal_content,
|
||||
:privacy_violation,
|
||||
:copyright,
|
||||
:impersonation,
|
||||
:non_consensual_intimate_media,
|
||||
:child_sexual_abuse_material,
|
||||
:threat_to_life_or_safety,
|
||||
:other
|
||||
]
|
||||
|
||||
field :status, Ecto.Enum,
|
||||
values: [
|
||||
:open,
|
||||
:urgent_review,
|
||||
:reviewing,
|
||||
:needs_information,
|
||||
:actioned,
|
||||
:rejected,
|
||||
:closed
|
||||
],
|
||||
default: :open
|
||||
|
||||
field :submitter_name, :string
|
||||
field :contact_email, :string
|
||||
|
||||
field :relationship, Ecto.Enum, values: [:self, :authorized_representative, :other]
|
||||
|
||||
field :content_locations, :string
|
||||
field :explanation, :string
|
||||
field :legal_basis, :string
|
||||
field :contact_verified_at, :utc_datetime
|
||||
field :good_faith, :boolean, default: false
|
||||
field :accurate_complete, :boolean, default: false
|
||||
field :electronic_signature, :string
|
||||
field :resolution_note, :string
|
||||
field :reviewed_at, :utc_datetime
|
||||
field :response_due_at, :utc_datetime
|
||||
field :acknowledgement_sent_at, :utc_datetime
|
||||
field :decision_sent_at, :utc_datetime
|
||||
belongs_to :requester, WhoNeedHelp.Accounts.User
|
||||
belongs_to :reviewed_by, WhoNeedHelp.Accounts.User
|
||||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
def submission_changeset(notice, attrs) do
|
||||
notice
|
||||
|> cast(attrs, [
|
||||
:category,
|
||||
:submitter_name,
|
||||
:contact_email,
|
||||
:relationship,
|
||||
:content_locations,
|
||||
:explanation,
|
||||
:legal_basis,
|
||||
:good_faith,
|
||||
:accurate_complete,
|
||||
:electronic_signature
|
||||
])
|
||||
|> validate_required([
|
||||
:category,
|
||||
:content_locations,
|
||||
:explanation,
|
||||
:reference,
|
||||
:regime
|
||||
])
|
||||
|> update_change(:contact_email, &normalize_email/1)
|
||||
|> validate_format(:contact_email, ~r/^[^@,;\s]+@[^@,;\s]+$/,
|
||||
message: "must have the @ sign and no spaces"
|
||||
)
|
||||
|> validate_length(:submitter_name, min: 2, max: 160)
|
||||
|> validate_length(:contact_email, max: 160)
|
||||
|> validate_length(:content_locations, min: 5, max: 10_000)
|
||||
|> validate_length(:explanation, min: 20, max: 10_000)
|
||||
|> validate_length(:legal_basis, max: 2_000)
|
||||
|> validate_length(:electronic_signature, min: 2, max: 160)
|
||||
|> validate_acceptance(:good_faith,
|
||||
message: "you must confirm your good-faith belief"
|
||||
)
|
||||
|> validate_acceptance(:accurate_complete,
|
||||
message: "you must confirm that the notice is accurate and complete"
|
||||
)
|
||||
|> validate_identity_requirements()
|
||||
|> validate_content_locations()
|
||||
|> validate_take_it_down_category()
|
||||
|> unique_constraint(:reference)
|
||||
end
|
||||
|
||||
def moderation_changeset(notice, attrs) do
|
||||
notice
|
||||
|> cast(attrs, [:status, :resolution_note, :reviewed_at, :reviewed_by_id, :decision_sent_at])
|
||||
|> validate_required([:status, :reviewed_at, :reviewed_by_id])
|
||||
|> validate_length(:resolution_note, max: 10_000)
|
||||
end
|
||||
|
||||
def content_urls(%__MODULE__{content_locations: locations}) when is_binary(locations) do
|
||||
locations
|
||||
|> String.split(~r/[\r\n]+/, trim: true)
|
||||
|> Enum.map(&String.trim/1)
|
||||
end
|
||||
|
||||
def content_urls(_notice), do: []
|
||||
|
||||
defp validate_content_locations(changeset) do
|
||||
validate_change(changeset, :content_locations, fn :content_locations, locations ->
|
||||
urls = locations |> String.split(~r/[\r\n]+/, trim: true) |> Enum.map(&String.trim/1)
|
||||
|
||||
cond do
|
||||
urls == [] ->
|
||||
[content_locations: "must contain at least one exact URL"]
|
||||
|
||||
length(urls) > 20 ->
|
||||
[content_locations: "cannot contain more than 20 URLs"]
|
||||
|
||||
Enum.any?(urls, &(not valid_http_url?(&1))) ->
|
||||
[content_locations: "must contain one full HTTP or HTTPS URL per line"]
|
||||
|
||||
true ->
|
||||
[]
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
defp validate_take_it_down_category(changeset) do
|
||||
if get_field(changeset, :regime) == :take_it_down and
|
||||
get_field(changeset, :category) not in [
|
||||
:non_consensual_intimate_media,
|
||||
:child_sexual_abuse_material
|
||||
] do
|
||||
add_error(changeset, :category, "must describe intimate visual material")
|
||||
else
|
||||
changeset
|
||||
end
|
||||
end
|
||||
|
||||
defp validate_identity_requirements(changeset) do
|
||||
if get_field(changeset, :category) == :child_sexual_abuse_material and
|
||||
get_field(changeset, :regime) != :take_it_down do
|
||||
changeset
|
||||
else
|
||||
validate_required(changeset, [
|
||||
:submitter_name,
|
||||
:contact_email,
|
||||
:relationship,
|
||||
:electronic_signature
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
defp valid_http_url?(value) do
|
||||
case URI.parse(value) do
|
||||
%URI{scheme: scheme, host: host}
|
||||
when scheme in ["http", "https"] and is_binary(host) and host != "" ->
|
||||
true
|
||||
|
||||
_ ->
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
defp normalize_email(email), do: email |> String.trim() |> String.downcase()
|
||||
end
|
||||
91
lib/who_need_help/content_removal/notifier.ex
Normal file
91
lib/who_need_help/content_removal/notifier.ex
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
defmodule WhoNeedHelp.ContentRemoval.Notifier do
|
||||
import Swoosh.Email
|
||||
|
||||
alias WhoNeedHelp.ContentRemoval.Notice
|
||||
alias WhoNeedHelp.Mailer
|
||||
|
||||
def deliver_received(%Notice{contact_email: email} = notice, status_url)
|
||||
when is_binary(email) and email != "" do
|
||||
deliver(
|
||||
email,
|
||||
"Who Need Help removal notice #{notice.reference}",
|
||||
"""
|
||||
We received removal notice #{notice.reference}.
|
||||
|
||||
Status: #{notice.status}
|
||||
|
||||
View the current status:
|
||||
#{status_url}
|
||||
|
||||
Do not reply with or upload intimate visual material. If someone is in immediate danger,
|
||||
contact the emergency service for their location.
|
||||
"""
|
||||
)
|
||||
end
|
||||
|
||||
def deliver_received(%Notice{}, _status_url), do: {:ok, :no_contact_email}
|
||||
|
||||
def deliver_decision(%Notice{contact_email: email} = notice, status_url)
|
||||
when is_binary(email) and email != "" do
|
||||
deliver(
|
||||
email,
|
||||
"Who Need Help removal notice update #{notice.reference}",
|
||||
"""
|
||||
Removal notice #{notice.reference} was updated.
|
||||
|
||||
Status: #{notice.status}
|
||||
Decision or request for information:
|
||||
#{notice.resolution_note || "No additional response was provided."}
|
||||
|
||||
View the current status:
|
||||
#{status_url}
|
||||
"""
|
||||
)
|
||||
end
|
||||
|
||||
def deliver_decision(%Notice{}, _status_url), do: {:ok, :no_contact_email}
|
||||
|
||||
def deliver_operator_alert(%Notice{} = notice) do
|
||||
case Application.get_env(:who_need_help, :support_inbox_address) do
|
||||
address when is_binary(address) and address != "" ->
|
||||
urgency = if notice.status == :urgent_review, do: "URGENT: ", else: ""
|
||||
|
||||
deliver(
|
||||
address,
|
||||
"#{urgency}New removal notice #{notice.reference}",
|
||||
"""
|
||||
A new #{notice.regime} content-removal notice is waiting for review.
|
||||
|
||||
Reference: #{notice.reference}
|
||||
Category: #{notice.category}
|
||||
Review due: #{notice.response_due_at || "no statutory deadline recorded"}
|
||||
Operator queue: #{WhoNeedHelpWeb.Endpoint.url()}/support/operations
|
||||
|
||||
Do not request the submitter to email or upload intimate visual material.
|
||||
"""
|
||||
)
|
||||
|
||||
_other ->
|
||||
{:ok, :not_configured}
|
||||
end
|
||||
end
|
||||
|
||||
defp deliver(recipient, subject, body) do
|
||||
from = Application.fetch_env!(:who_need_help, :mailer_from)
|
||||
|
||||
new()
|
||||
|> to(recipient)
|
||||
|> from({from[:name], from[:address]})
|
||||
|> maybe_reply_to()
|
||||
|> subject(subject)
|
||||
|> text_body(body)
|
||||
|> Mailer.deliver()
|
||||
end
|
||||
|
||||
defp maybe_reply_to(email) do
|
||||
case Application.get_env(:who_need_help, :support_inbox_address) do
|
||||
address when is_binary(address) and address != "" -> reply_to(email, address)
|
||||
_other -> email
|
||||
end
|
||||
end
|
||||
end
|
||||
227
lib/who_need_help/support.ex
Normal file
227
lib/who_need_help/support.ex
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
defmodule WhoNeedHelp.Support do
|
||||
@moduledoc "Public and authenticated support, privacy, and account-lifecycle requests."
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
alias WhoNeedHelp.Accounts
|
||||
alias WhoNeedHelp.Accounts.{Scope, User}
|
||||
alias WhoNeedHelp.Pagination
|
||||
alias WhoNeedHelp.Repo
|
||||
alias WhoNeedHelp.Support.{Notifier, SupportRequest}
|
||||
alias WhoNeedHelp.Trust
|
||||
alias WhoNeedHelp.Trust.RateLimiter
|
||||
|
||||
@access_salt "support-request-access"
|
||||
|
||||
def change_request(%SupportRequest{} = request, attrs \\ %{}) do
|
||||
SupportRequest.submission_changeset(request, attrs)
|
||||
end
|
||||
|
||||
def create_request(scope, attrs) when is_map(attrs) do
|
||||
user = scope_user(scope)
|
||||
attrs = normalize_keys(attrs)
|
||||
contact_email = if user, do: user.email, else: attrs["contact_email"]
|
||||
attrs = Map.put(attrs, "contact_email", contact_email)
|
||||
|
||||
with {:ok, _limit} <- RateLimiter.check(:support_request, rate_scope(user, contact_email)) do
|
||||
Repo.transact(fn ->
|
||||
with {:ok, request} <-
|
||||
%SupportRequest{
|
||||
reference: unique_reference("SUP"),
|
||||
requester_id: user && user.id,
|
||||
contact_verified_at: user && DateTime.utc_now(:second)
|
||||
}
|
||||
|> SupportRequest.submission_changeset(attrs)
|
||||
|> Repo.insert(),
|
||||
{:ok, _audit} <-
|
||||
Trust.audit(
|
||||
user && user.id,
|
||||
"support_request.created",
|
||||
"support_request",
|
||||
request.id,
|
||||
%{
|
||||
"kind" => to_string(request.kind)
|
||||
}
|
||||
) do
|
||||
{:ok, request}
|
||||
end
|
||||
end)
|
||||
|> notify_received()
|
||||
end
|
||||
end
|
||||
|
||||
def create_account_deletion_request(%Scope{user: %User{}} = scope, details \\ nil) do
|
||||
create_request(scope, %{
|
||||
"kind" => "account_deletion",
|
||||
"subject" => "Delete my Who Need Help account",
|
||||
"details" => details || "Please delete my account and associated personal data."
|
||||
})
|
||||
end
|
||||
|
||||
def list_for_user(%Scope{user: %User{id: user_id}}) do
|
||||
SupportRequest
|
||||
|> where([request], request.requester_id == ^user_id)
|
||||
|> order_by([request], desc: request.inserted_at, desc: request.id)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
def get_for_user(%Scope{user: %User{id: user_id}}, id) do
|
||||
with {:ok, id} <- Ecto.UUID.cast(id),
|
||||
%SupportRequest{} = request <-
|
||||
Repo.get_by(SupportRequest, id: id, requester_id: user_id) do
|
||||
{:ok, request}
|
||||
else
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def get_by_access_token(id, token) when is_binary(token) do
|
||||
with {:ok, id} <- Ecto.UUID.cast(id),
|
||||
{:ok, ^id} <-
|
||||
Phoenix.Token.verify(WhoNeedHelpWeb.Endpoint, @access_salt, token, max_age: 31_536_000),
|
||||
%SupportRequest{} = request <- Repo.get(SupportRequest, id) do
|
||||
verify_contact(request)
|
||||
else
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
def get_by_access_token(_id, _token), do: {:error, :not_found}
|
||||
|
||||
def access_token(%SupportRequest{id: id}) do
|
||||
Phoenix.Token.sign(WhoNeedHelpWeb.Endpoint, @access_salt, id)
|
||||
end
|
||||
|
||||
def status_url(%SupportRequest{} = request) do
|
||||
token = access_token(request)
|
||||
|
||||
WhoNeedHelpWeb.Endpoint.url() <>
|
||||
"/support/cases/#{request.id}?token=#{URI.encode_www_form(token)}"
|
||||
end
|
||||
|
||||
def paginate_for_staff(%Scope{user: user}, options \\ []) do
|
||||
if Accounts.moderator_authorized?(user) do
|
||||
limit = Pagination.limit(options)
|
||||
cursor = Pagination.cursor(options)
|
||||
|
||||
SupportRequest
|
||||
|> maybe_kind(Keyword.get(options, :kind))
|
||||
|> before(cursor)
|
||||
|> order_by([request], desc: request.inserted_at, desc: request.id)
|
||||
|> limit(^(limit + 1))
|
||||
|> preload([:requester, :reviewed_by])
|
||||
|> Repo.all()
|
||||
|> Pagination.page(limit, &{&1.inserted_at, &1.id})
|
||||
else
|
||||
%Pagination.Page{}
|
||||
end
|
||||
end
|
||||
|
||||
def moderate(%Scope{user: moderator}, id, attrs) do
|
||||
with {:ok, id} <- Ecto.UUID.cast(id),
|
||||
true <- Accounts.moderator_authorized?(moderator) do
|
||||
attrs =
|
||||
attrs
|
||||
|> normalize_keys()
|
||||
|> Map.merge(%{
|
||||
"reviewed_at" => DateTime.utc_now(:second),
|
||||
"reviewed_by_id" => moderator.id
|
||||
})
|
||||
|
||||
Repo.transact(fn ->
|
||||
request =
|
||||
SupportRequest
|
||||
|> where([request], request.id == ^id)
|
||||
|> lock("FOR UPDATE")
|
||||
|> Repo.one()
|
||||
|
||||
if request do
|
||||
with {:ok, request} <-
|
||||
request |> SupportRequest.moderation_changeset(attrs) |> Repo.update(),
|
||||
{:ok, _audit} <-
|
||||
Trust.audit(
|
||||
moderator.id,
|
||||
"support_request.moderated",
|
||||
"support_request",
|
||||
request.id,
|
||||
%{
|
||||
"status" => to_string(request.status)
|
||||
}
|
||||
) do
|
||||
{:ok, request}
|
||||
end
|
||||
else
|
||||
{:error, :not_found}
|
||||
end
|
||||
end)
|
||||
|> notify_decision()
|
||||
else
|
||||
false -> {:error, :forbidden}
|
||||
_ -> {:error, :not_found}
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_received({:ok, request}) do
|
||||
_ = Notifier.deliver_received(request, status_url(request))
|
||||
_ = Notifier.deliver_operator_alert(request)
|
||||
{:ok, request}
|
||||
end
|
||||
|
||||
defp notify_received(result), do: result
|
||||
|
||||
defp notify_decision({:ok, %SupportRequest{contact_verified_at: nil} = request}),
|
||||
do: {:ok, request}
|
||||
|
||||
defp notify_decision({:ok, request}) do
|
||||
case Notifier.deliver_decision(request, status_url(request)) do
|
||||
{:ok, _metadata} ->
|
||||
request
|
||||
|> Ecto.Changeset.change(response_sent_at: DateTime.utc_now(:second))
|
||||
|> Repo.update()
|
||||
|
||||
_error ->
|
||||
{:ok, request}
|
||||
end
|
||||
end
|
||||
|
||||
defp notify_decision(result), do: result
|
||||
|
||||
defp verify_contact(%SupportRequest{contact_verified_at: nil} = request) do
|
||||
request
|
||||
|> Ecto.Changeset.change(contact_verified_at: DateTime.utc_now(:second))
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
defp verify_contact(%SupportRequest{} = request), do: {:ok, request}
|
||||
|
||||
defp before(query, nil), do: query
|
||||
|
||||
defp before(query, {inserted_at, id}) do
|
||||
where(
|
||||
query,
|
||||
[request],
|
||||
request.inserted_at < ^inserted_at or
|
||||
(request.inserted_at == ^inserted_at and request.id < ^id)
|
||||
)
|
||||
end
|
||||
|
||||
defp maybe_kind(query, nil), do: query
|
||||
defp maybe_kind(query, kind), do: where(query, [request], request.kind == ^kind)
|
||||
|
||||
defp rate_scope(%User{id: id}, _email), do: "user:#{id}"
|
||||
|
||||
defp rate_scope(nil, email) when is_binary(email),
|
||||
do: "email:#{String.downcase(String.trim(email))}"
|
||||
|
||||
defp rate_scope(nil, _email), do: "missing-email"
|
||||
|
||||
defp scope_user(%Scope{user: %User{} = user}), do: user
|
||||
defp scope_user(_scope), do: nil
|
||||
|
||||
defp unique_reference(prefix) do
|
||||
suffix = 8 |> :crypto.strong_rand_bytes() |> Base.encode32(case: :upper, padding: false)
|
||||
"#{prefix}-#{suffix}"
|
||||
end
|
||||
|
||||
defp normalize_keys(attrs), do: Map.new(attrs, fn {key, value} -> {to_string(key), value} end)
|
||||
end
|
||||
81
lib/who_need_help/support/notifier.ex
Normal file
81
lib/who_need_help/support/notifier.ex
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
defmodule WhoNeedHelp.Support.Notifier do
|
||||
import Swoosh.Email
|
||||
|
||||
alias WhoNeedHelp.Mailer
|
||||
alias WhoNeedHelp.Support.SupportRequest
|
||||
|
||||
def deliver_received(%SupportRequest{} = request, status_url) do
|
||||
deliver(
|
||||
request.contact_email,
|
||||
"Who Need Help support request #{request.reference}",
|
||||
"""
|
||||
We received your support request #{request.reference}.
|
||||
|
||||
Subject: #{request.subject}
|
||||
Status: #{request.status}
|
||||
|
||||
View the current status:
|
||||
#{status_url}
|
||||
|
||||
If there is immediate danger, contact the emergency service for your location.
|
||||
"""
|
||||
)
|
||||
end
|
||||
|
||||
def deliver_decision(%SupportRequest{} = request, status_url) do
|
||||
deliver(
|
||||
request.contact_email,
|
||||
"Who Need Help support update #{request.reference}",
|
||||
"""
|
||||
Your support request #{request.reference} was updated.
|
||||
|
||||
Status: #{request.status}
|
||||
Response:
|
||||
#{request.resolution_note || "No additional response was provided."}
|
||||
|
||||
View the current status:
|
||||
#{status_url}
|
||||
"""
|
||||
)
|
||||
end
|
||||
|
||||
def deliver_operator_alert(%SupportRequest{} = request) do
|
||||
case Application.get_env(:who_need_help, :support_inbox_address) do
|
||||
address when is_binary(address) and address != "" ->
|
||||
deliver(
|
||||
address,
|
||||
"New support request #{request.reference}",
|
||||
"""
|
||||
A new #{request.kind} support request is waiting for review.
|
||||
|
||||
Reference: #{request.reference}
|
||||
Operator queue: #{WhoNeedHelpWeb.Endpoint.url()}/support/operations
|
||||
|
||||
Sign in with an authorised moderator or administrator account to review it.
|
||||
"""
|
||||
)
|
||||
|
||||
_other ->
|
||||
{:ok, :not_configured}
|
||||
end
|
||||
end
|
||||
|
||||
defp deliver(recipient, subject, body) do
|
||||
from = Application.fetch_env!(:who_need_help, :mailer_from)
|
||||
|
||||
new()
|
||||
|> to(recipient)
|
||||
|> from({from[:name], from[:address]})
|
||||
|> maybe_reply_to()
|
||||
|> subject(subject)
|
||||
|> text_body(body)
|
||||
|> Mailer.deliver()
|
||||
end
|
||||
|
||||
defp maybe_reply_to(email) do
|
||||
case Application.get_env(:who_need_help, :support_inbox_address) do
|
||||
address when is_binary(address) and address != "" -> reply_to(email, address)
|
||||
_other -> email
|
||||
end
|
||||
end
|
||||
end
|
||||
61
lib/who_need_help/support/support_request.ex
Normal file
61
lib/who_need_help/support/support_request.ex
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
defmodule WhoNeedHelp.Support.SupportRequest do
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
@primary_key {:id, :binary_id, autogenerate: true}
|
||||
@foreign_key_type :binary_id
|
||||
|
||||
schema "support_requests" do
|
||||
field :reference, :string
|
||||
|
||||
field :kind, Ecto.Enum,
|
||||
values: [
|
||||
:account_access,
|
||||
:technical_issue,
|
||||
:safety_concern,
|
||||
:moderation_appeal,
|
||||
:account_deletion,
|
||||
:data_export,
|
||||
:privacy_request,
|
||||
:other
|
||||
]
|
||||
|
||||
field :status, Ecto.Enum,
|
||||
values: [:open, :reviewing, :waiting_for_requester, :resolved, :closed],
|
||||
default: :open
|
||||
|
||||
field :contact_email, :string
|
||||
field :subject, :string
|
||||
field :details, :string
|
||||
field :contact_verified_at, :utc_datetime
|
||||
field :resolution_note, :string
|
||||
field :reviewed_at, :utc_datetime
|
||||
field :response_sent_at, :utc_datetime
|
||||
belongs_to :requester, WhoNeedHelp.Accounts.User
|
||||
belongs_to :reviewed_by, WhoNeedHelp.Accounts.User
|
||||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
def submission_changeset(request, attrs) do
|
||||
request
|
||||
|> cast(attrs, [:kind, :contact_email, :subject, :details])
|
||||
|> validate_required([:kind, :contact_email, :subject, :details, :reference])
|
||||
|> update_change(:contact_email, &normalize_email/1)
|
||||
|> validate_format(:contact_email, ~r/^[^@,;\s]+@[^@,;\s]+$/,
|
||||
message: "must have the @ sign and no spaces"
|
||||
)
|
||||
|> validate_length(:contact_email, max: 160)
|
||||
|> validate_length(:subject, min: 3, max: 160)
|
||||
|> validate_length(:details, min: 10, max: 5_000)
|
||||
|> unique_constraint(:reference)
|
||||
end
|
||||
|
||||
def moderation_changeset(request, attrs) do
|
||||
request
|
||||
|> cast(attrs, [:status, :resolution_note, :reviewed_at, :reviewed_by_id, :response_sent_at])
|
||||
|> validate_required([:status, :reviewed_at, :reviewed_by_id])
|
||||
|> validate_length(:resolution_note, max: 5_000)
|
||||
end
|
||||
|
||||
defp normalize_email(email), do: email |> String.trim() |> String.downcase()
|
||||
end
|
||||
|
|
@ -144,6 +144,10 @@ defmodule WhoNeedHelpWeb.Layouts do
|
|||
<footer class="border-t border-base-300 px-4 py-6 text-center text-xs text-base-content/70">
|
||||
<.link href={~p"/safety"} class="link">{gettext("Safety rules")}</.link>
|
||||
<span class="mx-2">·</span>
|
||||
<.link href={~p"/support"} class="link">{gettext("Support")}</.link>
|
||||
<span class="mx-2">·</span>
|
||||
<.link href={~p"/legal/content-removal"} class="link">{gettext("Report content")}</.link>
|
||||
<span class="mx-2">·</span>
|
||||
<.link href={~p"/feedback"} class="link">{gettext("Build Week feedback")}</.link>
|
||||
</footer>
|
||||
|
||||
|
|
@ -181,6 +185,11 @@ defmodule WhoNeedHelpWeb.Layouts do
|
|||
{gettext("Moderation")}
|
||||
</.link>
|
||||
</li>
|
||||
<li :if={@current_scope && @current_scope.user.role in [:moderator, :admin]}>
|
||||
<.link navigate={~p"/support/operations"} class={["btn-warning", @link_class]}>
|
||||
{gettext("Support queue")}
|
||||
</.link>
|
||||
</li>
|
||||
"""
|
||||
end
|
||||
|
||||
|
|
|
|||
103
lib/who_need_help_web/controllers/content_removal_controller.ex
Normal file
103
lib/who_need_help_web/controllers/content_removal_controller.ex
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
defmodule WhoNeedHelpWeb.ContentRemovalController do
|
||||
use WhoNeedHelpWeb, :controller
|
||||
|
||||
alias WhoNeedHelp.ContentRemoval
|
||||
alias WhoNeedHelp.ContentRemoval.Notice
|
||||
|
||||
def new(conn, params) do
|
||||
attrs =
|
||||
case internal_location(params["location"]) do
|
||||
nil -> %{}
|
||||
location -> %{"content_locations" => location}
|
||||
end
|
||||
|
||||
render_form(conn, :general, %Notice{}, attrs)
|
||||
end
|
||||
|
||||
def take_it_down(conn, _params), do: render_form(conn, :take_it_down, %Notice{}, %{})
|
||||
|
||||
def create(conn, %{"notice" => params}) when is_map(params),
|
||||
do: create_notice(conn, :general, params)
|
||||
|
||||
def create(conn, _params), do: send_resp(conn, :bad_request, "Bad Request")
|
||||
|
||||
def create_take_it_down(conn, %{"notice" => params}) when is_map(params),
|
||||
do: create_notice(conn, :take_it_down, params)
|
||||
|
||||
def create_take_it_down(conn, _params),
|
||||
do: send_resp(conn, :bad_request, "Bad Request")
|
||||
|
||||
def show(conn, %{"id" => id, "token" => token}) do
|
||||
case ContentRemoval.get_by_access_token(id, token) do
|
||||
{:ok, notice} -> render(conn, :show, notice: notice)
|
||||
{:error, :not_found} -> send_resp(conn, :not_found, "Not found")
|
||||
end
|
||||
end
|
||||
|
||||
def show(conn, _params), do: send_resp(conn, :not_found, "Not found")
|
||||
|
||||
defp create_notice(conn, regime, params) do
|
||||
case ContentRemoval.create_notice(conn.assigns.current_scope, regime, params) do
|
||||
{:ok, notice} ->
|
||||
redirect(conn,
|
||||
to: ~p"/legal/content-removal/received?reference=#{notice.reference}"
|
||||
)
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render_form(regime, changeset, params)
|
||||
|
||||
{:error, :rate_limited} ->
|
||||
conn
|
||||
|> put_status(:too_many_requests)
|
||||
|> put_flash(:error, gettext("Too many removal notices. Please try again later."))
|
||||
|> render_form(regime, %Notice{}, params)
|
||||
end
|
||||
end
|
||||
|
||||
def received(conn, %{"reference" => reference}) when is_binary(reference) do
|
||||
render(conn, :received, reference: String.slice(reference, 0, 64))
|
||||
end
|
||||
|
||||
def received(conn, _params), do: redirect(conn, to: ~p"/legal/content-removal")
|
||||
|
||||
defp render_form(conn, regime, %Ecto.Changeset{} = changeset, _attrs) do
|
||||
render(conn, form_template(regime),
|
||||
form: Phoenix.Component.to_form(changeset, as: :notice),
|
||||
contact_email: current_email(conn)
|
||||
)
|
||||
end
|
||||
|
||||
defp render_form(conn, regime, %Notice{} = notice, attrs) do
|
||||
attrs = with_contact_email(conn, attrs)
|
||||
notice = %{notice | regime: regime}
|
||||
changeset = ContentRemoval.change_notice(notice, attrs)
|
||||
render_form(conn, regime, changeset, attrs)
|
||||
end
|
||||
|
||||
defp form_template(:take_it_down), do: :take_it_down
|
||||
defp form_template(_regime), do: :new
|
||||
|
||||
defp with_contact_email(conn, attrs) do
|
||||
case current_email(conn) do
|
||||
nil -> attrs
|
||||
email -> Map.put(attrs, "contact_email", email)
|
||||
end
|
||||
end
|
||||
|
||||
defp current_email(%{assigns: %{current_scope: %{user: %{email: email}}}}), do: email
|
||||
defp current_email(_conn), do: nil
|
||||
|
||||
defp internal_location(value) when is_binary(value) do
|
||||
uri = URI.parse(value)
|
||||
|
||||
if uri.scheme == nil and uri.host == nil and is_binary(uri.path) and
|
||||
String.starts_with?(uri.path, "/") and not String.starts_with?(uri.path, "//") and
|
||||
not String.contains?(value, ["\r", "\n"]) do
|
||||
WhoNeedHelpWeb.Endpoint.url() <> value
|
||||
end
|
||||
end
|
||||
|
||||
defp internal_location(_value), do: nil
|
||||
end
|
||||
29
lib/who_need_help_web/controllers/content_removal_html.ex
Normal file
29
lib/who_need_help_web/controllers/content_removal_html.ex
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
defmodule WhoNeedHelpWeb.ContentRemovalHTML do
|
||||
use WhoNeedHelpWeb, :html
|
||||
|
||||
embed_templates "content_removal_html/*"
|
||||
|
||||
def category_label(:illegal_content), do: gettext("Illegal content")
|
||||
def category_label(:privacy_violation), do: gettext("Privacy violation")
|
||||
def category_label(:copyright), do: gettext("Copyright")
|
||||
def category_label(:impersonation), do: gettext("Impersonation")
|
||||
|
||||
def category_label(:non_consensual_intimate_media),
|
||||
do: gettext("Non-consensual intimate image or video")
|
||||
|
||||
def category_label(:child_sexual_abuse_material),
|
||||
do: gettext("Sexual material involving a minor")
|
||||
|
||||
def category_label(:threat_to_life_or_safety), do: gettext("Threat to life or safety")
|
||||
def category_label(:other), do: gettext("Other")
|
||||
def category_label(value), do: to_string(value)
|
||||
|
||||
def status_label(:open), do: gettext("Open")
|
||||
def status_label(:urgent_review), do: gettext("Urgent review")
|
||||
def status_label(:reviewing), do: gettext("Reviewing")
|
||||
def status_label(:needs_information), do: gettext("More information needed")
|
||||
def status_label(:actioned), do: gettext("Action taken")
|
||||
def status_label(:rejected), do: gettext("Rejected")
|
||||
def status_label(:closed), do: gettext("Closed")
|
||||
def status_label(value), do: to_string(value)
|
||||
end
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="text-sm font-semibold text-error">{gettext("CONTENT REMOVAL")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">{gettext("Report illegal or harmful content")}</h1>
|
||||
<p class="mt-3 text-base-content/65">
|
||||
{gettext(
|
||||
"Use this electronic notice for specific content on Who Need Help that you believe is illegal or infringes your rights. Ordinary safety reports inside a request or chat remain available to signed-in users."
|
||||
)}
|
||||
</p>
|
||||
<div class="alert alert-info mt-5 text-sm">
|
||||
{gettext(
|
||||
"Provide exact Who Need Help URLs. Do not upload or paste intimate imagery, identity documents, passwords, access codes, or unnecessary medical information."
|
||||
)}
|
||||
</div>
|
||||
|
||||
<.form for={@form} action={~p"/legal/content-removal"} class="mt-8 space-y-4">
|
||||
<.input
|
||||
field={@form[:category]}
|
||||
type="select"
|
||||
label={gettext("Reason")}
|
||||
options={[
|
||||
{gettext("Illegal content"), "illegal_content"},
|
||||
{gettext("Privacy violation"), "privacy_violation"},
|
||||
{gettext("Copyright"), "copyright"},
|
||||
{gettext("Impersonation"), "impersonation"},
|
||||
{gettext("Non-consensual intimate image or video"), "non_consensual_intimate_media"},
|
||||
{gettext("Sexual material involving a minor"), "child_sexual_abuse_material"},
|
||||
{gettext("Threat to life or safety"), "threat_to_life_or_safety"},
|
||||
{gettext("Other"), "other"}
|
||||
]}
|
||||
prompt={gettext("Choose a reason")}
|
||||
required
|
||||
/>
|
||||
<.input field={@form[:submitter_name]} label={gettext("Your name or organisation")} />
|
||||
<.input
|
||||
field={@form[:contact_email]}
|
||||
type="email"
|
||||
label={gettext("Contact email")}
|
||||
value={@contact_email || @form[:contact_email].value}
|
||||
readonly={not is_nil(@contact_email)}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:relationship]}
|
||||
type="select"
|
||||
label={gettext("Your relationship to the affected person or rights holder")}
|
||||
options={[
|
||||
{gettext("I am the affected person or rights holder"), "self"},
|
||||
{gettext("I am an authorised representative"), "authorized_representative"},
|
||||
{gettext("Other"), "other"}
|
||||
]}
|
||||
prompt={gettext("Choose a relationship")}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:content_locations]}
|
||||
type="textarea"
|
||||
label={gettext("Exact content URLs — one per line")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:explanation]}
|
||||
type="textarea"
|
||||
label={gettext("Why do you believe this content should be removed?")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:legal_basis]}
|
||||
type="textarea"
|
||||
label={gettext("Law, right, or policy involved, if known")}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:electronic_signature]}
|
||||
label={gettext("Electronic signature (type your full name)")}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:good_faith]}
|
||||
type="checkbox"
|
||||
label={
|
||||
gettext(
|
||||
"I believe in good faith that the identified content is illegal or infringes the stated right."
|
||||
)
|
||||
}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:accurate_complete]}
|
||||
type="checkbox"
|
||||
label={
|
||||
gettext(
|
||||
"I confirm that this notice is accurate and complete to the best of my knowledge."
|
||||
)
|
||||
}
|
||||
/>
|
||||
<p class="text-xs text-base-content/55">
|
||||
{gettext(
|
||||
"Identity and contact fields may be omitted for reports of sexual material involving a minor. Do not include or upload the material itself."
|
||||
)}
|
||||
</p>
|
||||
<.button class="btn btn-error w-full">{gettext("Submit removal notice")}</.button>
|
||||
</.form>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-xl text-center">
|
||||
<div class="text-sm font-semibold text-success">{gettext("NOTICE RECEIVED")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">
|
||||
{gettext("Your reference is %{reference}", reference: @reference)}
|
||||
</h1>
|
||||
<p class="mt-4 text-base-content/65">
|
||||
{gettext(
|
||||
"A private status link has been sent when a contact email was provided and delivery is configured. Opening that link verifies the contact address. Keep the reference for follow-up."
|
||||
)}
|
||||
</p>
|
||||
<.link navigate={~p"/legal/content-removal"} class="btn btn-primary mt-7">
|
||||
{gettext("Back to removal form")}
|
||||
</.link>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="badge badge-outline">{@notice.reference}</span>
|
||||
<span class={[
|
||||
"badge",
|
||||
@notice.status == :urgent_review && "badge-error",
|
||||
@notice.status != :urgent_review && "badge-primary"
|
||||
]}>
|
||||
{status_label(@notice.status)}
|
||||
</span>
|
||||
</div>
|
||||
<h1 class="mt-4 text-3xl font-black">{gettext("Content-removal notice")}</h1>
|
||||
<p class="mt-2 text-sm text-base-content/55">{category_label(@notice.category)}</p>
|
||||
<section class="mt-6 rounded-2xl bg-base-200 p-5">
|
||||
<h2 class="font-bold">{gettext("Reported locations")}</h2>
|
||||
<ul class="mt-3 list-disc space-y-1 pl-5 text-sm">
|
||||
<li
|
||||
:for={url <- WhoNeedHelp.ContentRemoval.Notice.content_urls(@notice)}
|
||||
class="break-all"
|
||||
>
|
||||
{url}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section
|
||||
:if={@notice.resolution_note not in [nil, ""]}
|
||||
class="mt-5 rounded-2xl border border-primary/30 p-5"
|
||||
>
|
||||
<h2 class="font-bold">{gettext("Decision or request for information")}</h2>
|
||||
<p class="mt-2 whitespace-pre-wrap">{@notice.resolution_note}</p>
|
||||
</section>
|
||||
<p class="mt-5 text-xs text-base-content/55">
|
||||
{gettext(
|
||||
"Keep this status link private. The submitter identity is not shown publicly or automatically disclosed to the person who posted the reported content."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="text-sm font-semibold text-error">{gettext("TAKE IT DOWN")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">
|
||||
{gettext("Request removal of intimate visual material")}
|
||||
</h1>
|
||||
<p class="mt-3 text-base-content/65">
|
||||
{gettext(
|
||||
"Use this dedicated process when an identifiable person is shown in an intimate image or video shared without consent, including a digital forgery. You may submit for yourself or as an authorised representative."
|
||||
)}
|
||||
</p>
|
||||
<div class="alert alert-error mt-5 text-sm font-semibold">
|
||||
{gettext(
|
||||
"Do not upload the image or video. Provide only the exact Who Need Help URL where it appears and enough text to identify it safely."
|
||||
)}
|
||||
</div>
|
||||
|
||||
<.form for={@form} action={~p"/legal/take-it-down"} class="mt-8 space-y-4">
|
||||
<.input
|
||||
field={@form[:category]}
|
||||
type="select"
|
||||
label={gettext("Material involved")}
|
||||
options={[
|
||||
{gettext("Non-consensual intimate image or video"), "non_consensual_intimate_media"},
|
||||
{gettext("Sexual material involving a minor"), "child_sexual_abuse_material"}
|
||||
]}
|
||||
prompt={gettext("Choose a category")}
|
||||
required
|
||||
/>
|
||||
<.input field={@form[:submitter_name]} label={gettext("Your full name")} required />
|
||||
<.input
|
||||
field={@form[:contact_email]}
|
||||
type="email"
|
||||
label={gettext("Contact email")}
|
||||
value={@contact_email || @form[:contact_email].value}
|
||||
readonly={not is_nil(@contact_email)}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:relationship]}
|
||||
type="select"
|
||||
label={gettext("Who are you submitting for?")}
|
||||
options={[
|
||||
{gettext("Myself"), "self"},
|
||||
{gettext("A person I am authorised to represent"), "authorized_representative"}
|
||||
]}
|
||||
prompt={gettext("Choose a relationship")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:content_locations]}
|
||||
type="textarea"
|
||||
label={gettext("Exact content URLs — one per line")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:explanation]}
|
||||
type="textarea"
|
||||
label={
|
||||
gettext(
|
||||
"Identify the material without reproducing it and explain why it is non-consensual"
|
||||
)
|
||||
}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:electronic_signature]}
|
||||
label={gettext("Electronic signature (type your full name)")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:good_faith]}
|
||||
type="checkbox"
|
||||
label={
|
||||
gettext(
|
||||
"I have a good-faith belief that this intimate visual material was shared without consent."
|
||||
)
|
||||
}
|
||||
/>
|
||||
<.input
|
||||
field={@form[:accurate_complete]}
|
||||
type="checkbox"
|
||||
label={
|
||||
gettext(
|
||||
"I confirm that the information in this request is accurate and that I am the depicted person or authorised to act for them."
|
||||
)
|
||||
}
|
||||
/>
|
||||
<.button class="btn btn-error w-full">{gettext("Submit urgent removal request")}</.button>
|
||||
</.form>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
128
lib/who_need_help_web/controllers/support_controller.ex
Normal file
128
lib/who_need_help_web/controllers/support_controller.ex
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
defmodule WhoNeedHelpWeb.SupportController do
|
||||
use WhoNeedHelpWeb, :controller
|
||||
|
||||
alias WhoNeedHelp.Support
|
||||
alias WhoNeedHelp.Support.SupportRequest
|
||||
|
||||
def index(conn, _params) do
|
||||
requests =
|
||||
case conn.assigns.current_scope do
|
||||
nil -> []
|
||||
scope -> Support.list_for_user(scope)
|
||||
end
|
||||
|
||||
render(conn, :index, requests: requests)
|
||||
end
|
||||
|
||||
def new(conn, _params) do
|
||||
render_form(conn, %SupportRequest{}, %{}, :new)
|
||||
end
|
||||
|
||||
def create(conn, %{"support_request" => params}) when is_map(params) do
|
||||
case Support.create_request(conn.assigns.current_scope, params) do
|
||||
{:ok, request} ->
|
||||
redirect(conn, to: ~p"/support/received?reference=#{request.reference}")
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render_form(changeset, %{}, :new)
|
||||
|
||||
{:error, :rate_limited} ->
|
||||
conn
|
||||
|> put_status(:too_many_requests)
|
||||
|> put_flash(:error, gettext("Too many support requests. Please try again later."))
|
||||
|> render_form(%SupportRequest{}, params, :new)
|
||||
end
|
||||
end
|
||||
|
||||
def create(conn, _params), do: send_resp(conn, :bad_request, "Bad Request")
|
||||
|
||||
def delete_account(conn, _params) do
|
||||
render_form(
|
||||
conn,
|
||||
%SupportRequest{},
|
||||
%{
|
||||
"kind" => "account_deletion",
|
||||
"subject" => gettext("Delete my Who Need Help account"),
|
||||
"details" => gettext("Please delete my account and associated personal data.")
|
||||
},
|
||||
:delete_account
|
||||
)
|
||||
end
|
||||
|
||||
def request_account_deletion(conn, %{"support_request" => params}) when is_map(params) do
|
||||
params =
|
||||
params
|
||||
|> Map.put("kind", "account_deletion")
|
||||
|> Map.put("subject", gettext("Delete my Who Need Help account"))
|
||||
|
||||
case Support.create_request(conn.assigns.current_scope, params) do
|
||||
{:ok, request} ->
|
||||
redirect(conn, to: ~p"/support/received?reference=#{request.reference}")
|
||||
|
||||
{:error, %Ecto.Changeset{} = changeset} ->
|
||||
conn
|
||||
|> put_status(:unprocessable_entity)
|
||||
|> render_form(changeset, params, :delete_account)
|
||||
|
||||
{:error, :rate_limited} ->
|
||||
conn
|
||||
|> put_status(:too_many_requests)
|
||||
|> put_flash(:error, gettext("Too many support requests. Please try again later."))
|
||||
|> render_form(%SupportRequest{}, params, :delete_account)
|
||||
end
|
||||
end
|
||||
|
||||
def request_account_deletion(conn, _params),
|
||||
do: send_resp(conn, :bad_request, "Bad Request")
|
||||
|
||||
def show(conn, %{"id" => id} = params) do
|
||||
token = params["token"]
|
||||
|
||||
result =
|
||||
case conn.assigns.current_scope do
|
||||
nil ->
|
||||
Support.get_by_access_token(id, token)
|
||||
|
||||
scope ->
|
||||
case Support.get_for_user(scope, id) do
|
||||
{:ok, request} -> {:ok, request}
|
||||
_ -> Support.get_by_access_token(id, token)
|
||||
end
|
||||
end
|
||||
|
||||
case result do
|
||||
{:ok, request} -> render(conn, :show, request: request)
|
||||
{:error, :not_found} -> send_resp(conn, :not_found, "Not found")
|
||||
end
|
||||
end
|
||||
|
||||
def received(conn, %{"reference" => reference}) when is_binary(reference) do
|
||||
render(conn, :received, reference: String.slice(reference, 0, 64))
|
||||
end
|
||||
|
||||
def received(conn, _params), do: redirect(conn, to: ~p"/support")
|
||||
|
||||
defp render_form(conn, %Ecto.Changeset{} = changeset, _attrs, page) do
|
||||
render(conn, page,
|
||||
form: Phoenix.Component.to_form(changeset, as: :support_request),
|
||||
contact_email: current_email(conn)
|
||||
)
|
||||
end
|
||||
|
||||
defp render_form(conn, %SupportRequest{} = request, attrs, page) do
|
||||
changeset = Support.change_request(request, with_contact_email(conn, attrs))
|
||||
render_form(conn, changeset, attrs, page)
|
||||
end
|
||||
|
||||
defp with_contact_email(conn, attrs) do
|
||||
case current_email(conn) do
|
||||
nil -> attrs
|
||||
email -> Map.put(attrs, "contact_email", email)
|
||||
end
|
||||
end
|
||||
|
||||
defp current_email(%{assigns: %{current_scope: %{user: %{email: email}}}}), do: email
|
||||
defp current_email(_conn), do: nil
|
||||
end
|
||||
22
lib/who_need_help_web/controllers/support_html.ex
Normal file
22
lib/who_need_help_web/controllers/support_html.ex
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
defmodule WhoNeedHelpWeb.SupportHTML do
|
||||
use WhoNeedHelpWeb, :html
|
||||
|
||||
embed_templates "support_html/*"
|
||||
|
||||
def kind_label(:account_access), do: gettext("Account access")
|
||||
def kind_label(:technical_issue), do: gettext("Technical issue")
|
||||
def kind_label(:safety_concern), do: gettext("Safety concern")
|
||||
def kind_label(:moderation_appeal), do: gettext("Moderation appeal")
|
||||
def kind_label(:account_deletion), do: gettext("Account deletion")
|
||||
def kind_label(:data_export), do: gettext("Data export")
|
||||
def kind_label(:privacy_request), do: gettext("Privacy request")
|
||||
def kind_label(:other), do: gettext("Other")
|
||||
def kind_label(value), do: to_string(value)
|
||||
|
||||
def status_label(:open), do: gettext("Open")
|
||||
def status_label(:reviewing), do: gettext("Reviewing")
|
||||
def status_label(:waiting_for_requester), do: gettext("Waiting for your response")
|
||||
def status_label(:resolved), do: gettext("Resolved")
|
||||
def status_label(:closed), do: gettext("Closed")
|
||||
def status_label(value), do: to_string(value)
|
||||
end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="text-sm font-semibold text-error">{gettext("ACCOUNT AND DATA")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">{gettext("Request account deletion")}</h1>
|
||||
<p class="mt-3 text-base-content/65">
|
||||
{gettext(
|
||||
"This requests deletion of your Who Need Help account and associated personal data. Some records may need to be retained when required for safety, fraud prevention, legal obligations, or resolving an active dispute; any retained data must be described in the applicable retention notice."
|
||||
)}
|
||||
</p>
|
||||
<div class="alert alert-warning mt-5 text-sm">
|
||||
{gettext(
|
||||
"Submitting this form does not immediately sign you out or erase evidence required for an open safety investigation. Support will verify and process the request."
|
||||
)}
|
||||
</div>
|
||||
|
||||
<.form for={@form} action={~p"/account/delete"} class="mt-8 space-y-4">
|
||||
<input type="hidden" name="support_request[kind]" value="account_deletion" />
|
||||
<input
|
||||
type="hidden"
|
||||
name="support_request[subject]"
|
||||
value="Delete my Who Need Help account"
|
||||
/>
|
||||
<.input
|
||||
field={@form[:contact_email]}
|
||||
type="email"
|
||||
label={gettext("Account email")}
|
||||
value={@contact_email || @form[:contact_email].value}
|
||||
readonly={not is_nil(@contact_email)}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:details]}
|
||||
type="textarea"
|
||||
label={gettext("Additional information")}
|
||||
required
|
||||
/>
|
||||
<.button class="btn btn-error w-full">{gettext("Request account deletion")}</.button>
|
||||
</.form>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-4xl">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div>
|
||||
<h1 class="mt-1 text-4xl font-black">{gettext("Your requests")}</h1>
|
||||
</div>
|
||||
<.link navigate={~p"/support/new"} class="btn btn-primary">{gettext("New request")}</.link>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 space-y-3">
|
||||
<.link
|
||||
:for={request <- @requests}
|
||||
navigate={~p"/support/cases/#{request.id}"}
|
||||
class="block rounded-2xl border border-base-300 p-5 transition hover:border-primary"
|
||||
>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="badge badge-outline">{request.reference}</span>
|
||||
<span class="badge badge-primary">{status_label(request.status)}</span>
|
||||
<span class="text-xs text-base-content/55">{kind_label(request.kind)}</span>
|
||||
</div>
|
||||
<h2 class="mt-3 font-bold">{request.subject}</h2>
|
||||
<time class="mt-1 block text-xs text-base-content/50">{request.inserted_at}</time>
|
||||
</.link>
|
||||
<p :if={@requests == []} class="rounded-2xl bg-base-200 p-6 text-base-content/60">
|
||||
{gettext("You have not submitted any support requests.")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
63
lib/who_need_help_web/controllers/support_html/new.html.heex
Normal file
63
lib/who_need_help_web/controllers/support_html/new.html.heex
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="text-sm font-semibold text-primary">{gettext("SUPPORT")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">{gettext("Contact Who Need Help")}</h1>
|
||||
<p class="mt-3 text-base-content/65">
|
||||
{gettext(
|
||||
"Use this form for account access, technical problems, privacy questions, or other support. For illegal content or a removal request, use the dedicated removal form."
|
||||
)}
|
||||
</p>
|
||||
|
||||
<div class="mt-5 flex flex-wrap gap-2">
|
||||
<.link navigate={~p"/legal/content-removal"} class="btn btn-outline btn-sm">
|
||||
{gettext("Report content")}
|
||||
</.link>
|
||||
<.link navigate={~p"/legal/take-it-down"} class="btn btn-outline btn-sm">
|
||||
{gettext("TAKE IT DOWN request")}
|
||||
</.link>
|
||||
<.link navigate={~p"/account/delete"} class="btn btn-outline btn-sm">
|
||||
{gettext("Delete an account")}
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<.form for={@form} action={~p"/support"} class="mt-8 space-y-4">
|
||||
<.input
|
||||
field={@form[:kind]}
|
||||
type="select"
|
||||
label={gettext("What do you need help with?")}
|
||||
options={[
|
||||
{gettext("Account access"), "account_access"},
|
||||
{gettext("Technical issue"), "technical_issue"},
|
||||
{gettext("Safety concern"), "safety_concern"},
|
||||
{gettext("Appeal a moderation decision"), "moderation_appeal"},
|
||||
{gettext("Privacy request"), "privacy_request"},
|
||||
{gettext("Data export"), "data_export"},
|
||||
{gettext("Other"), "other"}
|
||||
]}
|
||||
prompt={gettext("Choose a topic")}
|
||||
required
|
||||
/>
|
||||
<.input
|
||||
field={@form[:contact_email]}
|
||||
type="email"
|
||||
label={gettext("Contact email")}
|
||||
value={@contact_email || @form[:contact_email].value}
|
||||
readonly={not is_nil(@contact_email)}
|
||||
required
|
||||
/>
|
||||
<.input field={@form[:subject]} label={gettext("Subject")} required />
|
||||
<.input
|
||||
field={@form[:details]}
|
||||
type="textarea"
|
||||
label={gettext("Describe the problem")}
|
||||
required
|
||||
/>
|
||||
<p class="text-xs text-base-content/55">
|
||||
{gettext(
|
||||
"Do not include passwords, payment card details, access codes, prescriptions, or unnecessary medical information."
|
||||
)}
|
||||
</p>
|
||||
<.button class="btn btn-primary w-full">{gettext("Send support request")}</.button>
|
||||
</.form>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-xl text-center">
|
||||
<div class="text-sm font-semibold text-success">{gettext("REQUEST RECEIVED")}</div>
|
||||
<h1 class="mt-2 text-4xl font-black">{gettext("Check your email")}</h1>
|
||||
<p class="mt-4 text-base-content/65">
|
||||
{gettext(
|
||||
"We created support request %{reference}. A private status link has been sent to the contact email when delivery is configured. Opening that link verifies the address for public requests.",
|
||||
reference: @reference
|
||||
)}
|
||||
</p>
|
||||
<.link navigate={~p"/support"} class="btn btn-primary mt-7">{gettext("Back to support")}</.link>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="mx-auto max-w-2xl">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="badge badge-outline">{@request.reference}</span>
|
||||
<span class="badge badge-primary">{status_label(@request.status)}</span>
|
||||
</div>
|
||||
<h1 class="mt-4 text-3xl font-black">{@request.subject}</h1>
|
||||
<p class="mt-2 text-sm text-base-content/55">{kind_label(@request.kind)}</p>
|
||||
<div class="mt-6 rounded-2xl bg-base-200 p-5">
|
||||
<p class="whitespace-pre-wrap">{@request.details}</p>
|
||||
</div>
|
||||
<section
|
||||
:if={@request.resolution_note not in [nil, ""]}
|
||||
class="mt-5 rounded-2xl border border-primary/30 p-5"
|
||||
>
|
||||
<h2 class="font-bold">{gettext("Support response")}</h2>
|
||||
<p class="mt-2 whitespace-pre-wrap">{@request.resolution_note}</p>
|
||||
</section>
|
||||
<p class="mt-5 text-xs text-base-content/55">
|
||||
{gettext(
|
||||
"Keep this status link private. A copy is sent to the contact email when email delivery is configured."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
@ -108,4 +108,23 @@
|
|||
{gettext("Save Password")}
|
||||
</.button>
|
||||
</.form>
|
||||
|
||||
<div class="divider" />
|
||||
|
||||
<section class="rounded-3xl border border-error/40 p-5">
|
||||
<h2 class="text-lg font-bold text-error">{gettext("Account and personal data")}</h2>
|
||||
<p class="mt-1 text-sm text-base-content/60">
|
||||
{gettext(
|
||||
"Request deletion of your account and associated personal data, or contact support about access and export requests."
|
||||
)}
|
||||
</p>
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<.link navigate={~p"/account/delete"} class="btn btn-error btn-outline">
|
||||
{gettext("Request account deletion")}
|
||||
</.link>
|
||||
<.link navigate={~p"/support/requests"} class="btn btn-outline">
|
||||
{gettext("View support requests")}
|
||||
</.link>
|
||||
</div>
|
||||
</section>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
|
|
@ -689,6 +689,12 @@ defmodule WhoNeedHelpWeb.ActivityLive.Show do
|
|||
</.button>
|
||||
</.form>
|
||||
</section>
|
||||
<.link
|
||||
navigate={~p"/legal/content-removal?location=/activities/#{@activity.id}"}
|
||||
class="btn btn-ghost btn-sm w-full"
|
||||
>
|
||||
{gettext("Submit a legal content-removal notice")}
|
||||
</.link>
|
||||
</aside>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
|
|
@ -1120,6 +1120,12 @@ defmodule WhoNeedHelpWeb.RequestLive.Show do
|
|||
</.button>
|
||||
</.form>
|
||||
</div>
|
||||
<.link
|
||||
navigate={~p"/legal/content-removal?location=/requests/#{@request.id}"}
|
||||
class="btn btn-ghost btn-sm w-full"
|
||||
>
|
||||
{gettext("Submit a legal content-removal notice")}
|
||||
</.link>
|
||||
</aside>
|
||||
</div>
|
||||
</Layouts.app>
|
||||
|
|
|
|||
282
lib/who_need_help_web/live/support_operations_live.ex
Normal file
282
lib/who_need_help_web/live/support_operations_live.ex
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
defmodule WhoNeedHelpWeb.SupportOperationsLive do
|
||||
use WhoNeedHelpWeb, :live_view
|
||||
|
||||
alias WhoNeedHelp.{ContentRemoval, Support}
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
{:ok, socket |> assign(:page_title, gettext("Support operations")) |> load()}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("moderate-support", %{"id" => id, "moderation" => params}, socket) do
|
||||
respond(
|
||||
socket,
|
||||
Support.moderate(socket.assigns.current_scope, id, params),
|
||||
gettext("Support request updated.")
|
||||
)
|
||||
end
|
||||
|
||||
def handle_event("moderate-removal", %{"id" => id, "moderation" => params}, socket) do
|
||||
respond(
|
||||
socket,
|
||||
ContentRemoval.moderate(socket.assigns.current_scope, id, params),
|
||||
gettext("Removal notice updated.")
|
||||
)
|
||||
end
|
||||
|
||||
def handle_event("load-more-support", _params, socket) do
|
||||
page =
|
||||
Support.paginate_for_staff(socket.assigns.current_scope,
|
||||
after: socket.assigns.support_cursor
|
||||
)
|
||||
|
||||
{:noreply, append_page(socket, :support_requests, :support_cursor, page)}
|
||||
end
|
||||
|
||||
def handle_event("load-more-removals", _params, socket) do
|
||||
page =
|
||||
ContentRemoval.paginate_for_staff(socket.assigns.current_scope,
|
||||
after: socket.assigns.removal_cursor
|
||||
)
|
||||
|
||||
{:noreply, append_page(socket, :removal_notices, :removal_cursor, page)}
|
||||
end
|
||||
|
||||
defp respond(socket, {:ok, _record}, message) do
|
||||
{:noreply, socket |> put_flash(:info, message) |> load()}
|
||||
end
|
||||
|
||||
defp respond(socket, {:error, reason}, _message) do
|
||||
{:noreply, put_flash(socket, :error, error_message(reason))}
|
||||
end
|
||||
|
||||
defp load(socket) do
|
||||
support = Support.paginate_for_staff(socket.assigns.current_scope)
|
||||
removals = ContentRemoval.paginate_for_staff(socket.assigns.current_scope)
|
||||
|
||||
socket
|
||||
|> assign(:support_requests, support.entries)
|
||||
|> assign(:support_cursor, support.next_cursor)
|
||||
|> assign(:removal_notices, removals.entries)
|
||||
|> assign(:removal_cursor, removals.next_cursor)
|
||||
end
|
||||
|
||||
defp append_page(socket, entries_key, cursor_key, page) do
|
||||
existing = socket.assigns[entries_key]
|
||||
existing_ids = MapSet.new(existing, & &1.id)
|
||||
entries = existing ++ Enum.reject(page.entries, &MapSet.member?(existing_ids, &1.id))
|
||||
|
||||
socket |> assign(entries_key, entries) |> assign(cursor_key, page.next_cursor)
|
||||
end
|
||||
|
||||
defp error_message(:forbidden), do: gettext("Moderator access is required.")
|
||||
defp error_message(:not_found), do: gettext("The selected record is no longer available.")
|
||||
defp error_message(%Ecto.Changeset{}), do: gettext("Please check the submitted fields.")
|
||||
defp error_message(_reason), do: gettext("Could not update the request. Please try again.")
|
||||
|
||||
defp support_kind(:account_access), do: gettext("Account access")
|
||||
defp support_kind(:technical_issue), do: gettext("Technical issue")
|
||||
defp support_kind(:safety_concern), do: gettext("Safety concern")
|
||||
defp support_kind(:moderation_appeal), do: gettext("Moderation appeal")
|
||||
defp support_kind(:account_deletion), do: gettext("Account deletion")
|
||||
defp support_kind(:data_export), do: gettext("Data export")
|
||||
defp support_kind(:privacy_request), do: gettext("Privacy request")
|
||||
defp support_kind(:other), do: gettext("Other")
|
||||
defp support_kind(value), do: to_string(value)
|
||||
|
||||
defp removal_category(:illegal_content), do: gettext("Illegal content")
|
||||
defp removal_category(:privacy_violation), do: gettext("Privacy violation")
|
||||
defp removal_category(:copyright), do: gettext("Copyright")
|
||||
defp removal_category(:impersonation), do: gettext("Impersonation")
|
||||
|
||||
defp removal_category(:non_consensual_intimate_media),
|
||||
do: gettext("Non-consensual intimate image or video")
|
||||
|
||||
defp removal_category(:child_sexual_abuse_material),
|
||||
do: gettext("Sexual material involving a minor")
|
||||
|
||||
defp removal_category(:threat_to_life_or_safety), do: gettext("Threat to life or safety")
|
||||
defp removal_category(:other), do: gettext("Other")
|
||||
defp removal_category(value), do: to_string(value)
|
||||
|
||||
defp status_label(value), do: value |> to_string() |> String.replace("_", " ")
|
||||
|
||||
defp scoped_form(data, id), do: to_form(data, as: :moderation, id: id)
|
||||
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
~H"""
|
||||
<Layouts.app flash={@flash} current_scope={@current_scope}>
|
||||
<div class="text-sm font-semibold text-warning">{gettext("RESTRICTED WORKSPACE")}</div>
|
||||
<div class="flex flex-wrap items-end justify-between gap-3">
|
||||
<div>
|
||||
<h1 class="mt-1 text-4xl font-black">{gettext("Support operations")}</h1>
|
||||
<p class="mt-2 text-base-content/60">
|
||||
{gettext(
|
||||
"Support requests and legal removal notices are separate queues. Decisions and operator identity are audited."
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<.link navigate={~p"/moderation"} class="btn btn-outline btn-sm">
|
||||
{gettext("Trust and safety moderation")}
|
||||
</.link>
|
||||
</div>
|
||||
|
||||
<section class="mt-8">
|
||||
<h2 class="text-2xl font-bold">{gettext("Content removal and TAKE IT DOWN")}</h2>
|
||||
<div class="mt-4 space-y-4">
|
||||
<article
|
||||
:for={notice <- @removal_notices}
|
||||
class={[
|
||||
"rounded-2xl border p-5",
|
||||
notice.status == :urgent_review && "border-error bg-error/5",
|
||||
notice.status != :urgent_review && "border-base-300"
|
||||
]}
|
||||
>
|
||||
<% form =
|
||||
scoped_form(
|
||||
%{
|
||||
"status" => to_string(notice.status),
|
||||
"resolution_note" => notice.resolution_note || ""
|
||||
},
|
||||
"removal-#{notice.id}"
|
||||
) %>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="badge badge-error">{notice.reference}</span>
|
||||
<span class="badge badge-outline">{notice.regime}</span>
|
||||
<span class="badge">{status_label(notice.status)}</span>
|
||||
<span :if={is_nil(notice.contact_verified_at)} class="badge badge-warning">
|
||||
{gettext("contact unverified")}
|
||||
</span>
|
||||
<span class="text-xs text-base-content/55">{removal_category(notice.category)}</span>
|
||||
<span :if={notice.response_due_at} class="badge badge-error badge-outline">
|
||||
{gettext("review by %{time}", time: notice.response_due_at)}
|
||||
</span>
|
||||
</div>
|
||||
<dl class="mt-4 grid gap-2 text-sm sm:grid-cols-[10rem_1fr]">
|
||||
<dt class="font-semibold">{gettext("Submitter")}</dt>
|
||||
<dd>{notice.submitter_name || gettext("Not provided")}</dd>
|
||||
<dt class="font-semibold">{gettext("Contact")}</dt>
|
||||
<dd>{notice.contact_email || gettext("Not provided")}</dd>
|
||||
<dt class="font-semibold">{gettext("Locations")}</dt>
|
||||
<dd class="space-y-1">
|
||||
<div
|
||||
:for={url <- WhoNeedHelp.ContentRemoval.Notice.content_urls(notice)}
|
||||
class="break-all font-mono text-xs"
|
||||
>
|
||||
{url}
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<p class="mt-4 whitespace-pre-wrap text-sm">{notice.explanation}</p>
|
||||
<p
|
||||
:if={notice.legal_basis not in [nil, ""]}
|
||||
class="mt-3 whitespace-pre-wrap text-sm text-base-content/65"
|
||||
>
|
||||
<strong>{gettext("Stated basis:")}</strong> {notice.legal_basis}
|
||||
</p>
|
||||
<.form
|
||||
for={form}
|
||||
phx-submit="moderate-removal"
|
||||
phx-value-id={notice.id}
|
||||
class="mt-4 grid gap-2 md:grid-cols-[13rem_1fr_auto]"
|
||||
>
|
||||
<.input
|
||||
field={form[:status]}
|
||||
type="select"
|
||||
options={[
|
||||
{gettext("Open"), "open"},
|
||||
{gettext("Urgent review"), "urgent_review"},
|
||||
{gettext("Reviewing"), "reviewing"},
|
||||
{gettext("More information needed"), "needs_information"},
|
||||
{gettext("Action taken"), "actioned"},
|
||||
{gettext("Rejected"), "rejected"},
|
||||
{gettext("Closed"), "closed"}
|
||||
]}
|
||||
/>
|
||||
<.input
|
||||
field={form[:resolution_note]}
|
||||
type="textarea"
|
||||
placeholder={gettext("Decision or information request")}
|
||||
/>
|
||||
<.button class="btn btn-error self-end">{gettext("Save and notify")}</.button>
|
||||
</.form>
|
||||
</article>
|
||||
<p :if={@removal_notices == []} class="text-base-content/50">
|
||||
{gettext("No removal notices.")}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
:if={@removal_cursor}
|
||||
phx-click="load-more-removals"
|
||||
class="btn btn-outline btn-sm mt-4"
|
||||
>
|
||||
{gettext("Load more")}
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<section class="mt-12">
|
||||
<h2 class="text-2xl font-bold">{gettext("General support and data requests")}</h2>
|
||||
<div class="mt-4 space-y-4">
|
||||
<article :for={request <- @support_requests} class="rounded-2xl border border-base-300 p-5">
|
||||
<% form =
|
||||
scoped_form(
|
||||
%{
|
||||
"status" => to_string(request.status),
|
||||
"resolution_note" => request.resolution_note || ""
|
||||
},
|
||||
"support-#{request.id}"
|
||||
) %>
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="badge badge-primary">{request.reference}</span>
|
||||
<span class="badge">{status_label(request.status)}</span>
|
||||
<span :if={is_nil(request.contact_verified_at)} class="badge badge-warning">
|
||||
{gettext("contact unverified")}
|
||||
</span>
|
||||
<span class="text-xs text-base-content/55">{support_kind(request.kind)}</span>
|
||||
</div>
|
||||
<h3 class="mt-3 font-bold">{request.subject}</h3>
|
||||
<p class="mt-1 text-xs text-base-content/55">{request.contact_email}</p>
|
||||
<p class="mt-3 whitespace-pre-wrap text-sm">{request.details}</p>
|
||||
<.form
|
||||
for={form}
|
||||
phx-submit="moderate-support"
|
||||
phx-value-id={request.id}
|
||||
class="mt-4 grid gap-2 md:grid-cols-[13rem_1fr_auto]"
|
||||
>
|
||||
<.input
|
||||
field={form[:status]}
|
||||
type="select"
|
||||
options={[
|
||||
{gettext("Open"), "open"},
|
||||
{gettext("Reviewing"), "reviewing"},
|
||||
{gettext("Waiting for requester"), "waiting_for_requester"},
|
||||
{gettext("Resolved"), "resolved"},
|
||||
{gettext("Closed"), "closed"}
|
||||
]}
|
||||
/>
|
||||
<.input
|
||||
field={form[:resolution_note]}
|
||||
type="textarea"
|
||||
placeholder={gettext("Support response")}
|
||||
/>
|
||||
<.button class="btn btn-primary self-end">{gettext("Save and notify")}</.button>
|
||||
</.form>
|
||||
</article>
|
||||
<p :if={@support_requests == []} class="text-base-content/50">
|
||||
{gettext("No support requests.")}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
:if={@support_cursor}
|
||||
phx-click="load-more-support"
|
||||
class="btn btn-outline btn-sm mt-4"
|
||||
>
|
||||
{gettext("Load more")}
|
||||
</button>
|
||||
</section>
|
||||
</Layouts.app>
|
||||
"""
|
||||
end
|
||||
end
|
||||
|
|
@ -72,6 +72,19 @@ defmodule WhoNeedHelpWeb.Router do
|
|||
get "/", PageController, :home
|
||||
get "/feedback", FeedbackController, :show
|
||||
get "/safety", PageController, :safety
|
||||
get "/support", SupportController, :new
|
||||
get "/support/new", SupportController, :new
|
||||
post "/support", SupportController, :create
|
||||
get "/support/received", SupportController, :received
|
||||
get "/support/cases/:id", SupportController, :show
|
||||
get "/account/delete", SupportController, :delete_account
|
||||
post "/account/delete", SupportController, :request_account_deletion
|
||||
get "/legal/content-removal", ContentRemovalController, :new
|
||||
post "/legal/content-removal", ContentRemovalController, :create
|
||||
get "/legal/content-removal/received", ContentRemovalController, :received
|
||||
get "/legal/content-removal/:id", ContentRemovalController, :show
|
||||
get "/legal/take-it-down", ContentRemovalController, :take_it_down
|
||||
post "/legal/take-it-down", ContentRemovalController, :create_take_it_down
|
||||
end
|
||||
|
||||
# Other scopes may use custom stacks.
|
||||
|
|
@ -118,6 +131,7 @@ defmodule WhoNeedHelpWeb.Router do
|
|||
delete "/auth/google/link", GoogleAuthController, :disconnect
|
||||
get "/auth/social/:provider", SocialOAuthController, :request
|
||||
get "/auth/social/:provider/callback", SocialOAuthController, :callback
|
||||
get "/support/requests", SupportController, :index
|
||||
end
|
||||
|
||||
scope "/", WhoNeedHelpWeb do
|
||||
|
|
@ -139,6 +153,7 @@ defmodule WhoNeedHelpWeb.Router do
|
|||
live_session :moderation,
|
||||
on_mount: [{WhoNeedHelpWeb.UserAuth, :ensure_moderator}] do
|
||||
live "/moderation", ModerationLive, :index
|
||||
live "/support/operations", SupportOperationsLive, :index
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ msgid ""
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:111
|
||||
#: lib/who_need_help_web/components/layouts.ex:257
|
||||
#: lib/who_need_help_web/components/layouts.ex:266
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account settings"
|
||||
msgstr ""
|
||||
|
|
@ -30,13 +30,13 @@ msgstr ""
|
|||
msgid "Ask for help"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:295
|
||||
#: lib/who_need_help_web/components/layouts.ex:310
|
||||
#: lib/who_need_help_web/components/layouts.ex:304
|
||||
#: lib/who_need_help_web/components/layouts.ex:319
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempting to reconnect"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:171
|
||||
#: lib/who_need_help_web/components/layouts.ex:175
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Categories"
|
||||
msgstr ""
|
||||
|
|
@ -65,13 +65,13 @@ msgid "Log in"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:114
|
||||
#: lib/who_need_help_web/components/layouts.ex:260
|
||||
#: lib/who_need_help_web/components/layouts.ex:269
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:108
|
||||
#: lib/who_need_help_web/components/layouts.ex:254
|
||||
#: lib/who_need_help_web/components/layouts.ex:263
|
||||
#: lib/who_need_help_web/live/profile_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Profile"
|
||||
|
|
@ -83,7 +83,7 @@ msgstr ""
|
|||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:161
|
||||
#: lib/who_need_help_web/components/layouts.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Requests"
|
||||
msgstr ""
|
||||
|
|
@ -93,12 +93,12 @@ msgstr ""
|
|||
msgid "See nearby requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:302
|
||||
#: lib/who_need_help_web/components/layouts.ex:311
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Something went wrong!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:287
|
||||
#: lib/who_need_help_web/components/layouts.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We can't find the internet"
|
||||
msgstr ""
|
||||
|
|
@ -174,7 +174,7 @@ msgid "Account Settings"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:63
|
||||
#: lib/who_need_help_web/components/layouts.ex:192
|
||||
#: lib/who_need_help_web/components/layouts.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and language"
|
||||
msgstr ""
|
||||
|
|
@ -195,7 +195,7 @@ msgstr ""
|
|||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:166
|
||||
#: lib/who_need_help_web/components/layouts.ex:170
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Activities"
|
||||
|
|
@ -367,7 +367,7 @@ msgstr ""
|
|||
msgid "Briefly describe the help you need"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#: lib/who_need_help_web/components/layouts.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Build Week feedback"
|
||||
msgstr ""
|
||||
|
|
@ -641,7 +641,7 @@ msgstr ""
|
|||
msgid "Dismissed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:76
|
||||
#: lib/who_need_help_web/live/profile_live.ex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Display name"
|
||||
|
|
@ -662,7 +662,7 @@ msgstr ""
|
|||
msgid "Double-blind review"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:62
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:67
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:89
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:122
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:15
|
||||
|
|
@ -817,7 +817,7 @@ msgstr ""
|
|||
msgid "Helper: %{name}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:176
|
||||
#: lib/who_need_help_web/components/layouts.ex:180
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Helpers"
|
||||
msgstr ""
|
||||
|
|
@ -872,7 +872,7 @@ msgid "Human decisions retained"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:39
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:85
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am 18 or older and accept the safety rules"
|
||||
msgstr ""
|
||||
|
|
@ -913,9 +913,12 @@ msgstr ""
|
|||
msgid "If your email is in our system, you will receive instructions for logging in shortly."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:9
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:25
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:678
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:253
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1109
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:91
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Impersonation"
|
||||
msgstr ""
|
||||
|
|
@ -1122,7 +1125,7 @@ msgstr ""
|
|||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:181
|
||||
#: lib/who_need_help_web/components/layouts.ex:185
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:9
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:291
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1136,6 +1139,7 @@ msgid "Moderator"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:230
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:73
|
||||
#: lib/who_need_help_web/user_auth.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderator access is required."
|
||||
|
|
@ -1270,12 +1274,16 @@ msgstr ""
|
|||
msgid "Only the organizer and approved participants can read or send these messages."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:16
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:166
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:342
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:257
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:176
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:177
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:636
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:189
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:252
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
|
@ -1320,10 +1328,17 @@ msgstr ""
|
|||
msgid "Organizer social links"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:18
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:49
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:13
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:35
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:679
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:254
|
||||
#: lib/who_need_help_web/live/profile_live.ex:311
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1110
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:85
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
|
@ -1374,6 +1389,7 @@ msgid "Please check the entered data."
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:240
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please check the submitted fields."
|
||||
msgstr ""
|
||||
|
|
@ -1497,6 +1513,7 @@ msgid "READ BEFORE USING THE SERVICE"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:290
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RESTRICTED WORKSPACE"
|
||||
msgstr ""
|
||||
|
|
@ -1517,11 +1534,12 @@ msgstr ""
|
|||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:77
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Read the"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:20
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:672
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reason"
|
||||
|
|
@ -1633,8 +1651,10 @@ msgstr ""
|
|||
msgid "Resolution note"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:19
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:259
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:365
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:255
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resolved"
|
||||
msgstr ""
|
||||
|
|
@ -1662,8 +1682,12 @@ msgstr ""
|
|||
msgid "Reviewed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:23
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:17
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:258
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:364
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:191
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:253
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reviewing"
|
||||
msgstr ""
|
||||
|
|
@ -2129,12 +2153,12 @@ msgstr ""
|
|||
msgid "Use a public first meeting point. Do not publish a home address, access code, travel document, or other sensitive information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#: lib/who_need_help_web/components/layouts.ex:358
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use light theme"
|
||||
msgstr ""
|
||||
|
|
@ -2150,7 +2174,7 @@ msgstr ""
|
|||
msgid "Use private chat and optional live location sharing."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:331
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use system theme"
|
||||
msgstr ""
|
||||
|
|
@ -2266,7 +2290,7 @@ msgstr ""
|
|||
msgid "Who Need Help home"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who Need Help is not an emergency or medical service. Medicine requests are limited to pickup of legal items already purchased or reserved."
|
||||
msgstr ""
|
||||
|
|
@ -2407,6 +2431,7 @@ msgstr ""
|
|||
msgid "Your request is now visible to nearby helpers."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:6
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:342
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your requests"
|
||||
|
|
@ -2432,7 +2457,7 @@ msgstr ""
|
|||
msgid "activity message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:79
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "before confirming."
|
||||
msgstr ""
|
||||
|
|
@ -2509,7 +2534,7 @@ msgstr ""
|
|||
msgid "rating %{rating}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:78
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "safety rules"
|
||||
msgstr ""
|
||||
|
|
@ -2617,7 +2642,9 @@ msgstr ""
|
|||
msgid "Reciprocal rating ring"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:26
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:263
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:194
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rejected"
|
||||
msgstr ""
|
||||
|
|
@ -2650,6 +2677,8 @@ msgstr ""
|
|||
#: lib/who_need_help_web/live/profile_live.ex:354
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:303
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:360
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:215
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:276
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
|
@ -2736,6 +2765,7 @@ msgid "The registration form is invalid."
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:239
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The selected record is no longer available."
|
||||
msgstr ""
|
||||
|
|
@ -2835,7 +2865,7 @@ msgstr ""
|
|||
msgid "Connect Google only after signing in here. We never merge accounts automatically by matching email addresses."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:96
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:101
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create account and email me a link"
|
||||
msgstr ""
|
||||
|
|
@ -2897,7 +2927,7 @@ msgstr ""
|
|||
msgid "Google sign-in will be available after the operator configures it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sending link..."
|
||||
msgstr ""
|
||||
|
|
@ -2981,3 +3011,632 @@ msgstr ""
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "No Google account is connected."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A person I am authorised to represent"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A private status link has been sent when a contact email was provided and delivery is configured. Opening that link verifies the contact address. Keep the reference for follow-up."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ACCOUNT AND DATA"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account access"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and personal data"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:10
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account deletion"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:193
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Action taken"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Additional information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:32
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Appeal a moderation decision"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to removal form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to support"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "CONTENT REMOVAL"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Check your email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a category"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a reason"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:51
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a relationship"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a topic"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:27
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:20
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:195
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:256
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:160
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact Who Need Help"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:38
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:34
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content removal and TAKE IT DOWN"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content-removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Copyright"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:76
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Could not update the request. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:11
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:34
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data export"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or information request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or request for information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete an account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Describe the problem"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not include passwords, payment card details, access codes, prescriptions, or unnecessary medical information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not upload the image or video. Provide only the exact Who Need Help URL where it appears and enough text to identify it safely."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:72
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Electronic signature (type your full name)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:56
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Exact content URLs — one per line"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "General support and data requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am an authorised representative"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am the affected person or rights holder"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I believe in good faith that the identified content is illegal or infringes the stated right."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that the information in this request is accurate and that I am the depicted person or authorised to act for them."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that this notice is accurate and complete to the best of my knowledge."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I have a good-faith belief that this intimate visual material was shared without consent."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identify the material without reproducing it and explain why it is non-consensual"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:93
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identity and contact fields may be omitted for reports of sexual material involving a minor. Do not include or upload the material itself."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Illegal content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. A copy is sent to the contact email when email delivery is configured."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. The submitter identity is not shown publicly or automatically disclosed to the person who posted the reported content."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Law, right, or policy involved, if known"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:162
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Locations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Material involved"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:9
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:81
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderation appeal"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:192
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "More information needed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Myself"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "NOTICE RECEIVED"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:207
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No removal notices."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:268
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No support requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:26
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Non-consensual intimate image or video"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:159
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not provided"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:33
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:23
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy violation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Provide exact Who Need Help URLs. Do not upload or paste intimate imagery, identity documents, passwords, access codes, or unnecessary medical information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "REQUEST RECEIVED"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Removal notice updated."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:149
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report illegal or harmful content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reported locations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:4
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:37
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:123
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request account deletion"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:117
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request deletion of your account and associated personal data, or contact support about access and export requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request removal of intimate visual material"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:5
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SUPPORT"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:31
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:80
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Safety concern"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:203
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:264
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save and notify"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send support request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:15
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:27
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sexual material involving a minor"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:177
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stated basis:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:696
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit a legal content-removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit urgent removal request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitter"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitting this form does not immediately sign you out or erase evidence required for an open safety investigation. Support will verify and process the request."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:8
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support operations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support queue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support request updated."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:116
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support requests and legal removal notices are separate queues. Decisions and operator identity are audited."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:16
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support response"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:30
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Technical issue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This requests deletion of your Who Need Help account and associated personal data. Some records may need to be retained when required for safety, fraud prevention, legal obligations, or resolving an active dispute; any retained data must be described in the applicable retention notice."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:17
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:28
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Threat to life or safety"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_controller.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many removal notices. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:34
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many support requests. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Trust and safety moderation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Urgent review"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this dedicated process when an identifiable person is shown in an intimate image or video shared without consent, including a digital forgery. You may submit for yourself or as an authorised representative."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this electronic notice for specific content on Who Need Help that you believe is illegal or infringes your rights. Ordinary safety reports inside a request or chat remain available to signed-in users."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form for account access, technical problems, privacy questions, or other support. For illegal content or a removal request, use the dedicated removal form."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:126
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View support requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:254
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for requester"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for your response"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We created support request %{reference}. A private status link has been sent to the contact email when delivery is configured. Opening that link verifies the address for public requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "What do you need help with?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who are you submitting for?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Why do you believe this content should be removed?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have not submitted any support requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your full name"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your name or organisation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your reference is %{reference}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your relationship to the affected person or rights holder"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:150
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:235
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "contact unverified"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:154
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "review by %{time}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:47
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete my Who Need Help account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please delete my account and associated personal data."
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:111
|
||||
#: lib/who_need_help_web/components/layouts.ex:257
|
||||
#: lib/who_need_help_web/components/layouts.ex:266
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account settings"
|
||||
msgstr ""
|
||||
|
|
@ -30,13 +30,13 @@ msgstr ""
|
|||
msgid "Ask for help"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:295
|
||||
#: lib/who_need_help_web/components/layouts.ex:310
|
||||
#: lib/who_need_help_web/components/layouts.ex:304
|
||||
#: lib/who_need_help_web/components/layouts.ex:319
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempting to reconnect"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:171
|
||||
#: lib/who_need_help_web/components/layouts.ex:175
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Categories"
|
||||
msgstr ""
|
||||
|
|
@ -65,13 +65,13 @@ msgid "Log in"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:114
|
||||
#: lib/who_need_help_web/components/layouts.ex:260
|
||||
#: lib/who_need_help_web/components/layouts.ex:269
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:108
|
||||
#: lib/who_need_help_web/components/layouts.ex:254
|
||||
#: lib/who_need_help_web/components/layouts.ex:263
|
||||
#: lib/who_need_help_web/live/profile_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Profile"
|
||||
|
|
@ -83,7 +83,7 @@ msgstr ""
|
|||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:161
|
||||
#: lib/who_need_help_web/components/layouts.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Requests"
|
||||
msgstr ""
|
||||
|
|
@ -93,12 +93,12 @@ msgstr ""
|
|||
msgid "See nearby requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:302
|
||||
#: lib/who_need_help_web/components/layouts.ex:311
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Something went wrong!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:287
|
||||
#: lib/who_need_help_web/components/layouts.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We can't find the internet"
|
||||
msgstr ""
|
||||
|
|
@ -174,7 +174,7 @@ msgid "Account Settings"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:63
|
||||
#: lib/who_need_help_web/components/layouts.ex:192
|
||||
#: lib/who_need_help_web/components/layouts.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and language"
|
||||
msgstr ""
|
||||
|
|
@ -195,7 +195,7 @@ msgstr ""
|
|||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:166
|
||||
#: lib/who_need_help_web/components/layouts.ex:170
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Activities"
|
||||
|
|
@ -367,7 +367,7 @@ msgstr ""
|
|||
msgid "Briefly describe the help you need"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#: lib/who_need_help_web/components/layouts.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Build Week feedback"
|
||||
msgstr ""
|
||||
|
|
@ -641,7 +641,7 @@ msgstr ""
|
|||
msgid "Dismissed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:76
|
||||
#: lib/who_need_help_web/live/profile_live.ex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Display name"
|
||||
|
|
@ -662,7 +662,7 @@ msgstr ""
|
|||
msgid "Double-blind review"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:62
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:67
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:89
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:122
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:15
|
||||
|
|
@ -817,7 +817,7 @@ msgstr ""
|
|||
msgid "Helper: %{name}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:176
|
||||
#: lib/who_need_help_web/components/layouts.ex:180
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Helpers"
|
||||
msgstr ""
|
||||
|
|
@ -872,7 +872,7 @@ msgid "Human decisions retained"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:39
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:85
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am 18 or older and accept the safety rules"
|
||||
msgstr ""
|
||||
|
|
@ -913,9 +913,12 @@ msgstr ""
|
|||
msgid "If your email is in our system, you will receive instructions for logging in shortly."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:9
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:25
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:678
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:253
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1109
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:91
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Impersonation"
|
||||
msgstr ""
|
||||
|
|
@ -1122,7 +1125,7 @@ msgstr ""
|
|||
msgid "Mode"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:181
|
||||
#: lib/who_need_help_web/components/layouts.ex:185
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:9
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:291
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1136,6 +1139,7 @@ msgid "Moderator"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:230
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:73
|
||||
#: lib/who_need_help_web/user_auth.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderator access is required."
|
||||
|
|
@ -1270,12 +1274,16 @@ msgstr ""
|
|||
msgid "Only the organizer and approved participants can read or send these messages."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:16
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:166
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:342
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:257
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:176
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:177
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:636
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:189
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:252
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
|
@ -1320,10 +1328,17 @@ msgstr ""
|
|||
msgid "Organizer social links"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:18
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:49
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:13
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:35
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:679
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:254
|
||||
#: lib/who_need_help_web/live/profile_live.ex:311
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1110
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:85
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other"
|
||||
msgstr ""
|
||||
|
|
@ -1374,6 +1389,7 @@ msgid "Please check the entered data."
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:240
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please check the submitted fields."
|
||||
msgstr ""
|
||||
|
|
@ -1497,6 +1513,7 @@ msgid "READ BEFORE USING THE SERVICE"
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:290
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RESTRICTED WORKSPACE"
|
||||
msgstr ""
|
||||
|
|
@ -1517,11 +1534,12 @@ msgstr ""
|
|||
msgid "Rating"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:77
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Read the"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:20
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:672
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reason"
|
||||
|
|
@ -1633,8 +1651,10 @@ msgstr ""
|
|||
msgid "Resolution note"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:19
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:259
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:365
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:255
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resolved"
|
||||
msgstr ""
|
||||
|
|
@ -1662,8 +1682,12 @@ msgstr ""
|
|||
msgid "Reviewed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:23
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:17
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:258
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:364
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:191
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:253
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reviewing"
|
||||
msgstr ""
|
||||
|
|
@ -2129,12 +2153,12 @@ msgstr ""
|
|||
msgid "Use a public first meeting point. Do not publish a home address, access code, travel document, or other sensitive information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#: lib/who_need_help_web/components/layouts.ex:358
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use dark theme"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use light theme"
|
||||
msgstr ""
|
||||
|
|
@ -2150,7 +2174,7 @@ msgstr ""
|
|||
msgid "Use private chat and optional live location sharing."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:331
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use system theme"
|
||||
msgstr ""
|
||||
|
|
@ -2266,7 +2290,7 @@ msgstr ""
|
|||
msgid "Who Need Help home"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who Need Help is not an emergency or medical service. Medicine requests are limited to pickup of legal items already purchased or reserved."
|
||||
msgstr ""
|
||||
|
|
@ -2407,6 +2431,7 @@ msgstr ""
|
|||
msgid "Your request is now visible to nearby helpers."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:6
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:342
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your requests"
|
||||
|
|
@ -2432,7 +2457,7 @@ msgstr ""
|
|||
msgid "activity message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:79
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "before confirming."
|
||||
msgstr ""
|
||||
|
|
@ -2509,7 +2534,7 @@ msgstr ""
|
|||
msgid "rating %{rating}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:78
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "safety rules"
|
||||
msgstr ""
|
||||
|
|
@ -2617,7 +2642,9 @@ msgstr ""
|
|||
msgid "Reciprocal rating ring"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:26
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:263
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:194
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rejected"
|
||||
msgstr ""
|
||||
|
|
@ -2650,6 +2677,8 @@ msgstr ""
|
|||
#: lib/who_need_help_web/live/profile_live.ex:354
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:303
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:360
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:215
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:276
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Load more"
|
||||
msgstr ""
|
||||
|
|
@ -2736,6 +2765,7 @@ msgid "The registration form is invalid."
|
|||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:239
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The selected record is no longer available."
|
||||
msgstr ""
|
||||
|
|
@ -2835,7 +2865,7 @@ msgstr ""
|
|||
msgid "Connect Google only after signing in here. We never merge accounts automatically by matching email addresses."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:96
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:101
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create account and email me a link"
|
||||
msgstr ""
|
||||
|
|
@ -2897,7 +2927,7 @@ msgstr ""
|
|||
msgid "Google sign-in will be available after the operator configures it."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sending link..."
|
||||
msgstr ""
|
||||
|
|
@ -2981,3 +3011,632 @@ msgstr "Google sign-in disconnected."
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "No Google account is connected."
|
||||
msgstr "No Google account is connected."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A person I am authorised to represent"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A private status link has been sent when a contact email was provided and delivery is configured. Opening that link verifies the contact address. Keep the reference for follow-up."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ACCOUNT AND DATA"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:78
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Account access"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and personal data"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:10
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:82
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Account deletion"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:26
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Account email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:193
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Action taken"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Additional information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:32
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Appeal a moderation decision"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to removal form"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to support"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "CONTENT REMOVAL"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Check your email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:27
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Choose a category"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a reason"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:51
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a relationship"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a topic"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:27
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:20
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:195
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:256
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Closed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:160
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact Who Need Help"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:38
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:34
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact email"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content removal and TAKE IT DOWN"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content-removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Copyright"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:76
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Could not update the request. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:11
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:34
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data export"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or information request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or request for information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete an account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Describe the problem"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not include passwords, payment card details, access codes, prescriptions, or unnecessary medical information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not upload the image or video. Provide only the exact Who Need Help URL where it appears and enough text to identify it safely."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:72
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Electronic signature (type your full name)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:56
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Exact content URLs — one per line"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "General support and data requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am an authorised representative"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am the affected person or rights holder"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I believe in good faith that the identified content is illegal or infringes the stated right."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that the information in this request is accurate and that I am the depicted person or authorised to act for them."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that this notice is accurate and complete to the best of my knowledge."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I have a good-faith belief that this intimate visual material was shared without consent."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identify the material without reproducing it and explain why it is non-consensual"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:93
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identity and contact fields may be omitted for reports of sexual material involving a minor. Do not include or upload the material itself."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Illegal content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. A copy is sent to the contact email when email delivery is configured."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. The submitter identity is not shown publicly or automatically disclosed to the person who posted the reported content."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Law, right, or policy involved, if known"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:162
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Locations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Material involved"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:9
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:81
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Moderation appeal"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:192
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "More information needed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Myself"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "NOTICE RECEIVED"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "New request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:207
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No removal notices."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:268
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No support requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:26
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Non-consensual intimate image or video"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:159
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not provided"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:33
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:23
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy violation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Provide exact Who Need Help URLs. Do not upload or paste intimate imagery, identity documents, passwords, access codes, or unnecessary medical information."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "REQUEST RECEIVED"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Removal notice updated."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:149
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Report content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report illegal or harmful content"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reported locations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:4
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:37
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:123
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Request account deletion"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:117
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request deletion of your account and associated personal data, or contact support about access and export requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request removal of intimate visual material"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:5
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SUPPORT"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:31
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:80
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Safety concern"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:203
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:264
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save and notify"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send support request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:15
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:27
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sexual material involving a minor"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:177
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stated basis:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:696
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit a legal content-removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:97
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Submit removal notice"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit urgent removal request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitter"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitting this form does not immediately sign you out or erase evidence required for an open safety investigation. Support will verify and process the request."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:8
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support operations"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support queue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support request updated."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:116
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support requests and legal removal notices are separate queues. Decisions and operator identity are audited."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:16
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support response"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:30
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Technical issue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This requests deletion of your Who Need Help account and associated personal data. Some records may need to be retained when required for safety, fraud prevention, legal obligations, or resolving an active dispute; any retained data must be described in the applicable retention notice."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:17
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:28
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Threat to life or safety"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_controller.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many removal notices. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:34
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many support requests. Please try again later."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Trust and safety moderation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Urgent review"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this dedicated process when an identifiable person is shown in an intimate image or video shared without consent, including a digital forgery. You may submit for yourself or as an authorised representative."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this electronic notice for specific content on Who Need Help that you believe is illegal or infringes your rights. Ordinary safety reports inside a request or chat remain available to signed-in users."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form for account access, technical problems, privacy questions, or other support. For illegal content or a removal request, use the dedicated removal form."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:126
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View support requests"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:254
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Waiting for requester"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for your response"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We created support request %{reference}. A private status link has been sent to the contact email when delivery is configured. Opening that link verifies the address for public requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:27
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "What do you need help with?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who are you submitting for?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Why do you believe this content should be removed?"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have not submitted any support requests."
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your full name"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your name or organisation"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your reference is %{reference}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your relationship to the affected person or rights holder"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:150
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:235
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "contact unverified"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:154
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "review by %{time}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:47
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete my Who Need Help account"
|
||||
msgstr ""
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please delete my account and associated personal data."
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100 != 11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10||n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:111
|
||||
#: lib/who_need_help_web/components/layouts.ex:257
|
||||
#: lib/who_need_help_web/components/layouts.ex:266
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account settings"
|
||||
msgstr "Настройки аккаунта"
|
||||
|
|
@ -30,13 +30,13 @@ msgstr "Действия"
|
|||
msgid "Ask for help"
|
||||
msgstr "Попросить о помощи"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:295
|
||||
#: lib/who_need_help_web/components/layouts.ex:310
|
||||
#: lib/who_need_help_web/components/layouts.ex:304
|
||||
#: lib/who_need_help_web/components/layouts.ex:319
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempting to reconnect"
|
||||
msgstr "Пытаемся восстановить соединение"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:171
|
||||
#: lib/who_need_help_web/components/layouts.ex:175
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Categories"
|
||||
msgstr "Категории"
|
||||
|
|
@ -65,13 +65,13 @@ msgid "Log in"
|
|||
msgstr "Войти"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:114
|
||||
#: lib/who_need_help_web/components/layouts.ex:260
|
||||
#: lib/who_need_help_web/components/layouts.ex:269
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log out"
|
||||
msgstr "Выйти"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:108
|
||||
#: lib/who_need_help_web/components/layouts.ex:254
|
||||
#: lib/who_need_help_web/components/layouts.ex:263
|
||||
#: lib/who_need_help_web/live/profile_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Profile"
|
||||
|
|
@ -83,7 +83,7 @@ msgstr "Профиль"
|
|||
msgid "Register"
|
||||
msgstr "Регистрация"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:161
|
||||
#: lib/who_need_help_web/components/layouts.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Requests"
|
||||
msgstr "Заявки"
|
||||
|
|
@ -93,12 +93,12 @@ msgstr "Заявки"
|
|||
msgid "See nearby requests"
|
||||
msgstr "Заявки рядом"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:302
|
||||
#: lib/who_need_help_web/components/layouts.ex:311
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Something went wrong!"
|
||||
msgstr "Что-то пошло не так!"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:287
|
||||
#: lib/who_need_help_web/components/layouts.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We can't find the internet"
|
||||
msgstr "Нет соединения с интернетом"
|
||||
|
|
@ -179,7 +179,7 @@ msgid "Account Settings"
|
|||
msgstr "Настройки аккаунта"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:63
|
||||
#: lib/who_need_help_web/components/layouts.ex:192
|
||||
#: lib/who_need_help_web/components/layouts.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and language"
|
||||
msgstr "Аккаунт и язык"
|
||||
|
|
@ -200,7 +200,7 @@ msgstr "Центр действий"
|
|||
msgid "Active"
|
||||
msgstr "Активный"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:166
|
||||
#: lib/who_need_help_web/components/layouts.ex:170
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Activities"
|
||||
|
|
@ -384,7 +384,7 @@ msgstr ""
|
|||
msgid "Briefly describe the help you need"
|
||||
msgstr "Кратко опишите, какая помощь вам нужна"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#: lib/who_need_help_web/components/layouts.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Build Week feedback"
|
||||
msgstr "Отчёт для Build Week"
|
||||
|
|
@ -667,7 +667,7 @@ msgstr ""
|
|||
msgid "Dismissed"
|
||||
msgstr "Отклонено"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:76
|
||||
#: lib/who_need_help_web/live/profile_live.ex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Display name"
|
||||
|
|
@ -691,7 +691,7 @@ msgstr "Нет аккаунта?"
|
|||
msgid "Double-blind review"
|
||||
msgstr "Двусторонний скрытый отзыв"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:62
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:67
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:89
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:122
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:15
|
||||
|
|
@ -857,7 +857,7 @@ msgstr "Помощник"
|
|||
msgid "Helper: %{name}"
|
||||
msgstr "Помощник: %{name}"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:176
|
||||
#: lib/who_need_help_web/components/layouts.ex:180
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Helpers"
|
||||
msgstr "Помощники"
|
||||
|
|
@ -933,7 +933,7 @@ msgid "Human decisions retained"
|
|||
msgstr "Решения остаются за человеком"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:39
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:85
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am 18 or older and accept the safety rules"
|
||||
msgstr "Мне 18 лет и я принимаю правила безопасности."
|
||||
|
|
@ -987,9 +987,12 @@ msgstr ""
|
|||
"Если этот адрес электронной почты есть в нашей системе, вскоре вы получите "
|
||||
"инструкции для входа."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:9
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:25
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:678
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:253
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1109
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:91
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Impersonation"
|
||||
msgstr "Выдача себя за другого человека"
|
||||
|
|
@ -1212,7 +1215,7 @@ msgstr "Написать одобренной группе"
|
|||
msgid "Mode"
|
||||
msgstr "Режим"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:181
|
||||
#: lib/who_need_help_web/components/layouts.ex:185
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:9
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:291
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1226,6 +1229,7 @@ msgid "Moderator"
|
|||
msgstr "Модератор"
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:230
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:73
|
||||
#: lib/who_need_help_web/user_auth.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderator access is required."
|
||||
|
|
@ -1370,12 +1374,16 @@ msgstr ""
|
|||
"Только организатор и одобренные участники могут читать или отправлять эти "
|
||||
"сообщения."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:16
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:166
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:342
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:257
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:176
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:177
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:636
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:189
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:252
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Open"
|
||||
msgstr "Открыта"
|
||||
|
|
@ -1420,10 +1428,17 @@ msgstr "Управление организатора"
|
|||
msgid "Organizer social links"
|
||||
msgstr "Ссылки организатора на соцсети"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:18
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:49
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:13
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:35
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:679
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:254
|
||||
#: lib/who_need_help_web/live/profile_live.ex:311
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1110
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:85
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other"
|
||||
msgstr "Другое"
|
||||
|
|
@ -1474,6 +1489,7 @@ msgid "Please check the entered data."
|
|||
msgstr "Пожалуйста, проверьте введенные данные."
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:240
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please check the submitted fields."
|
||||
msgstr "Пожалуйста, проверьте представленные поля."
|
||||
|
|
@ -1610,6 +1626,7 @@ msgid "READ BEFORE USING THE SERVICE"
|
|||
msgstr "ПРОЧИТАЙТЕ ПЕРЕД ИСПОЛЬЗОВАНИЕМ СЕРВИСА"
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:290
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RESTRICTED WORKSPACE"
|
||||
msgstr "ОГРАНИЧЕННАЯ РАБОЧАЯ ОБЛАСТЬ"
|
||||
|
|
@ -1634,11 +1651,12 @@ msgstr ""
|
|||
msgid "Rating"
|
||||
msgstr "Оценка"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:77
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Read the"
|
||||
msgstr "Прочитайте"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:20
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:672
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reason"
|
||||
|
|
@ -1752,8 +1770,10 @@ msgstr "Автор заявки: %{count} завершено"
|
|||
msgid "Resolution note"
|
||||
msgstr "Примечание к решению"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:19
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:259
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:365
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:255
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resolved"
|
||||
msgstr "Решено"
|
||||
|
|
@ -1782,8 +1802,12 @@ msgstr ""
|
|||
msgid "Reviewed"
|
||||
msgstr "Проверено"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:23
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:17
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:258
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:364
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:191
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:253
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reviewing"
|
||||
msgstr "На рассмотрении"
|
||||
|
|
@ -2269,12 +2293,12 @@ msgstr ""
|
|||
"адрес, код доступа, документ для поездки или другую чувствительную "
|
||||
"информацию."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#: lib/who_need_help_web/components/layouts.ex:358
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use dark theme"
|
||||
msgstr "Включить тёмную тему"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use light theme"
|
||||
msgstr "Включить светлую тему"
|
||||
|
|
@ -2292,7 +2316,7 @@ msgstr ""
|
|||
"Используйте приватный чат и, по желанию, передачу геопозиции в реальном "
|
||||
"времени."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:331
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use system theme"
|
||||
msgstr "Использовать системную тему"
|
||||
|
|
@ -2414,7 +2438,7 @@ msgstr ""
|
|||
msgid "Who Need Help home"
|
||||
msgstr "Главная Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who Need Help is not an emergency or medical service. Medicine requests are limited to pickup of legal items already purchased or reserved."
|
||||
msgstr ""
|
||||
|
|
@ -2567,6 +2591,7 @@ msgstr "Ваш профиль"
|
|||
msgid "Your request is now visible to nearby helpers."
|
||||
msgstr "Теперь вашу заявку видят помощники рядом."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:6
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:342
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your requests"
|
||||
|
|
@ -2593,7 +2618,7 @@ msgstr "активность"
|
|||
msgid "activity message"
|
||||
msgstr "сообщение активности"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:79
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "before confirming."
|
||||
msgstr "перед подтверждением."
|
||||
|
|
@ -2670,7 +2695,7 @@ msgstr "оценка"
|
|||
msgid "rating %{rating}"
|
||||
msgstr "оценка %{rating}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:78
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "safety rules"
|
||||
msgstr "Правила безопасности"
|
||||
|
|
@ -2778,7 +2803,9 @@ msgstr "Объединено"
|
|||
msgid "Reciprocal rating ring"
|
||||
msgstr "Кольцо взаимных оценок"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:26
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:263
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:194
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rejected"
|
||||
msgstr "Отклонено"
|
||||
|
|
@ -2811,6 +2838,8 @@ msgstr "Загрузить предыдущие сообщения"
|
|||
#: lib/who_need_help_web/live/profile_live.ex:354
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:303
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:360
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:215
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:276
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Load more"
|
||||
msgstr "Загрузить ещё"
|
||||
|
|
@ -2897,6 +2926,7 @@ msgid "The registration form is invalid."
|
|||
msgstr "Форма регистрации заполнена неверно."
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:239
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The selected record is no longer available."
|
||||
msgstr "Выбранная запись больше недоступна."
|
||||
|
|
@ -2996,7 +3026,7 @@ msgstr "Подключить аккаунт Google"
|
|||
msgid "Connect Google only after signing in here. We never merge accounts automatically by matching email addresses."
|
||||
msgstr "Подключайте Google только после входа здесь. Мы никогда не объединяем аккаунты автоматически по совпадению email."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:96
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:101
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create account and email me a link"
|
||||
msgstr "Создать аккаунт и отправить ссылку на email"
|
||||
|
|
@ -3058,7 +3088,7 @@ msgstr "Сессия входа через Google недействительна
|
|||
msgid "Google sign-in will be available after the operator configures it."
|
||||
msgstr "Вход через Google станет доступен после настройки оператором."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sending link..."
|
||||
msgstr "Отправляем ссылку..."
|
||||
|
|
@ -3142,3 +3172,632 @@ msgstr "Вход через Google отключён."
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "No Google account is connected."
|
||||
msgstr "Аккаунт Google не подключён."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A person I am authorised to represent"
|
||||
msgstr "Лицо, которое я уполномочен представлять"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A private status link has been sent when a contact email was provided and delivery is configured. Opening that link verifies the contact address. Keep the reference for follow-up."
|
||||
msgstr "Если указан контактный email и настроена доставка писем, на него отправлена приватная ссылка для проверки статуса. Переход по ссылке подтверждает адрес. Сохраните номер обращения."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ACCOUNT AND DATA"
|
||||
msgstr "АККАУНТ И ДАННЫЕ"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account access"
|
||||
msgstr "Доступ к аккаунту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and personal data"
|
||||
msgstr "Аккаунт и персональные данные"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:10
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account deletion"
|
||||
msgstr "Удаление аккаунта"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account email"
|
||||
msgstr "Email аккаунта"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:193
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Action taken"
|
||||
msgstr "Приняты меры"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Additional information"
|
||||
msgstr "Дополнительная информация"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:32
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Appeal a moderation decision"
|
||||
msgstr "Обжаловать решение модерации"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to removal form"
|
||||
msgstr "Вернуться к форме удаления"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to support"
|
||||
msgstr "Вернуться в поддержку"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "CONTENT REMOVAL"
|
||||
msgstr "УДАЛЕНИЕ КОНТЕНТА"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Check your email"
|
||||
msgstr "Проверьте почту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a category"
|
||||
msgstr "Выберите категорию"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a reason"
|
||||
msgstr "Выберите причину"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:51
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a relationship"
|
||||
msgstr "Выберите отношение"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a topic"
|
||||
msgstr "Выберите тему"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:27
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:20
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:195
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:256
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Closed"
|
||||
msgstr "Закрыто"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:160
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact"
|
||||
msgstr "Контакт"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact Who Need Help"
|
||||
msgstr "Связаться с Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:38
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:34
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact email"
|
||||
msgstr "Контактный email"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content removal and TAKE IT DOWN"
|
||||
msgstr "Удаление контента и TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content-removal notice"
|
||||
msgstr "Уведомление об удалении контента"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Copyright"
|
||||
msgstr "Авторские права"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:76
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Could not update the request. Please try again."
|
||||
msgstr "Не удалось обновить обращение. Попробуйте ещё раз."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:11
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:34
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data export"
|
||||
msgstr "Экспорт данных"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or information request"
|
||||
msgstr "Решение или запрос дополнительной информации"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or request for information"
|
||||
msgstr "Решение или запрос дополнительной информации"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete an account"
|
||||
msgstr "Удалить аккаунт"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Describe the problem"
|
||||
msgstr "Опишите проблему"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not include passwords, payment card details, access codes, prescriptions, or unnecessary medical information."
|
||||
msgstr "Не указывайте пароли, данные платёжных карт, коды доступа, рецепты или лишнюю медицинскую информацию."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not upload the image or video. Provide only the exact Who Need Help URL where it appears and enough text to identify it safely."
|
||||
msgstr "Не загружайте изображение или видео. Укажите только точный URL в Who Need Help и безопасное текстовое описание, достаточное для идентификации материала."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:72
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Electronic signature (type your full name)"
|
||||
msgstr "Электронная подпись (введите полное имя)"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:56
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Exact content URLs — one per line"
|
||||
msgstr "Точные URL контента — по одному в строке"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "General support and data requests"
|
||||
msgstr "Общая поддержка и запросы по данным"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am an authorised representative"
|
||||
msgstr "Я уполномоченный представитель"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am the affected person or rights holder"
|
||||
msgstr "Я пострадавшее лицо или правообладатель"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I believe in good faith that the identified content is illegal or infringes the stated right."
|
||||
msgstr "Я добросовестно считаю, что указанный контент незаконен или нарушает заявленное право."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that the information in this request is accurate and that I am the depicted person or authorised to act for them."
|
||||
msgstr "Я подтверждаю точность сведений и то, что являюсь изображённым лицом либо уполномочен действовать от его имени."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that this notice is accurate and complete to the best of my knowledge."
|
||||
msgstr "Я подтверждаю, что, насколько мне известно, это уведомление является точным и полным."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I have a good-faith belief that this intimate visual material was shared without consent."
|
||||
msgstr "Я добросовестно считаю, что этот интимный визуальный материал был опубликован без согласия."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identify the material without reproducing it and explain why it is non-consensual"
|
||||
msgstr "Опишите материал, не воспроизводя его, и объясните, почему он размещён без согласия"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:93
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identity and contact fields may be omitted for reports of sexual material involving a minor. Do not include or upload the material itself."
|
||||
msgstr "При сообщении о сексуальном материале с участием несовершеннолетнего поля имени и контакта можно не заполнять. Не прикладывайте и не загружайте сам материал."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Illegal content"
|
||||
msgstr "Незаконный контент"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. A copy is sent to the contact email when email delivery is configured."
|
||||
msgstr "Не передавайте эту ссылку статуса другим. При настроенной доставке писем её копия отправляется на контактный email."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. The submitter identity is not shown publicly or automatically disclosed to the person who posted the reported content."
|
||||
msgstr "Не передавайте эту ссылку статуса другим. Личность заявителя не публикуется и не раскрывается автоматически автору обжалуемого контента."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Law, right, or policy involved, if known"
|
||||
msgstr "Применимый закон, право или правило, если известно"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:162
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Locations"
|
||||
msgstr "Адреса контента"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Material involved"
|
||||
msgstr "Тип материала"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:9
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:81
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderation appeal"
|
||||
msgstr "Обжалование модерации"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:192
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "More information needed"
|
||||
msgstr "Нужна дополнительная информация"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Myself"
|
||||
msgstr "Себя"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "NOTICE RECEIVED"
|
||||
msgstr "УВЕДОМЛЕНИЕ ПОЛУЧЕНО"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New request"
|
||||
msgstr "Новое обращение"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:207
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No removal notices."
|
||||
msgstr "Нет уведомлений об удалении."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:268
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No support requests."
|
||||
msgstr "Нет обращений в поддержку."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:26
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Non-consensual intimate image or video"
|
||||
msgstr "Интимное изображение или видео без согласия"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:159
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not provided"
|
||||
msgstr "Не указано"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:33
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy request"
|
||||
msgstr "Запрос по конфиденциальности"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:23
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy violation"
|
||||
msgstr "Нарушение конфиденциальности"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Provide exact Who Need Help URLs. Do not upload or paste intimate imagery, identity documents, passwords, access codes, or unnecessary medical information."
|
||||
msgstr "Укажите точные URL в Who Need Help. Не загружайте и не вставляйте интимные материалы, документы, удостоверяющие личность, пароли, коды доступа или лишнюю медицинскую информацию."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "REQUEST RECEIVED"
|
||||
msgstr "ОБРАЩЕНИЕ ПОЛУЧЕНО"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Removal notice updated."
|
||||
msgstr "Уведомление об удалении обновлено."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:149
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report content"
|
||||
msgstr "Пожаловаться"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report illegal or harmful content"
|
||||
msgstr "Сообщить о незаконном или вредоносном контенте"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reported locations"
|
||||
msgstr "Указанные адреса контента"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:4
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:37
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:123
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request account deletion"
|
||||
msgstr "Запросить удаление аккаунта"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:117
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request deletion of your account and associated personal data, or contact support about access and export requests."
|
||||
msgstr "Запросите удаление аккаунта и связанных персональных данных либо обратитесь в поддержку по вопросам доступа и экспорта."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request removal of intimate visual material"
|
||||
msgstr "Запросить удаление интимного визуального материала"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:5
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SUPPORT"
|
||||
msgstr "ПОДДЕРЖКА"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:31
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:80
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Safety concern"
|
||||
msgstr "Проблема безопасности"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:203
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:264
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save and notify"
|
||||
msgstr "Сохранить и уведомить"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send support request"
|
||||
msgstr "Отправить обращение"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:15
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:27
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sexual material involving a minor"
|
||||
msgstr "Сексуальный материал с участием несовершеннолетнего"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:177
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stated basis:"
|
||||
msgstr "Указанное основание:"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Subject"
|
||||
msgstr "Тема"
|
||||
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:696
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit a legal content-removal notice"
|
||||
msgstr "Подать юридическое уведомление об удалении контента"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit removal notice"
|
||||
msgstr "Отправить уведомление об удалении"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit urgent removal request"
|
||||
msgstr "Отправить срочный запрос на удаление"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitter"
|
||||
msgstr "Заявитель"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitting this form does not immediately sign you out or erase evidence required for an open safety investigation. Support will verify and process the request."
|
||||
msgstr "Отправка формы не приводит к немедленному выходу из аккаунта и не удаляет доказательства, необходимые для открытого расследования безопасности. Поддержка проверит и обработает запрос."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support"
|
||||
msgstr "Поддержка"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:8
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support operations"
|
||||
msgstr "Рабочее место поддержки"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support queue"
|
||||
msgstr "Очередь поддержки"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support request updated."
|
||||
msgstr "Обращение в поддержку обновлено."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:116
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support requests and legal removal notices are separate queues. Decisions and operator identity are audited."
|
||||
msgstr "Обращения в поддержку и юридические уведомления об удалении находятся в разных очередях. Решения и личность оператора фиксируются в аудите."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:16
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support response"
|
||||
msgstr "Ответ поддержки"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN"
|
||||
msgstr "TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN request"
|
||||
msgstr "Запрос TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:30
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Technical issue"
|
||||
msgstr "Техническая проблема"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This requests deletion of your Who Need Help account and associated personal data. Some records may need to be retained when required for safety, fraud prevention, legal obligations, or resolving an active dispute; any retained data must be described in the applicable retention notice."
|
||||
msgstr "Это запрос на удаление аккаунта Who Need Help и связанных персональных данных. Некоторые записи могут сохраняться, если это необходимо для безопасности, предотвращения мошенничества, выполнения закона или разрешения активного спора; сохранённые данные должны быть описаны в применимом уведомлении о хранении."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:17
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:28
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Threat to life or safety"
|
||||
msgstr "Угроза жизни или безопасности"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_controller.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many removal notices. Please try again later."
|
||||
msgstr "Слишком много уведомлений об удалении. Повторите попытку позже."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:34
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many support requests. Please try again later."
|
||||
msgstr "Слишком много обращений в поддержку. Повторите попытку позже."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Trust and safety moderation"
|
||||
msgstr "Модерация доверия и безопасности"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Urgent review"
|
||||
msgstr "Срочное рассмотрение"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this dedicated process when an identifiable person is shown in an intimate image or video shared without consent, including a digital forgery. You may submit for yourself or as an authorised representative."
|
||||
msgstr "Используйте эту специальную процедуру, если узнаваемый человек показан на интимном изображении или видео, опубликованном без согласия, включая цифровую подделку. Запрос можно подать за себя или как уполномоченный представитель."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this electronic notice for specific content on Who Need Help that you believe is illegal or infringes your rights. Ordinary safety reports inside a request or chat remain available to signed-in users."
|
||||
msgstr "Используйте это электронное уведомление для конкретного контента в Who Need Help, который вы считаете незаконным или нарушающим ваши права. Обычные жалобы на безопасность внутри заявки или чата доступны вошедшим пользователям."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form for account access, technical problems, privacy questions, or other support. For illegal content or a removal request, use the dedicated removal form."
|
||||
msgstr "Используйте эту форму для вопросов доступа к аккаунту, технических проблем, конфиденциальности и другой поддержки. Для незаконного контента или запроса на удаление используйте специальную форму."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:126
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View support requests"
|
||||
msgstr "Посмотреть обращения в поддержку"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:254
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for requester"
|
||||
msgstr "Ожидается ответ заявителя"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for your response"
|
||||
msgstr "Ожидается ваш ответ"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We created support request %{reference}. A private status link has been sent to the contact email when delivery is configured. Opening that link verifies the address for public requests."
|
||||
msgstr "Мы создали обращение %{reference}. При настроенной доставке писем приватная ссылка статуса отправлена на контактный email. Переход по ней подтверждает адрес для публичных обращений."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "What do you need help with?"
|
||||
msgstr "Какая помощь вам нужна?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who are you submitting for?"
|
||||
msgstr "От чьего имени вы подаёте запрос?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Why do you believe this content should be removed?"
|
||||
msgstr "Почему вы считаете, что этот контент следует удалить?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have not submitted any support requests."
|
||||
msgstr "Вы ещё не отправляли обращений в поддержку."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your full name"
|
||||
msgstr "Ваше полное имя"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your name or organisation"
|
||||
msgstr "Ваше имя или организация"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your reference is %{reference}"
|
||||
msgstr "Номер вашего обращения: %{reference}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your relationship to the affected person or rights holder"
|
||||
msgstr "Ваше отношение к пострадавшему лицу или правообладателю"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:150
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:235
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "contact unverified"
|
||||
msgstr "контакт не подтверждён"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:154
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "review by %{time}"
|
||||
msgstr "рассмотреть до %{time}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:47
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete my Who Need Help account"
|
||||
msgstr "Удалить мой аккаунт Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please delete my account and associated personal data."
|
||||
msgstr "Пожалуйста, удалите мой аккаунт и связанные персональные данные."
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ msgstr ""
|
|||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100 != 11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10||n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:111
|
||||
#: lib/who_need_help_web/components/layouts.ex:257
|
||||
#: lib/who_need_help_web/components/layouts.ex:266
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account settings"
|
||||
msgstr "Параметри облікового запису"
|
||||
|
|
@ -30,13 +30,13 @@ msgstr "Дії"
|
|||
msgid "Ask for help"
|
||||
msgstr "Попросити допомоги"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:295
|
||||
#: lib/who_need_help_web/components/layouts.ex:310
|
||||
#: lib/who_need_help_web/components/layouts.ex:304
|
||||
#: lib/who_need_help_web/components/layouts.ex:319
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempting to reconnect"
|
||||
msgstr "Спроба повторного з’єднання"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:171
|
||||
#: lib/who_need_help_web/components/layouts.ex:175
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Categories"
|
||||
msgstr "Категорії"
|
||||
|
|
@ -65,13 +65,13 @@ msgid "Log in"
|
|||
msgstr "Вхід"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:114
|
||||
#: lib/who_need_help_web/components/layouts.ex:260
|
||||
#: lib/who_need_help_web/components/layouts.ex:269
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Log out"
|
||||
msgstr "Вийти"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:108
|
||||
#: lib/who_need_help_web/components/layouts.ex:254
|
||||
#: lib/who_need_help_web/components/layouts.ex:263
|
||||
#: lib/who_need_help_web/live/profile_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Profile"
|
||||
|
|
@ -83,7 +83,7 @@ msgstr "Профіль"
|
|||
msgid "Register"
|
||||
msgstr "Зареєструватися"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:161
|
||||
#: lib/who_need_help_web/components/layouts.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Requests"
|
||||
msgstr "Запити"
|
||||
|
|
@ -93,12 +93,12 @@ msgstr "Запити"
|
|||
msgid "See nearby requests"
|
||||
msgstr "Переглянути заявки поруч"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:302
|
||||
#: lib/who_need_help_web/components/layouts.ex:311
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Something went wrong!"
|
||||
msgstr "Щось пішло не так!"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:287
|
||||
#: lib/who_need_help_web/components/layouts.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We can't find the internet"
|
||||
msgstr "Немає з’єднання з інтернетом"
|
||||
|
|
@ -179,7 +179,7 @@ msgid "Account Settings"
|
|||
msgstr "Параметри облікового запису"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:63
|
||||
#: lib/who_need_help_web/components/layouts.ex:192
|
||||
#: lib/who_need_help_web/components/layouts.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and language"
|
||||
msgstr "Акаунт і мова"
|
||||
|
|
@ -200,7 +200,7 @@ msgstr "Центр дій"
|
|||
msgid "Active"
|
||||
msgstr "Активний"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:166
|
||||
#: lib/who_need_help_web/components/layouts.ex:170
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Activities"
|
||||
|
|
@ -385,7 +385,7 @@ msgstr ""
|
|||
msgid "Briefly describe the help you need"
|
||||
msgstr "Коротко опишіть, яка допомога вам потрібна"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#: lib/who_need_help_web/components/layouts.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Build Week feedback"
|
||||
msgstr "Звіт для Build Week"
|
||||
|
|
@ -668,7 +668,7 @@ msgstr ""
|
|||
msgid "Dismissed"
|
||||
msgstr "Відхилено"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:71
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:76
|
||||
#: lib/who_need_help_web/live/profile_live.ex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Display name"
|
||||
|
|
@ -692,7 +692,7 @@ msgstr "Немає акаунта?"
|
|||
msgid "Double-blind review"
|
||||
msgstr "Двосторонній прихований відгук"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:62
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:67
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:89
|
||||
#: lib/who_need_help_web/controllers/user_session_html/new.html.heex:122
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:15
|
||||
|
|
@ -857,7 +857,7 @@ msgstr "Помічник"
|
|||
msgid "Helper: %{name}"
|
||||
msgstr "Помічник: %{name}"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:176
|
||||
#: lib/who_need_help_web/components/layouts.ex:180
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Helpers"
|
||||
msgstr "Помічники"
|
||||
|
|
@ -933,7 +933,7 @@ msgid "Human decisions retained"
|
|||
msgstr "Рішення залишаються за людиною"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:39
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:85
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am 18 or older and accept the safety rules"
|
||||
msgstr "Мені 18 років, і я приймаю правила безпеки."
|
||||
|
|
@ -985,9 +985,12 @@ msgstr ""
|
|||
"Якщо ця адреса електронної пошти є в нашій системі, незабаром ви отримаєте "
|
||||
"інструкції для входу."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:9
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:25
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:678
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:253
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1109
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:91
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Impersonation"
|
||||
msgstr "Видавання себе за іншу особу"
|
||||
|
|
@ -1208,7 +1211,7 @@ msgstr "Надіслати повідомлення схваленій груп
|
|||
msgid "Mode"
|
||||
msgstr "Режим"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:181
|
||||
#: lib/who_need_help_web/components/layouts.ex:185
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:9
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:291
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
@ -1222,6 +1225,7 @@ msgid "Moderator"
|
|||
msgstr "Модератор"
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:230
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:73
|
||||
#: lib/who_need_help_web/user_auth.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderator access is required."
|
||||
|
|
@ -1365,12 +1369,16 @@ msgstr ""
|
|||
"Тільки організатор і схвалені учасники можуть читати або надсилати ці "
|
||||
"повідомлення."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:16
|
||||
#: lib/who_need_help_web/live/activity_live/index.ex:166
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:342
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:257
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:176
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:177
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:636
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:189
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:252
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Open"
|
||||
msgstr "Відкрита"
|
||||
|
|
@ -1415,10 +1423,17 @@ msgstr "Керування організатора"
|
|||
msgid "Organizer social links"
|
||||
msgstr "Посилання організатора на соцмережі"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:18
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:49
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:13
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:35
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:679
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:254
|
||||
#: lib/who_need_help_web/live/profile_live.ex:311
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1110
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:85
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other"
|
||||
msgstr "Інше"
|
||||
|
|
@ -1469,6 +1484,7 @@ msgid "Please check the entered data."
|
|||
msgstr "Будь ласка, перевірте введені дані."
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:240
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please check the submitted fields."
|
||||
msgstr "Будь ласка, перевірте вказані поля."
|
||||
|
|
@ -1605,6 +1621,7 @@ msgid "READ BEFORE USING THE SERVICE"
|
|||
msgstr "ПРОЧИТАЙТЕ ПЕРЕД ВИКОРИСТАННЯМ СЕРВІСУ"
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:290
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:111
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RESTRICTED WORKSPACE"
|
||||
msgstr "ОБМЕЖЕНА РОБОЧА ОБЛАСТЬ"
|
||||
|
|
@ -1628,11 +1645,12 @@ msgstr ""
|
|||
msgid "Rating"
|
||||
msgstr "Оцінка"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:77
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Read the"
|
||||
msgstr "Прочитайте"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:20
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:672
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reason"
|
||||
|
|
@ -1746,8 +1764,10 @@ msgstr "Автор заявки: %{count} завершено"
|
|||
msgid "Resolution note"
|
||||
msgstr "Примітка до рішення"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:19
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:259
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:365
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:255
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resolved"
|
||||
msgstr "Вирішено"
|
||||
|
|
@ -1777,8 +1797,12 @@ msgstr ""
|
|||
msgid "Reviewed"
|
||||
msgstr "Перевірено"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:23
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:17
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:258
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:364
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:191
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:253
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reviewing"
|
||||
msgstr "На розгляді"
|
||||
|
|
@ -2263,12 +2287,12 @@ msgstr ""
|
|||
"Призначайте першу зустріч у громадському місці. Не публікуйте домашню "
|
||||
"адресу, код доступу, документ для подорожі чи іншу чутливу інформацію."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#: lib/who_need_help_web/components/layouts.ex:358
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use dark theme"
|
||||
msgstr "Увімкнути темну тему"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#: lib/who_need_help_web/components/layouts.ex:349
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use light theme"
|
||||
msgstr "Увімкнути світлу тему"
|
||||
|
|
@ -2286,7 +2310,7 @@ msgstr ""
|
|||
"Користуйтеся приватним чатом і, за бажанням, передаванням геопозиції в "
|
||||
"реальному часі."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:331
|
||||
#: lib/who_need_help_web/components/layouts.ex:340
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use system theme"
|
||||
msgstr "Використати системну тему"
|
||||
|
|
@ -2408,7 +2432,7 @@ msgstr ""
|
|||
msgid "Who Need Help home"
|
||||
msgstr "Головна Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:90
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who Need Help is not an emergency or medical service. Medicine requests are limited to pickup of legal items already purchased or reserved."
|
||||
msgstr ""
|
||||
|
|
@ -2557,6 +2581,7 @@ msgstr "Ваш профіль"
|
|||
msgid "Your request is now visible to nearby helpers."
|
||||
msgstr "Тепер вашу заявку бачать помічники поруч."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:6
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:342
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your requests"
|
||||
|
|
@ -2583,7 +2608,7 @@ msgstr "активність"
|
|||
msgid "activity message"
|
||||
msgstr "повідомлення активності"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:79
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "before confirming."
|
||||
msgstr "перед підтвердженням."
|
||||
|
|
@ -2660,7 +2685,7 @@ msgstr "оцінка"
|
|||
msgid "rating %{rating}"
|
||||
msgstr "оцінка %{rating}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:78
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "safety rules"
|
||||
msgstr "правила безпеки"
|
||||
|
|
@ -2768,7 +2793,9 @@ msgstr "Об’єднано"
|
|||
msgid "Reciprocal rating ring"
|
||||
msgstr "Кільце взаємних оцінок"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:26
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:263
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:194
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rejected"
|
||||
msgstr "Відхилено"
|
||||
|
|
@ -2801,6 +2828,8 @@ msgstr "Завантажити попередні повідомлення"
|
|||
#: lib/who_need_help_web/live/profile_live.ex:354
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:303
|
||||
#: lib/who_need_help_web/live/request_live/index.ex:360
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:215
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:276
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Load more"
|
||||
msgstr "Завантажити ще"
|
||||
|
|
@ -2887,6 +2916,7 @@ msgid "The registration form is invalid."
|
|||
msgstr "Форму реєстрації заповнено неправильно."
|
||||
|
||||
#: lib/who_need_help_web/live/moderation_live.ex:239
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:74
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The selected record is no longer available."
|
||||
msgstr "Вибраний запис більше недоступний."
|
||||
|
|
@ -2986,7 +3016,7 @@ msgstr "Підключити обліковий запис Google"
|
|||
msgid "Connect Google only after signing in here. We never merge accounts automatically by matching email addresses."
|
||||
msgstr "Підключайте Google лише після входу тут. Ми ніколи не об’єднуємо облікові записи автоматично за збігом email."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:96
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:101
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Create account and email me a link"
|
||||
msgstr "Створити обліковий запис і надіслати посилання на email"
|
||||
|
|
@ -3048,7 +3078,7 @@ msgstr "Сесія входу через Google недійсна."
|
|||
msgid "Google sign-in will be available after the operator configures it."
|
||||
msgstr "Вхід через Google стане доступним після налаштування оператором."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:95
|
||||
#: lib/who_need_help_web/controllers/user_registration_html/new.html.heex:100
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sending link..."
|
||||
msgstr "Надсилаємо посилання..."
|
||||
|
|
@ -3132,3 +3162,632 @@ msgstr "Вхід через Google відключено."
|
|||
#, elixir-autogen, elixir-format
|
||||
msgid "No Google account is connected."
|
||||
msgstr "Обліковий запис Google не підключено."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A person I am authorised to represent"
|
||||
msgstr "Особа, яку я уповноважений представляти"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "A private status link has been sent when a contact email was provided and delivery is configured. Opening that link verifies the contact address. Keep the reference for follow-up."
|
||||
msgstr "Якщо вказано контактний email і налаштовано доставку листів, на нього надіслано приватне посилання для перевірки статусу. Перехід за посиланням підтверджує адресу. Збережіть номер звернення."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ACCOUNT AND DATA"
|
||||
msgstr "ОБЛІКОВИЙ ЗАПИС І ДАНІ"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:29
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account access"
|
||||
msgstr "Доступ до облікового запису"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:115
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account and personal data"
|
||||
msgstr "Обліковий запис і персональні дані"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:10
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:82
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account deletion"
|
||||
msgstr "Видалення облікового запису"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Account email"
|
||||
msgstr "Email облікового запису"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:193
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Action taken"
|
||||
msgstr "Вжито заходів"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Additional information"
|
||||
msgstr "Додаткова інформація"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:32
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Appeal a moderation decision"
|
||||
msgstr "Оскаржити рішення модерації"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to removal form"
|
||||
msgstr "Повернутися до форми видалення"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Back to support"
|
||||
msgstr "Повернутися до підтримки"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "CONTENT REMOVAL"
|
||||
msgstr "ВИДАЛЕННЯ КОНТЕНТУ"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Check your email"
|
||||
msgstr "Перевірте пошту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a category"
|
||||
msgstr "Виберіть категорію"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:31
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a reason"
|
||||
msgstr "Виберіть причину"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:51
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a relationship"
|
||||
msgstr "Виберіть відношення"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Choose a topic"
|
||||
msgstr "Виберіть тему"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:27
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:20
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:195
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:256
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Closed"
|
||||
msgstr "Закрито"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:160
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact"
|
||||
msgstr "Контакт"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact Who Need Help"
|
||||
msgstr "Зв’язатися з Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:38
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:34
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Contact email"
|
||||
msgstr "Контактний email"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content removal and TAKE IT DOWN"
|
||||
msgstr "Видалення контенту та TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Content-removal notice"
|
||||
msgstr "Повідомлення про видалення контенту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:90
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Copyright"
|
||||
msgstr "Авторські права"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:76
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Could not update the request. Please try again."
|
||||
msgstr "Не вдалося оновити звернення. Спробуйте ще раз."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:11
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:34
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data export"
|
||||
msgstr "Експорт даних"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:201
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or information request"
|
||||
msgstr "Рішення або запит додаткової інформації"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decision or request for information"
|
||||
msgstr "Рішення або запит додаткової інформації"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete an account"
|
||||
msgstr "Видалити обліковий запис"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Describe the problem"
|
||||
msgstr "Опишіть проблему"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:56
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not include passwords, payment card details, access codes, prescriptions, or unnecessary medical information."
|
||||
msgstr "Не вказуйте паролі, дані платіжних карток, коди доступу, рецепти або зайву медичну інформацію."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Do not upload the image or video. Provide only the exact Who Need Help URL where it appears and enough text to identify it safely."
|
||||
msgstr "Не завантажуйте зображення чи відео. Укажіть лише точний URL у Who Need Help і безпечний текстовий опис, достатній для ідентифікації матеріалу."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:72
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Electronic signature (type your full name)"
|
||||
msgstr "Електронний підпис (введіть повне ім’я)"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:56
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Exact content URLs — one per line"
|
||||
msgstr "Точні URL контенту — по одному в рядку"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "General support and data requests"
|
||||
msgstr "Загальна підтримка та запити щодо даних"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am an authorised representative"
|
||||
msgstr "Я уповноважений представник"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:47
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I am the affected person or rights holder"
|
||||
msgstr "Я постраждала особа або правовласник"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I believe in good faith that the identified content is illegal or infringes the stated right."
|
||||
msgstr "Я добросовісно вважаю, що зазначений контент є незаконним або порушує заявлене право."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that the information in this request is accurate and that I am the depicted person or authorised to act for them."
|
||||
msgstr "Я підтверджую точність відомостей і те, що є зображеною особою або уповноважений діяти від її імені."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I confirm that this notice is accurate and complete to the best of my knowledge."
|
||||
msgstr "Я підтверджую, що, наскільки мені відомо, це повідомлення є точним і повним."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:75
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "I have a good-faith belief that this intimate visual material was shared without consent."
|
||||
msgstr "Я добросовісно вважаю, що цей інтимний візуальний матеріал було поширено без згоди."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identify the material without reproducing it and explain why it is non-consensual"
|
||||
msgstr "Опишіть матеріал, не відтворюючи його, і поясніть, чому його поширено без згоди"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:93
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Identity and contact fields may be omitted for reports of sexual material involving a minor. Do not include or upload the material itself."
|
||||
msgstr "У повідомленні про сексуальний матеріал за участю неповнолітнього поля імені й контакту можна не заповнювати. Не додавайте й не завантажуйте сам матеріал."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:6
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:88
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Illegal content"
|
||||
msgstr "Незаконний контент"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. A copy is sent to the contact email when email delivery is configured."
|
||||
msgstr "Не передавайте це посилання статусу іншим. Якщо доставку листів налаштовано, його копія надсилається на контактний email."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Keep this status link private. The submitter identity is not shown publicly or automatically disclosed to the person who posted the reported content."
|
||||
msgstr "Не передавайте це посилання статусу іншим. Особа заявника не публікується й автоматично не розкривається автору оскаржуваного контенту."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Law, right, or policy involved, if known"
|
||||
msgstr "Застосовний закон, право або правило, якщо відомо"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:162
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Locations"
|
||||
msgstr "Адреси контенту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Material involved"
|
||||
msgstr "Тип матеріалу"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:9
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:81
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Moderation appeal"
|
||||
msgstr "Оскарження модерації"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:192
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "More information needed"
|
||||
msgstr "Потрібна додаткова інформація"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Myself"
|
||||
msgstr "Себе"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "NOTICE RECEIVED"
|
||||
msgstr "ПОВІДОМЛЕННЯ ОТРИМАНО"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "New request"
|
||||
msgstr "Нове звернення"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:207
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No removal notices."
|
||||
msgstr "Немає повідомлень про видалення."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:268
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No support requests."
|
||||
msgstr "Немає звернень до підтримки."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:26
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:24
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:94
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Non-consensual intimate image or video"
|
||||
msgstr "Інтимне зображення або відео без згоди"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:159
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not provided"
|
||||
msgstr "Не вказано"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:12
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:33
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy request"
|
||||
msgstr "Запит щодо конфіденційності"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:23
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Privacy violation"
|
||||
msgstr "Порушення конфіденційності"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Provide exact Who Need Help URLs. Do not upload or paste intimate imagery, identity documents, passwords, access codes, or unnecessary medical information."
|
||||
msgstr "Укажіть точні URL у Who Need Help. Не завантажуйте й не вставляйте інтимні матеріали, документи, що посвідчують особу, паролі, коди доступу або зайву медичну інформацію."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "REQUEST RECEIVED"
|
||||
msgstr "ЗВЕРНЕННЯ ОТРИМАНО"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Removal notice updated."
|
||||
msgstr "Повідомлення про видалення оновлено."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:149
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report content"
|
||||
msgstr "Поскаржитися"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Report illegal or harmful content"
|
||||
msgstr "Повідомити про незаконний або шкідливий контент"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/show.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Reported locations"
|
||||
msgstr "Указані адреси контенту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:4
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:37
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:123
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request account deletion"
|
||||
msgstr "Запросити видалення облікового запису"
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:117
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request deletion of your account and associated personal data, or contact support about access and export requests."
|
||||
msgstr "Запросіть видалення облікового запису та пов’язаних персональних даних або зверніться до підтримки щодо доступу й експорту."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request removal of intimate visual material"
|
||||
msgstr "Запросити видалення інтимного візуального матеріалу"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:5
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SUPPORT"
|
||||
msgstr "ПІДТРИМКА"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:8
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:31
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:80
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Safety concern"
|
||||
msgstr "Проблема безпеки"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:203
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:264
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Save and notify"
|
||||
msgstr "Зберегти й повідомити"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Send support request"
|
||||
msgstr "Надіслати звернення"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:15
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:27
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:25
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sexual material involving a minor"
|
||||
msgstr "Сексуальний матеріал за участю неповнолітнього"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:177
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stated basis:"
|
||||
msgstr "Зазначена підстава:"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Subject"
|
||||
msgstr "Тема"
|
||||
|
||||
#: lib/who_need_help_web/live/activity_live/show.ex:696
|
||||
#: lib/who_need_help_web/live/request_live/show.ex:1127
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit a legal content-removal notice"
|
||||
msgstr "Подати юридичне повідомлення про видалення контенту"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit removal notice"
|
||||
msgstr "Надіслати повідомлення про видалення"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:89
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submit urgent removal request"
|
||||
msgstr "Надіслати терміновий запит на видалення"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitter"
|
||||
msgstr "Заявник"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Submitting this form does not immediately sign you out or erase evidence required for an open safety investigation. Support will verify and process the request."
|
||||
msgstr "Надсилання форми не призводить до негайного виходу з облікового запису й не видаляє докази, потрібні для відкритого розслідування безпеки. Підтримка перевірить та опрацює запит."
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:147
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support"
|
||||
msgstr "Підтримка"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:8
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support operations"
|
||||
msgstr "Робоче місце підтримки"
|
||||
|
||||
#: lib/who_need_help_web/components/layouts.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support queue"
|
||||
msgstr "Черга підтримки"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support request updated."
|
||||
msgstr "Звернення до підтримки оновлено."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:116
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support requests and legal removal notices are separate queues. Decisions and operator identity are audited."
|
||||
msgstr "Звернення до підтримки та юридичні повідомлення про видалення перебувають у різних чергах. Рішення й особа оператора фіксуються в аудиті."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/show.html.heex:16
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Support response"
|
||||
msgstr "Відповідь підтримки"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:3
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN"
|
||||
msgstr "TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TAKE IT DOWN request"
|
||||
msgstr "Запит TAKE IT DOWN"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:7
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:30
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Technical issue"
|
||||
msgstr "Технічна проблема"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This requests deletion of your Who Need Help account and associated personal data. Some records may need to be retained when required for safety, fraud prevention, legal obligations, or resolving an active dispute; any retained data must be described in the applicable retention notice."
|
||||
msgstr "Це запит на видалення облікового запису Who Need Help і пов’язаних персональних даних. Деякі записи можуть зберігатися, якщо це потрібно для безпеки, запобігання шахрайству, виконання закону або вирішення активного спору; збережені дані мають бути описані у відповідному повідомленні про зберігання."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:17
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:28
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:99
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Threat to life or safety"
|
||||
msgstr "Загроза життю або безпеці"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_controller.ex:54
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many removal notices. Please try again later."
|
||||
msgstr "Забагато повідомлень про видалення. Спробуйте пізніше."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:34
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Too many support requests. Please try again later."
|
||||
msgstr "Забагато звернень до підтримки. Спробуйте пізніше."
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:122
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Trust and safety moderation"
|
||||
msgstr "Модерація довіри й безпеки"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html.ex:22
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:190
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Urgent review"
|
||||
msgstr "Терміновий розгляд"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this dedicated process when an identifiable person is shown in an intimate image or video shared without consent, including a digital forgery. You may submit for yourself or as an authorised representative."
|
||||
msgstr "Скористайтеся цією спеціальною процедурою, якщо впізнавану людину показано на інтимному зображенні чи відео, поширеному без згоди, зокрема на цифровій підробці. Запит можна подати за себе або як уповноважений представник."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this electronic notice for specific content on Who Need Help that you believe is illegal or infringes your rights. Ordinary safety reports inside a request or chat remain available to signed-in users."
|
||||
msgstr "Скористайтеся цим електронним повідомленням для конкретного контенту в Who Need Help, який ви вважаєте незаконним або таким, що порушує ваші права. Звичайні скарги на безпеку всередині заявки чи чату доступні користувачам, які ввійшли."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Use this form for account access, technical problems, privacy questions, or other support. For illegal content or a removal request, use the dedicated removal form."
|
||||
msgstr "Скористайтеся цією формою для питань доступу до облікового запису, технічних проблем, конфіденційності та іншої підтримки. Для незаконного контенту або запиту на видалення скористайтеся спеціальною формою."
|
||||
|
||||
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:126
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View support requests"
|
||||
msgstr "Переглянути звернення до підтримки"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:254
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for requester"
|
||||
msgstr "Очікується відповідь заявника"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Waiting for your response"
|
||||
msgstr "Очікується ваша відповідь"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/received.html.heex:6
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "We created support request %{reference}. A private status link has been sent to the contact email when delivery is configured. Opening that link verifies the address for public requests."
|
||||
msgstr "Ми створили звернення %{reference}. Якщо доставку листів налаштовано, приватне посилання статусу надіслано на контактний email. Перехід за ним підтверджує адресу для публічних звернень."
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/new.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "What do you need help with?"
|
||||
msgstr "Яка допомога вам потрібна?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:42
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Who are you submitting for?"
|
||||
msgstr "Від чийого імені ви подаєте запит?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Why do you believe this content should be removed?"
|
||||
msgstr "Чому ви вважаєте, що цей контент слід видалити?"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_html/index.html.heex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You have not submitted any support requests."
|
||||
msgstr "Ви ще не надсилали звернень до підтримки."
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/take_it_down.html.heex:30
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your full name"
|
||||
msgstr "Ваше повне ім’я"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:34
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your name or organisation"
|
||||
msgstr "Ваше ім’я або організація"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/received.html.heex:5
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your reference is %{reference}"
|
||||
msgstr "Номер вашого звернення: %{reference}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/content_removal_html/new.html.heex:45
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Your relationship to the affected person or rights holder"
|
||||
msgstr "Ваше відношення до постраждалої особи або правовласника"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:150
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:235
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "contact unverified"
|
||||
msgstr "контакт не підтверджено"
|
||||
|
||||
#: lib/who_need_help_web/live/support_operations_live.ex:154
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "review by %{time}"
|
||||
msgstr "розглянути до %{time}"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:47
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Delete my Who Need Help account"
|
||||
msgstr "Видалити мій обліковий запис Who Need Help"
|
||||
|
||||
#: lib/who_need_help_web/controllers/support_controller.ex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Please delete my account and associated personal data."
|
||||
msgstr "Будь ласка, видаліть мій обліковий запис і пов’язані персональні дані."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
defmodule WhoNeedHelp.Repo.Migrations.CreateSupportAndContentRemoval do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:support_requests, primary_key: false) do
|
||||
add :id, :binary_id, primary_key: true
|
||||
add :reference, :string, null: false
|
||||
add :kind, :string, null: false
|
||||
add :status, :string, null: false, default: "open"
|
||||
add :contact_email, :string, null: false
|
||||
add :subject, :string, null: false
|
||||
add :details, :text, null: false
|
||||
add :contact_verified_at, :utc_datetime
|
||||
add :resolution_note, :text
|
||||
add :reviewed_at, :utc_datetime
|
||||
add :response_sent_at, :utc_datetime
|
||||
add :requester_id, references(:users, type: :binary_id, on_delete: :nilify_all)
|
||||
add :reviewed_by_id, references(:users, type: :binary_id, on_delete: :nilify_all)
|
||||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
create unique_index(:support_requests, [:reference])
|
||||
create index(:support_requests, [:status, :inserted_at, :id])
|
||||
create index(:support_requests, [:kind, :status, :inserted_at, :id])
|
||||
create index(:support_requests, [:requester_id, :inserted_at, :id])
|
||||
|
||||
create table(:content_removal_notices, primary_key: false) do
|
||||
add :id, :binary_id, primary_key: true
|
||||
add :reference, :string, null: false
|
||||
add :regime, :string, null: false, default: "general"
|
||||
add :category, :string, null: false
|
||||
add :status, :string, null: false, default: "open"
|
||||
add :submitter_name, :string
|
||||
add :contact_email, :string
|
||||
add :relationship, :string
|
||||
add :content_locations, :text, null: false
|
||||
add :explanation, :text, null: false
|
||||
add :legal_basis, :text
|
||||
add :contact_verified_at, :utc_datetime
|
||||
add :good_faith, :boolean, null: false, default: false
|
||||
add :accurate_complete, :boolean, null: false, default: false
|
||||
add :electronic_signature, :string
|
||||
add :resolution_note, :text
|
||||
add :reviewed_at, :utc_datetime
|
||||
add :response_due_at, :utc_datetime
|
||||
add :acknowledgement_sent_at, :utc_datetime
|
||||
add :decision_sent_at, :utc_datetime
|
||||
add :requester_id, references(:users, type: :binary_id, on_delete: :nilify_all)
|
||||
add :reviewed_by_id, references(:users, type: :binary_id, on_delete: :nilify_all)
|
||||
timestamps(type: :utc_datetime)
|
||||
end
|
||||
|
||||
create unique_index(:content_removal_notices, [:reference])
|
||||
create index(:content_removal_notices, [:status, :inserted_at, :id])
|
||||
create index(:content_removal_notices, [:regime, :status, :inserted_at, :id])
|
||||
create index(:content_removal_notices, [:requester_id, :inserted_at, :id])
|
||||
end
|
||||
end
|
||||
|
|
@ -96,6 +96,7 @@ smtp_auth=${PRODUCTION_SMTP_AUTH:-always}
|
|||
smtp_tls=${PRODUCTION_SMTP_TLS:-always}
|
||||
smtp_ssl=${PRODUCTION_SMTP_SSL:-false}
|
||||
email_from_address=${PRODUCTION_EMAIL_FROM_ADDRESS:-"contact@$domain"}
|
||||
support_inbox_address=${PRODUCTION_SUPPORT_INBOX_ADDRESS:-}
|
||||
|
||||
tmp=$(mktemp "$target_dir/.production-env.XXXXXX")
|
||||
trap 'rm -f "$tmp"' EXIT HUP INT TERM
|
||||
|
|
@ -123,6 +124,7 @@ SMTP_AUTH_VALUE=$smtp_auth \
|
|||
SMTP_TLS_VALUE=$smtp_tls \
|
||||
SMTP_SSL_VALUE=$smtp_ssl \
|
||||
EMAIL_FROM_ADDRESS_VALUE=$email_from_address \
|
||||
SUPPORT_INBOX_ADDRESS_VALUE=$support_inbox_address \
|
||||
awk '
|
||||
BEGIN {
|
||||
replacement["DEPLOYMENT_TARGET"] = "compose"
|
||||
|
|
@ -155,6 +157,7 @@ EMAIL_FROM_ADDRESS_VALUE=$email_from_address \
|
|||
replacement["SMTP_TLS"] = ENVIRON["SMTP_TLS_VALUE"]
|
||||
replacement["SMTP_SSL"] = ENVIRON["SMTP_SSL_VALUE"]
|
||||
replacement["EMAIL_FROM_ADDRESS"] = ENVIRON["EMAIL_FROM_ADDRESS_VALUE"]
|
||||
replacement["SUPPORT_INBOX_ADDRESS"] = ENVIRON["SUPPORT_INBOX_ADDRESS_VALUE"]
|
||||
replacement["CODEX_SESSION_ID"] = "not-configured"
|
||||
}
|
||||
{
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ smtp_auth=$(require_value SMTP_AUTH)
|
|||
smtp_tls=$(require_value SMTP_TLS)
|
||||
smtp_ssl=$(require_value SMTP_SSL)
|
||||
email_from_address=$(require_value EMAIL_FROM_ADDRESS)
|
||||
support_inbox_address=$(optional_value SUPPORT_INBOX_ADDRESS)
|
||||
google_oauth_client_id=$(optional_value GOOGLE_OAUTH_CLIENT_ID)
|
||||
google_oauth_client_secret=$(optional_value GOOGLE_OAUTH_CLIENT_SECRET)
|
||||
|
||||
|
|
@ -224,6 +225,11 @@ fi
|
|||
echo "EMAIL_FROM_ADDRESS is not an email address." >&2
|
||||
exit 1
|
||||
}
|
||||
if [[ -n "$support_inbox_address" &&
|
||||
! "$support_inbox_address" =~ ^[^@,\;[:space:]]+@[^@,\;[:space:]]+$ ]]; then
|
||||
echo "SUPPORT_INBOX_ADDRESS is not an email address." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -n "$google_oauth_client_id" || -n "$google_oauth_client_secret" ]]; then
|
||||
[[ -n "$google_oauth_client_id" && -n "$google_oauth_client_secret" ]] || {
|
||||
|
|
|
|||
202
test/who_need_help/support_and_content_removal_test.exs
Normal file
202
test/who_need_help/support_and_content_removal_test.exs
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
defmodule WhoNeedHelp.SupportAndContentRemovalTest do
|
||||
use WhoNeedHelp.DataCase, async: false
|
||||
|
||||
import WhoNeedHelp.AccountsFixtures
|
||||
import Swoosh.TestAssertions
|
||||
|
||||
alias WhoNeedHelp.{ContentRemoval, Repo, Support}
|
||||
alias WhoNeedHelp.ContentRemoval.Notice
|
||||
alias WhoNeedHelp.Support.SupportRequest
|
||||
alias WhoNeedHelp.Trust.AuditEvent
|
||||
|
||||
test "public support request is persisted, acknowledged, and verified only through its email link" do
|
||||
assert {:ok, request} =
|
||||
Support.create_request(nil, %{
|
||||
"kind" => "technical_issue",
|
||||
"contact_email" => " Person@Example.com ",
|
||||
"subject" => "Map does not open",
|
||||
"details" => "The request map remains unavailable after reloading the page."
|
||||
})
|
||||
|
||||
assert request.reference =~ "SUP-"
|
||||
assert request.contact_email == "person@example.com"
|
||||
assert is_nil(request.contact_verified_at)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
email.subject =~ request.reference and email.text_body =~ Support.status_url(request)
|
||||
end)
|
||||
|
||||
assert {:error, :not_found} = Support.get_by_access_token(request.id, "invalid")
|
||||
|
||||
assert {:ok, verified} =
|
||||
Support.get_by_access_token(request.id, Support.access_token(request))
|
||||
|
||||
assert verified.contact_verified_at
|
||||
|
||||
assert Repo.exists?(
|
||||
from event in AuditEvent,
|
||||
where:
|
||||
event.action == "support_request.created" and
|
||||
event.target_id == ^request.id
|
||||
)
|
||||
end
|
||||
|
||||
test "configured support inbox receives a metadata-only operator alert and Reply-To" do
|
||||
previous = Application.get_env(:who_need_help, :support_inbox_address)
|
||||
Application.put_env(:who_need_help, :support_inbox_address, "support@example.com")
|
||||
on_exit(fn -> Application.put_env(:who_need_help, :support_inbox_address, previous) end)
|
||||
|
||||
assert {:ok, request} =
|
||||
Support.create_request(nil, %{
|
||||
"kind" => "moderation_appeal",
|
||||
"contact_email" => "appeal@example.com",
|
||||
"subject" => "Appeal moderation decision",
|
||||
"details" =>
|
||||
"Please review the moderation decision identified in my account notice."
|
||||
})
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
email.to == [{"", "appeal@example.com"}] and
|
||||
email.reply_to == {"", "support@example.com"}
|
||||
end)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
email.to == [{"", "support@example.com"}] and email.subject =~ request.reference and
|
||||
email.text_body =~ "/support/operations" and
|
||||
not String.contains?(email.text_body, request.details)
|
||||
end)
|
||||
end
|
||||
|
||||
test "authenticated support uses the account email and staff moderation is audited" do
|
||||
user = user_fixture()
|
||||
assert_email_sent()
|
||||
scope = user_scope_fixture(user)
|
||||
|
||||
assert {:ok, request} =
|
||||
Support.create_request(scope, %{
|
||||
"kind" => "data_export",
|
||||
"contact_email" => "forged@example.com",
|
||||
"subject" => "Export my data",
|
||||
"details" =>
|
||||
"Please prepare an export of the personal data associated with my account."
|
||||
})
|
||||
|
||||
assert request.contact_email == user.email
|
||||
assert request.contact_verified_at
|
||||
assert_email_sent()
|
||||
|
||||
moderator =
|
||||
user_fixture()
|
||||
|> Ecto.Changeset.change(role: :moderator)
|
||||
|> Repo.update!()
|
||||
|
||||
assert_email_sent()
|
||||
|
||||
assert {:error, :forbidden} =
|
||||
Support.moderate(scope, request.id, %{
|
||||
"status" => "resolved",
|
||||
"resolution_note" => "Not allowed"
|
||||
})
|
||||
|
||||
assert {:ok, resolved} =
|
||||
Support.moderate(user_scope_fixture(moderator), request.id, %{
|
||||
"status" => "resolved",
|
||||
"resolution_note" => "The export is ready for the verified account owner."
|
||||
})
|
||||
|
||||
assert resolved.status == :resolved
|
||||
assert resolved.response_sent_at
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
email.subject =~ "support update" and email.text_body =~ "export is ready"
|
||||
end)
|
||||
end
|
||||
|
||||
test "TAKE IT DOWN notices use a separate urgent queue and never accept an unrelated category" do
|
||||
attrs = %{
|
||||
"category" => "non_consensual_intimate_media",
|
||||
"submitter_name" => "Affected Person",
|
||||
"contact_email" => "affected@example.com",
|
||||
"relationship" => "self",
|
||||
"content_locations" => "https://example.test/requests/one",
|
||||
"explanation" => "An intimate visual depiction of me was posted without my consent.",
|
||||
"electronic_signature" => "Affected Person",
|
||||
"good_faith" => "true",
|
||||
"accurate_complete" => "true"
|
||||
}
|
||||
|
||||
assert {:ok, notice} = ContentRemoval.create_notice(nil, :take_it_down, attrs)
|
||||
assert notice.regime == :take_it_down
|
||||
assert notice.status == :urgent_review
|
||||
assert notice.response_due_at
|
||||
assert is_nil(notice.contact_verified_at)
|
||||
|
||||
assert_email_sent(fn email ->
|
||||
email.subject =~ notice.reference and
|
||||
email.text_body =~ "Do not reply with or upload intimate visual material"
|
||||
end)
|
||||
|
||||
assert {:error, changeset} =
|
||||
ContentRemoval.create_notice(nil, :take_it_down, %{
|
||||
attrs
|
||||
| "category" => "copyright",
|
||||
"contact_email" => "copyright@example.com"
|
||||
})
|
||||
|
||||
assert "must describe intimate visual material" in errors_on(changeset).category
|
||||
end
|
||||
|
||||
test "general notice validates exact URLs and permits anonymous child-safety reporting" do
|
||||
assert {:error, changeset} =
|
||||
ContentRemoval.create_notice(nil, :general, %{
|
||||
"category" => "illegal_content",
|
||||
"submitter_name" => "Reporter",
|
||||
"contact_email" => "reporter@example.com",
|
||||
"relationship" => "other",
|
||||
"content_locations" => "not a URL",
|
||||
"explanation" =>
|
||||
"This is a sufficiently long explanation of the reported content.",
|
||||
"electronic_signature" => "Reporter",
|
||||
"good_faith" => "true",
|
||||
"accurate_complete" => "true"
|
||||
})
|
||||
|
||||
assert "must contain one full HTTP or HTTPS URL per line" in errors_on(changeset).content_locations
|
||||
|
||||
assert {:ok, notice} =
|
||||
ContentRemoval.create_notice(nil, :general, %{
|
||||
"category" => "child_sexual_abuse_material",
|
||||
"content_locations" => "https://example.test/messages/safety-reference",
|
||||
"explanation" =>
|
||||
"The referenced location appears to contain sexual material involving a minor.",
|
||||
"good_faith" => "true",
|
||||
"accurate_complete" => "true"
|
||||
})
|
||||
|
||||
assert notice.status == :urgent_review
|
||||
assert is_nil(notice.contact_email)
|
||||
assert is_nil(notice.acknowledgement_sent_at)
|
||||
assert [%Notice{id: id}] = ContentRemoval.paginate_for_staff(moderator_scope()).entries
|
||||
assert id == notice.id
|
||||
end
|
||||
|
||||
test "account deletion is represented as a dedicated verified account-lifecycle request" do
|
||||
user = user_fixture()
|
||||
|
||||
assert {:ok, request} =
|
||||
user
|
||||
|> user_scope_fixture()
|
||||
|> Support.create_account_deletion_request()
|
||||
|
||||
assert %SupportRequest{kind: :account_deletion, requester_id: requester_id} = request
|
||||
assert requester_id == user.id
|
||||
assert request.contact_verified_at
|
||||
end
|
||||
|
||||
defp moderator_scope do
|
||||
user_fixture()
|
||||
|> Ecto.Changeset.change(role: :moderator)
|
||||
|> Repo.update!()
|
||||
|> user_scope_fixture()
|
||||
end
|
||||
end
|
||||
158
test/who_need_help_web/controllers/support_controller_test.exs
Normal file
158
test/who_need_help_web/controllers/support_controller_test.exs
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
defmodule WhoNeedHelpWeb.SupportControllerTest do
|
||||
use WhoNeedHelpWeb.ConnCase, async: false
|
||||
|
||||
import WhoNeedHelp.AccountsFixtures
|
||||
import Swoosh.TestAssertions
|
||||
|
||||
describe "public support and removal intake" do
|
||||
test "renders each public form", %{conn: conn} do
|
||||
assert html_response(get(conn, ~p"/support"), 200) =~ "Contact Who Need Help"
|
||||
assert html_response(get(conn, ~p"/account/delete"), 200) =~ "Request account deletion"
|
||||
|
||||
assert html_response(get(conn, ~p"/legal/content-removal"), 200) =~
|
||||
"Report illegal or harmful content"
|
||||
|
||||
assert html_response(
|
||||
get(conn, ~p"/legal/content-removal?location=/requests/specific-id"),
|
||||
200
|
||||
) =~ "/requests/specific-id"
|
||||
|
||||
assert html_response(get(conn, ~p"/legal/take-it-down"), 200) =~
|
||||
"Do not upload the image or video"
|
||||
end
|
||||
|
||||
test "creates support request without exposing its status token in the redirect", %{
|
||||
conn: conn
|
||||
} do
|
||||
conn =
|
||||
post(conn, ~p"/support", %{
|
||||
"support_request" => %{
|
||||
"kind" => "technical_issue",
|
||||
"contact_email" => "person@example.com",
|
||||
"subject" => "Unable to open a request",
|
||||
"details" => "The request page reports an error after the form is submitted."
|
||||
}
|
||||
})
|
||||
|
||||
location = redirected_to(conn)
|
||||
assert location =~ "/support/received?reference=SUP-"
|
||||
refute location =~ "token="
|
||||
assert_email_sent()
|
||||
end
|
||||
|
||||
test "creates urgent TAKE IT DOWN notice without accepting a media upload", %{conn: conn} do
|
||||
conn =
|
||||
post(conn, ~p"/legal/take-it-down", %{
|
||||
"notice" => %{
|
||||
"category" => "non_consensual_intimate_media",
|
||||
"submitter_name" => "Affected Person",
|
||||
"contact_email" => "affected@example.com",
|
||||
"relationship" => "self",
|
||||
"content_locations" => "https://example.test/requests/reported",
|
||||
"explanation" => "The identified intimate image was posted without my consent.",
|
||||
"electronic_signature" => "Affected Person",
|
||||
"good_faith" => "true",
|
||||
"accurate_complete" => "true"
|
||||
}
|
||||
})
|
||||
|
||||
location = redirected_to(conn)
|
||||
assert location =~ "/legal/content-removal/received?reference=REM-"
|
||||
refute location =~ "token="
|
||||
assert_email_sent()
|
||||
end
|
||||
|
||||
test "rejects malformed public form shapes without crashing", %{conn: conn} do
|
||||
assert response(post(conn, ~p"/support", %{"support_request" => "invalid"}), 400)
|
||||
|
||||
assert response(
|
||||
post(conn, ~p"/legal/content-removal", %{"notice" => "invalid"}),
|
||||
400
|
||||
)
|
||||
|
||||
assert response(
|
||||
post(conn, ~p"/legal/take-it-down", %{"notice" => "invalid"}),
|
||||
400
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated support" do
|
||||
setup :register_and_log_in_user
|
||||
|
||||
test "lists the current user's cases and links account deletion from settings", %{
|
||||
conn: conn,
|
||||
user: user
|
||||
} do
|
||||
{:ok, request} =
|
||||
WhoNeedHelp.Support.create_request(user_scope_fixture(user), %{
|
||||
"kind" => "account_access",
|
||||
"subject" => "Account question",
|
||||
"details" => "I need assistance understanding an account setting."
|
||||
})
|
||||
|
||||
assert html_response(get(conn, ~p"/support/requests"), 200) =~ request.reference
|
||||
assert html_response(get(conn, ~p"/users/settings"), 200) =~ ~p"/account/delete"
|
||||
end
|
||||
end
|
||||
|
||||
describe "operator queue authorization" do
|
||||
test "requires a moderator", %{conn: conn} do
|
||||
conn = get(conn, ~p"/support/operations")
|
||||
assert redirected_to(conn) == ~p"/users/log-in"
|
||||
end
|
||||
|
||||
test "renders separate support and removal queues for a moderator", %{conn: conn} do
|
||||
moderator =
|
||||
user_fixture()
|
||||
|> Ecto.Changeset.change(role: :moderator)
|
||||
|> WhoNeedHelp.Repo.update!()
|
||||
|
||||
{:ok, _support_request} =
|
||||
WhoNeedHelp.Support.create_request(nil, %{
|
||||
"kind" => "technical_issue",
|
||||
"contact_email" => "support-queue@example.com",
|
||||
"subject" => "Check the support queue",
|
||||
"details" => "This request verifies that an open status remains selected."
|
||||
})
|
||||
|
||||
{:ok, _removal_notice} =
|
||||
WhoNeedHelp.ContentRemoval.create_notice(nil, :general, %{
|
||||
"category" => "illegal_content",
|
||||
"submitter_name" => "Queue Reporter",
|
||||
"contact_email" => "removal-queue@example.com",
|
||||
"relationship" => "self",
|
||||
"content_locations" => "https://example.test/requests/queue-check",
|
||||
"explanation" => "This notice verifies that an open status remains selected.",
|
||||
"electronic_signature" => "Queue Reporter",
|
||||
"good_faith" => "true",
|
||||
"accurate_complete" => "true"
|
||||
})
|
||||
|
||||
response =
|
||||
conn
|
||||
|> log_in_user(moderator)
|
||||
|> get(~p"/support/operations")
|
||||
|> html_response(200)
|
||||
|
||||
assert response =~ "Content removal and TAKE IT DOWN"
|
||||
assert response =~ "General support and data requests"
|
||||
|
||||
document = LazyHTML.from_document(response)
|
||||
|
||||
assert Enum.count(
|
||||
LazyHTML.query(
|
||||
document,
|
||||
"select[id^='removal-'] option[value='open'][selected]"
|
||||
)
|
||||
) == 1
|
||||
|
||||
assert Enum.count(
|
||||
LazyHTML.query(
|
||||
document,
|
||||
"select[id^='support-'] option[value='open'][selected]"
|
||||
)
|
||||
) == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue
Block a user