Scale map discovery and harden account lifecycle support

This commit is contained in:
SimpleTest 2026-08-27 23:03:58 +03:00
parent 05dc9372e6
commit 01971f1bc4
27 changed files with 2396 additions and 647 deletions

View File

@ -595,6 +595,11 @@ const createAidMap = element => {
state.expandServerCluster = point => {
if (!point || !state.map) return
if (point.expansion_lookup === true) {
state.onClusterExpand?.({cluster_id: point.cluster_id})
return
}
const count = Number(point.count) || 1
const requestedZoom = Number(point.expansion_zoom)
const currentZoom = state.map.getZoom()
@ -625,6 +630,41 @@ const createAidMap = element => {
})
}
state.applyClusterExpansion = expansion => {
if (!expansion || !state.map) return
const longitude = Number(expansion.longitude)
const latitude = Number(expansion.latitude)
const requestedZoom = Number(expansion.zoom)
const count = Number(expansion.point_count) || 1
if (![longitude, latitude, requestedZoom].every(Number.isFinite)) return
const currentZoom = state.map.getZoom()
const expansionZoom = clusterExpansionTarget(currentZoom, requestedZoom)
if (currentZoom >= 21.75 && expansionZoom <= 22) {
const label = (state.element.dataset.clusterLabel || "%{count} items")
.replace("%{count}", String(count))
new maplibregl.Popup({offset: 18})
.setLngLat([longitude, latitude])
.setDOMContent(state.popupContent({
title: label,
location: state.element.dataset.clusterMaxZoomLabel || ""
}))
.addTo(state.map)
return
}
state.clusterExpansionPending = true
state.map.easeTo({
center: [longitude, latitude],
zoom: expansionZoom,
duration: 300
})
}
state.syncClusterImages = points => {
if (!state.map || state.element.dataset.discoveryMap !== "true") return
@ -2011,6 +2051,9 @@ export const Hooks = {
this.pushEvent("map-viewport-change", viewport)
this.aidMap.onClusterExpand = viewport =>
this.pushEvent("expand-map-cluster", viewport)
this.handleEvent("map-cluster-expansion", expansion =>
this.aidMap.applyClusterExpansion(expansion)
)
this.aidMap.mount()
},
updated() {

View File

@ -130,14 +130,19 @@ traffic; the public OpenStreetMap tile service is best-effort and has a usage
policy, not an application backend.
Request discovery is bounded by the validated map viewport sent by the
browser. PostGIS filters open requests against that area and groups visible
coordinates into Web Mercator grid cells sized from the geographic bounds and
rendered map dimensions. Dense cells are returned as aggregate clusters;
single cells preserve a request marker or privacy-radius area. Coordinate-free
requests are excluded from the map and appear in the list only when the user
supplies a matching public area/city search. LiveView subscribes to bounded
regional PubSub tiles plus the signed-in user's topic instead of the global
request stream.
browser. Persistent hourly rollups store additive Web Mercator cell counts for
zoom hierarchy levels 0 through 12. A read combines future-hour summaries with
raw rows from the current partial hour, then subtracts blocked owners exactly.
At higher zoom levels, and for searches whose predicates are not represented
by the rollup dimensions, PostGIS reads the bounded raw rows. Dense cells are
returned as aggregate clusters; a cell containing one visible record is
hydrated as its request marker or privacy-radius area. Cluster expansion uses
the exact surviving records in that cell, so bounds and zoom remain correct
for the current viewer rather than exposing a summary-only approximation.
Coordinate-free requests are excluded from the map and appear in the list only
when the user supplies a matching public area/city search. LiveView subscribes
to bounded regional PubSub tiles plus the signed-in user's topic instead of the
global request stream.
## Data durability and retention

View File

@ -822,10 +822,37 @@ application-level samples recorded the following medians:
| World | 56.182 / 3,975.605 ms | 3,910.191 / 7,416.714 ms | 10 / 791,753 |
Server clustering kept each measured map payload between 135 and 1,463 bytes
instead of returning hundreds of thousands of points. The broad low-zoom map
queries remain the measured optimization target: clustering bounds the
network/browser payload, but PostgreSQL still reads and groups the matching
records.
instead of returning hundreds of thousands of points. At that revision, the
broad low-zoom map queries were the measured optimization target: clustering
bounded the network/browser payload, but PostgreSQL still read and grouped the
matching records.
### Persistent discovery-rollup candidate
Observed locally on 2026-08-27 against a scratch clone of the persistent
million-request plus million-activity database. PostgreSQL was constrained to
one CPU. The source scale database and its named volume were not modified.
The candidate migration built hourly Web Mercator rollups for levels 0 through
12 in 16.7 seconds inside a 18.2-second full migration run. The resulting help
rollup contained 406,244 rows and occupied 116 MiB; the Activity rollup
contained 338,293 rows and occupied 88 MiB.
Warm authenticated discovery observations were:
| Query | No blocked users | One blocked user |
| --- | ---: | ---: |
| Help world / Europe / Kyiv level 10 | ~9 / 60 / 2 ms | ~16 / 76 / 3.6 ms |
| Activity world / Europe / Kyiv level 10 | ~7 / 50 / 2.6 ms | ~12 / 7 / 3.2 ms |
| Raw high-zoom help / Activity | ~19 / 24 ms | ~28 / 30 ms |
The represented totals remained exact at 950,523 visible help requests and
1,000,000 visible activities. A deliberately concentrated case with 100
blocked synthetic owners, requiring exact subtraction of roughly 100,000
objects, took approximately 0.5–0.8 seconds. That case remains a measured
worst-case optimization target; no arbitrary block-list limit or hidden
fallback was introduced. These workstation observations verify the query
shape and relative improvement. They are not a production capacity claim or a
minimum-resource requirement.
A headed Chrome check used the same persistent profile. It verified 24-card
initial pages, duplicate-free 48-card pagination, List/Map/Together layouts,

View File

@ -40,21 +40,33 @@ at most 20 locations in one notice.
## Contact verification and status access
Public support submissions display a reference but never expose the signed
status token in the redirect. They are stored as `pending_verification`, are not
visible in the operator queue, and do not produce an operator alert. The private
status link is sent to the contact email. Opening it atomically verifies the
address, changes the request to `open`, makes it visible to authorised staff,
and enqueues at most one metadata-only operator alert when that optional mode is
enabled. Opening the same link again does not send another alert. An authenticated
submission uses the confirmed account email, is verified immediately, and enters
the queue without this extra step. Ongoing requester messages update the staff
workspace through PubSub and do not generate one operator email per message.
Ordinary public support submissions display a reference but never expose the
signed status token in the redirect. They are stored as
`pending_verification`, are not visible in the operator queue, and do not
produce an operator alert. The private status link is sent to the contact
email. Opening it atomically verifies the address, changes the request to
`open`, makes it visible to authorised staff, and enqueues at most one
metadata-only operator alert when that optional mode is enabled. Opening the
same link again does not send another alert. An authenticated submission uses
the confirmed account email, is verified immediately, and enters the queue
without this extra step. Ongoing requester messages update the staff workspace
through PubSub and do not generate one operator email per message.
Exact repeats of the same unverified public support submission are represented
by one pending row. Its temporary fingerprint is a SHA-256 digest of normalized
form fields; it is cleared on verification and does not replace the original
record or its audit history. A pending support request or an emailed removal
Anonymous `account_access` and `account_deletion` submissions intentionally
use a stricter lifecycle contract. The normalized submitted address must match
exactly one existing account. The response is generic in every case, so it does
not disclose whether an account exists. An unknown or ambiguous address creates
no support row and sends no email. A unique match creates one account-linked
pending request per lifecycle kind and sends confirmation only to the email
already stored on that account. The request enters the staff queue only after
that mailbox confirms it. Repeated submissions reuse the pending request rather
than creating queue spam. No submitted address is silently substituted into a
different field or linked to a different account.
Exact repeats of the same unverified ordinary public support submission are
represented by one pending row. Its temporary fingerprint is a SHA-256 digest
of normalized form fields; it is cleared on verification and does not replace
the original record or its audit history. A pending support request or an emailed removal
notice that is still unverified after
`PUBLIC_CONTACT_VERIFICATION_MAX_AGE_SECONDS` is deleted by the maintenance
worker together with its creation audit entry. This verification-lifecycle

View File

@ -101,6 +101,29 @@ defmodule WhoNeedHelp.Accounts do
Repo.get_by(User, email: String.trim(email))
end
@doc """
Looks up an account by its normalized email without requiring confirmation.
The result is deliberately explicit when legacy data contains more than one
case-variant of the same address so callers never choose an account
arbitrarily.
"""
def get_user_by_normalized_email(email) when is_binary(email) do
normalized = email |> String.trim() |> String.downcase()
users =
User
|> where([user], fragment("lower(?)", user.email) == ^normalized)
|> limit(2)
|> Repo.all()
case users do
[user] -> {:ok, user}
[] -> {:error, :not_found}
[_first, _second] -> {:error, :ambiguous}
end
end
@doc """
Gets a user by email and password.

View File

@ -10,6 +10,7 @@ defmodule WhoNeedHelp.Activities do
alias WhoNeedHelp.Activities.{Activity, Message, Participant}
alias WhoNeedHelp.Catalog
alias WhoNeedHelp.Catalog.Category
alias WhoNeedHelp.Discovery.Rollup
alias WhoNeedHelp.Help.{DiscoveryCluster, DiscoveryViewport}
alias WhoNeedHelp.Pagination
alias WhoNeedHelp.Repo
@ -62,6 +63,19 @@ defmodule WhoNeedHelp.Activities do
def map_discovery_items(%Scope{user: user}, filters, %DiscoveryViewport{} = viewport) do
level = DiscoveryCluster.level_for_zoom(viewport.zoom)
if DiscoveryCluster.rollup_level?(level) and blank_area_filter?(filters) do
Rollup.activity_items(user, filters, viewport, level)
else
raw_map_discovery_items(user, filters, viewport, level)
end
end
def map_cluster_expansion(%Scope{user: user}, filters, cluster_id) do
Rollup.activity_expansion(user, filters, cluster_id)
end
defp raw_map_discovery_items(user, filters, viewport, level) do
cell_count = Integer.pow(2, level) * 1.0
points =
@ -166,13 +180,13 @@ defmodule WhoNeedHelp.Activities do
|> where(
[activity],
activity.creator_id not in subquery(
from block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id
from(block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id)
)
)
|> where(
[activity],
activity.creator_id not in subquery(
from block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id
from(block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id)
)
)
|> before_my_activity(cursor)
@ -528,11 +542,12 @@ defmodule WhoNeedHelp.Activities do
defp approved_participant_id?(activity_id, user_id) do
Repo.exists?(
from participant in Participant,
from(participant in Participant,
where:
participant.activity_id == ^activity_id and participant.user_id == ^user_id and
participant.status == :approved
)
)
end
defp validate_category_and_data(changeset) do
@ -794,13 +809,13 @@ defmodule WhoNeedHelp.Activities do
|> where(
[activity],
activity.creator_id not in subquery(
from block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id
from(block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id)
)
)
|> where(
[activity],
activity.creator_id not in subquery(
from block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id
from(block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id)
)
)
|> maybe_filter_category(filters["category_id"] || filters[:category_id])
@ -1015,6 +1030,14 @@ defmodule WhoNeedHelp.Activities do
|> String.replace("_", "\\_")
end
defp blank_area_filter?(filters) do
case filters["area"] || filters[:area] do
nil -> true
area when is_binary(area) -> String.trim(area) == ""
_invalid -> false
end
end
defp locked_activity(id) do
Activity
|> where([activity], activity.id == ^id)

View File

@ -0,0 +1,645 @@
defmodule WhoNeedHelp.Discovery.Rollup do
@moduledoc """
Reads the persistent, zoom-indexed discovery summaries.
The summary tables intentionally contain no user-specific state. A map read
combines their future-hour buckets with exact rows from the current partial
hour and subtracts rows owned by either side of a block. This keeps expiry
and blocking exact without grouping the complete discovery data set for
every viewport request.
"""
alias WhoNeedHelp.Accounts.User
alias WhoNeedHelp.Help.{DiscoveryCluster, DiscoveryViewport}
alias WhoNeedHelp.Repo
@type filters :: %{optional(String.t() | atom()) => term()}
def help_items(%User{} = user, filters, %DiscoveryViewport{} = viewport, level)
when is_integer(level) do
with true <- DiscoveryCluster.rollup_level?(level),
{:ok, category_id} <- optional_uuid(filter(filters, :category_id)),
{:ok, urgency} <- optional_urgency(filter(filters, :urgency)) do
{now, next_hour} = time_window()
query_help_rows(viewport, level, [
level,
now,
next_hour,
Ecto.UUID.dump!(user.id),
category_id,
urgency
])
|> Enum.map(&help_item(&1, level))
else
_unsupported_or_invalid_filter -> []
end
end
def activity_items(%User{} = user, filters, %DiscoveryViewport{} = viewport, level)
when is_integer(level) do
with true <- DiscoveryCluster.rollup_level?(level),
{:ok, category_id} <- optional_uuid(filter(filters, :category_id)) do
{now, next_hour} = time_window()
query_activity_rows(viewport, level, [
level,
now,
next_hour,
Ecto.UUID.dump!(user.id),
category_id
])
|> Enum.map(&activity_item(&1, level))
else
_unsupported_or_invalid_filter -> []
end
end
def help_expansion(%User{} = user, filters, cluster_id) when is_binary(cluster_id) do
with {:ok, {level, cell_x, cell_y}} <-
DiscoveryCluster.parse_cluster_id(:request, cluster_id),
true <- DiscoveryCluster.rollup_level?(level),
{:ok, category_id} <- optional_uuid(filter(filters, :category_id)),
{:ok, urgency} <- optional_urgency(filter(filters, :urgency)),
[count, west, south, east, north] when count > 0 <-
help_expansion_row(
expansion_params(
user,
level,
cell_x,
cell_y,
category_id,
urgency
)
) do
{:ok, expansion(cluster_id, level, count, west, south, east, north)}
else
_invalid_or_empty -> :error
end
end
def activity_expansion(%User{} = user, filters, cluster_id) when is_binary(cluster_id) do
with {:ok, {level, cell_x, cell_y}} <-
DiscoveryCluster.parse_cluster_id(:activity, cluster_id),
true <- DiscoveryCluster.rollup_level?(level),
{:ok, category_id} <- optional_uuid(filter(filters, :category_id)),
[count, west, south, east, north] when count > 0 <-
activity_expansion_row(
activity_expansion_params(user, level, cell_x, cell_y, category_id)
) do
{:ok, expansion(cluster_id, level, count, west, south, east, north)}
else
_invalid_or_empty -> :error
end
end
def prune_expired do
{_now, current_hour} = time_window()
help =
Repo.query!(
"DELETE FROM help_discovery_rollups WHERE visible_until_hour < $1",
[current_hour],
log: false
).num_rows
activities =
Repo.query!(
"DELETE FROM activity_discovery_rollups WHERE visible_until_hour < $1",
[current_hour],
log: false
).num_rows
%{help: help, activities: activities}
end
defp help_sql(viewport, level) do
cell_filter = cell_filter_sql(viewport, level)
cell_x = cell_x_sql("request.public_longitude", "$1")
cell_y = cell_y_sql("request.public_latitude", "$1")
"""
WITH blocked_users AS MATERIALIZED (
#{blocked_users_sql()}
), future_rollup AS MATERIALIZED (
SELECT
cell_x,
cell_y,
sum(point_count)::bigint AS point_count,
sum(point_count) FILTER (WHERE urgency = 'now')::bigint AS urgent_count
FROM help_discovery_rollups
WHERE level = $1
AND visible_until_hour >= $3
AND ($5::uuid IS NULL OR category_id = $5)
AND ($6::text IS NULL OR urgency = $6)
AND #{cell_filter}
GROUP BY cell_x, cell_y
), current_points AS MATERIALIZED (
SELECT
#{cell_x} AS cell_x,
#{cell_y} AS cell_y,
request.urgency
FROM help_requests AS request
WHERE #{eligible_help_sql("request")}
AND request.expires_at > $2
AND request.expires_at < $3
AND ($5::uuid IS NULL OR request.category_id = $5)
AND ($6::text IS NULL OR request.urgency = $6)
AND NOT #{blocked_user_sql("request.requester_id")}
), current_cells AS MATERIALIZED (
SELECT
cell_x,
cell_y,
count(*)::bigint AS point_count,
count(*) FILTER (WHERE urgency = 'now')::bigint AS urgent_count
FROM current_points
WHERE #{cell_filter}
GROUP BY cell_x, cell_y
), blocked_future_points AS MATERIALIZED (
SELECT
#{cell_x} AS cell_x,
#{cell_y} AS cell_y,
request.urgency
FROM blocked_users
JOIN help_requests AS request ON request.requester_id = blocked_users.user_id
WHERE #{eligible_help_sql("request")}
AND request.expires_at >= $3
AND ($5::uuid IS NULL OR request.category_id = $5)
AND ($6::text IS NULL OR request.urgency = $6)
), blocked_future_cells AS MATERIALIZED (
SELECT
cell_x,
cell_y,
-count(*)::bigint AS point_count,
-count(*) FILTER (WHERE urgency = 'now')::bigint AS urgent_count
FROM blocked_future_points
WHERE #{cell_filter}
GROUP BY cell_x, cell_y
), totals AS MATERIALIZED (
SELECT
cell_x,
cell_y,
sum(point_count)::bigint AS point_count,
sum(urgent_count)::bigint AS urgent_count
FROM (
SELECT * FROM future_rollup
UNION ALL
SELECT * FROM current_cells
UNION ALL
SELECT * FROM blocked_future_cells
) AS contributions
GROUP BY cell_x, cell_y
HAVING sum(point_count) > 0
)
SELECT
totals.cell_x,
totals.cell_y,
totals.point_count,
totals.urgent_count,
singleton.id,
singleton.title,
singleton.location_label,
singleton.public_longitude,
singleton.public_latitude,
singleton.location_visibility,
singleton.location_radius_meters
FROM totals
LEFT JOIN LATERAL (
SELECT
request.id,
request.title,
request.location_label,
request.public_longitude,
request.public_latitude,
request.location_visibility,
request.location_radius_meters
FROM help_requests AS request
WHERE totals.point_count = 1
AND #{eligible_help_sql("request")}
AND request.expires_at > $2
AND ($5::uuid IS NULL OR request.category_id = $5)
AND ($6::text IS NULL OR request.urgency = $6)
AND NOT #{blocked_user_sql("request.requester_id")}
AND #{cell_x} = totals.cell_x
AND #{cell_y} = totals.cell_y
LIMIT 1
) AS singleton ON totals.point_count = 1
ORDER BY totals.cell_x, totals.cell_y
"""
end
defp activity_sql(viewport, level) do
cell_filter = cell_filter_sql(viewport, level)
cell_x = cell_x_sql("activity.public_longitude", "$1")
cell_y = cell_y_sql("activity.public_latitude", "$1")
"""
WITH blocked_users AS MATERIALIZED (
#{blocked_users_sql()}
), future_rollup AS MATERIALIZED (
SELECT cell_x, cell_y, sum(point_count)::bigint AS point_count
FROM activity_discovery_rollups
WHERE level = $1
AND visible_until_hour >= $3
AND ($5::uuid IS NULL OR category_id = $5)
AND #{cell_filter}
GROUP BY cell_x, cell_y
), current_points AS MATERIALIZED (
SELECT #{cell_x} AS cell_x, #{cell_y} AS cell_y
FROM activities AS activity
WHERE #{eligible_activity_sql("activity")}
AND activity.starts_at > $2
AND activity.join_deadline > $2
AND (activity.starts_at < $3 OR activity.join_deadline < $3)
AND ($5::uuid IS NULL OR activity.category_id = $5)
AND NOT #{blocked_user_sql("activity.creator_id")}
), current_cells AS MATERIALIZED (
SELECT cell_x, cell_y, count(*)::bigint AS point_count
FROM current_points
WHERE #{cell_filter}
GROUP BY cell_x, cell_y
), blocked_future_points AS MATERIALIZED (
SELECT #{cell_x} AS cell_x, #{cell_y} AS cell_y
FROM blocked_users
JOIN activities AS activity ON activity.creator_id = blocked_users.user_id
WHERE #{eligible_activity_sql("activity")}
AND activity.starts_at > $2
AND activity.join_deadline > $2
AND activity.starts_at >= $3
AND activity.join_deadline >= $3
AND ($5::uuid IS NULL OR activity.category_id = $5)
), blocked_future_cells AS MATERIALIZED (
SELECT cell_x, cell_y, -count(*)::bigint AS point_count
FROM blocked_future_points
WHERE #{cell_filter}
GROUP BY cell_x, cell_y
), totals AS MATERIALIZED (
SELECT cell_x, cell_y, sum(point_count)::bigint AS point_count
FROM (
SELECT * FROM future_rollup
UNION ALL
SELECT * FROM current_cells
UNION ALL
SELECT * FROM blocked_future_cells
) AS contributions
GROUP BY cell_x, cell_y
HAVING sum(point_count) > 0
)
SELECT
totals.cell_x,
totals.cell_y,
totals.point_count,
singleton.id,
singleton.title,
singleton.location_label,
singleton.public_longitude,
singleton.public_latitude
FROM totals
LEFT JOIN LATERAL (
SELECT
activity.id,
activity.title,
activity.location_label,
activity.public_longitude,
activity.public_latitude
FROM activities AS activity
WHERE totals.point_count = 1
AND #{eligible_activity_sql("activity")}
AND activity.starts_at > $2
AND activity.join_deadline > $2
AND ($5::uuid IS NULL OR activity.category_id = $5)
AND NOT #{blocked_user_sql("activity.creator_id")}
AND #{cell_x} = totals.cell_x
AND #{cell_y} = totals.cell_y
LIMIT 1
) AS singleton ON totals.point_count = 1
ORDER BY totals.cell_x, totals.cell_y
"""
end
defp help_expansion_sql do
cell_x = cell_x_sql("request.public_longitude", "$3")
cell_y = cell_y_sql("request.public_latitude", "$3")
"""
SELECT
count(*)::bigint,
min(request.public_longitude),
min(request.public_latitude),
max(request.public_longitude),
max(request.public_latitude)
FROM help_requests AS request
WHERE #{eligible_help_sql("request")}
AND request.expires_at > $1
AND NOT #{expansion_blocked_owner_sql("request.requester_id")}
AND ($6::uuid IS NULL OR request.category_id = $6)
AND ($7::text IS NULL OR request.urgency = $7)
AND request.public_longitude >= $8
AND request.public_longitude <= $9
AND request.public_latitude >= $10
AND request.public_latitude <= $11
AND #{cell_x} = $4
AND #{cell_y} = $5
"""
end
defp activity_expansion_sql do
cell_x = cell_x_sql("activity.public_longitude", "$3")
cell_y = cell_y_sql("activity.public_latitude", "$3")
"""
SELECT
count(*)::bigint,
min(activity.public_longitude),
min(activity.public_latitude),
max(activity.public_longitude),
max(activity.public_latitude)
FROM activities AS activity
WHERE #{eligible_activity_sql("activity")}
AND activity.starts_at > $1
AND activity.join_deadline > $1
AND NOT #{expansion_blocked_owner_sql("activity.creator_id")}
AND ($6::uuid IS NULL OR activity.category_id = $6)
AND activity.public_longitude >= $7
AND activity.public_longitude <= $8
AND activity.public_latitude >= $9
AND activity.public_latitude <= $10
AND #{cell_x} = $4
AND #{cell_y} = $5
"""
end
defp expansion_params(user, level, cell_x, cell_y, category_id, urgency) do
bounds = DiscoveryCluster.cell_bounds(level, cell_x, cell_y)
[
DateTime.utc_now(:second) |> DateTime.to_naive(),
Ecto.UUID.dump!(user.id),
level,
cell_x,
cell_y,
category_id,
urgency,
bounds.west,
bounds.east,
bounds.south,
bounds.north
]
end
defp activity_expansion_params(user, level, cell_x, cell_y, category_id) do
bounds = DiscoveryCluster.cell_bounds(level, cell_x, cell_y)
[
DateTime.utc_now(:second) |> DateTime.to_naive(),
Ecto.UUID.dump!(user.id),
level,
cell_x,
cell_y,
category_id,
bounds.west,
bounds.east,
bounds.south,
bounds.north
]
end
# The statement is assembled only from hard-coded SQL fragments plus
# viewport cell ranges already normalised to integers. Every external filter
# remains a PostgreSQL bind parameter.
# sobelow_skip ["SQL.Query"]
defp query_help_rows(viewport, level, params) do
Repo.query!(help_sql(viewport, level), params, log: false).rows
end
# sobelow_skip ["SQL.Query"]
defp query_activity_rows(viewport, level, params) do
Repo.query!(activity_sql(viewport, level), params, log: false).rows
end
# sobelow_skip ["SQL.Query"]
defp help_expansion_row(params) do
case Repo.query!(help_expansion_sql(), params, log: false).rows do
[row] -> row
_unexpected -> nil
end
end
# sobelow_skip ["SQL.Query"]
defp activity_expansion_row(params) do
case Repo.query!(activity_expansion_sql(), params, log: false).rows do
[row] -> row
_unexpected -> nil
end
end
defp expansion(cluster_id, level, count, west, south, east, north) do
%{
cluster_id: cluster_id,
point_count: count,
bounds: %{west: west, south: south, east: east, north: north},
longitude: (west + east) / 2.0,
latitude: (south + north) / 2.0,
zoom: DiscoveryCluster.expansion_zoom_for_bounds(level, west, south, east, north)
}
end
defp help_item(
[
cell_x,
cell_y,
1,
urgent_count,
id,
title,
location,
longitude,
latitude,
visibility,
radius
],
level
)
when not is_nil(id) do
%{
type: "request",
id: load_uuid(id),
parent_cluster_id: DiscoveryCluster.parent_id(:request, level, cell_x, cell_y),
hierarchy_level: level,
title: title,
location: location,
latitude: latitude,
longitude: longitude,
exact: visibility == "exact_public",
radius_meters: radius,
count: 1,
urgent_count: urgent_count
}
end
defp help_item([cell_x, cell_y, count, urgent_count | _singleton], level) do
cluster_item(:request, level, cell_x, cell_y, count)
|> Map.put(:urgent_count, urgent_count)
end
defp activity_item(
[cell_x, cell_y, 1, id, title, location, longitude, latitude],
level
)
when not is_nil(id) do
%{
type: "activity",
id: load_uuid(id),
parent_cluster_id: DiscoveryCluster.parent_id(:activity, level, cell_x, cell_y),
hierarchy_level: level,
title: title,
location: location,
latitude: latitude,
longitude: longitude,
exact: false,
count: 1
}
end
defp activity_item([cell_x, cell_y, count | _singleton], level) do
cluster_item(:activity, level, cell_x, cell_y, count)
end
defp cluster_item(kind, level, cell_x, cell_y, count) do
cluster_id = DiscoveryCluster.cluster_id(kind, level, cell_x, cell_y)
{longitude, latitude} = DiscoveryCluster.cell_center(level, cell_x, cell_y)
%{
type: "cluster",
id: cluster_id,
cluster_id: cluster_id,
parent_cluster_id: DiscoveryCluster.parent_id(kind, level, cell_x, cell_y),
hierarchy_level: level,
point_count: count,
count: count,
latitude: latitude,
longitude: longitude,
expansion_lookup: true
}
end
defp time_window do
now = DateTime.utc_now(:second) |> DateTime.to_naive()
current_hour = %{now | minute: 0, second: 0, microsecond: {0, 0}}
{now, NaiveDateTime.add(current_hour, 3_600, :second)}
end
defp filter(filters, key), do: filters[to_string(key)] || filters[key]
defp optional_uuid(value) when value in [nil, ""], do: {:ok, nil}
defp optional_uuid(value) do
case Ecto.UUID.dump(value) do
{:ok, dumped} -> {:ok, dumped}
:error -> :error
end
end
defp optional_urgency(value) when value in [nil, ""], do: {:ok, nil}
defp optional_urgency(value) when value in [:now, "now"], do: {:ok, "now"}
defp optional_urgency(value) when value in [:today, "today"], do: {:ok, "today"}
defp optional_urgency(value) when value in [:scheduled, "scheduled"], do: {:ok, "scheduled"}
defp optional_urgency(_value), do: :error
defp load_uuid(binary) when is_binary(binary) do
case Ecto.UUID.load(binary) do
{:ok, uuid} -> uuid
:error -> binary
end
end
defp cell_filter_sql(viewport, level) do
viewport
|> DiscoveryCluster.viewport_cell_ranges(level)
|> Enum.map_join(" OR ", fn {west, south, east, north} ->
"(cell_x BETWEEN #{west} AND #{east} AND cell_y BETWEEN #{south} AND #{north})"
end)
|> then(&"(#{&1})")
end
defp blocked_users_sql do
"""
SELECT block.blocked_id AS user_id
FROM blocks AS block
WHERE block.blocker_id = $4
UNION
SELECT block.blocker_id AS user_id
FROM blocks AS block
WHERE block.blocked_id = $4
"""
end
defp blocked_user_sql(owner) do
"""
EXISTS (
SELECT 1 FROM blocked_users WHERE blocked_users.user_id = #{owner}
)
"""
end
defp expansion_blocked_owner_sql(owner) do
"""
EXISTS (
SELECT 1
FROM blocks AS block
WHERE (block.blocker_id = $2 AND block.blocked_id = #{owner})
OR (block.blocked_id = $2 AND block.blocker_id = #{owner})
)
"""
end
defp eligible_help_sql(alias_name) do
"""
#{alias_name}.status = 'open'
AND #{alias_name}.hidden_at IS NULL
AND #{alias_name}.location_visibility <> 'hidden'
AND #{alias_name}.public_longitude IS NOT NULL
AND #{alias_name}.public_latitude IS NOT NULL
"""
end
defp eligible_activity_sql(alias_name) do
"""
#{alias_name}.status = 'open'
AND #{alias_name}.hidden_at IS NULL
AND #{alias_name}.location_visibility = 'approximate_public'
AND #{alias_name}.public_longitude IS NOT NULL
AND #{alias_name}.public_latitude IS NOT NULL
"""
end
defp cell_x_sql(longitude, level) do
"""
least(
power(2, #{level})::bigint - 1,
greatest(0, floor(((#{longitude} + 180.0) / 360.0) * power(2, #{level})))::bigint
)
"""
end
defp cell_y_sql(latitude, level) do
"""
least(
power(2, #{level})::bigint - 1,
greatest(
0,
floor(
(
ln(
tan(
pi() / 4.0 +
radians(least(85.05112878, greatest(-85.05112878, #{latitude}))) / 2.0
)
) / pi() + 1.0
) / 2.0 * power(2, #{level})
)::bigint
)
)
"""
end
end

View File

@ -7,6 +7,7 @@ defmodule WhoNeedHelp.Help do
alias WhoNeedHelp.Accounts.Scope
alias WhoNeedHelp.Catalog
alias WhoNeedHelp.Catalog.Category
alias WhoNeedHelp.Discovery.Rollup
alias WhoNeedHelp.Help.{Assignment, DiscoveryCluster, DiscoveryViewport, HelpRequest}
alias WhoNeedHelp.Pagination
alias WhoNeedHelp.ProductAnalytics
@ -73,6 +74,19 @@ defmodule WhoNeedHelp.Help do
def map_discovery_items(%Scope{user: user}, filters, %DiscoveryViewport{} = viewport) do
level = DiscoveryCluster.level_for_zoom(viewport.zoom)
if DiscoveryCluster.rollup_level?(level) and blank_area_filter?(filters) do
Rollup.help_items(user, filters, viewport, level)
else
raw_map_discovery_items(user, filters, viewport, level)
end
end
def map_cluster_expansion(%Scope{user: user}, filters, cluster_id) do
Rollup.help_expansion(user, filters, cluster_id)
end
defp raw_map_discovery_items(user, filters, viewport, level) do
cell_count = Integer.pow(2, level) * 1.0
points =
@ -211,11 +225,12 @@ defmodule WhoNeedHelp.Help do
[request],
request.requester_id == ^user.id or
request.id in subquery(
from assignment in Assignment,
from(assignment in Assignment,
where: assignment.helper_id == ^user.id,
select: assignment.request_id
)
)
)
|> before_my_request(cursor)
|> order_by([request], desc: request.inserted_at, desc: request.id)
|> limit(^(limit + 1))
@ -1136,6 +1151,14 @@ defmodule WhoNeedHelp.Help do
|> String.replace("_", "\\_")
end
defp blank_area_filter?(filters) do
case filters["area"] || filters[:area] do
nil -> true
area when is_binary(area) -> String.trim(area) == ""
_invalid -> false
end
end
defp open_requests_query(user, filters, viewport) do
now = DateTime.utc_now(:second)
@ -1147,13 +1170,13 @@ defmodule WhoNeedHelp.Help do
|> where(
[request],
request.requester_id not in subquery(
from block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id
from(block in Block, where: block.blocker_id == ^user.id, select: block.blocked_id)
)
)
|> where(
[request],
request.requester_id not in subquery(
from block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id
from(block in Block, where: block.blocked_id == ^user.id, select: block.blocker_id)
)
)
|> filter_open_requests(filters)

View File

@ -24,6 +24,7 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
@minimum_level 0
@maximum_map_zoom 22
@maximum_level @maximum_map_zoom + @cluster_level_offset
@maximum_rollup_level 12
@type kind :: :request | :activity
@ -34,6 +35,8 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
|> clamp(@minimum_level, @maximum_level)
end
def rollup_level?(level), do: is_integer(level) and level in 0..@maximum_rollup_level
def cell_size_meters(level) when is_integer(level) and level in 0..@maximum_level do
@world_width_meters / :math.pow(2.0, level)
end
@ -53,8 +56,16 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
def viewport_envelopes(%DiscoveryViewport{} = viewport, level)
when is_integer(level) and level in 0..@maximum_level do
viewport
|> viewport_cell_ranges(level)
|> Enum.map(&cell_range_envelope(&1, level))
|> Enum.uniq()
end
def viewport_cell_ranges(%DiscoveryViewport{} = viewport, level)
when is_integer(level) and level in 0..@maximum_level do
viewport
|> DiscoveryViewport.envelopes()
|> Enum.map(&align_envelope_to_cells(&1, level))
|> Enum.map(&envelope_cell_range(&1, level))
|> Enum.uniq()
end
@ -64,6 +75,37 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
"#{kind}:#{level}:#{cell_x}:#{cell_y}"
end
def parse_cluster_id(kind, cluster_id)
when kind in [:request, :activity] and is_binary(cluster_id) do
with [encoded_kind, level, cell_x, cell_y] <- String.split(cluster_id, ":"),
true <- encoded_kind == Atom.to_string(kind),
{level, ""} <- Integer.parse(level),
{cell_x, ""} <- Integer.parse(cell_x),
{cell_y, ""} <- Integer.parse(cell_y),
true <- level in 0..@maximum_level,
maximum_index = Integer.pow(2, level) - 1,
true <- cell_x in 0..maximum_index and cell_y in 0..maximum_index do
{:ok, {level, cell_x, cell_y}}
else
_invalid_cluster_id -> :error
end
end
def cell_bounds(level, cell_x, cell_y)
when is_integer(level) and level in 0..@maximum_level and is_integer(cell_x) and
is_integer(cell_y) do
maximum_index = Integer.pow(2, level) - 1
cell_x = clamp(cell_x, 0, maximum_index)
cell_y = clamp(cell_y, 0, maximum_index)
%{
west: cell_x |> cell_start(level) |> mercator_x_to_longitude(),
south: cell_y |> cell_start(level) |> mercator_y_to_latitude(),
east: cell_x |> cell_end(level) |> mercator_x_to_longitude(),
north: cell_y |> cell_end(level) |> mercator_y_to_latitude()
}
end
@doc """
Returns the stable geographic center of one hierarchy cell.
@ -152,7 +194,7 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
|> floor()
end
defp align_envelope_to_cells({west, south, east, north}, level) do
defp envelope_cell_range({west, south, east, north}, level) do
maximum_index = Integer.pow(2, level) - 1
west_index =
@ -183,6 +225,10 @@ defmodule WhoNeedHelp.Help.DiscoveryCluster do
|> Kernel.+(1)
|> clamp(0, maximum_index)
{west_index, south_index, east_index, north_index}
end
defp cell_range_envelope({west_index, south_index, east_index, north_index}, level) do
{
west_index |> cell_start(level) |> mercator_x_to_longitude(),
south_index |> cell_start(level) |> mercator_y_to_latitude(),

View File

@ -40,6 +40,15 @@ defmodule WhoNeedHelp.Support do
def create_request(scope, attrs, client_scope) when is_map(attrs) do
user = scope_user(scope)
attrs = normalize_keys(attrs)
if is_nil(user) and anonymous_account_lifecycle_kind?(attrs["kind"]) do
create_anonymous_account_lifecycle_request(attrs, client_scope)
else
create_standard_request(user, attrs, client_scope)
end
end
defp create_standard_request(user, attrs, client_scope) do
contact_email = if user, do: user.email, else: attrs["contact_email"]
attrs = Map.put(attrs, "contact_email", contact_email)
fingerprint = if user, do: nil, else: public_submission_fingerprint(attrs)
@ -88,6 +97,119 @@ defmodule WhoNeedHelp.Support do
end
end
defp create_anonymous_account_lifecycle_request(attrs, client_scope) do
contact_email = attrs["contact_email"]
with :ok <- validate_anonymous_account_lifecycle_attrs(attrs),
{:ok, _limits} <-
RateLimiter.check_many(rate_scopes(nil, contact_email, client_scope)) do
case Accounts.get_user_by_normalized_email(contact_email || "") do
{:ok, user} -> create_pending_account_lifecycle_request(user, attrs)
{:error, reason} when reason in [:not_found, :ambiguous] -> {:ok, :accepted}
end
end
end
defp validate_anonymous_account_lifecycle_attrs(attrs) do
changeset =
%SupportRequest{reference: "SUP-VALIDATION"}
|> SupportRequest.submission_changeset(attrs)
if changeset.valid?, do: :ok, else: {:error, changeset}
end
defp create_pending_account_lifecycle_request(%User{} = user, attrs) do
attrs = Map.put(attrs, "contact_email", user.email)
kind = account_lifecycle_kind(attrs["kind"])
result =
Repo.transact(fn ->
case pending_account_lifecycle_request(user.id, kind, lock: true) do
%SupportRequest{} = request ->
with {:ok, _job} <- enqueue_created_email(request) do
{:ok, request}
end
nil ->
insert_pending_account_lifecycle_request(user, attrs)
end
end)
result
|> resolve_pending_account_lifecycle_conflict(user.id, kind)
|> broadcast_request_update()
end
defp insert_pending_account_lifecycle_request(%User{} = user, attrs) do
with {:ok, request} <-
%SupportRequest{
reference: unique_reference("SUP"),
requester_id: user.id,
status: :pending_verification
}
|> SupportRequest.submission_changeset(attrs)
|> Repo.insert(),
{:ok, _audit} <-
Trust.audit(
nil,
"support_request.created",
"support_request",
request.id,
%{"kind" => to_string(request.kind)}
),
{:ok, _event} <-
record_status_event(request, nil, request.status, nil, :requester),
{:ok, _job} <- enqueue_created_email(request) do
{:ok, request}
end
end
defp pending_account_lifecycle_request(user_id, kind, options \\ []) do
query =
from request in SupportRequest,
where:
request.requester_id == ^user_id and request.kind == ^kind and
request.status == :pending_verification and
is_nil(request.contact_verified_at)
query = if Keyword.get(options, :lock, false), do: lock(query, "FOR UPDATE"), else: query
Repo.one(query)
end
defp resolve_pending_account_lifecycle_conflict(
{:error, %Ecto.Changeset{} = changeset} = error,
user_id,
kind
) do
if pending_account_lifecycle_constraint_error?(changeset) do
case pending_account_lifecycle_request(user_id, kind) do
%SupportRequest{} = request -> {:ok, request}
nil -> error
end
else
error
end
end
defp resolve_pending_account_lifecycle_conflict(result, _user_id, _kind), do: result
defp pending_account_lifecycle_constraint_error?(changeset) do
Enum.any?(changeset.errors, fn
{_field, {_message, metadata}} ->
metadata[:constraint_name] ==
"support_requests_one_pending_account_lifecycle_per_user_index"
_other ->
false
end)
end
defp anonymous_account_lifecycle_kind?(kind),
do: kind in ["account_access", "account_deletion"]
defp account_lifecycle_kind("account_access"), do: :account_access
defp account_lifecycle_kind("account_deletion"), do: :account_deletion
def create_inbound_request(attrs, external_source, external_id)
when is_map(attrs) and is_binary(external_source) and is_binary(external_id) do
attrs = normalize_keys(attrs)

View File

@ -67,6 +67,9 @@ defmodule WhoNeedHelp.Support.SupportRequest do
|> validate_length(:details, min: 10, max: 5_000)
|> unique_constraint(:reference)
|> unique_constraint(:public_submission_fingerprint)
|> unique_constraint([:requester_id, :kind],
name: :support_requests_one_pending_account_lifecycle_per_user_index
)
end
def inbound_changeset(request, attrs, external_source, external_id) do

View File

@ -4,6 +4,7 @@ defmodule WhoNeedHelp.Workers.ExpireRequests do
import Ecto.Query
alias WhoNeedHelp.Help
alias WhoNeedHelp.ContentRemoval.Notice
alias WhoNeedHelp.Discovery.Rollup
alias WhoNeedHelp.Help.HelpRequest
alias WhoNeedHelp.Repo
alias WhoNeedHelp.Support.SupportRequest
@ -20,6 +21,7 @@ defmodule WhoNeedHelp.Workers.ExpireRequests do
{:ok, removal_pruned} <- prune_unverified_removal(verification_cutoff(now), 0) do
{pruned_buckets, _} = RateLimiter.prune_expired()
{pruned_user_tokens, _} = WhoNeedHelp.Accounts.delete_expired_user_tokens(now)
discovery_rollups_pruned = Rollup.prune_expired()
{:ok,
%{
@ -29,7 +31,9 @@ defmodule WhoNeedHelp.Workers.ExpireRequests do
unverified_support_pruned: support_pruned,
unverified_removal_pruned: removal_pruned,
rate_limit_buckets_pruned: pruned_buckets,
user_tokens_pruned: pruned_user_tokens
user_tokens_pruned: pruned_user_tokens,
help_discovery_rollups_pruned: discovery_rollups_pruned.help,
activity_discovery_rollups_pruned: discovery_rollups_pruned.activities
}}
end
end

View File

@ -28,8 +28,11 @@ defmodule WhoNeedHelpWeb.SupportController do
params,
ClientIp.rate_limit_scope(conn)
) do
{:ok, request} ->
redirect(conn, to: ~p"/support/received?reference=#{request.reference}")
{:ok, %SupportRequest{} = request} ->
redirect_after_create(conn, request, params)
{:ok, :accepted} ->
redirect(conn, to: ~p"/support/received?flow=account")
{:error, %Ecto.Changeset{} = changeset} ->
conn
@ -70,8 +73,11 @@ defmodule WhoNeedHelpWeb.SupportController do
params,
ClientIp.rate_limit_scope(conn)
) do
{:ok, request} ->
redirect(conn, to: ~p"/support/received?reference=#{request.reference}")
{:ok, %SupportRequest{} = request} ->
redirect_after_create(conn, request, params)
{:ok, :accepted} ->
redirect(conn, to: ~p"/support/received?flow=account")
{:error, %Ecto.Changeset{} = changeset} ->
conn
@ -192,14 +198,34 @@ defmodule WhoNeedHelpWeb.SupportController do
end
end
def received(conn, %{"reference" => reference}) when is_binary(reference) do
render(conn, :received,
reference: String.slice(reference, 0, 64),
page_title: gettext("Support request received")
)
def received(conn, params) do
reference =
case params["reference"] do
reference when is_binary(reference) -> String.slice(reference, 0, 64)
_other -> nil
end
def received(conn, _params), do: redirect(conn, to: ~p"/support")
account_lookup = params["flow"] == "account"
if account_lookup or is_binary(reference) do
render(conn, :received,
reference: reference,
account_lookup: account_lookup,
page_title: gettext("Support request received")
)
else
redirect(conn, to: ~p"/support")
end
end
defp redirect_after_create(conn, request, params) do
if is_nil(conn.assigns.current_scope) and
params["kind"] in ["account_access", "account_deletion"] do
redirect(conn, to: ~p"/support/received?flow=account")
else
redirect(conn, to: ~p"/support/received?reference=#{request.reference}")
end
end
defp render_case(conn, request, token) do
Phoenix.LiveView.Controller.live_render(conn, WhoNeedHelpWeb.SupportCaseLive,

View File

@ -6,14 +6,18 @@
>
<div class="text-center">
<div class="text-sm font-semibold text-success">
{if @current_scope,
do: gettext("REQUEST RECEIVED"),
else: gettext("EMAIL CONFIRMATION REQUIRED")}
{cond do
@current_scope -> gettext("REQUEST RECEIVED")
@account_lookup -> gettext("REQUEST CHECKED")
true -> gettext("EMAIL CONFIRMATION REQUIRED")
end}
</div>
<h1 class="mt-2 text-4xl font-black">
{if @current_scope,
do: gettext("Support request created"),
else: gettext("Check your email")}
{cond do
@current_scope -> gettext("Support request created")
@account_lookup -> gettext("Check your email")
true -> gettext("Check your email")
end}
</h1>
<p :if={@current_scope} class="mt-4 text-base-content/65">
{gettext(
@ -21,10 +25,15 @@
reference: @reference
)}
</p>
<p :if={is_nil(@current_scope)} class="mt-4 text-base-content/65">
<p :if={is_nil(@current_scope) and @account_lookup} class="mt-4 text-base-content/65">
{gettext(
"If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
)}
</p>
<p :if={is_nil(@current_scope) and not @account_lookup} class="mt-4 text-base-content/65">
{gettext(
"We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review.",
reference: @reference
reference: @reference || ""
)}
</p>
<div class="mt-7 flex flex-wrap justify-center gap-3">

View File

@ -193,6 +193,20 @@ defmodule WhoNeedHelpWeb.ActivityLive.Index do
end
end
def handle_event("expand-map-cluster", %{"cluster_id" => cluster_id}, socket) do
case Activities.map_cluster_expansion(
socket.assigns.current_scope,
socket.assigns.filters,
cluster_id
) do
{:ok, expansion} ->
{:noreply, push_event(socket, "map-cluster-expansion", expansion)}
:error ->
{:noreply, socket}
end
end
def handle_event("expand-map-cluster", params, socket) do
case DiscoveryViewport.cast(params) do
{:ok, viewport} ->

View File

@ -163,6 +163,20 @@ defmodule WhoNeedHelpWeb.RequestLive.Index do
end
end
def handle_event("expand-map-cluster", %{"cluster_id" => cluster_id}, socket) do
case Help.map_cluster_expansion(
socket.assigns.current_scope,
socket.assigns.filters,
cluster_id
) do
{:ok, expansion} ->
{:noreply, push_event(socket, "map-cluster-expansion", expansion)}
:error ->
{:noreply, socket}
end
end
def handle_event("expand-map-cluster", params, socket) do
case DiscoveryViewport.cast(params) do
{:ok, viewport} ->

View File

@ -252,7 +252,7 @@ msgstr ""
msgid "Activity restored."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:522
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/new.ex:204
#, elixir-autogen, elixir-format
msgid "Activity type"
@ -270,12 +270,12 @@ msgstr ""
msgid "Administrator"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:524
#: lib/who_need_help_web/live/activity_live/index.ex:538
#, elixir-autogen, elixir-format
msgid "All activities"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:558
#: lib/who_need_help_web/live/request_live/index.ex:572
#, elixir-autogen, elixir-format
msgid "All categories"
msgstr ""
@ -290,7 +290,7 @@ msgstr ""
msgid "Another helper already accepted this request."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:573
#: lib/who_need_help_web/live/request_live/index.ex:587
#, elixir-autogen, elixir-format
msgid "Any urgency"
msgstr ""
@ -405,16 +405,16 @@ msgstr ""
msgid "Cancel request"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:453
#: lib/who_need_help_web/live/activity_live/index.ex:467
#: lib/who_need_help_web/live/activity_live/show.ex:344
#: lib/who_need_help_web/live/request_live/index.ex:478
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:492
#: lib/who_need_help_web/live/request_live/index.ex:493
#: lib/who_need_help_web/live/request_live/show.ex:1005
#, elixir-autogen, elixir-format
msgid "Cancelled"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:556
#: lib/who_need_help_web/live/request_live/index.ex:570
#: lib/who_need_help_web/live/request_live/new.ex:302
#, elixir-autogen, elixir-format
msgid "Category"
@ -494,7 +494,7 @@ msgstr ""
msgid "Coffee and conversation"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:467
#: lib/who_need_help_web/live/activity_live/index.ex:481
#, elixir-autogen, elixir-format
msgid "Coffee, cinema, walks, and hikes are separate from urgent help and never affect helper ratings."
msgstr ""
@ -509,19 +509,19 @@ msgstr ""
msgid "Community helpers"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:715
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/show.ex:403
#: lib/who_need_help_web/live/activity_live/show.ex:639
#: lib/who_need_help_web/live/activity_live/show.ex:698
#: lib/who_need_help_web/live/request_live/index.ex:756
#: lib/who_need_help_web/live/request_live/index.ex:770
#, elixir-autogen, elixir-format
msgid "Community member"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:452
#: lib/who_need_help_web/live/activity_live/index.ex:466
#: lib/who_need_help_web/live/activity_live/show.ex:343
#: lib/who_need_help_web/live/request_live/index.ex:476
#: lib/who_need_help_web/live/request_live/index.ex:477
#: lib/who_need_help_web/live/request_live/index.ex:490
#: lib/who_need_help_web/live/request_live/index.ex:491
#: lib/who_need_help_web/live/request_live/show.ex:1004
#: lib/who_need_help_web/live/request_live/show.ex:1023
#, elixir-autogen, elixir-format
@ -569,13 +569,13 @@ msgstr ""
msgid "Confirming..."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:473
#: lib/who_need_help_web/live/activity_live/index.ex:487
#: lib/who_need_help_web/live/activity_live/new.ex:12
#, elixir-autogen, elixir-format
msgid "Create activity"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:790
#: lib/who_need_help_web/live/activity_live/index.ex:804
#: lib/who_need_help_web/live/activity_live/new.ex:180
#, elixir-autogen, elixir-format
msgid "Create an activity"
@ -586,7 +586,7 @@ msgstr ""
msgid "Create category"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:507
#: lib/who_need_help_web/live/request_live/index.ex:521
#, elixir-autogen, elixir-format
msgid "Create urgent request"
msgstr ""
@ -731,7 +731,7 @@ msgstr ""
msgid "Explain what is already arranged and what the volunteer needs to do."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:464
#: lib/who_need_help_web/live/activity_live/index.ex:478
#, elixir-autogen, elixir-format
msgid "Find people to join"
msgstr ""
@ -878,8 +878,8 @@ msgstr ""
msgid "In a browser this works only while the page remains open. The Android app shows a persistent notification and can continue after it is minimized. Raw coordinates are removed when sharing stops."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:474
#: lib/who_need_help_web/live/request_live/index.ex:475
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:489
#: lib/who_need_help_web/live/request_live/show.ex:1003
#, elixir-autogen, elixir-format
msgid "In progress"
@ -997,8 +997,8 @@ msgstr ""
msgid "Match and coordinate"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:472
#: lib/who_need_help_web/live/request_live/index.ex:473
#: lib/who_need_help_web/live/request_live/index.ex:486
#: lib/who_need_help_web/live/request_live/index.ex:487
#: lib/who_need_help_web/live/request_live/show.ex:1001
#, elixir-autogen, elixir-format
msgid "Matched"
@ -1024,7 +1024,7 @@ msgstr ""
msgid "Medicine requests"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:480
#: lib/who_need_help_web/live/activity_live/index.ex:494
#, elixir-autogen, elixir-format
msgid "Meet in public first, keep exact details inside the approved group, and leave or report anything that feels unsafe."
msgstr ""
@ -1071,7 +1071,7 @@ msgstr ""
msgid "Moderator access is required."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:498
#: lib/who_need_help_web/live/request_live/index.ex:512
#, elixir-autogen, elixir-format
msgid "NEARBY MUTUAL AID"
msgstr ""
@ -1147,9 +1147,9 @@ msgid "Not for emergencies"
msgstr ""
#: lib/who_need_help_web/live/notification_live.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:462
#: lib/who_need_help_web/live/request_live/index.ex:463
#: lib/who_need_help_web/live/request_live/index.ex:574
#: lib/who_need_help_web/live/request_live/index.ex:476
#: lib/who_need_help_web/live/request_live/index.ex:477
#: lib/who_need_help_web/live/request_live/index.ex:588
#: lib/who_need_help_web/live/request_live/new.ex:449
#: lib/who_need_help_web/live/request_live/show.ex:992
#: lib/who_need_help_web/live/request_live/show.ex:993
@ -1157,7 +1157,7 @@ msgstr ""
msgid "Now"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:462
#: lib/who_need_help_web/live/activity_live/index.ex:476
#, elixir-autogen, elixir-format
msgid "OPTIONAL SOCIAL PLANS"
msgstr ""
@ -1175,14 +1175,14 @@ msgstr ""
#: lib/who_need_help/notifications/text.ex:140
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
#: lib/who_need_help_web/controllers/support_html.ex:17
#: lib/who_need_help_web/live/activity_live/index.ex:451
#: lib/who_need_help_web/live/activity_live/index.ex:465
#: lib/who_need_help_web/live/activity_live/show.ex:342
#: lib/who_need_help_web/live/moderation_live.ex:636
#: lib/who_need_help_web/live/moderation_live.ex:817
#: lib/who_need_help_web/live/moderation_live.ex:941
#: lib/who_need_help_web/live/report_live.ex:104
#: lib/who_need_help_web/live/request_live/index.ex:470
#: lib/who_need_help_web/live/request_live/index.ex:471
#: lib/who_need_help_web/live/request_live/index.ex:484
#: lib/who_need_help_web/live/request_live/index.ex:485
#: lib/who_need_help_web/live/request_live/show.ex:1000
#: lib/who_need_help_web/live/support_operation_live.ex:310
#: lib/who_need_help_web/live/support_operation_live.ex:414
@ -1627,9 +1627,9 @@ msgid "Save profile"
msgstr ""
#: lib/who_need_help_web/live/notification_live.ex:738
#: lib/who_need_help_web/live/request_live/index.ex:466
#: lib/who_need_help_web/live/request_live/index.ex:467
#: lib/who_need_help_web/live/request_live/index.ex:576
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:481
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/request_live/new.ex:451
#: lib/who_need_help_web/live/request_live/show.ex:996
#: lib/who_need_help_web/live/request_live/show.ex:997
@ -1894,7 +1894,7 @@ msgstr ""
msgid "This interaction is blocked."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:514
#: lib/who_need_help_web/live/request_live/index.ex:528
#: lib/who_need_help_web/live/request_live/show.ex:1071
#, elixir-autogen, elixir-format
msgid "This is not an emergency service. Contact local emergency services for immediate danger."
@ -1942,9 +1942,9 @@ msgid "To see sent emails, visit"
msgstr ""
#: lib/who_need_help_web/live/notification_live.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:464
#: lib/who_need_help_web/live/request_live/index.ex:465
#: lib/who_need_help_web/live/request_live/index.ex:575
#: lib/who_need_help_web/live/request_live/index.ex:478
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:589
#: lib/who_need_help_web/live/request_live/new.ex:450
#: lib/who_need_help_web/live/request_live/show.ex:994
#: lib/who_need_help_web/live/request_live/show.ex:995
@ -2014,7 +2014,7 @@ msgid "Unique people"
msgstr ""
#: lib/who_need_help_web/live/notification_live.ex:731
#: lib/who_need_help_web/live/request_live/index.ex:571
#: lib/who_need_help_web/live/request_live/index.ex:585
#: lib/who_need_help_web/live/request_live/new.ex:447
#, elixir-autogen, elixir-format
msgid "Urgency"
@ -2147,7 +2147,7 @@ msgstr ""
msgid "Who Need Help was developed with the local Codex CLI authenticated through the builder's ChatGPT subscription. No OpenAI API key or usage-based API fallback is used."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:499
#: lib/who_need_help_web/live/request_live/index.ex:513
#, elixir-autogen, elixir-format
msgid "Who needs help?"
msgstr ""
@ -2261,7 +2261,7 @@ msgstr ""
msgid "Your review is revealed only after both participants submit."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:824
#: lib/who_need_help_web/live/request_live/index.ex:838
#, elixir-autogen, elixir-format
msgid "Your trust summary"
msgstr ""
@ -2272,16 +2272,16 @@ msgstr ""
msgid "before confirming."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:714
#: lib/who_need_help_web/live/activity_live/index.ex:728
#: lib/who_need_help_web/live/category_proposal_live.ex:252
#: lib/who_need_help_web/live/request_live/index.ex:755
#: lib/who_need_help_web/live/request_live/index.ex:769
#, elixir-autogen, elixir-format
msgid "by %{name}"
msgstr ""
#: lib/who_need_help_web/live/profile_live.ex:190
#: lib/who_need_help_web/live/public_profile_live.ex:133
#: lib/who_need_help_web/live/request_live/index.ex:828
#: lib/who_need_help_web/live/request_live/index.ex:842
#: lib/who_need_help_web/live/request_live/show.ex:1478
#, elixir-autogen, elixir-format
msgid "completed"
@ -2317,7 +2317,7 @@ msgstr ""
msgid "participants only"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:832
#: lib/who_need_help_web/live/request_live/index.ex:846
#: lib/who_need_help_web/live/request_live/show.ex:1482
#, elixir-autogen, elixir-format
msgid "people"
@ -2377,7 +2377,7 @@ msgstr ""
#: lib/who_need_help_web/live/activity_live/show.ex:719
#: lib/who_need_help_web/live/profile_live.ex:285
#: lib/who_need_help_web/live/public_profile_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:836
#: lib/who_need_help_web/live/request_live/index.ex:850
#: lib/who_need_help_web/live/request_live/show.ex:1142
#: lib/who_need_help_web/live/request_live/show.ex:1580
#, elixir-autogen, elixir-format
@ -2410,8 +2410,8 @@ msgstr ""
msgid "Approved"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:481
#: lib/who_need_help_web/live/request_live/index.ex:494
#: lib/who_need_help_web/live/request_live/index.ex:495
#, elixir-autogen, elixir-format
msgid "Expired"
msgstr ""
@ -2465,21 +2465,21 @@ msgstr ""
msgid "Load earlier messages"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:726
#: lib/who_need_help_web/live/activity_live/index.ex:819
#: lib/who_need_help_web/live/activity_live/index.ex:740
#: lib/who_need_help_web/live/activity_live/index.ex:833
#: lib/who_need_help_web/live/category_proposal_live.ex:284
#: lib/who_need_help_web/live/leaderboard_live.ex:91
#: lib/who_need_help_web/live/profile_live.ex:233
#: lib/who_need_help_web/live/profile_live.ex:363
#: lib/who_need_help_web/live/public_profile_live.ex:178
#: lib/who_need_help_web/live/report_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:905
#: lib/who_need_help_web/live/request_live/index.ex:919
#, elixir-autogen, elixir-format
msgid "Load more"
msgstr ""
#: lib/who_need_help_web/live/activity_live/show.ex:544
#: lib/who_need_help_web/live/request_live/index.ex:801
#: lib/who_need_help_web/live/request_live/index.ex:815
#: lib/who_need_help_web/live/request_live/show.ex:1324
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Request details remain usable."
@ -2847,7 +2847,7 @@ msgstr ""
msgid "Back to removal form"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#: lib/who_need_help_web/controllers/support_html/received.html.heex:43
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:30
#, elixir-autogen, elixir-format
msgid "Back to support"
@ -2859,7 +2859,8 @@ msgstr ""
msgid "CONTENT REMOVAL"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:16
#: lib/who_need_help_web/controllers/support_html/received.html.heex:18
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#, elixir-autogen, elixir-format
msgid "Check your email"
msgstr ""
@ -3139,7 +3140,7 @@ msgstr ""
msgid "Reported locations"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:241
#: lib/who_need_help_web/controllers/support_controller.ex:267
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:42
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:128
@ -3290,8 +3291,8 @@ msgstr ""
msgid "Too many removal notices. Please try again later."
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:42
#: lib/who_need_help_web/controllers/support_controller.ex:84
#: lib/who_need_help_web/controllers/support_controller.ex:45
#: lib/who_need_help_web/controllers/support_controller.ex:90
#, elixir-autogen, elixir-format
msgid "Too many support requests. Please try again later."
msgstr ""
@ -3373,13 +3374,13 @@ msgstr ""
msgid "Your relationship to the affected person or rights holder"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:55
#: lib/who_need_help_web/controllers/support_controller.ex:66
#: lib/who_need_help_web/controllers/support_controller.ex:58
#: lib/who_need_help_web/controllers/support_controller.ex:69
#, elixir-autogen, elixir-format
msgid "Delete my Who Need Help account"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:56
#: lib/who_need_help_web/controllers/support_controller.ex:59
#, elixir-autogen, elixir-format
msgid "Please delete my account and associated personal data."
msgstr ""
@ -4316,7 +4317,7 @@ msgid "View my notices"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
#: lib/who_need_help_web/controllers/support_html/received.html.heex:32
#: lib/who_need_help_web/controllers/support_html/received.html.heex:41
#, elixir-autogen, elixir-format
msgid "View my requests"
msgstr ""
@ -4431,37 +4432,37 @@ msgstr ""
msgid "Exact point selected. Drag the red pin or click the map to move it."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:533
#: lib/who_need_help_web/live/request_live/index.ex:581
#: lib/who_need_help_web/live/activity_live/index.ex:547
#: lib/who_need_help_web/live/request_live/index.ex:595
#, elixir-autogen, elixir-format
msgid "Area or city"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:656
#: lib/who_need_help_web/live/request_live/index.ex:702
#: lib/who_need_help_web/live/activity_live/index.ex:670
#: lib/who_need_help_web/live/request_live/index.ex:716
#, elixir-autogen, elixir-format
msgid "Choose an area on the map"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:501
#: lib/who_need_help_web/live/request_live/index.ex:515
#, elixir-autogen, elixir-format
msgid "Explore privacy-friendly areas and public exact meeting points chosen by requesters."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:623
#: lib/who_need_help_web/live/request_live/index.ex:669
#: lib/who_need_help_web/live/activity_live/index.ex:637
#: lib/who_need_help_web/live/request_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "List"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:777
#: lib/who_need_help_web/live/request_live/index.ex:791
#, elixir-autogen, elixir-format
msgid "Load more in this area"
msgstr ""
#: lib/who_need_help_web/components/layouts/root.html.heex:5
#: lib/who_need_help_web/live/activity_live/index.ex:643
#: lib/who_need_help_web/live/request_live/index.ex:689
#: lib/who_need_help_web/live/activity_live/index.ex:657
#: lib/who_need_help_web/live/request_live/index.ex:703
#, elixir-autogen, elixir-format
msgid "Map"
msgstr ""
@ -4471,41 +4472,41 @@ msgstr ""
msgid "Map preview"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:672
#: lib/who_need_help_web/live/request_live/index.ex:718
#: lib/who_need_help_web/live/activity_live/index.ex:686
#: lib/who_need_help_web/live/request_live/index.ex:732
#, elixir-autogen, elixir-format
msgid "Move or zoom the map to search somewhere else."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:715
#: lib/who_need_help_web/live/request_live/index.ex:729
#, elixir-autogen, elixir-format
msgid "No open requests in this area"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:704
#: lib/who_need_help_web/live/request_live/index.ex:718
#, elixir-autogen, elixir-format
msgid "Only requests from the selected map area will be loaded."
msgstr ""
#: lib/who_need_help_web/components/layouts/root.html.heex:8
#: lib/who_need_help_web/live/request_live/index.ex:804
#: lib/who_need_help_web/live/request_live/index.ex:818
#, elixir-autogen, elixir-format
msgid "Open request"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:534
#: lib/who_need_help_web/live/request_live/index.ex:582
#: lib/who_need_help_web/live/activity_live/index.ex:548
#: lib/who_need_help_web/live/request_live/index.ex:596
#, elixir-autogen, elixir-format
msgid "Optional text search"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:783
#: lib/who_need_help_web/live/request_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "Requests without map coordinates appear only when their public area description matches the text search."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:614
#: lib/who_need_help_web/live/request_live/index.ex:660
#: lib/who_need_help_web/live/activity_live/index.ex:628
#: lib/who_need_help_web/live/request_live/index.ex:674
#, elixir-autogen, elixir-format
msgid "Results layout"
msgstr ""
@ -4515,21 +4516,21 @@ msgstr ""
msgid "Static preview"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:633
#: lib/who_need_help_web/live/request_live/index.ex:679
#: lib/who_need_help_web/live/activity_live/index.ex:647
#: lib/who_need_help_web/live/request_live/index.ex:693
#, elixir-autogen, elixir-format
msgid "Together"
msgstr ""
#: lib/who_need_help_web/components/layouts/root.html.heex:6
#: lib/who_need_help_web/controllers/page_html/home.html.heex:166
#: lib/who_need_help_web/live/activity_live/index.ex:749
#: lib/who_need_help_web/live/activity_live/index.ex:763
#: lib/who_need_help_web/live/activity_live/new.ex:355
#: lib/who_need_help_web/live/activity_live/new.ex:414
#: lib/who_need_help_web/live/activity_live/show.ex:546
#: lib/who_need_help_web/live/notification_live.ex:590
#: lib/who_need_help_web/live/notification_live.ex:609
#: lib/who_need_help_web/live/request_live/index.ex:803
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/new.ex:485
#: lib/who_need_help_web/live/request_live/new.ex:563
#: lib/who_need_help_web/live/request_live/show.ex:1326
@ -4886,7 +4887,7 @@ msgid "Nearby alert deleted."
msgstr ""
#: lib/who_need_help_web/live/notification_live.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:527
#: lib/who_need_help_web/live/request_live/index.ex:541
#, elixir-autogen, elixir-format
msgid "Nearby requests"
msgstr ""
@ -5209,7 +5210,7 @@ msgid "WebGL is unavailable in this browser, so the full map cannot start. Selec
msgstr ""
#: lib/who_need_help_web/components/layouts/root.html.heex:7
#: lib/who_need_help_web/live/activity_live/index.ex:750
#: lib/who_need_help_web/live/activity_live/index.ex:764
#: lib/who_need_help_web/live/activity_live/show.ex:547
#: lib/who_need_help_web/live/request_live/show.ex:1327
#, elixir-autogen, elixir-format
@ -5250,7 +5251,7 @@ msgid "Case status"
msgstr ""
#: lib/who_need_help_web/controllers/page_html/child_safety.html.heex:42
#: lib/who_need_help_web/controllers/support_controller.ex:242
#: lib/who_need_help_web/controllers/support_controller.ex:268
#: lib/who_need_help_web/live/report_live.ex:50
#, elixir-autogen, elixir-format
msgid "Contact support"
@ -5272,8 +5273,8 @@ msgstr ""
msgid "Conversation"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:152
#: lib/who_need_help_web/controllers/support_controller.ex:168
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:174
#: lib/who_need_help_web/live/support_case_live.ex:73
#, elixir-autogen, elixir-format
msgid "Could not send your message. Please check it and try again."
@ -5336,7 +5337,7 @@ msgstr ""
msgid "No status history is available for this older case."
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:187
#: lib/who_need_help_web/controllers/support_controller.ex:193
#: lib/who_need_help_web/live/support_case_live.ex:95
#, elixir-autogen, elixir-format
msgid "Only a resolved or closed request can be reopened."
@ -5441,12 +5442,12 @@ msgstr ""
msgid "Status history"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:15
#: lib/who_need_help_web/controllers/support_html/received.html.heex:17
#, elixir-autogen, elixir-format
msgid "Support request created"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:198
#: lib/who_need_help_web/controllers/support_controller.ex:214
#, elixir-autogen, elixir-format
msgid "Support request received"
msgstr ""
@ -5482,7 +5483,7 @@ msgstr ""
msgid "The requester states whether the medicine is paid, reserved, or still needs to be purchased."
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:182
#: lib/who_need_help_web/controllers/support_controller.ex:188
#: lib/who_need_help_web/live/support_case_live.ex:88
#, elixir-autogen, elixir-format
msgid "The support request is open again."
@ -5510,7 +5511,7 @@ msgstr ""
msgid "This support request is no longer available."
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:164
#: lib/who_need_help_web/live/support_case_live.ex:60
#, elixir-autogen, elixir-format
msgid "Too many messages. Please try again later."
@ -5521,7 +5522,7 @@ msgstr ""
msgid "Use the dedicated urgent process. Never upload or reproduce the image or video."
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#: lib/who_need_help_web/controllers/support_html/received.html.heex:23
#, elixir-autogen, elixir-format
msgid "We created support request %{reference} and added it to your account. You can open it now and return to it from My support requests."
msgstr ""
@ -5547,7 +5548,7 @@ msgstr ""
msgid "Your content-removal notices"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:145
#: lib/who_need_help_web/controllers/support_controller.ex:151
#: lib/who_need_help_web/live/support_case_live.ex:53
#, elixir-autogen, elixir-format
msgid "Your message was sent to support."
@ -5711,7 +5712,7 @@ msgstr ""
msgid "Delivery settings"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:760
#: lib/who_need_help_web/live/request_live/index.ex:774
#, elixir-autogen, elixir-format
msgid "Expires"
msgstr ""
@ -5731,22 +5732,22 @@ msgstr ""
msgid "Notification sections"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:742
#: lib/who_need_help_web/live/activity_live/index.ex:756
#, elixir-autogen, elixir-format
msgid "%{count} activities"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:805
#: lib/who_need_help_web/live/request_live/index.ex:819
#, elixir-autogen, elixir-format
msgid "%{count} requests"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:785
#: lib/who_need_help_web/live/activity_live/index.ex:799
#, elixir-autogen, elixir-format
msgid "Activities you create or ask to join will appear here. Leaving removes an activity from this list."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:488
#: lib/who_need_help_web/live/activity_live/index.ex:502
#, elixir-autogen, elixir-format
msgid "Activity views"
msgstr ""
@ -5761,12 +5762,12 @@ msgstr ""
msgid "Confirm the safety guidance before asking nearby people for help."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:853
#: lib/who_need_help_web/live/request_live/index.ex:867
#, elixir-autogen, elixir-format
msgid "Create request"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:876
#: lib/who_need_help_web/live/request_live/index.ex:890
#, elixir-autogen, elixir-format
msgid "Create your first request"
msgstr ""
@ -5781,43 +5782,43 @@ msgstr ""
msgid "Location"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:494
#: lib/who_need_help_web/live/activity_live/index.ex:508
#, elixir-autogen, elixir-format
msgid "My activities"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:528
#: lib/who_need_help_web/live/request_live/index.ex:847
#: lib/who_need_help_web/live/request_live/index.ex:542
#: lib/who_need_help_web/live/request_live/index.ex:861
#, elixir-autogen, elixir-format
msgid "My requests"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:493
#: lib/who_need_help_web/live/activity_live/index.ex:507
#, elixir-autogen, elixir-format
msgid "Nearby activities"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:783
#: lib/who_need_help_web/live/activity_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "No activities yet"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:669
#: lib/who_need_help_web/live/activity_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "No open activities in this area"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:871
#: lib/who_need_help_web/live/request_live/index.ex:885
#, elixir-autogen, elixir-format
msgid "No requests yet"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:658
#: lib/who_need_help_web/live/activity_live/index.ex:672
#, elixir-autogen, elixir-format
msgid "Only activities from the selected map area will be loaded."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:741
#: lib/who_need_help_web/live/activity_live/index.ex:755
#, elixir-autogen, elixir-format
msgid "Open activity"
msgstr ""
@ -5827,12 +5828,12 @@ msgstr ""
msgid "Request form steps"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:522
#: lib/who_need_help_web/live/request_live/index.ex:536
#, elixir-autogen, elixir-format
msgid "Request views"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:873
#: lib/who_need_help_web/live/request_live/index.ex:887
#, elixir-autogen, elixir-format
msgid "Requests you publish or accept will appear here."
msgstr ""
@ -5857,7 +5858,7 @@ msgstr ""
msgid "Share only as much location detail as helpers need."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:747
#: lib/who_need_help_web/live/activity_live/index.ex:761
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Activity details remain usable."
msgstr ""
@ -5867,7 +5868,7 @@ msgstr ""
msgid "Timing"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:849
#: lib/who_need_help_web/live/request_live/index.ex:863
#, elixir-autogen, elixir-format
msgid "Track requests you created and requests you accepted as a helper."
msgstr ""
@ -6522,91 +6523,91 @@ msgstr ""
msgid "Choose the meeting point on the map or use your current location."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:573
#: lib/who_need_help_web/live/activity_live/index.ex:668
#: lib/who_need_help_web/live/activity_live/index.ex:775
#: lib/who_need_help_web/live/request_live/index.ex:619
#: lib/who_need_help_web/live/request_live/index.ex:714
#: lib/who_need_help_web/live/request_live/index.ex:863
#: lib/who_need_help_web/live/activity_live/index.ex:587
#: lib/who_need_help_web/live/activity_live/index.ex:682
#: lib/who_need_help_web/live/activity_live/index.ex:789
#: lib/who_need_help_web/live/request_live/index.ex:633
#: lib/who_need_help_web/live/request_live/index.ex:728
#: lib/who_need_help_web/live/request_live/index.ex:877
#, elixir-autogen, elixir-format
msgid "Loading results…"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:744
#: lib/who_need_help_web/live/activity_live/index.ex:758
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching activities are listed beside the map."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:807
#: lib/who_need_help_web/live/request_live/index.ex:821
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching requests are listed beside the map."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:554
#: lib/who_need_help_web/live/activity_live/index.ex:568
#, elixir-autogen, elixir-format
msgid "%{count} activity in the selected map area"
msgid_plural "%{count} activities in the selected map area"
msgstr[0] ""
msgstr[1] ""
#: lib/who_need_help_web/live/request_live/index.ex:600
#: lib/who_need_help_web/live/request_live/index.ex:614
#, elixir-autogen, elixir-format
msgid "%{count} request in the selected map area"
msgid_plural "%{count} requests in the selected map area"
msgstr[0] ""
msgstr[1] ""
#: lib/who_need_help_web/live/activity_live/index.ex:579
#: lib/who_need_help_web/live/request_live/index.ex:625
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:639
#, elixir-autogen, elixir-format
msgid "Map moved. Results still show the previous area."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:597
#: lib/who_need_help_web/live/activity_live/index.ex:611
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show activities in this area”."
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:643
#: lib/who_need_help_web/live/request_live/index.ex:657
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show requests in this area”."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:591
#: lib/who_need_help_web/live/request_live/index.ex:637
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:651
#, elixir-autogen, elixir-format
msgid "Results update automatically after you stop moving the map."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:761
#: lib/who_need_help_web/live/activity_live/index.ex:775
#, elixir-autogen, elixir-format
msgid "Show activities in this area"
msgstr ""
#: lib/who_need_help_web/live/request_live/index.ex:819
#: lib/who_need_help_web/live/request_live/index.ex:833
#, elixir-autogen, elixir-format
msgid "Show requests in this area"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:563
#: lib/who_need_help_web/live/request_live/index.ex:609
#: lib/who_need_help_web/live/activity_live/index.ex:577
#: lib/who_need_help_web/live/request_live/index.ex:623
#, elixir-autogen, elixir-format
msgid "Showing %{shown} of %{count} in the list."
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:611
#: lib/who_need_help_web/live/request_live/index.ex:657
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:671
#, elixir-autogen, elixir-format
msgid "Update results as map moves"
msgstr ""
#: lib/who_need_help_web/live/activity_live/index.ex:585
#: lib/who_need_help_web/live/request_live/index.ex:631
#: lib/who_need_help_web/live/activity_live/index.ex:599
#: lib/who_need_help_web/live/request_live/index.ex:645
#, elixir-autogen, elixir-format
msgid "Updating results for the visible map area…"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#: lib/who_need_help_web/controllers/support_html/received.html.heex:12
#, elixir-autogen, elixir-format
msgid "EMAIL CONFIRMATION REQUIRED"
msgstr ""
@ -6626,7 +6627,7 @@ msgstr ""
msgid "Pending email verification"
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:25
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#, elixir-autogen, elixir-format
msgid "We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review."
msgstr ""
@ -7690,7 +7691,7 @@ msgstr ""
msgid "Your email was confirmed and the notice was sent for review."
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:122
#: lib/who_need_help_web/controllers/support_controller.ex:128
#, elixir-autogen, elixir-format
msgid "Your email was confirmed and the request was sent to support."
msgstr ""
@ -7888,7 +7889,7 @@ msgstr ""
msgid "Confirm content-removal notice"
msgstr ""
#: lib/who_need_help_web/controllers/support_controller.ex:106
#: lib/who_need_help_web/controllers/support_controller.ex:112
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:9
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:23
#, elixir-autogen, elixir-format
@ -7914,3 +7915,13 @@ msgstr ""
#, elixir-autogen, elixir-format
msgid "If you did not submit this request, close this page. Nothing will be sent to support."
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:29
#, elixir-autogen, elixir-format
msgid "If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
msgstr ""
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#, elixir-autogen, elixir-format
msgid "REQUEST CHECKED"
msgstr ""

View File

@ -252,7 +252,7 @@ msgstr "Activity published. You approve every participant."
msgid "Activity restored."
msgstr "Activity restored."
#: lib/who_need_help_web/live/activity_live/index.ex:504
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/new.ex:204
#, elixir-autogen, elixir-format
msgid "Activity type"
@ -270,12 +270,12 @@ msgstr "Add unverified link"
msgid "Administrator"
msgstr "Administrator"
#: lib/who_need_help_web/live/activity_live/index.ex:506
#: lib/who_need_help_web/live/activity_live/index.ex:538
#, elixir-autogen, elixir-format
msgid "All activities"
msgstr "All activities"
#: lib/who_need_help_web/live/request_live/index.ex:539
#: lib/who_need_help_web/live/request_live/index.ex:572
#, elixir-autogen, elixir-format
msgid "All categories"
msgstr "All categories"
@ -290,7 +290,7 @@ msgstr "Already registered?"
msgid "Another helper already accepted this request."
msgstr "Another helper already accepted this request."
#: lib/who_need_help_web/live/request_live/index.ex:554
#: lib/who_need_help_web/live/request_live/index.ex:587
#, elixir-autogen, elixir-format
msgid "Any urgency"
msgstr "Any urgency"
@ -405,16 +405,16 @@ msgstr "Cancel activity"
msgid "Cancel request"
msgstr "Cancel request"
#: lib/who_need_help_web/live/activity_live/index.ex:435
#: lib/who_need_help_web/live/activity_live/index.ex:467
#: lib/who_need_help_web/live/activity_live/show.ex:344
#: lib/who_need_help_web/live/request_live/index.ex:459
#: lib/who_need_help_web/live/request_live/index.ex:460
#: lib/who_need_help_web/live/request_live/index.ex:492
#: lib/who_need_help_web/live/request_live/index.ex:493
#: lib/who_need_help_web/live/request_live/show.ex:1005
#, elixir-autogen, elixir-format
msgid "Cancelled"
msgstr "Cancelled"
#: lib/who_need_help_web/live/request_live/index.ex:537
#: lib/who_need_help_web/live/request_live/index.ex:570
#: lib/who_need_help_web/live/request_live/new.ex:302
#, elixir-autogen, elixir-format
msgid "Category"
@ -494,7 +494,7 @@ msgstr "Close"
msgid "Coffee and conversation"
msgstr "Coffee and conversation"
#: lib/who_need_help_web/live/activity_live/index.ex:449
#: lib/who_need_help_web/live/activity_live/index.ex:481
#, elixir-autogen, elixir-format
msgid "Coffee, cinema, walks, and hikes are separate from urgent help and never affect helper ratings."
msgstr "Coffee, cinema, walks, and hikes are separate from urgent help and never affect helper ratings."
@ -509,19 +509,19 @@ msgstr "Comment (optional)"
msgid "Community helpers"
msgstr "Community helpers"
#: lib/who_need_help_web/live/activity_live/index.ex:697
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/show.ex:403
#: lib/who_need_help_web/live/activity_live/show.ex:639
#: lib/who_need_help_web/live/activity_live/show.ex:698
#: lib/who_need_help_web/live/request_live/index.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:770
#, elixir-autogen, elixir-format
msgid "Community member"
msgstr "Community member"
#: lib/who_need_help_web/live/activity_live/index.ex:434
#: lib/who_need_help_web/live/activity_live/index.ex:466
#: lib/who_need_help_web/live/activity_live/show.ex:343
#: lib/who_need_help_web/live/request_live/index.ex:457
#: lib/who_need_help_web/live/request_live/index.ex:458
#: lib/who_need_help_web/live/request_live/index.ex:490
#: lib/who_need_help_web/live/request_live/index.ex:491
#: lib/who_need_help_web/live/request_live/show.ex:1004
#: lib/who_need_help_web/live/request_live/show.ex:1023
#, elixir-autogen, elixir-format
@ -569,13 +569,13 @@ msgstr "Confirm your email and ensure your account is active before publishing."
msgid "Confirming..."
msgstr "Confirming..."
#: lib/who_need_help_web/live/activity_live/index.ex:455
#: lib/who_need_help_web/live/activity_live/index.ex:487
#: lib/who_need_help_web/live/activity_live/new.ex:12
#, elixir-autogen, elixir-format
msgid "Create activity"
msgstr "Create activity"
#: lib/who_need_help_web/live/activity_live/index.ex:772
#: lib/who_need_help_web/live/activity_live/index.ex:804
#: lib/who_need_help_web/live/activity_live/new.ex:180
#, elixir-autogen, elixir-format
msgid "Create an activity"
@ -586,7 +586,7 @@ msgstr "Create an activity"
msgid "Create category"
msgstr "Create category"
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:521
#, elixir-autogen, elixir-format
msgid "Create urgent request"
msgstr "Create urgent request"
@ -731,7 +731,7 @@ msgstr "Expires:"
msgid "Explain what is already arranged and what the volunteer needs to do."
msgstr "Explain what is already arranged and what the volunteer needs to do."
#: lib/who_need_help_web/live/activity_live/index.ex:446
#: lib/who_need_help_web/live/activity_live/index.ex:478
#, elixir-autogen, elixir-format
msgid "Find people to join"
msgstr "Find people to join"
@ -878,8 +878,8 @@ msgstr "Impersonation"
msgid "In a browser this works only while the page remains open. The Android app shows a persistent notification and can continue after it is minimized. Raw coordinates are removed when sharing stops."
msgstr "In a browser this works only while the page remains open. The Android app shows a persistent notification and can continue after it is minimized. Raw coordinates are removed when sharing stops."
#: lib/who_need_help_web/live/request_live/index.ex:455
#: lib/who_need_help_web/live/request_live/index.ex:456
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:489
#: lib/who_need_help_web/live/request_live/show.ex:1003
#, elixir-autogen, elixir-format
msgid "In progress"
@ -997,8 +997,8 @@ msgstr "Mark completed"
msgid "Match and coordinate"
msgstr "Match and coordinate"
#: lib/who_need_help_web/live/request_live/index.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:454
#: lib/who_need_help_web/live/request_live/index.ex:486
#: lib/who_need_help_web/live/request_live/index.ex:487
#: lib/who_need_help_web/live/request_live/show.ex:1001
#, elixir-autogen, elixir-format
msgid "Matched"
@ -1024,7 +1024,7 @@ msgstr "Medicine pickup remains the first priority. Roadside categories use the
msgid "Medicine requests"
msgstr "Medicine requests"
#: lib/who_need_help_web/live/activity_live/index.ex:462
#: lib/who_need_help_web/live/activity_live/index.ex:494
#, elixir-autogen, elixir-format
msgid "Meet in public first, keep exact details inside the approved group, and leave or report anything that feels unsafe."
msgstr "Meet in public first, keep exact details inside the approved group, and leave or report anything that feels unsafe."
@ -1071,7 +1071,7 @@ msgstr "Moderator"
msgid "Moderator access is required."
msgstr "Moderator access is required."
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:512
#, elixir-autogen, elixir-format
msgid "NEARBY MUTUAL AID"
msgstr "NEARBY MUTUAL AID"
@ -1147,9 +1147,9 @@ msgid "Not for emergencies"
msgstr "Not for emergencies"
#: lib/who_need_help_web/live/notification_live.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:443
#: lib/who_need_help_web/live/request_live/index.ex:444
#: lib/who_need_help_web/live/request_live/index.ex:555
#: lib/who_need_help_web/live/request_live/index.ex:476
#: lib/who_need_help_web/live/request_live/index.ex:477
#: lib/who_need_help_web/live/request_live/index.ex:588
#: lib/who_need_help_web/live/request_live/new.ex:449
#: lib/who_need_help_web/live/request_live/show.ex:992
#: lib/who_need_help_web/live/request_live/show.ex:993
@ -1157,7 +1157,7 @@ msgstr "Not for emergencies"
msgid "Now"
msgstr "Now"
#: lib/who_need_help_web/live/activity_live/index.ex:444
#: lib/who_need_help_web/live/activity_live/index.ex:476
#, elixir-autogen, elixir-format
msgid "OPTIONAL SOCIAL PLANS"
msgstr "OPTIONAL SOCIAL PLANS"
@ -1175,14 +1175,14 @@ msgstr "Only the organizer and approved participants can read or send these mess
#: lib/who_need_help/notifications/text.ex:140
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
#: lib/who_need_help_web/controllers/support_html.ex:17
#: lib/who_need_help_web/live/activity_live/index.ex:433
#: lib/who_need_help_web/live/activity_live/index.ex:465
#: lib/who_need_help_web/live/activity_live/show.ex:342
#: lib/who_need_help_web/live/moderation_live.ex:636
#: lib/who_need_help_web/live/moderation_live.ex:817
#: lib/who_need_help_web/live/moderation_live.ex:941
#: lib/who_need_help_web/live/report_live.ex:104
#: lib/who_need_help_web/live/request_live/index.ex:451
#: lib/who_need_help_web/live/request_live/index.ex:452
#: lib/who_need_help_web/live/request_live/index.ex:484
#: lib/who_need_help_web/live/request_live/index.ex:485
#: lib/who_need_help_web/live/request_live/show.ex:1000
#: lib/who_need_help_web/live/support_operation_live.ex:310
#: lib/who_need_help_web/live/support_operation_live.ex:414
@ -1627,9 +1627,9 @@ msgid "Save profile"
msgstr "Save profile"
#: lib/who_need_help_web/live/notification_live.ex:738
#: lib/who_need_help_web/live/request_live/index.ex:447
#: lib/who_need_help_web/live/request_live/index.ex:448
#: lib/who_need_help_web/live/request_live/index.ex:557
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:481
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/request_live/new.ex:451
#: lib/who_need_help_web/live/request_live/show.ex:996
#: lib/who_need_help_web/live/request_live/show.ex:997
@ -1894,7 +1894,7 @@ msgstr "This activity state has already changed."
msgid "This interaction is blocked."
msgstr "This interaction is blocked."
#: lib/who_need_help_web/live/request_live/index.ex:495
#: lib/who_need_help_web/live/request_live/index.ex:528
#: lib/who_need_help_web/live/request_live/show.ex:1071
#, elixir-autogen, elixir-format
msgid "This is not an emergency service. Contact local emergency services for immediate danger."
@ -1942,9 +1942,9 @@ msgid "To see sent emails, visit"
msgstr "To see sent emails, visit"
#: lib/who_need_help_web/live/notification_live.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:445
#: lib/who_need_help_web/live/request_live/index.ex:446
#: lib/who_need_help_web/live/request_live/index.ex:556
#: lib/who_need_help_web/live/request_live/index.ex:478
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:589
#: lib/who_need_help_web/live/request_live/new.ex:450
#: lib/who_need_help_web/live/request_live/show.ex:994
#: lib/who_need_help_web/live/request_live/show.ex:995
@ -2014,7 +2014,7 @@ msgid "Unique people"
msgstr "Unique people"
#: lib/who_need_help_web/live/notification_live.ex:731
#: lib/who_need_help_web/live/request_live/index.ex:552
#: lib/who_need_help_web/live/request_live/index.ex:585
#: lib/who_need_help_web/live/request_live/new.ex:447
#, elixir-autogen, elixir-format
msgid "Urgency"
@ -2147,7 +2147,7 @@ msgstr "Who Need Help home"
msgid "Who Need Help was developed with the local Codex CLI authenticated through the builder's ChatGPT subscription. No OpenAI API key or usage-based API fallback is used."
msgstr "Who Need Help was developed with the local Codex CLI authenticated through the builder's ChatGPT subscription. No OpenAI API key or usage-based API fallback is used."
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:513
#, elixir-autogen, elixir-format
msgid "Who needs help?"
msgstr "Who needs help?"
@ -2261,7 +2261,7 @@ msgstr "Your requests"
msgid "Your review is revealed only after both participants submit."
msgstr "Your review is revealed only after both participants submit."
#: lib/who_need_help_web/live/request_live/index.ex:805
#: lib/who_need_help_web/live/request_live/index.ex:838
#, elixir-autogen, elixir-format
msgid "Your trust summary"
msgstr "Your trust summary"
@ -2272,16 +2272,16 @@ msgstr "Your trust summary"
msgid "before confirming."
msgstr "before confirming."
#: lib/who_need_help_web/live/activity_live/index.ex:696
#: lib/who_need_help_web/live/activity_live/index.ex:728
#: lib/who_need_help_web/live/category_proposal_live.ex:252
#: lib/who_need_help_web/live/request_live/index.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:769
#, elixir-autogen, elixir-format
msgid "by %{name}"
msgstr "by %{name}"
#: lib/who_need_help_web/live/profile_live.ex:190
#: lib/who_need_help_web/live/public_profile_live.ex:133
#: lib/who_need_help_web/live/request_live/index.ex:809
#: lib/who_need_help_web/live/request_live/index.ex:842
#: lib/who_need_help_web/live/request_live/show.ex:1478
#, elixir-autogen, elixir-format
msgid "completed"
@ -2317,7 +2317,7 @@ msgstr "organizer"
msgid "participants only"
msgstr "participants only"
#: lib/who_need_help_web/live/request_live/index.ex:813
#: lib/who_need_help_web/live/request_live/index.ex:846
#: lib/who_need_help_web/live/request_live/show.ex:1482
#, elixir-autogen, elixir-format
msgid "people"
@ -2377,7 +2377,7 @@ msgstr "urgent"
#: lib/who_need_help_web/live/activity_live/show.ex:719
#: lib/who_need_help_web/live/profile_live.ex:285
#: lib/who_need_help_web/live/public_profile_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/index.ex:850
#: lib/who_need_help_web/live/request_live/show.ex:1142
#: lib/who_need_help_web/live/request_live/show.ex:1580
#, elixir-autogen, elixir-format
@ -2410,8 +2410,8 @@ msgstr "← Requests"
msgid "Approved"
msgstr "Approved"
#: lib/who_need_help_web/live/request_live/index.ex:461
#: lib/who_need_help_web/live/request_live/index.ex:462
#: lib/who_need_help_web/live/request_live/index.ex:494
#: lib/who_need_help_web/live/request_live/index.ex:495
#, elixir-autogen, elixir-format
msgid "Expired"
msgstr "Expired"
@ -2465,21 +2465,21 @@ msgstr "Unusual action rate"
msgid "Load earlier messages"
msgstr "Load earlier messages"
#: lib/who_need_help_web/live/activity_live/index.ex:708
#: lib/who_need_help_web/live/activity_live/index.ex:801
#: lib/who_need_help_web/live/activity_live/index.ex:740
#: lib/who_need_help_web/live/activity_live/index.ex:833
#: lib/who_need_help_web/live/category_proposal_live.ex:284
#: lib/who_need_help_web/live/leaderboard_live.ex:91
#: lib/who_need_help_web/live/profile_live.ex:233
#: lib/who_need_help_web/live/profile_live.ex:363
#: lib/who_need_help_web/live/public_profile_live.ex:178
#: lib/who_need_help_web/live/report_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:886
#: lib/who_need_help_web/live/request_live/index.ex:919
#, elixir-autogen, elixir-format
msgid "Load more"
msgstr "Load more"
#: lib/who_need_help_web/live/activity_live/show.ex:544
#: lib/who_need_help_web/live/request_live/index.ex:782
#: lib/who_need_help_web/live/request_live/index.ex:815
#: lib/who_need_help_web/live/request_live/show.ex:1324
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Request details remain usable."
@ -2847,7 +2847,7 @@ msgstr "Appeal a moderation decision"
msgid "Back to removal form"
msgstr "Back to removal form"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#: lib/who_need_help_web/controllers/support_html/received.html.heex:43
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:30
#, elixir-autogen, elixir-format
msgid "Back to support"
@ -2859,7 +2859,8 @@ msgstr "Back to support"
msgid "CONTENT REMOVAL"
msgstr "CONTENT REMOVAL"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:16
#: lib/who_need_help_web/controllers/support_html/received.html.heex:18
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#, elixir-autogen, elixir-format
msgid "Check your email"
msgstr "Check your email"
@ -3139,7 +3140,7 @@ msgstr "Report illegal or harmful content"
msgid "Reported locations"
msgstr "Reported locations"
#: lib/who_need_help_web/controllers/support_controller.ex:241
#: lib/who_need_help_web/controllers/support_controller.ex:267
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:42
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:128
@ -3290,8 +3291,8 @@ msgstr "Threat to life or safety"
msgid "Too many removal notices. Please try again later."
msgstr "Too many removal notices. Please try again later."
#: lib/who_need_help_web/controllers/support_controller.ex:42
#: lib/who_need_help_web/controllers/support_controller.ex:84
#: lib/who_need_help_web/controllers/support_controller.ex:45
#: lib/who_need_help_web/controllers/support_controller.ex:90
#, elixir-autogen, elixir-format
msgid "Too many support requests. Please try again later."
msgstr "Too many support requests. Please try again later."
@ -3373,13 +3374,13 @@ msgstr "Your reference is %{reference}"
msgid "Your relationship to the affected person or rights holder"
msgstr "Your relationship to the affected person or rights holder"
#: lib/who_need_help_web/controllers/support_controller.ex:55
#: lib/who_need_help_web/controllers/support_controller.ex:66
#: lib/who_need_help_web/controllers/support_controller.ex:58
#: lib/who_need_help_web/controllers/support_controller.ex:69
#, elixir-autogen, elixir-format
msgid "Delete my Who Need Help account"
msgstr "Delete my Who Need Help account"
#: lib/who_need_help_web/controllers/support_controller.ex:56
#: lib/who_need_help_web/controllers/support_controller.ex:59
#, elixir-autogen, elixir-format
msgid "Please delete my account and associated personal data."
msgstr "Please delete my account and associated personal data."
@ -4316,7 +4317,7 @@ msgid "View my notices"
msgstr "View my notices"
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
#: lib/who_need_help_web/controllers/support_html/received.html.heex:32
#: lib/who_need_help_web/controllers/support_html/received.html.heex:41
#, elixir-autogen, elixir-format
msgid "View my requests"
msgstr "View my requests"
@ -4431,37 +4432,37 @@ msgstr "Drag to move the exact point"
msgid "Exact point selected. Drag the red pin or click the map to move it."
msgstr "Exact point selected. Drag the red pin or click the map to move it."
#: lib/who_need_help_web/live/activity_live/index.ex:515
#: lib/who_need_help_web/live/request_live/index.ex:562
#: lib/who_need_help_web/live/activity_live/index.ex:547
#: lib/who_need_help_web/live/request_live/index.ex:595
#, elixir-autogen, elixir-format
msgid "Area or city"
msgstr "Area or city"
#: lib/who_need_help_web/live/activity_live/index.ex:638
#: lib/who_need_help_web/live/request_live/index.ex:683
#: lib/who_need_help_web/live/activity_live/index.ex:670
#: lib/who_need_help_web/live/request_live/index.ex:716
#, elixir-autogen, elixir-format
msgid "Choose an area on the map"
msgstr "Choose an area on the map"
#: lib/who_need_help_web/live/request_live/index.ex:482
#: lib/who_need_help_web/live/request_live/index.ex:515
#, elixir-autogen, elixir-format
msgid "Explore privacy-friendly areas and public exact meeting points chosen by requesters."
msgstr "Explore privacy-friendly areas and public exact meeting points chosen by requesters."
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:637
#: lib/who_need_help_web/live/request_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "List"
msgstr "List"
#: lib/who_need_help_web/live/request_live/index.ex:758
#: lib/who_need_help_web/live/request_live/index.ex:791
#, elixir-autogen, elixir-format
msgid "Load more in this area"
msgstr "Load more in this area"
#: lib/who_need_help_web/components/layouts/root.html.heex:5
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:670
#: lib/who_need_help_web/live/activity_live/index.ex:657
#: lib/who_need_help_web/live/request_live/index.ex:703
#, elixir-autogen, elixir-format
msgid "Map"
msgstr "Map"
@ -4471,41 +4472,41 @@ msgstr "Map"
msgid "Map preview"
msgstr "Map preview"
#: lib/who_need_help_web/live/activity_live/index.ex:654
#: lib/who_need_help_web/live/request_live/index.ex:699
#: lib/who_need_help_web/live/activity_live/index.ex:686
#: lib/who_need_help_web/live/request_live/index.ex:732
#, elixir-autogen, elixir-format
msgid "Move or zoom the map to search somewhere else."
msgstr "Move or zoom the map to search somewhere else."
#: lib/who_need_help_web/live/request_live/index.ex:696
#: lib/who_need_help_web/live/request_live/index.ex:729
#, elixir-autogen, elixir-format
msgid "No open requests in this area"
msgstr "No open requests in this area"
#: lib/who_need_help_web/live/request_live/index.ex:685
#: lib/who_need_help_web/live/request_live/index.ex:718
#, elixir-autogen, elixir-format
msgid "Only requests from the selected map area will be loaded."
msgstr "Only requests from the selected map area will be loaded."
#: lib/who_need_help_web/components/layouts/root.html.heex:8
#: lib/who_need_help_web/live/request_live/index.ex:785
#: lib/who_need_help_web/live/request_live/index.ex:818
#, elixir-autogen, elixir-format
msgid "Open request"
msgstr "Open request"
#: lib/who_need_help_web/live/activity_live/index.ex:516
#: lib/who_need_help_web/live/request_live/index.ex:563
#: lib/who_need_help_web/live/activity_live/index.ex:548
#: lib/who_need_help_web/live/request_live/index.ex:596
#, elixir-autogen, elixir-format
msgid "Optional text search"
msgstr "Optional text search"
#: lib/who_need_help_web/live/request_live/index.ex:764
#: lib/who_need_help_web/live/request_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "Requests without map coordinates appear only when their public area description matches the text search."
msgstr "Requests without map coordinates appear only when their public area description matches the text search."
#: lib/who_need_help_web/live/activity_live/index.ex:596
#: lib/who_need_help_web/live/request_live/index.ex:641
#: lib/who_need_help_web/live/activity_live/index.ex:628
#: lib/who_need_help_web/live/request_live/index.ex:674
#, elixir-autogen, elixir-format
msgid "Results layout"
msgstr "Results layout"
@ -4515,21 +4516,21 @@ msgstr "Results layout"
msgid "Static preview"
msgstr "Static preview"
#: lib/who_need_help_web/live/activity_live/index.ex:615
#: lib/who_need_help_web/live/request_live/index.ex:660
#: lib/who_need_help_web/live/activity_live/index.ex:647
#: lib/who_need_help_web/live/request_live/index.ex:693
#, elixir-autogen, elixir-format
msgid "Together"
msgstr "Together"
#: lib/who_need_help_web/components/layouts/root.html.heex:6
#: lib/who_need_help_web/controllers/page_html/home.html.heex:166
#: lib/who_need_help_web/live/activity_live/index.ex:731
#: lib/who_need_help_web/live/activity_live/index.ex:763
#: lib/who_need_help_web/live/activity_live/new.ex:355
#: lib/who_need_help_web/live/activity_live/new.ex:414
#: lib/who_need_help_web/live/activity_live/show.ex:546
#: lib/who_need_help_web/live/notification_live.ex:590
#: lib/who_need_help_web/live/notification_live.ex:609
#: lib/who_need_help_web/live/request_live/index.ex:784
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/new.ex:485
#: lib/who_need_help_web/live/request_live/new.ex:563
#: lib/who_need_help_web/live/request_live/show.ex:1326
@ -4886,7 +4887,7 @@ msgid "Nearby alert deleted."
msgstr "Nearby alert deleted."
#: lib/who_need_help_web/live/notification_live.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:508
#: lib/who_need_help_web/live/request_live/index.ex:541
#, elixir-autogen, elixir-format
msgid "Nearby requests"
msgstr "Nearby requests"
@ -5209,7 +5210,7 @@ msgid "WebGL is unavailable in this browser, so the full map cannot start. Selec
msgstr "WebGL is unavailable in this browser, so the full map cannot start. Select an example below or retry the map."
#: lib/who_need_help_web/components/layouts/root.html.heex:7
#: lib/who_need_help_web/live/activity_live/index.ex:732
#: lib/who_need_help_web/live/activity_live/index.ex:764
#: lib/who_need_help_web/live/activity_live/show.ex:547
#: lib/who_need_help_web/live/request_live/show.ex:1327
#, elixir-autogen, elixir-format
@ -5250,7 +5251,7 @@ msgid "Case status"
msgstr "Case status"
#: lib/who_need_help_web/controllers/page_html/child_safety.html.heex:42
#: lib/who_need_help_web/controllers/support_controller.ex:242
#: lib/who_need_help_web/controllers/support_controller.ex:268
#: lib/who_need_help_web/live/report_live.ex:50
#, elixir-autogen, elixir-format
msgid "Contact support"
@ -5272,8 +5273,8 @@ msgstr "Content-removal notice received"
msgid "Conversation"
msgstr "Conversation"
#: lib/who_need_help_web/controllers/support_controller.ex:152
#: lib/who_need_help_web/controllers/support_controller.ex:168
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:174
#: lib/who_need_help_web/live/support_case_live.ex:73
#, elixir-autogen, elixir-format
msgid "Could not send your message. Please check it and try again."
@ -5336,7 +5337,7 @@ msgstr "No reports submitted"
msgid "No status history is available for this older case."
msgstr "No status history is available for this older case."
#: lib/who_need_help_web/controllers/support_controller.ex:187
#: lib/who_need_help_web/controllers/support_controller.ex:193
#: lib/who_need_help_web/live/support_case_live.ex:95
#, elixir-autogen, elixir-format
msgid "Only a resolved or closed request can be reopened."
@ -5441,12 +5442,12 @@ msgstr "Send message"
msgid "Status history"
msgstr "Status history"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:15
#: lib/who_need_help_web/controllers/support_html/received.html.heex:17
#, elixir-autogen, elixir-format
msgid "Support request created"
msgstr "Support request created"
#: lib/who_need_help_web/controllers/support_controller.ex:198
#: lib/who_need_help_web/controllers/support_controller.ex:214
#, elixir-autogen, elixir-format
msgid "Support request received"
msgstr "Support request received"
@ -5482,7 +5483,7 @@ msgstr "TRUST AND SAFETY"
msgid "The requester states whether the medicine is paid, reserved, or still needs to be purchased."
msgstr "The requester states whether the medicine is paid, reserved, or still needs to be purchased."
#: lib/who_need_help_web/controllers/support_controller.ex:182
#: lib/who_need_help_web/controllers/support_controller.ex:188
#: lib/who_need_help_web/live/support_case_live.ex:88
#, elixir-autogen, elixir-format
msgid "The support request is open again."
@ -5510,7 +5511,7 @@ msgstr "This private history shows reports you submitted and the latest moderati
msgid "This support request is no longer available."
msgstr "This support request is no longer available."
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:164
#: lib/who_need_help_web/live/support_case_live.ex:60
#, elixir-autogen, elixir-format
msgid "Too many messages. Please try again later."
@ -5521,7 +5522,7 @@ msgstr "Too many messages. Please try again later."
msgid "Use the dedicated urgent process. Never upload or reproduce the image or video."
msgstr "Use the dedicated urgent process. Never upload or reproduce the image or video."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#: lib/who_need_help_web/controllers/support_html/received.html.heex:23
#, elixir-autogen, elixir-format
msgid "We created support request %{reference} and added it to your account. You can open it now and return to it from My support requests."
msgstr "We created support request %{reference} and added it to your account. You can open it now and return to it from My support requests."
@ -5547,7 +5548,7 @@ msgstr "You"
msgid "Your content-removal notices"
msgstr "Your content-removal notices"
#: lib/who_need_help_web/controllers/support_controller.ex:145
#: lib/who_need_help_web/controllers/support_controller.ex:151
#: lib/who_need_help_web/live/support_case_live.ex:53
#, elixir-autogen, elixir-format
msgid "Your message was sent to support."
@ -5711,7 +5712,7 @@ msgstr "Your review is now visible"
msgid "Delivery settings"
msgstr "Delivery settings"
#: lib/who_need_help_web/live/request_live/index.ex:741
#: lib/who_need_help_web/live/request_live/index.ex:774
#, elixir-autogen, elixir-format
msgid "Expires"
msgstr "Expires"
@ -5731,22 +5732,22 @@ msgstr "Nearby alerts"
msgid "Notification sections"
msgstr "Notification sections"
#: lib/who_need_help_web/live/activity_live/index.ex:724
#: lib/who_need_help_web/live/activity_live/index.ex:756
#, elixir-autogen, elixir-format
msgid "%{count} activities"
msgstr "%{count} activities"
#: lib/who_need_help_web/live/request_live/index.ex:786
#: lib/who_need_help_web/live/request_live/index.ex:819
#, elixir-autogen, elixir-format
msgid "%{count} requests"
msgstr "%{count} requests"
#: lib/who_need_help_web/live/activity_live/index.ex:767
#: lib/who_need_help_web/live/activity_live/index.ex:799
#, elixir-autogen, elixir-format
msgid "Activities you create or ask to join will appear here. Leaving removes an activity from this list."
msgstr "Activities you create or ask to join will appear here. Leaving removes an activity from this list."
#: lib/who_need_help_web/live/activity_live/index.ex:470
#: lib/who_need_help_web/live/activity_live/index.ex:502
#, elixir-autogen, elixir-format
msgid "Activity views"
msgstr "Activity views"
@ -5761,12 +5762,12 @@ msgstr "Choose a category and describe the task clearly."
msgid "Confirm the safety guidance before asking nearby people for help."
msgstr "Confirm the safety guidance before asking nearby people for help."
#: lib/who_need_help_web/live/request_live/index.ex:834
#: lib/who_need_help_web/live/request_live/index.ex:867
#, elixir-autogen, elixir-format
msgid "Create request"
msgstr "Create request"
#: lib/who_need_help_web/live/request_live/index.ex:857
#: lib/who_need_help_web/live/request_live/index.ex:890
#, elixir-autogen, elixir-format
msgid "Create your first request"
msgstr "Create your first request"
@ -5781,43 +5782,43 @@ msgstr "Help details"
msgid "Location"
msgstr "Location"
#: lib/who_need_help_web/live/activity_live/index.ex:476
#: lib/who_need_help_web/live/activity_live/index.ex:508
#, elixir-autogen, elixir-format
msgid "My activities"
msgstr "My activities"
#: lib/who_need_help_web/live/request_live/index.ex:509
#: lib/who_need_help_web/live/request_live/index.ex:828
#: lib/who_need_help_web/live/request_live/index.ex:542
#: lib/who_need_help_web/live/request_live/index.ex:861
#, elixir-autogen, elixir-format
msgid "My requests"
msgstr "My requests"
#: lib/who_need_help_web/live/activity_live/index.ex:475
#: lib/who_need_help_web/live/activity_live/index.ex:507
#, elixir-autogen, elixir-format
msgid "Nearby activities"
msgstr "Nearby activities"
#: lib/who_need_help_web/live/activity_live/index.ex:765
#: lib/who_need_help_web/live/activity_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "No activities yet"
msgstr "No activities yet"
#: lib/who_need_help_web/live/activity_live/index.ex:651
#: lib/who_need_help_web/live/activity_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "No open activities in this area"
msgstr "No open activities in this area"
#: lib/who_need_help_web/live/request_live/index.ex:852
#: lib/who_need_help_web/live/request_live/index.ex:885
#, elixir-autogen, elixir-format
msgid "No requests yet"
msgstr "No requests yet"
#: lib/who_need_help_web/live/activity_live/index.ex:640
#: lib/who_need_help_web/live/activity_live/index.ex:672
#, elixir-autogen, elixir-format
msgid "Only activities from the selected map area will be loaded."
msgstr "Only activities from the selected map area will be loaded."
#: lib/who_need_help_web/live/activity_live/index.ex:723
#: lib/who_need_help_web/live/activity_live/index.ex:755
#, elixir-autogen, elixir-format
msgid "Open activity"
msgstr "Open activity"
@ -5827,12 +5828,12 @@ msgstr "Open activity"
msgid "Request form steps"
msgstr "Request form steps"
#: lib/who_need_help_web/live/request_live/index.ex:503
#: lib/who_need_help_web/live/request_live/index.ex:536
#, elixir-autogen, elixir-format
msgid "Request views"
msgstr "Request views"
#: lib/who_need_help_web/live/request_live/index.ex:854
#: lib/who_need_help_web/live/request_live/index.ex:887
#, elixir-autogen, elixir-format
msgid "Requests you publish or accept will appear here."
msgstr "Requests you publish or accept will appear here."
@ -5857,7 +5858,7 @@ msgstr "Set urgency and when this request should close."
msgid "Share only as much location detail as helpers need."
msgstr "Share only as much location detail as helpers need."
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/index.ex:761
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Activity details remain usable."
msgstr "The map is unavailable in this browser. Activity details remain usable."
@ -5867,7 +5868,7 @@ msgstr "The map is unavailable in this browser. Activity details remain usable."
msgid "Timing"
msgstr "Timing"
#: lib/who_need_help_web/live/request_live/index.ex:830
#: lib/who_need_help_web/live/request_live/index.ex:863
#, elixir-autogen, elixir-format
msgid "Track requests you created and requests you accepted as a helper."
msgstr "Track requests you created and requests you accepted as a helper."
@ -6522,91 +6523,91 @@ msgstr "What should people see before approval?"
msgid "Choose the meeting point on the map or use your current location."
msgstr "Choose the meeting point on the map or use your current location."
#: lib/who_need_help_web/live/activity_live/index.ex:555
#: lib/who_need_help_web/live/activity_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:757
#: lib/who_need_help_web/live/request_live/index.ex:600
#: lib/who_need_help_web/live/request_live/index.ex:695
#: lib/who_need_help_web/live/request_live/index.ex:844
#: lib/who_need_help_web/live/activity_live/index.ex:587
#: lib/who_need_help_web/live/activity_live/index.ex:682
#: lib/who_need_help_web/live/activity_live/index.ex:789
#: lib/who_need_help_web/live/request_live/index.ex:633
#: lib/who_need_help_web/live/request_live/index.ex:728
#: lib/who_need_help_web/live/request_live/index.ex:877
#, elixir-autogen, elixir-format
msgid "Loading results…"
msgstr "Loading results…"
#: lib/who_need_help_web/live/activity_live/index.ex:726
#: lib/who_need_help_web/live/activity_live/index.ex:758
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching activities are listed beside the map."
msgstr "Maximum zoom reached. Matching activities are listed beside the map."
#: lib/who_need_help_web/live/request_live/index.ex:788
#: lib/who_need_help_web/live/request_live/index.ex:821
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching requests are listed beside the map."
msgstr "Maximum zoom reached. Matching requests are listed beside the map."
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/index.ex:568
#, elixir-autogen, elixir-format
msgid "%{count} activity in the selected map area"
msgid_plural "%{count} activities in the selected map area"
msgstr[0] "%{count} activity in the selected map area"
msgstr[1] "%{count} activities in the selected map area"
#: lib/who_need_help_web/live/request_live/index.ex:581
#: lib/who_need_help_web/live/request_live/index.ex:614
#, elixir-autogen, elixir-format
msgid "%{count} request in the selected map area"
msgid_plural "%{count} requests in the selected map area"
msgstr[0] "%{count} request in the selected map area"
msgstr[1] "%{count} requests in the selected map area"
#: lib/who_need_help_web/live/activity_live/index.ex:561
#: lib/who_need_help_web/live/request_live/index.ex:606
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:639
#, elixir-autogen, elixir-format
msgid "Map moved. Results still show the previous area."
msgstr "Map moved. Results still show the previous area."
#: lib/who_need_help_web/live/activity_live/index.ex:579
#: lib/who_need_help_web/live/activity_live/index.ex:611
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show activities in this area”."
msgstr "Move or zoom the map, then choose “Show activities in this area”."
#: lib/who_need_help_web/live/request_live/index.ex:624
#: lib/who_need_help_web/live/request_live/index.ex:657
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show requests in this area”."
msgstr "Move or zoom the map, then choose “Show requests in this area”."
#: lib/who_need_help_web/live/activity_live/index.ex:573
#: lib/who_need_help_web/live/request_live/index.ex:618
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:651
#, elixir-autogen, elixir-format
msgid "Results update automatically after you stop moving the map."
msgstr "Results update automatically after you stop moving the map."
#: lib/who_need_help_web/live/activity_live/index.ex:743
#: lib/who_need_help_web/live/activity_live/index.ex:775
#, elixir-autogen, elixir-format
msgid "Show activities in this area"
msgstr "Show activities in this area"
#: lib/who_need_help_web/live/request_live/index.ex:800
#: lib/who_need_help_web/live/request_live/index.ex:833
#, elixir-autogen, elixir-format
msgid "Show requests in this area"
msgstr "Show requests in this area"
#: lib/who_need_help_web/live/activity_live/index.ex:545
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/activity_live/index.ex:577
#: lib/who_need_help_web/live/request_live/index.ex:623
#, elixir-autogen, elixir-format
msgid "Showing %{shown} of %{count} in the list."
msgstr "Showing %{shown} of %{count} in the list."
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:638
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:671
#, elixir-autogen, elixir-format
msgid "Update results as map moves"
msgstr "Update results as map moves"
#: lib/who_need_help_web/live/activity_live/index.ex:567
#: lib/who_need_help_web/live/request_live/index.ex:612
#: lib/who_need_help_web/live/activity_live/index.ex:599
#: lib/who_need_help_web/live/request_live/index.ex:645
#, elixir-autogen, elixir-format
msgid "Updating results for the visible map area…"
msgstr "Updating results for the visible map area…"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#: lib/who_need_help_web/controllers/support_html/received.html.heex:12
#, elixir-autogen, elixir-format
msgid "EMAIL CONFIRMATION REQUIRED"
msgstr "EMAIL CONFIRMATION REQUIRED"
@ -6626,7 +6627,7 @@ msgstr "Waiting for location permission…"
msgid "Pending email verification"
msgstr "Pending email verification"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:25
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#, elixir-autogen, elixir-format
msgid "We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review."
msgstr "We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review."
@ -7690,7 +7691,7 @@ msgstr "You do not have permission for this action. Role changes also require a
msgid "Your email was confirmed and the notice was sent for review."
msgstr "Your email was confirmed and the notice was sent for review."
#: lib/who_need_help_web/controllers/support_controller.ex:122
#: lib/who_need_help_web/controllers/support_controller.ex:128
#, elixir-autogen, elixir-format
msgid "Your email was confirmed and the request was sent to support."
msgstr "Your email was confirmed and the request was sent to support."
@ -7888,7 +7889,7 @@ msgstr "Copy and paste this secure address into your browser:"
msgid "Confirm content-removal notice"
msgstr "Confirm content-removal notice"
#: lib/who_need_help_web/controllers/support_controller.ex:106
#: lib/who_need_help_web/controllers/support_controller.ex:112
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:9
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:23
#, elixir-autogen, elixir-format
@ -7914,3 +7915,13 @@ msgstr "If you did not submit this notice, close this page. Nothing will be sent
#, elixir-autogen, elixir-format
msgid "If you did not submit this request, close this page. Nothing will be sent to support."
msgstr "If you did not submit this request, close this page. Nothing will be sent to support."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:29
#, elixir-autogen, elixir-format
msgid "If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
msgstr "If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#, elixir-autogen, elixir-format
msgid "REQUEST CHECKED"
msgstr "REQUEST CHECKED"

View File

@ -262,7 +262,7 @@ msgstr "Активность опубликована. Вы одобряете
msgid "Activity restored."
msgstr "Активность восстановлена."
#: lib/who_need_help_web/live/activity_live/index.ex:504
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/new.ex:204
#, elixir-autogen, elixir-format
msgid "Activity type"
@ -280,12 +280,12 @@ msgstr "Добавить неподтверждённую ссылку"
msgid "Administrator"
msgstr "Администратор"
#: lib/who_need_help_web/live/activity_live/index.ex:506
#: lib/who_need_help_web/live/activity_live/index.ex:538
#, elixir-autogen, elixir-format
msgid "All activities"
msgstr "Все активности"
#: lib/who_need_help_web/live/request_live/index.ex:539
#: lib/who_need_help_web/live/request_live/index.ex:572
#, elixir-autogen, elixir-format
msgid "All categories"
msgstr "Все категории"
@ -300,7 +300,7 @@ msgstr "Уже зарегистрированы?"
msgid "Another helper already accepted this request."
msgstr "Другой помощник уже принял эту заявку."
#: lib/who_need_help_web/live/request_live/index.ex:554
#: lib/who_need_help_web/live/request_live/index.ex:587
#, elixir-autogen, elixir-format
msgid "Any urgency"
msgstr "Любая срочность"
@ -420,16 +420,16 @@ msgstr "Отменить активность"
msgid "Cancel request"
msgstr "Отменить заявку"
#: lib/who_need_help_web/live/activity_live/index.ex:435
#: lib/who_need_help_web/live/activity_live/index.ex:467
#: lib/who_need_help_web/live/activity_live/show.ex:344
#: lib/who_need_help_web/live/request_live/index.ex:459
#: lib/who_need_help_web/live/request_live/index.ex:460
#: lib/who_need_help_web/live/request_live/index.ex:492
#: lib/who_need_help_web/live/request_live/index.ex:493
#: lib/who_need_help_web/live/request_live/show.ex:1005
#, elixir-autogen, elixir-format
msgid "Cancelled"
msgstr "Отменено"
#: lib/who_need_help_web/live/request_live/index.ex:537
#: lib/who_need_help_web/live/request_live/index.ex:570
#: lib/who_need_help_web/live/request_live/new.ex:302
#, elixir-autogen, elixir-format
msgid "Category"
@ -510,7 +510,7 @@ msgstr "Закрыть"
msgid "Coffee and conversation"
msgstr "Кофе и разговоры"
#: lib/who_need_help_web/live/activity_live/index.ex:449
#: lib/who_need_help_web/live/activity_live/index.ex:481
#, elixir-autogen, elixir-format
msgid "Coffee, cinema, walks, and hikes are separate from urgent help and never affect helper ratings."
msgstr ""
@ -527,19 +527,19 @@ msgstr "Комментарий (необязательно)"
msgid "Community helpers"
msgstr "Помощники сообщества"
#: lib/who_need_help_web/live/activity_live/index.ex:697
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/show.ex:403
#: lib/who_need_help_web/live/activity_live/show.ex:639
#: lib/who_need_help_web/live/activity_live/show.ex:698
#: lib/who_need_help_web/live/request_live/index.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:770
#, elixir-autogen, elixir-format
msgid "Community member"
msgstr "Член сообщества"
#: lib/who_need_help_web/live/activity_live/index.ex:434
#: lib/who_need_help_web/live/activity_live/index.ex:466
#: lib/who_need_help_web/live/activity_live/show.ex:343
#: lib/who_need_help_web/live/request_live/index.ex:457
#: lib/who_need_help_web/live/request_live/index.ex:458
#: lib/who_need_help_web/live/request_live/index.ex:490
#: lib/who_need_help_web/live/request_live/index.ex:491
#: lib/who_need_help_web/live/request_live/show.ex:1004
#: lib/who_need_help_web/live/request_live/show.ex:1023
#, elixir-autogen, elixir-format
@ -589,13 +589,13 @@ msgstr ""
msgid "Confirming..."
msgstr "Подтверждение…"
#: lib/who_need_help_web/live/activity_live/index.ex:455
#: lib/who_need_help_web/live/activity_live/index.ex:487
#: lib/who_need_help_web/live/activity_live/new.ex:12
#, elixir-autogen, elixir-format
msgid "Create activity"
msgstr "Создать активность"
#: lib/who_need_help_web/live/activity_live/index.ex:772
#: lib/who_need_help_web/live/activity_live/index.ex:804
#: lib/who_need_help_web/live/activity_live/new.ex:180
#, elixir-autogen, elixir-format
msgid "Create an activity"
@ -606,7 +606,7 @@ msgstr "Создать активность"
msgid "Create category"
msgstr "Создать категорию"
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:521
#, elixir-autogen, elixir-format
msgid "Create urgent request"
msgstr "Создать срочную заявку"
@ -761,7 +761,7 @@ msgstr "Истекает:"
msgid "Explain what is already arranged and what the volunteer needs to do."
msgstr "Объясните, что уже сделано и что нужно сделать волонтеру."
#: lib/who_need_help_web/live/activity_live/index.ex:446
#: lib/who_need_help_web/live/activity_live/index.ex:478
#, elixir-autogen, elixir-format
msgid "Find people to join"
msgstr "Найти компанию"
@ -927,8 +927,8 @@ msgstr ""
"Android показывает постоянное уведомление и может продолжать передачу после "
"сворачивания. При остановке передачи исходные координаты удаляются."
#: lib/who_need_help_web/live/request_live/index.ex:455
#: lib/who_need_help_web/live/request_live/index.ex:456
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:489
#: lib/who_need_help_web/live/request_live/show.ex:1003
#, elixir-autogen, elixir-format
msgid "In progress"
@ -1053,8 +1053,8 @@ msgstr "Отметить завершённой"
msgid "Match and coordinate"
msgstr "Найдите помощника и согласуйте детали"
#: lib/who_need_help_web/live/request_live/index.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:454
#: lib/who_need_help_web/live/request_live/index.ex:486
#: lib/who_need_help_web/live/request_live/index.ex:487
#: lib/who_need_help_web/live/request_live/show.ex:1001
#, elixir-autogen, elixir-format
msgid "Matched"
@ -1083,7 +1083,7 @@ msgstr ""
msgid "Medicine requests"
msgstr "Заявки на лекарства"
#: lib/who_need_help_web/live/activity_live/index.ex:462
#: lib/who_need_help_web/live/activity_live/index.ex:494
#, elixir-autogen, elixir-format
msgid "Meet in public first, keep exact details inside the approved group, and leave or report anything that feels unsafe."
msgstr ""
@ -1133,7 +1133,7 @@ msgstr "Модератор"
msgid "Moderator access is required."
msgstr "Требуется доступ модератора."
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:512
#, elixir-autogen, elixir-format
msgid "NEARBY MUTUAL AID"
msgstr "ВЗАИМОПОМОЩЬ РЯДОМ"
@ -1211,9 +1211,9 @@ msgid "Not for emergencies"
msgstr "Не для чрезвычайных ситуаций"
#: lib/who_need_help_web/live/notification_live.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:443
#: lib/who_need_help_web/live/request_live/index.ex:444
#: lib/who_need_help_web/live/request_live/index.ex:555
#: lib/who_need_help_web/live/request_live/index.ex:476
#: lib/who_need_help_web/live/request_live/index.ex:477
#: lib/who_need_help_web/live/request_live/index.ex:588
#: lib/who_need_help_web/live/request_live/new.ex:449
#: lib/who_need_help_web/live/request_live/show.ex:992
#: lib/who_need_help_web/live/request_live/show.ex:993
@ -1221,7 +1221,7 @@ msgstr "Не для чрезвычайных ситуаций"
msgid "Now"
msgstr "Сейчас"
#: lib/who_need_help_web/live/activity_live/index.ex:444
#: lib/who_need_help_web/live/activity_live/index.ex:476
#, elixir-autogen, elixir-format
msgid "OPTIONAL SOCIAL PLANS"
msgstr "НЕОБЯЗАТЕЛЬНЫЕ СОВМЕСТНЫЕ ПЛАНЫ"
@ -1241,14 +1241,14 @@ msgstr ""
#: lib/who_need_help/notifications/text.ex:140
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
#: lib/who_need_help_web/controllers/support_html.ex:17
#: lib/who_need_help_web/live/activity_live/index.ex:433
#: lib/who_need_help_web/live/activity_live/index.ex:465
#: lib/who_need_help_web/live/activity_live/show.ex:342
#: lib/who_need_help_web/live/moderation_live.ex:636
#: lib/who_need_help_web/live/moderation_live.ex:817
#: lib/who_need_help_web/live/moderation_live.ex:941
#: lib/who_need_help_web/live/report_live.ex:104
#: lib/who_need_help_web/live/request_live/index.ex:451
#: lib/who_need_help_web/live/request_live/index.ex:452
#: lib/who_need_help_web/live/request_live/index.ex:484
#: lib/who_need_help_web/live/request_live/index.ex:485
#: lib/who_need_help_web/live/request_live/show.ex:1000
#: lib/who_need_help_web/live/support_operation_live.ex:310
#: lib/who_need_help_web/live/support_operation_live.ex:414
@ -1712,9 +1712,9 @@ msgid "Save profile"
msgstr "Сохранить профиль"
#: lib/who_need_help_web/live/notification_live.ex:738
#: lib/who_need_help_web/live/request_live/index.ex:447
#: lib/who_need_help_web/live/request_live/index.ex:448
#: lib/who_need_help_web/live/request_live/index.ex:557
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:481
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/request_live/new.ex:451
#: lib/who_need_help_web/live/request_live/show.ex:996
#: lib/who_need_help_web/live/request_live/show.ex:997
@ -1988,7 +1988,7 @@ msgstr "Состояние этой активности уже изменило
msgid "This interaction is blocked."
msgstr "Это взаимодействие заблокировано."
#: lib/who_need_help_web/live/request_live/index.ex:495
#: lib/who_need_help_web/live/request_live/index.ex:528
#: lib/who_need_help_web/live/request_live/show.ex:1071
#, elixir-autogen, elixir-format
msgid "This is not an emergency service. Contact local emergency services for immediate danger."
@ -2041,9 +2041,9 @@ msgid "To see sent emails, visit"
msgstr "Чтобы посмотреть отправленные письма, откройте"
#: lib/who_need_help_web/live/notification_live.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:445
#: lib/who_need_help_web/live/request_live/index.ex:446
#: lib/who_need_help_web/live/request_live/index.ex:556
#: lib/who_need_help_web/live/request_live/index.ex:478
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:589
#: lib/who_need_help_web/live/request_live/new.ex:450
#: lib/who_need_help_web/live/request_live/show.ex:994
#: lib/who_need_help_web/live/request_live/show.ex:995
@ -2113,7 +2113,7 @@ msgid "Unique people"
msgstr "Уникальные люди"
#: lib/who_need_help_web/live/notification_live.ex:731
#: lib/who_need_help_web/live/request_live/index.ex:552
#: lib/who_need_help_web/live/request_live/index.ex:585
#: lib/who_need_help_web/live/request_live/new.ex:447
#, elixir-autogen, elixir-format
msgid "Urgency"
@ -2257,7 +2257,7 @@ msgstr ""
"через подписку ChatGPT разработчика. Ключ OpenAI API и резервный вариант API"
" с оплатой по использованию не применяются."
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:513
#, elixir-autogen, elixir-format
msgid "Who needs help?"
msgstr "Кому нужна помощь?"
@ -2377,7 +2377,7 @@ msgid "Your review is revealed only after both participants submit."
msgstr ""
"Ваш отзыв откроется только после того, как его отправят оба участника."
#: lib/who_need_help_web/live/request_live/index.ex:805
#: lib/who_need_help_web/live/request_live/index.ex:838
#, elixir-autogen, elixir-format
msgid "Your trust summary"
msgstr "Ваши показатели доверия"
@ -2388,16 +2388,16 @@ msgstr "Ваши показатели доверия"
msgid "before confirming."
msgstr "перед подтверждением."
#: lib/who_need_help_web/live/activity_live/index.ex:696
#: lib/who_need_help_web/live/activity_live/index.ex:728
#: lib/who_need_help_web/live/category_proposal_live.ex:252
#: lib/who_need_help_web/live/request_live/index.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:769
#, elixir-autogen, elixir-format
msgid "by %{name}"
msgstr "автор: %{name}"
#: lib/who_need_help_web/live/profile_live.ex:190
#: lib/who_need_help_web/live/public_profile_live.ex:133
#: lib/who_need_help_web/live/request_live/index.ex:809
#: lib/who_need_help_web/live/request_live/index.ex:842
#: lib/who_need_help_web/live/request_live/show.ex:1478
#, elixir-autogen, elixir-format
msgid "completed"
@ -2433,7 +2433,7 @@ msgstr "организатор"
msgid "participants only"
msgstr "только участники"
#: lib/who_need_help_web/live/request_live/index.ex:813
#: lib/who_need_help_web/live/request_live/index.ex:846
#: lib/who_need_help_web/live/request_live/show.ex:1482
#, elixir-autogen, elixir-format
msgid "people"
@ -2493,7 +2493,7 @@ msgstr "срочно"
#: lib/who_need_help_web/live/activity_live/show.ex:719
#: lib/who_need_help_web/live/profile_live.ex:285
#: lib/who_need_help_web/live/public_profile_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/index.ex:850
#: lib/who_need_help_web/live/request_live/show.ex:1142
#: lib/who_need_help_web/live/request_live/show.ex:1580
#, elixir-autogen, elixir-format
@ -2526,8 +2526,8 @@ msgstr "← Заявки"
msgid "Approved"
msgstr "Одобрено"
#: lib/who_need_help_web/live/request_live/index.ex:461
#: lib/who_need_help_web/live/request_live/index.ex:462
#: lib/who_need_help_web/live/request_live/index.ex:494
#: lib/who_need_help_web/live/request_live/index.ex:495
#, elixir-autogen, elixir-format
msgid "Expired"
msgstr "Истекло"
@ -2581,21 +2581,21 @@ msgstr "Необычная частота действий"
msgid "Load earlier messages"
msgstr "Загрузить предыдущие сообщения"
#: lib/who_need_help_web/live/activity_live/index.ex:708
#: lib/who_need_help_web/live/activity_live/index.ex:801
#: lib/who_need_help_web/live/activity_live/index.ex:740
#: lib/who_need_help_web/live/activity_live/index.ex:833
#: lib/who_need_help_web/live/category_proposal_live.ex:284
#: lib/who_need_help_web/live/leaderboard_live.ex:91
#: lib/who_need_help_web/live/profile_live.ex:233
#: lib/who_need_help_web/live/profile_live.ex:363
#: lib/who_need_help_web/live/public_profile_live.ex:178
#: lib/who_need_help_web/live/report_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:886
#: lib/who_need_help_web/live/request_live/index.ex:919
#, elixir-autogen, elixir-format
msgid "Load more"
msgstr "Загрузить ещё"
#: lib/who_need_help_web/live/activity_live/show.ex:544
#: lib/who_need_help_web/live/request_live/index.ex:782
#: lib/who_need_help_web/live/request_live/index.ex:815
#: lib/who_need_help_web/live/request_live/show.ex:1324
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Request details remain usable."
@ -2963,7 +2963,7 @@ msgstr "Обжаловать решение модерации"
msgid "Back to removal form"
msgstr "Вернуться к форме удаления"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#: lib/who_need_help_web/controllers/support_html/received.html.heex:43
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:30
#, elixir-autogen, elixir-format
msgid "Back to support"
@ -2975,7 +2975,8 @@ msgstr "Вернуться в поддержку"
msgid "CONTENT REMOVAL"
msgstr "УДАЛЕНИЕ КОНТЕНТА"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:16
#: lib/who_need_help_web/controllers/support_html/received.html.heex:18
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#, elixir-autogen, elixir-format
msgid "Check your email"
msgstr "Проверьте почту"
@ -3255,7 +3256,7 @@ msgstr "Сообщить о незаконном или вредоносном
msgid "Reported locations"
msgstr "Указанные адреса контента"
#: lib/who_need_help_web/controllers/support_controller.ex:241
#: lib/who_need_help_web/controllers/support_controller.ex:267
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:42
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:128
@ -3406,8 +3407,8 @@ msgstr "Угроза жизни или безопасности"
msgid "Too many removal notices. Please try again later."
msgstr "Слишком много уведомлений об удалении. Повторите попытку позже."
#: lib/who_need_help_web/controllers/support_controller.ex:42
#: lib/who_need_help_web/controllers/support_controller.ex:84
#: lib/who_need_help_web/controllers/support_controller.ex:45
#: lib/who_need_help_web/controllers/support_controller.ex:90
#, elixir-autogen, elixir-format
msgid "Too many support requests. Please try again later."
msgstr "Слишком много обращений в поддержку. Повторите попытку позже."
@ -3489,13 +3490,13 @@ msgstr "Номер вашего обращения: %{reference}"
msgid "Your relationship to the affected person or rights holder"
msgstr "Ваше отношение к пострадавшему лицу или правообладателю"
#: lib/who_need_help_web/controllers/support_controller.ex:55
#: lib/who_need_help_web/controllers/support_controller.ex:66
#: lib/who_need_help_web/controllers/support_controller.ex:58
#: lib/who_need_help_web/controllers/support_controller.ex:69
#, elixir-autogen, elixir-format
msgid "Delete my Who Need Help account"
msgstr "Удалить мой аккаунт Who Need Help"
#: lib/who_need_help_web/controllers/support_controller.ex:56
#: lib/who_need_help_web/controllers/support_controller.ex:59
#, elixir-autogen, elixir-format
msgid "Please delete my account and associated personal data."
msgstr "Пожалуйста, удалите мой аккаунт и связанные персональные данные."
@ -4432,7 +4433,7 @@ msgid "View my notices"
msgstr "Посмотреть мои уведомления"
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
#: lib/who_need_help_web/controllers/support_html/received.html.heex:32
#: lib/who_need_help_web/controllers/support_html/received.html.heex:41
#, elixir-autogen, elixir-format
msgid "View my requests"
msgstr "Посмотреть мои обращения"
@ -4547,37 +4548,37 @@ msgstr "Перетащите, чтобы переместить точную т
msgid "Exact point selected. Drag the red pin or click the map to move it."
msgstr "Точная точка выбрана. Перетащите красный маркер или нажмите на карту, чтобы переместить её."
#: lib/who_need_help_web/live/activity_live/index.ex:515
#: lib/who_need_help_web/live/request_live/index.ex:562
#: lib/who_need_help_web/live/activity_live/index.ex:547
#: lib/who_need_help_web/live/request_live/index.ex:595
#, elixir-autogen, elixir-format
msgid "Area or city"
msgstr "Район или город"
#: lib/who_need_help_web/live/activity_live/index.ex:638
#: lib/who_need_help_web/live/request_live/index.ex:683
#: lib/who_need_help_web/live/activity_live/index.ex:670
#: lib/who_need_help_web/live/request_live/index.ex:716
#, elixir-autogen, elixir-format
msgid "Choose an area on the map"
msgstr "Выберите область на карте"
#: lib/who_need_help_web/live/request_live/index.ex:482
#: lib/who_need_help_web/live/request_live/index.ex:515
#, elixir-autogen, elixir-format
msgid "Explore privacy-friendly areas and public exact meeting points chosen by requesters."
msgstr "Просматривайте безопасные для приватности области и точные публичные места встречи, выбранные авторами заявок."
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:637
#: lib/who_need_help_web/live/request_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "List"
msgstr "Список"
#: lib/who_need_help_web/live/request_live/index.ex:758
#: lib/who_need_help_web/live/request_live/index.ex:791
#, elixir-autogen, elixir-format
msgid "Load more in this area"
msgstr "Загрузить ещё в этой области"
#: lib/who_need_help_web/components/layouts/root.html.heex:5
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:670
#: lib/who_need_help_web/live/activity_live/index.ex:657
#: lib/who_need_help_web/live/request_live/index.ex:703
#, elixir-autogen, elixir-format
msgid "Map"
msgstr "Карта"
@ -4587,41 +4588,41 @@ msgstr "Карта"
msgid "Map preview"
msgstr "Предпросмотр карты"
#: lib/who_need_help_web/live/activity_live/index.ex:654
#: lib/who_need_help_web/live/request_live/index.ex:699
#: lib/who_need_help_web/live/activity_live/index.ex:686
#: lib/who_need_help_web/live/request_live/index.ex:732
#, elixir-autogen, elixir-format
msgid "Move or zoom the map to search somewhere else."
msgstr "Переместите или масштабируйте карту, чтобы искать в другом месте."
#: lib/who_need_help_web/live/request_live/index.ex:696
#: lib/who_need_help_web/live/request_live/index.ex:729
#, elixir-autogen, elixir-format
msgid "No open requests in this area"
msgstr "В этой области нет открытых заявок"
#: lib/who_need_help_web/live/request_live/index.ex:685
#: lib/who_need_help_web/live/request_live/index.ex:718
#, elixir-autogen, elixir-format
msgid "Only requests from the selected map area will be loaded."
msgstr "Будут загружены только заявки из выбранной области карты."
#: lib/who_need_help_web/components/layouts/root.html.heex:8
#: lib/who_need_help_web/live/request_live/index.ex:785
#: lib/who_need_help_web/live/request_live/index.ex:818
#, elixir-autogen, elixir-format
msgid "Open request"
msgstr "Открыть заявку"
#: lib/who_need_help_web/live/activity_live/index.ex:516
#: lib/who_need_help_web/live/request_live/index.ex:563
#: lib/who_need_help_web/live/activity_live/index.ex:548
#: lib/who_need_help_web/live/request_live/index.ex:596
#, elixir-autogen, elixir-format
msgid "Optional text search"
msgstr "Необязательный текстовый поиск"
#: lib/who_need_help_web/live/request_live/index.ex:764
#: lib/who_need_help_web/live/request_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "Requests without map coordinates appear only when their public area description matches the text search."
msgstr "Заявки без координат на карте отображаются только тогда, когда описание публичной области совпадает с текстовым поиском."
#: lib/who_need_help_web/live/activity_live/index.ex:596
#: lib/who_need_help_web/live/request_live/index.ex:641
#: lib/who_need_help_web/live/activity_live/index.ex:628
#: lib/who_need_help_web/live/request_live/index.ex:674
#, elixir-autogen, elixir-format
msgid "Results layout"
msgstr "Расположение результатов"
@ -4631,21 +4632,21 @@ msgstr "Расположение результатов"
msgid "Static preview"
msgstr "Статический просмотр"
#: lib/who_need_help_web/live/activity_live/index.ex:615
#: lib/who_need_help_web/live/request_live/index.ex:660
#: lib/who_need_help_web/live/activity_live/index.ex:647
#: lib/who_need_help_web/live/request_live/index.ex:693
#, elixir-autogen, elixir-format
msgid "Together"
msgstr "Вместе"
#: lib/who_need_help_web/components/layouts/root.html.heex:6
#: lib/who_need_help_web/controllers/page_html/home.html.heex:166
#: lib/who_need_help_web/live/activity_live/index.ex:731
#: lib/who_need_help_web/live/activity_live/index.ex:763
#: lib/who_need_help_web/live/activity_live/new.ex:355
#: lib/who_need_help_web/live/activity_live/new.ex:414
#: lib/who_need_help_web/live/activity_live/show.ex:546
#: lib/who_need_help_web/live/notification_live.ex:590
#: lib/who_need_help_web/live/notification_live.ex:609
#: lib/who_need_help_web/live/request_live/index.ex:784
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/new.ex:485
#: lib/who_need_help_web/live/request_live/new.ex:563
#: lib/who_need_help_web/live/request_live/show.ex:1326
@ -5003,7 +5004,7 @@ msgid "Nearby alert deleted."
msgstr "Уведомление поблизости удалено."
#: lib/who_need_help_web/live/notification_live.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:508
#: lib/who_need_help_web/live/request_live/index.ex:541
#, elixir-autogen, elixir-format
msgid "Nearby requests"
msgstr "Заявки поблизости"
@ -5326,7 +5327,7 @@ msgid "WebGL is unavailable in this browser, so the full map cannot start. Selec
msgstr "WebGL недоступен в этом браузере, поэтому полная карта не может запуститься. Выберите пример ниже или попробуйте запустить карту ещё раз."
#: lib/who_need_help_web/components/layouts/root.html.heex:7
#: lib/who_need_help_web/live/activity_live/index.ex:732
#: lib/who_need_help_web/live/activity_live/index.ex:764
#: lib/who_need_help_web/live/activity_live/show.ex:547
#: lib/who_need_help_web/live/request_live/show.ex:1327
#, elixir-autogen, elixir-format
@ -5367,7 +5368,7 @@ msgid "Case status"
msgstr "Статус обращения"
#: lib/who_need_help_web/controllers/page_html/child_safety.html.heex:42
#: lib/who_need_help_web/controllers/support_controller.ex:242
#: lib/who_need_help_web/controllers/support_controller.ex:268
#: lib/who_need_help_web/live/report_live.ex:50
#, elixir-autogen, elixir-format
msgid "Contact support"
@ -5389,8 +5390,8 @@ msgstr "Уведомление об удалении контента получ
msgid "Conversation"
msgstr "Переписка"
#: lib/who_need_help_web/controllers/support_controller.ex:152
#: lib/who_need_help_web/controllers/support_controller.ex:168
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:174
#: lib/who_need_help_web/live/support_case_live.ex:73
#, elixir-autogen, elixir-format
msgid "Could not send your message. Please check it and try again."
@ -5453,7 +5454,7 @@ msgstr "Жалоб не отправлено"
msgid "No status history is available for this older case."
msgstr "Для этого старого обращения история статусов недоступна."
#: lib/who_need_help_web/controllers/support_controller.ex:187
#: lib/who_need_help_web/controllers/support_controller.ex:193
#: lib/who_need_help_web/live/support_case_live.ex:95
#, elixir-autogen, elixir-format
msgid "Only a resolved or closed request can be reopened."
@ -5558,12 +5559,12 @@ msgstr "Отправить сообщение"
msgid "Status history"
msgstr "История статусов"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:15
#: lib/who_need_help_web/controllers/support_html/received.html.heex:17
#, elixir-autogen, elixir-format
msgid "Support request created"
msgstr "Обращение в поддержку создано"
#: lib/who_need_help_web/controllers/support_controller.ex:198
#: lib/who_need_help_web/controllers/support_controller.ex:214
#, elixir-autogen, elixir-format
msgid "Support request received"
msgstr "Обращение в поддержку получено"
@ -5599,7 +5600,7 @@ msgstr "ДОВЕРИЕ И БЕЗОПАСНОСТЬ"
msgid "The requester states whether the medicine is paid, reserved, or still needs to be purchased."
msgstr "Автор заявки указывает, оплачено ли лекарство, зарезервировано или его ещё нужно купить."
#: lib/who_need_help_web/controllers/support_controller.ex:182
#: lib/who_need_help_web/controllers/support_controller.ex:188
#: lib/who_need_help_web/live/support_case_live.ex:88
#, elixir-autogen, elixir-format
msgid "The support request is open again."
@ -5627,7 +5628,7 @@ msgstr "В этой личной истории показаны ваши жал
msgid "This support request is no longer available."
msgstr "Это обращение в поддержку больше недоступно."
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:164
#: lib/who_need_help_web/live/support_case_live.ex:60
#, elixir-autogen, elixir-format
msgid "Too many messages. Please try again later."
@ -5638,7 +5639,7 @@ msgstr "Слишком много сообщений. Попробуйте по
msgid "Use the dedicated urgent process. Never upload or reproduce the image or video."
msgstr "Используйте специальную срочную процедуру. Никогда не загружайте и не воспроизводите изображение или видео."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#: lib/who_need_help_web/controllers/support_html/received.html.heex:23
#, elixir-autogen, elixir-format
msgid "We created support request %{reference} and added it to your account. You can open it now and return to it from My support requests."
msgstr "Мы создали обращение %{reference} и добавили его в ваш аккаунт. Его можно открыть сейчас или вернуться к нему из раздела «Мои обращения»."
@ -5664,7 +5665,7 @@ msgstr "Вы"
msgid "Your content-removal notices"
msgstr "Ваши уведомления об удалении контента"
#: lib/who_need_help_web/controllers/support_controller.ex:145
#: lib/who_need_help_web/controllers/support_controller.ex:151
#: lib/who_need_help_web/live/support_case_live.ex:53
#, elixir-autogen, elixir-format
msgid "Your message was sent to support."
@ -5828,7 +5829,7 @@ msgstr "Теперь ваш отзыв виден"
msgid "Delivery settings"
msgstr "Настройки доставки"
#: lib/who_need_help_web/live/request_live/index.ex:741
#: lib/who_need_help_web/live/request_live/index.ex:774
#, elixir-autogen, elixir-format
msgid "Expires"
msgstr "Истекает"
@ -5848,22 +5849,22 @@ msgstr "Оповещения рядом"
msgid "Notification sections"
msgstr "Разделы уведомлений"
#: lib/who_need_help_web/live/activity_live/index.ex:724
#: lib/who_need_help_web/live/activity_live/index.ex:756
#, elixir-autogen, elixir-format
msgid "%{count} activities"
msgstr "Активностей: %{count}"
#: lib/who_need_help_web/live/request_live/index.ex:786
#: lib/who_need_help_web/live/request_live/index.ex:819
#, elixir-autogen, elixir-format
msgid "%{count} requests"
msgstr "Заявок: %{count}"
#: lib/who_need_help_web/live/activity_live/index.ex:767
#: lib/who_need_help_web/live/activity_live/index.ex:799
#, elixir-autogen, elixir-format
msgid "Activities you create or ask to join will appear here. Leaving removes an activity from this list."
msgstr "Созданные вами активности и те, к которым вы попросили присоединиться, появятся здесь. После выхода активность исчезнет из списка."
#: lib/who_need_help_web/live/activity_live/index.ex:470
#: lib/who_need_help_web/live/activity_live/index.ex:502
#, elixir-autogen, elixir-format
msgid "Activity views"
msgstr "Разделы активностей"
@ -5878,12 +5879,12 @@ msgstr "Выберите категорию и понятно опишите з
msgid "Confirm the safety guidance before asking nearby people for help."
msgstr "Подтвердите правила безопасности перед публикацией заявки."
#: lib/who_need_help_web/live/request_live/index.ex:834
#: lib/who_need_help_web/live/request_live/index.ex:867
#, elixir-autogen, elixir-format
msgid "Create request"
msgstr "Создать заявку"
#: lib/who_need_help_web/live/request_live/index.ex:857
#: lib/who_need_help_web/live/request_live/index.ex:890
#, elixir-autogen, elixir-format
msgid "Create your first request"
msgstr "Создать первую заявку"
@ -5898,43 +5899,43 @@ msgstr "Что нужно сделать"
msgid "Location"
msgstr "Место"
#: lib/who_need_help_web/live/activity_live/index.ex:476
#: lib/who_need_help_web/live/activity_live/index.ex:508
#, elixir-autogen, elixir-format
msgid "My activities"
msgstr "Мои активности"
#: lib/who_need_help_web/live/request_live/index.ex:509
#: lib/who_need_help_web/live/request_live/index.ex:828
#: lib/who_need_help_web/live/request_live/index.ex:542
#: lib/who_need_help_web/live/request_live/index.ex:861
#, elixir-autogen, elixir-format
msgid "My requests"
msgstr "Мои заявки"
#: lib/who_need_help_web/live/activity_live/index.ex:475
#: lib/who_need_help_web/live/activity_live/index.ex:507
#, elixir-autogen, elixir-format
msgid "Nearby activities"
msgstr "Активности рядом"
#: lib/who_need_help_web/live/activity_live/index.ex:765
#: lib/who_need_help_web/live/activity_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "No activities yet"
msgstr "Активностей пока нет"
#: lib/who_need_help_web/live/activity_live/index.ex:651
#: lib/who_need_help_web/live/activity_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "No open activities in this area"
msgstr "В этой области нет открытых активностей"
#: lib/who_need_help_web/live/request_live/index.ex:852
#: lib/who_need_help_web/live/request_live/index.ex:885
#, elixir-autogen, elixir-format
msgid "No requests yet"
msgstr "Заявок пока нет"
#: lib/who_need_help_web/live/activity_live/index.ex:640
#: lib/who_need_help_web/live/activity_live/index.ex:672
#, elixir-autogen, elixir-format
msgid "Only activities from the selected map area will be loaded."
msgstr "Будут загружены только активности из выбранной области карты."
#: lib/who_need_help_web/live/activity_live/index.ex:723
#: lib/who_need_help_web/live/activity_live/index.ex:755
#, elixir-autogen, elixir-format
msgid "Open activity"
msgstr "Открыть активность"
@ -5944,12 +5945,12 @@ msgstr "Открыть активность"
msgid "Request form steps"
msgstr "Шаги создания заявки"
#: lib/who_need_help_web/live/request_live/index.ex:503
#: lib/who_need_help_web/live/request_live/index.ex:536
#, elixir-autogen, elixir-format
msgid "Request views"
msgstr "Разделы заявок"
#: lib/who_need_help_web/live/request_live/index.ex:854
#: lib/who_need_help_web/live/request_live/index.ex:887
#, elixir-autogen, elixir-format
msgid "Requests you publish or accept will appear here."
msgstr "Здесь появятся заявки, которые вы создали или приняли."
@ -5974,7 +5975,7 @@ msgstr "Укажите срочность и время закрытия зая
msgid "Share only as much location detail as helpers need."
msgstr "Покажите помощникам только необходимую информацию о месте."
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/index.ex:761
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Activity details remain usable."
msgstr "Карта недоступна в этом браузере. Информация об активностях по-прежнему доступна."
@ -5984,7 +5985,7 @@ msgstr "Карта недоступна в этом браузере. Инфор
msgid "Timing"
msgstr "Время"
#: lib/who_need_help_web/live/request_live/index.ex:830
#: lib/who_need_help_web/live/request_live/index.ex:863
#, elixir-autogen, elixir-format
msgid "Track requests you created and requests you accepted as a helper."
msgstr "Следите за созданными заявками и за теми, которые вы приняли как помощник."
@ -6639,27 +6640,27 @@ msgstr "Что должны видеть люди до одобрения?"
msgid "Choose the meeting point on the map or use your current location."
msgstr "Выберите место встречи на карте или используйте своё текущее местоположение."
#: lib/who_need_help_web/live/activity_live/index.ex:555
#: lib/who_need_help_web/live/activity_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:757
#: lib/who_need_help_web/live/request_live/index.ex:600
#: lib/who_need_help_web/live/request_live/index.ex:695
#: lib/who_need_help_web/live/request_live/index.ex:844
#: lib/who_need_help_web/live/activity_live/index.ex:587
#: lib/who_need_help_web/live/activity_live/index.ex:682
#: lib/who_need_help_web/live/activity_live/index.ex:789
#: lib/who_need_help_web/live/request_live/index.ex:633
#: lib/who_need_help_web/live/request_live/index.ex:728
#: lib/who_need_help_web/live/request_live/index.ex:877
#, elixir-autogen, elixir-format
msgid "Loading results…"
msgstr "Загружаем результаты…"
#: lib/who_need_help_web/live/activity_live/index.ex:726
#: lib/who_need_help_web/live/activity_live/index.ex:758
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching activities are listed beside the map."
msgstr "Достигнут максимальный масштаб. Подходящие мероприятия перечислены рядом с картой."
#: lib/who_need_help_web/live/request_live/index.ex:788
#: lib/who_need_help_web/live/request_live/index.ex:821
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching requests are listed beside the map."
msgstr "Достигнут максимальный масштаб. Подходящие заявки перечислены рядом с картой."
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/index.ex:568
#, elixir-autogen, elixir-format
msgid "%{count} activity in the selected map area"
msgid_plural "%{count} activities in the selected map area"
@ -6667,7 +6668,7 @@ msgstr[0] "%{count} мероприятие в выбранной области
msgstr[1] "%{count} мероприятия в выбранной области карты"
msgstr[2] "%{count} мероприятий в выбранной области карты"
#: lib/who_need_help_web/live/request_live/index.ex:581
#: lib/who_need_help_web/live/request_live/index.ex:614
#, elixir-autogen, elixir-format
msgid "%{count} request in the selected map area"
msgid_plural "%{count} requests in the selected map area"
@ -6675,57 +6676,57 @@ msgstr[0] "%{count} заявка в выбранной области карты
msgstr[1] "%{count} заявки в выбранной области карты"
msgstr[2] "%{count} заявок в выбранной области карты"
#: lib/who_need_help_web/live/activity_live/index.ex:561
#: lib/who_need_help_web/live/request_live/index.ex:606
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:639
#, elixir-autogen, elixir-format
msgid "Map moved. Results still show the previous area."
msgstr "Карта перемещена. Пока показаны результаты для предыдущей области."
#: lib/who_need_help_web/live/activity_live/index.ex:579
#: lib/who_need_help_web/live/activity_live/index.ex:611
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show activities in this area”."
msgstr "Переместите или масштабируйте карту, затем нажмите «Показать мероприятия в этой области»."
#: lib/who_need_help_web/live/request_live/index.ex:624
#: lib/who_need_help_web/live/request_live/index.ex:657
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show requests in this area”."
msgstr "Переместите или масштабируйте карту, затем нажмите «Показать заявки в этой области»."
#: lib/who_need_help_web/live/activity_live/index.ex:573
#: lib/who_need_help_web/live/request_live/index.ex:618
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:651
#, elixir-autogen, elixir-format
msgid "Results update automatically after you stop moving the map."
msgstr "Результаты обновятся автоматически, когда вы закончите перемещать карту."
#: lib/who_need_help_web/live/activity_live/index.ex:743
#: lib/who_need_help_web/live/activity_live/index.ex:775
#, elixir-autogen, elixir-format
msgid "Show activities in this area"
msgstr "Показать мероприятия в этой области"
#: lib/who_need_help_web/live/request_live/index.ex:800
#: lib/who_need_help_web/live/request_live/index.ex:833
#, elixir-autogen, elixir-format
msgid "Show requests in this area"
msgstr "Показать заявки в этой области"
#: lib/who_need_help_web/live/activity_live/index.ex:545
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/activity_live/index.ex:577
#: lib/who_need_help_web/live/request_live/index.ex:623
#, elixir-autogen, elixir-format
msgid "Showing %{shown} of %{count} in the list."
msgstr "В списке показано %{shown} из %{count}."
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:638
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:671
#, elixir-autogen, elixir-format
msgid "Update results as map moves"
msgstr "Обновлять результаты при перемещении карты"
#: lib/who_need_help_web/live/activity_live/index.ex:567
#: lib/who_need_help_web/live/request_live/index.ex:612
#: lib/who_need_help_web/live/activity_live/index.ex:599
#: lib/who_need_help_web/live/request_live/index.ex:645
#, elixir-autogen, elixir-format
msgid "Updating results for the visible map area…"
msgstr "Обновляем результаты для видимой области карты…"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#: lib/who_need_help_web/controllers/support_html/received.html.heex:12
#, elixir-autogen, elixir-format
msgid "EMAIL CONFIRMATION REQUIRED"
msgstr "ТРЕБУЕТСЯ ПОДТВЕРЖДЕНИЕ EMAIL"
@ -6745,7 +6746,7 @@ msgstr "Ожидаем разрешения на геолокацию…"
msgid "Pending email verification"
msgstr "Ожидает подтверждения email"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:25
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#, elixir-autogen, elixir-format
msgid "We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review."
msgstr "Мы сохранили ожидающую заявку %{reference}. Она ещё не попала в очередь поддержки. Откройте приватную ссылку из письма, чтобы подтвердить адрес и отправить заявку на рассмотрение."
@ -7810,7 +7811,7 @@ msgstr "У вас нет разрешения на это действие. Дл
msgid "Your email was confirmed and the notice was sent for review."
msgstr "Ваш email подтверждён, уведомление отправлено на проверку."
#: lib/who_need_help_web/controllers/support_controller.ex:122
#: lib/who_need_help_web/controllers/support_controller.ex:128
#, elixir-autogen, elixir-format
msgid "Your email was confirmed and the request was sent to support."
msgstr "Ваш email подтверждён, обращение отправлено в поддержку."
@ -8008,7 +8009,7 @@ msgstr "Скопируйте этот безопасный адрес и вст
msgid "Confirm content-removal notice"
msgstr "Подтвердить уведомление об удалении контента"
#: lib/who_need_help_web/controllers/support_controller.ex:106
#: lib/who_need_help_web/controllers/support_controller.ex:112
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:9
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:23
#, elixir-autogen, elixir-format
@ -8034,3 +8035,13 @@ msgstr "Если вы не отправляли это уведомление,
#, elixir-autogen, elixir-format
msgid "If you did not submit this request, close this page. Nothing will be sent to support."
msgstr "Если вы не отправляли это обращение, закройте страницу. В поддержку ничего не поступит."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:29
#, elixir-autogen, elixir-format
msgid "If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
msgstr "Если этот адрес принадлежит аккаунту Who Need Help, мы отправили приватную ссылку подтверждения на электронную почту аккаунта. Обращение в поддержку будет создано только после перехода по этой ссылке."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#, elixir-autogen, elixir-format
msgid "REQUEST CHECKED"
msgstr "ЗАПРОС ПРОВЕРЕН"

View File

@ -262,7 +262,7 @@ msgstr "Активність опубліковано. Ви схвалюєте
msgid "Activity restored."
msgstr "Активність відновлено."
#: lib/who_need_help_web/live/activity_live/index.ex:504
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/new.ex:204
#, elixir-autogen, elixir-format
msgid "Activity type"
@ -280,12 +280,12 @@ msgstr "Додати непідтверджене посилання"
msgid "Administrator"
msgstr "Адміністратор"
#: lib/who_need_help_web/live/activity_live/index.ex:506
#: lib/who_need_help_web/live/activity_live/index.ex:538
#, elixir-autogen, elixir-format
msgid "All activities"
msgstr "Усі активності"
#: lib/who_need_help_web/live/request_live/index.ex:539
#: lib/who_need_help_web/live/request_live/index.ex:572
#, elixir-autogen, elixir-format
msgid "All categories"
msgstr "Усі категорії"
@ -300,7 +300,7 @@ msgstr "Уже зареєстровані?"
msgid "Another helper already accepted this request."
msgstr "Інший помічник уже прийняв цю заявку."
#: lib/who_need_help_web/live/request_live/index.ex:554
#: lib/who_need_help_web/live/request_live/index.ex:587
#, elixir-autogen, elixir-format
msgid "Any urgency"
msgstr "Будь-яка терміновість"
@ -420,16 +420,16 @@ msgstr "Скасувати активність"
msgid "Cancel request"
msgstr "Скасувати запит"
#: lib/who_need_help_web/live/activity_live/index.ex:435
#: lib/who_need_help_web/live/activity_live/index.ex:467
#: lib/who_need_help_web/live/activity_live/show.ex:344
#: lib/who_need_help_web/live/request_live/index.ex:459
#: lib/who_need_help_web/live/request_live/index.ex:460
#: lib/who_need_help_web/live/request_live/index.ex:492
#: lib/who_need_help_web/live/request_live/index.ex:493
#: lib/who_need_help_web/live/request_live/show.ex:1005
#, elixir-autogen, elixir-format
msgid "Cancelled"
msgstr "Скасовано"
#: lib/who_need_help_web/live/request_live/index.ex:537
#: lib/who_need_help_web/live/request_live/index.ex:570
#: lib/who_need_help_web/live/request_live/new.ex:302
#, elixir-autogen, elixir-format
msgid "Category"
@ -510,7 +510,7 @@ msgstr "Закрити"
msgid "Coffee and conversation"
msgstr "Кава й розмова"
#: lib/who_need_help_web/live/activity_live/index.ex:449
#: lib/who_need_help_web/live/activity_live/index.ex:481
#, elixir-autogen, elixir-format
msgid "Coffee, cinema, walks, and hikes are separate from urgent help and never affect helper ratings."
msgstr ""
@ -527,19 +527,19 @@ msgstr "Коментар (необов’язково)"
msgid "Community helpers"
msgstr "Помічники спільноти"
#: lib/who_need_help_web/live/activity_live/index.ex:697
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/show.ex:403
#: lib/who_need_help_web/live/activity_live/show.ex:639
#: lib/who_need_help_web/live/activity_live/show.ex:698
#: lib/who_need_help_web/live/request_live/index.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:770
#, elixir-autogen, elixir-format
msgid "Community member"
msgstr "Член спільноти"
#: lib/who_need_help_web/live/activity_live/index.ex:434
#: lib/who_need_help_web/live/activity_live/index.ex:466
#: lib/who_need_help_web/live/activity_live/show.ex:343
#: lib/who_need_help_web/live/request_live/index.ex:457
#: lib/who_need_help_web/live/request_live/index.ex:458
#: lib/who_need_help_web/live/request_live/index.ex:490
#: lib/who_need_help_web/live/request_live/index.ex:491
#: lib/who_need_help_web/live/request_live/show.ex:1004
#: lib/who_need_help_web/live/request_live/show.ex:1023
#, elixir-autogen, elixir-format
@ -590,13 +590,13 @@ msgstr ""
msgid "Confirming..."
msgstr "Підтвердження…"
#: lib/who_need_help_web/live/activity_live/index.ex:455
#: lib/who_need_help_web/live/activity_live/index.ex:487
#: lib/who_need_help_web/live/activity_live/new.ex:12
#, elixir-autogen, elixir-format
msgid "Create activity"
msgstr "Створити активність"
#: lib/who_need_help_web/live/activity_live/index.ex:772
#: lib/who_need_help_web/live/activity_live/index.ex:804
#: lib/who_need_help_web/live/activity_live/new.ex:180
#, elixir-autogen, elixir-format
msgid "Create an activity"
@ -607,7 +607,7 @@ msgstr "Створити активність"
msgid "Create category"
msgstr "Створити категорію"
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:521
#, elixir-autogen, elixir-format
msgid "Create urgent request"
msgstr "Створити термінову заявку"
@ -760,7 +760,7 @@ msgstr "Спливає:"
msgid "Explain what is already arranged and what the volunteer needs to do."
msgstr "Поясніть, що вже організовано й що має зробити волонтер."
#: lib/who_need_help_web/live/activity_live/index.ex:446
#: lib/who_need_help_web/live/activity_live/index.ex:478
#, elixir-autogen, elixir-format
msgid "Find people to join"
msgstr "Знайти компанію"
@ -925,8 +925,8 @@ msgstr ""
"Android показує постійне сповіщення й може продовжувати передавання після "
"згортання. Після зупинення передавання вихідні координати видаляються."
#: lib/who_need_help_web/live/request_live/index.ex:455
#: lib/who_need_help_web/live/request_live/index.ex:456
#: lib/who_need_help_web/live/request_live/index.ex:488
#: lib/who_need_help_web/live/request_live/index.ex:489
#: lib/who_need_help_web/live/request_live/show.ex:1003
#, elixir-autogen, elixir-format
msgid "In progress"
@ -1049,8 +1049,8 @@ msgstr "Позначити завершеною"
msgid "Match and coordinate"
msgstr "Знайдіть помічника й узгодьте деталі"
#: lib/who_need_help_web/live/request_live/index.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:454
#: lib/who_need_help_web/live/request_live/index.ex:486
#: lib/who_need_help_web/live/request_live/index.ex:487
#: lib/who_need_help_web/live/request_live/show.ex:1001
#, elixir-autogen, elixir-format
msgid "Matched"
@ -1079,7 +1079,7 @@ msgstr ""
msgid "Medicine requests"
msgstr "Запити на ліки"
#: lib/who_need_help_web/live/activity_live/index.ex:462
#: lib/who_need_help_web/live/activity_live/index.ex:494
#, elixir-autogen, elixir-format
msgid "Meet in public first, keep exact details inside the approved group, and leave or report anything that feels unsafe."
msgstr ""
@ -1129,7 +1129,7 @@ msgstr "Модератор"
msgid "Moderator access is required."
msgstr "Потрібен доступ модератора."
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:512
#, elixir-autogen, elixir-format
msgid "NEARBY MUTUAL AID"
msgstr "ВЗАЄМОДОПОМОГА ПОРУЧ"
@ -1207,9 +1207,9 @@ msgid "Not for emergencies"
msgstr "Не для екстрених ситуацій"
#: lib/who_need_help_web/live/notification_live.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:443
#: lib/who_need_help_web/live/request_live/index.ex:444
#: lib/who_need_help_web/live/request_live/index.ex:555
#: lib/who_need_help_web/live/request_live/index.ex:476
#: lib/who_need_help_web/live/request_live/index.ex:477
#: lib/who_need_help_web/live/request_live/index.ex:588
#: lib/who_need_help_web/live/request_live/new.ex:449
#: lib/who_need_help_web/live/request_live/show.ex:992
#: lib/who_need_help_web/live/request_live/show.ex:993
@ -1217,7 +1217,7 @@ msgstr "Не для екстрених ситуацій"
msgid "Now"
msgstr "Зараз"
#: lib/who_need_help_web/live/activity_live/index.ex:444
#: lib/who_need_help_web/live/activity_live/index.ex:476
#, elixir-autogen, elixir-format
msgid "OPTIONAL SOCIAL PLANS"
msgstr "НЕОБОВ’ЯЗКОВІ СПІЛЬНІ ПЛАНИ"
@ -1237,14 +1237,14 @@ msgstr ""
#: lib/who_need_help/notifications/text.ex:140
#: lib/who_need_help_web/controllers/content_removal_html.ex:21
#: lib/who_need_help_web/controllers/support_html.ex:17
#: lib/who_need_help_web/live/activity_live/index.ex:433
#: lib/who_need_help_web/live/activity_live/index.ex:465
#: lib/who_need_help_web/live/activity_live/show.ex:342
#: lib/who_need_help_web/live/moderation_live.ex:636
#: lib/who_need_help_web/live/moderation_live.ex:817
#: lib/who_need_help_web/live/moderation_live.ex:941
#: lib/who_need_help_web/live/report_live.ex:104
#: lib/who_need_help_web/live/request_live/index.ex:451
#: lib/who_need_help_web/live/request_live/index.ex:452
#: lib/who_need_help_web/live/request_live/index.ex:484
#: lib/who_need_help_web/live/request_live/index.ex:485
#: lib/who_need_help_web/live/request_live/show.ex:1000
#: lib/who_need_help_web/live/support_operation_live.ex:310
#: lib/who_need_help_web/live/support_operation_live.ex:414
@ -1709,9 +1709,9 @@ msgid "Save profile"
msgstr "Зберегти профіль"
#: lib/who_need_help_web/live/notification_live.ex:738
#: lib/who_need_help_web/live/request_live/index.ex:447
#: lib/who_need_help_web/live/request_live/index.ex:448
#: lib/who_need_help_web/live/request_live/index.ex:557
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:481
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/request_live/new.ex:451
#: lib/who_need_help_web/live/request_live/show.ex:996
#: lib/who_need_help_web/live/request_live/show.ex:997
@ -1985,7 +1985,7 @@ msgstr "Цей стан активності вже змінено."
msgid "This interaction is blocked."
msgstr "Ця взаємодія заблокована."
#: lib/who_need_help_web/live/request_live/index.ex:495
#: lib/who_need_help_web/live/request_live/index.ex:528
#: lib/who_need_help_web/live/request_live/show.ex:1071
#, elixir-autogen, elixir-format
msgid "This is not an emergency service. Contact local emergency services for immediate danger."
@ -2038,9 +2038,9 @@ msgid "To see sent emails, visit"
msgstr "Щоб переглянути надіслані листи, відкрийте"
#: lib/who_need_help_web/live/notification_live.ex:737
#: lib/who_need_help_web/live/request_live/index.ex:445
#: lib/who_need_help_web/live/request_live/index.ex:446
#: lib/who_need_help_web/live/request_live/index.ex:556
#: lib/who_need_help_web/live/request_live/index.ex:478
#: lib/who_need_help_web/live/request_live/index.ex:479
#: lib/who_need_help_web/live/request_live/index.ex:589
#: lib/who_need_help_web/live/request_live/new.ex:450
#: lib/who_need_help_web/live/request_live/show.ex:994
#: lib/who_need_help_web/live/request_live/show.ex:995
@ -2110,7 +2110,7 @@ msgid "Unique people"
msgstr "Унікальні люди"
#: lib/who_need_help_web/live/notification_live.ex:731
#: lib/who_need_help_web/live/request_live/index.ex:552
#: lib/who_need_help_web/live/request_live/index.ex:585
#: lib/who_need_help_web/live/request_live/new.ex:447
#, elixir-autogen, elixir-format
msgid "Urgency"
@ -2253,7 +2253,7 @@ msgstr ""
"через підписку ChatGPT розробника. Ключ OpenAI API та резервний варіант API "
"з оплатою за використання не застосовуються."
#: lib/who_need_help_web/live/request_live/index.ex:480
#: lib/who_need_help_web/live/request_live/index.ex:513
#, elixir-autogen, elixir-format
msgid "Who needs help?"
msgstr "Хто потребує допомоги?"
@ -2371,7 +2371,7 @@ msgid "Your review is revealed only after both participants submit."
msgstr ""
"Ваш відгук відкриється лише після того, як його надішлють обидва учасники."
#: lib/who_need_help_web/live/request_live/index.ex:805
#: lib/who_need_help_web/live/request_live/index.ex:838
#, elixir-autogen, elixir-format
msgid "Your trust summary"
msgstr "Ваші показники довіри"
@ -2382,16 +2382,16 @@ msgstr "Ваші показники довіри"
msgid "before confirming."
msgstr "перед підтвердженням."
#: lib/who_need_help_web/live/activity_live/index.ex:696
#: lib/who_need_help_web/live/activity_live/index.ex:728
#: lib/who_need_help_web/live/category_proposal_live.ex:252
#: lib/who_need_help_web/live/request_live/index.ex:736
#: lib/who_need_help_web/live/request_live/index.ex:769
#, elixir-autogen, elixir-format
msgid "by %{name}"
msgstr "автор: %{name}"
#: lib/who_need_help_web/live/profile_live.ex:190
#: lib/who_need_help_web/live/public_profile_live.ex:133
#: lib/who_need_help_web/live/request_live/index.ex:809
#: lib/who_need_help_web/live/request_live/index.ex:842
#: lib/who_need_help_web/live/request_live/show.ex:1478
#, elixir-autogen, elixir-format
msgid "completed"
@ -2427,7 +2427,7 @@ msgstr "організатор"
msgid "participants only"
msgstr "лише учасники"
#: lib/who_need_help_web/live/request_live/index.ex:813
#: lib/who_need_help_web/live/request_live/index.ex:846
#: lib/who_need_help_web/live/request_live/show.ex:1482
#, elixir-autogen, elixir-format
msgid "people"
@ -2487,7 +2487,7 @@ msgstr "терміново"
#: lib/who_need_help_web/live/activity_live/show.ex:719
#: lib/who_need_help_web/live/profile_live.ex:285
#: lib/who_need_help_web/live/public_profile_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/index.ex:850
#: lib/who_need_help_web/live/request_live/show.ex:1142
#: lib/who_need_help_web/live/request_live/show.ex:1580
#, elixir-autogen, elixir-format
@ -2520,8 +2520,8 @@ msgstr "← Заявки"
msgid "Approved"
msgstr "Схвалено"
#: lib/who_need_help_web/live/request_live/index.ex:461
#: lib/who_need_help_web/live/request_live/index.ex:462
#: lib/who_need_help_web/live/request_live/index.ex:494
#: lib/who_need_help_web/live/request_live/index.ex:495
#, elixir-autogen, elixir-format
msgid "Expired"
msgstr "Спливло"
@ -2575,21 +2575,21 @@ msgstr "Незвична частота дій"
msgid "Load earlier messages"
msgstr "Завантажити попередні повідомлення"
#: lib/who_need_help_web/live/activity_live/index.ex:708
#: lib/who_need_help_web/live/activity_live/index.ex:801
#: lib/who_need_help_web/live/activity_live/index.ex:740
#: lib/who_need_help_web/live/activity_live/index.ex:833
#: lib/who_need_help_web/live/category_proposal_live.ex:284
#: lib/who_need_help_web/live/leaderboard_live.ex:91
#: lib/who_need_help_web/live/profile_live.ex:233
#: lib/who_need_help_web/live/profile_live.ex:363
#: lib/who_need_help_web/live/public_profile_live.ex:178
#: lib/who_need_help_web/live/report_live.ex:98
#: lib/who_need_help_web/live/request_live/index.ex:886
#: lib/who_need_help_web/live/request_live/index.ex:919
#, elixir-autogen, elixir-format
msgid "Load more"
msgstr "Завантажити ще"
#: lib/who_need_help_web/live/activity_live/show.ex:544
#: lib/who_need_help_web/live/request_live/index.ex:782
#: lib/who_need_help_web/live/request_live/index.ex:815
#: lib/who_need_help_web/live/request_live/show.ex:1324
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Request details remain usable."
@ -2957,7 +2957,7 @@ msgstr "Оскаржити рішення модерації"
msgid "Back to removal form"
msgstr "Повернутися до форми видалення"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#: lib/who_need_help_web/controllers/support_html/received.html.heex:43
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:30
#, elixir-autogen, elixir-format
msgid "Back to support"
@ -2969,7 +2969,8 @@ msgstr "Повернутися до підтримки"
msgid "CONTENT REMOVAL"
msgstr "ВИДАЛЕННЯ КОНТЕНТУ"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:16
#: lib/who_need_help_web/controllers/support_html/received.html.heex:18
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#, elixir-autogen, elixir-format
msgid "Check your email"
msgstr "Перевірте пошту"
@ -3249,7 +3250,7 @@ msgstr "Повідомити про незаконний або шкідливи
msgid "Reported locations"
msgstr "Указані адреси контенту"
#: lib/who_need_help_web/controllers/support_controller.ex:241
#: lib/who_need_help_web/controllers/support_controller.ex:267
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:6
#: lib/who_need_help_web/controllers/support_html/delete_account.html.heex:42
#: lib/who_need_help_web/controllers/user_settings_html/edit.html.heex:128
@ -3400,8 +3401,8 @@ msgstr "Загроза життю або безпеці"
msgid "Too many removal notices. Please try again later."
msgstr "Забагато повідомлень про видалення. Спробуйте пізніше."
#: lib/who_need_help_web/controllers/support_controller.ex:42
#: lib/who_need_help_web/controllers/support_controller.ex:84
#: lib/who_need_help_web/controllers/support_controller.ex:45
#: lib/who_need_help_web/controllers/support_controller.ex:90
#, elixir-autogen, elixir-format
msgid "Too many support requests. Please try again later."
msgstr "Забагато звернень до підтримки. Спробуйте пізніше."
@ -3483,13 +3484,13 @@ msgstr "Номер вашого звернення: %{reference}"
msgid "Your relationship to the affected person or rights holder"
msgstr "Ваше відношення до постраждалої особи або правовласника"
#: lib/who_need_help_web/controllers/support_controller.ex:55
#: lib/who_need_help_web/controllers/support_controller.ex:66
#: lib/who_need_help_web/controllers/support_controller.ex:58
#: lib/who_need_help_web/controllers/support_controller.ex:69
#, elixir-autogen, elixir-format
msgid "Delete my Who Need Help account"
msgstr "Видалити мій обліковий запис Who Need Help"
#: lib/who_need_help_web/controllers/support_controller.ex:56
#: lib/who_need_help_web/controllers/support_controller.ex:59
#, elixir-autogen, elixir-format
msgid "Please delete my account and associated personal data."
msgstr "Будь ласка, видаліть мій обліковий запис і пов’язані персональні дані."
@ -4426,7 +4427,7 @@ msgid "View my notices"
msgstr "Переглянути мої повідомлення"
#: lib/who_need_help_web/controllers/support_html/new.html.heex:13
#: lib/who_need_help_web/controllers/support_html/received.html.heex:32
#: lib/who_need_help_web/controllers/support_html/received.html.heex:41
#, elixir-autogen, elixir-format
msgid "View my requests"
msgstr "Переглянути мої звернення"
@ -4541,37 +4542,37 @@ msgstr "Перетягніть, щоб перемістити точну точ
msgid "Exact point selected. Drag the red pin or click the map to move it."
msgstr "Точну точку вибрано. Перетягніть червоний маркер або натисніть на карту, щоб перемістити її."
#: lib/who_need_help_web/live/activity_live/index.ex:515
#: lib/who_need_help_web/live/request_live/index.ex:562
#: lib/who_need_help_web/live/activity_live/index.ex:547
#: lib/who_need_help_web/live/request_live/index.ex:595
#, elixir-autogen, elixir-format
msgid "Area or city"
msgstr "Район або місто"
#: lib/who_need_help_web/live/activity_live/index.ex:638
#: lib/who_need_help_web/live/request_live/index.ex:683
#: lib/who_need_help_web/live/activity_live/index.ex:670
#: lib/who_need_help_web/live/request_live/index.ex:716
#, elixir-autogen, elixir-format
msgid "Choose an area on the map"
msgstr "Виберіть область на карті"
#: lib/who_need_help_web/live/request_live/index.ex:482
#: lib/who_need_help_web/live/request_live/index.ex:515
#, elixir-autogen, elixir-format
msgid "Explore privacy-friendly areas and public exact meeting points chosen by requesters."
msgstr "Переглядайте приватні області та точні публічні місця зустрічі, вибрані авторами заявок."
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:637
#: lib/who_need_help_web/live/request_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "List"
msgstr "Список"
#: lib/who_need_help_web/live/request_live/index.ex:758
#: lib/who_need_help_web/live/request_live/index.ex:791
#, elixir-autogen, elixir-format
msgid "Load more in this area"
msgstr "Завантажити ще в цій області"
#: lib/who_need_help_web/components/layouts/root.html.heex:5
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:670
#: lib/who_need_help_web/live/activity_live/index.ex:657
#: lib/who_need_help_web/live/request_live/index.ex:703
#, elixir-autogen, elixir-format
msgid "Map"
msgstr "Карта"
@ -4581,41 +4582,41 @@ msgstr "Карта"
msgid "Map preview"
msgstr "Попередній перегляд карти"
#: lib/who_need_help_web/live/activity_live/index.ex:654
#: lib/who_need_help_web/live/request_live/index.ex:699
#: lib/who_need_help_web/live/activity_live/index.ex:686
#: lib/who_need_help_web/live/request_live/index.ex:732
#, elixir-autogen, elixir-format
msgid "Move or zoom the map to search somewhere else."
msgstr "Перемістіть або масштабуйте карту, щоб шукати в іншому місці."
#: lib/who_need_help_web/live/request_live/index.ex:696
#: lib/who_need_help_web/live/request_live/index.ex:729
#, elixir-autogen, elixir-format
msgid "No open requests in this area"
msgstr "У цій області немає відкритих заявок"
#: lib/who_need_help_web/live/request_live/index.ex:685
#: lib/who_need_help_web/live/request_live/index.ex:718
#, elixir-autogen, elixir-format
msgid "Only requests from the selected map area will be loaded."
msgstr "Буде завантажено лише заявки з вибраної області карти."
#: lib/who_need_help_web/components/layouts/root.html.heex:8
#: lib/who_need_help_web/live/request_live/index.ex:785
#: lib/who_need_help_web/live/request_live/index.ex:818
#, elixir-autogen, elixir-format
msgid "Open request"
msgstr "Відкрити заявку"
#: lib/who_need_help_web/live/activity_live/index.ex:516
#: lib/who_need_help_web/live/request_live/index.ex:563
#: lib/who_need_help_web/live/activity_live/index.ex:548
#: lib/who_need_help_web/live/request_live/index.ex:596
#, elixir-autogen, elixir-format
msgid "Optional text search"
msgstr "Необов’язковий текстовий пошук"
#: lib/who_need_help_web/live/request_live/index.ex:764
#: lib/who_need_help_web/live/request_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "Requests without map coordinates appear only when their public area description matches the text search."
msgstr "Заявки без координат на карті з’являються лише тоді, коли опис публічної області збігається з текстовим пошуком."
#: lib/who_need_help_web/live/activity_live/index.ex:596
#: lib/who_need_help_web/live/request_live/index.ex:641
#: lib/who_need_help_web/live/activity_live/index.ex:628
#: lib/who_need_help_web/live/request_live/index.ex:674
#, elixir-autogen, elixir-format
msgid "Results layout"
msgstr "Розташування результатів"
@ -4625,21 +4626,21 @@ msgstr "Розташування результатів"
msgid "Static preview"
msgstr "Статичний перегляд"
#: lib/who_need_help_web/live/activity_live/index.ex:615
#: lib/who_need_help_web/live/request_live/index.ex:660
#: lib/who_need_help_web/live/activity_live/index.ex:647
#: lib/who_need_help_web/live/request_live/index.ex:693
#, elixir-autogen, elixir-format
msgid "Together"
msgstr "Разом"
#: lib/who_need_help_web/components/layouts/root.html.heex:6
#: lib/who_need_help_web/controllers/page_html/home.html.heex:166
#: lib/who_need_help_web/live/activity_live/index.ex:731
#: lib/who_need_help_web/live/activity_live/index.ex:763
#: lib/who_need_help_web/live/activity_live/new.ex:355
#: lib/who_need_help_web/live/activity_live/new.ex:414
#: lib/who_need_help_web/live/activity_live/show.ex:546
#: lib/who_need_help_web/live/notification_live.ex:590
#: lib/who_need_help_web/live/notification_live.ex:609
#: lib/who_need_help_web/live/request_live/index.ex:784
#: lib/who_need_help_web/live/request_live/index.ex:817
#: lib/who_need_help_web/live/request_live/new.ex:485
#: lib/who_need_help_web/live/request_live/new.ex:563
#: lib/who_need_help_web/live/request_live/show.ex:1326
@ -4997,7 +4998,7 @@ msgid "Nearby alert deleted."
msgstr "Сповіщення поблизу видалено."
#: lib/who_need_help_web/live/notification_live.ex:453
#: lib/who_need_help_web/live/request_live/index.ex:508
#: lib/who_need_help_web/live/request_live/index.ex:541
#, elixir-autogen, elixir-format
msgid "Nearby requests"
msgstr "Заявки поблизу"
@ -5320,7 +5321,7 @@ msgid "WebGL is unavailable in this browser, so the full map cannot start. Selec
msgstr "WebGL недоступний у цьому браузері, тому повна карта не може запуститися. Виберіть приклад нижче або спробуйте запустити карту ще раз."
#: lib/who_need_help_web/components/layouts/root.html.heex:7
#: lib/who_need_help_web/live/activity_live/index.ex:732
#: lib/who_need_help_web/live/activity_live/index.ex:764
#: lib/who_need_help_web/live/activity_live/show.ex:547
#: lib/who_need_help_web/live/request_live/show.ex:1327
#, elixir-autogen, elixir-format
@ -5361,7 +5362,7 @@ msgid "Case status"
msgstr "Статус звернення"
#: lib/who_need_help_web/controllers/page_html/child_safety.html.heex:42
#: lib/who_need_help_web/controllers/support_controller.ex:242
#: lib/who_need_help_web/controllers/support_controller.ex:268
#: lib/who_need_help_web/live/report_live.ex:50
#, elixir-autogen, elixir-format
msgid "Contact support"
@ -5383,8 +5384,8 @@ msgstr "Повідомлення про видалення контенту от
msgid "Conversation"
msgstr "Розмова"
#: lib/who_need_help_web/controllers/support_controller.ex:152
#: lib/who_need_help_web/controllers/support_controller.ex:168
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:174
#: lib/who_need_help_web/live/support_case_live.ex:73
#, elixir-autogen, elixir-format
msgid "Could not send your message. Please check it and try again."
@ -5447,7 +5448,7 @@ msgstr "Скарг не подано"
msgid "No status history is available for this older case."
msgstr "Для цього старого звернення історія статусів недоступна."
#: lib/who_need_help_web/controllers/support_controller.ex:187
#: lib/who_need_help_web/controllers/support_controller.ex:193
#: lib/who_need_help_web/live/support_case_live.ex:95
#, elixir-autogen, elixir-format
msgid "Only a resolved or closed request can be reopened."
@ -5552,12 +5553,12 @@ msgstr "Надіслати повідомлення"
msgid "Status history"
msgstr "Історія статусів"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:15
#: lib/who_need_help_web/controllers/support_html/received.html.heex:17
#, elixir-autogen, elixir-format
msgid "Support request created"
msgstr "Звернення до підтримки створено"
#: lib/who_need_help_web/controllers/support_controller.ex:198
#: lib/who_need_help_web/controllers/support_controller.ex:214
#, elixir-autogen, elixir-format
msgid "Support request received"
msgstr "Звернення до підтримки отримано"
@ -5593,7 +5594,7 @@ msgstr "ДОВІРА ТА БЕЗПЕКА"
msgid "The requester states whether the medicine is paid, reserved, or still needs to be purchased."
msgstr "Автор заявки вказує, чи ліки вже оплачені, зарезервовані або їх ще потрібно придбати."
#: lib/who_need_help_web/controllers/support_controller.ex:182
#: lib/who_need_help_web/controllers/support_controller.ex:188
#: lib/who_need_help_web/live/support_case_live.ex:88
#, elixir-autogen, elixir-format
msgid "The support request is open again."
@ -5621,7 +5622,7 @@ msgstr "У цій приватній історії показано ваші с
msgid "This support request is no longer available."
msgstr "Це звернення до підтримки більше не доступне."
#: lib/who_need_help_web/controllers/support_controller.ex:158
#: lib/who_need_help_web/controllers/support_controller.ex:164
#: lib/who_need_help_web/live/support_case_live.ex:60
#, elixir-autogen, elixir-format
msgid "Too many messages. Please try again later."
@ -5632,7 +5633,7 @@ msgstr "Забагато повідомлень. Спробуйте пізніш
msgid "Use the dedicated urgent process. Never upload or reproduce the image or video."
msgstr "Скористайтеся спеціальною терміновою процедурою. Ніколи не завантажуйте й не відтворюйте зображення або відео."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:19
#: lib/who_need_help_web/controllers/support_html/received.html.heex:23
#, elixir-autogen, elixir-format
msgid "We created support request %{reference} and added it to your account. You can open it now and return to it from My support requests."
msgstr "Ми створили звернення %{reference} і додали його до вашого облікового запису. Його можна відкрити зараз або повернутися до нього з розділу «Мої звернення»."
@ -5658,7 +5659,7 @@ msgstr "Ви"
msgid "Your content-removal notices"
msgstr "Ваші повідомлення про видалення контенту"
#: lib/who_need_help_web/controllers/support_controller.ex:145
#: lib/who_need_help_web/controllers/support_controller.ex:151
#: lib/who_need_help_web/live/support_case_live.ex:53
#, elixir-autogen, elixir-format
msgid "Your message was sent to support."
@ -5822,7 +5823,7 @@ msgstr "Тепер ваш відгук видно"
msgid "Delivery settings"
msgstr "Налаштування доставки"
#: lib/who_need_help_web/live/request_live/index.ex:741
#: lib/who_need_help_web/live/request_live/index.ex:774
#, elixir-autogen, elixir-format
msgid "Expires"
msgstr "Спливає"
@ -5842,22 +5843,22 @@ msgstr "Сповіщення поруч"
msgid "Notification sections"
msgstr "Розділи сповіщень"
#: lib/who_need_help_web/live/activity_live/index.ex:724
#: lib/who_need_help_web/live/activity_live/index.ex:756
#, elixir-autogen, elixir-format
msgid "%{count} activities"
msgstr "Активностей: %{count}"
#: lib/who_need_help_web/live/request_live/index.ex:786
#: lib/who_need_help_web/live/request_live/index.ex:819
#, elixir-autogen, elixir-format
msgid "%{count} requests"
msgstr "Запитів: %{count}"
#: lib/who_need_help_web/live/activity_live/index.ex:767
#: lib/who_need_help_web/live/activity_live/index.ex:799
#, elixir-autogen, elixir-format
msgid "Activities you create or ask to join will appear here. Leaving removes an activity from this list."
msgstr "Створені вами активності й ті, до яких ви попросили приєднатися, з’являться тут. Після виходу активність зникне зі списку."
#: lib/who_need_help_web/live/activity_live/index.ex:470
#: lib/who_need_help_web/live/activity_live/index.ex:502
#, elixir-autogen, elixir-format
msgid "Activity views"
msgstr "Розділи активностей"
@ -5872,12 +5873,12 @@ msgstr "Оберіть категорію та зрозуміло опишіть
msgid "Confirm the safety guidance before asking nearby people for help."
msgstr "Підтвердьте правила безпеки перед публікацією запиту."
#: lib/who_need_help_web/live/request_live/index.ex:834
#: lib/who_need_help_web/live/request_live/index.ex:867
#, elixir-autogen, elixir-format
msgid "Create request"
msgstr "Створити запит"
#: lib/who_need_help_web/live/request_live/index.ex:857
#: lib/who_need_help_web/live/request_live/index.ex:890
#, elixir-autogen, elixir-format
msgid "Create your first request"
msgstr "Створити перший запит"
@ -5892,43 +5893,43 @@ msgstr "Що потрібно зробити"
msgid "Location"
msgstr "Місце"
#: lib/who_need_help_web/live/activity_live/index.ex:476
#: lib/who_need_help_web/live/activity_live/index.ex:508
#, elixir-autogen, elixir-format
msgid "My activities"
msgstr "Мої активності"
#: lib/who_need_help_web/live/request_live/index.ex:509
#: lib/who_need_help_web/live/request_live/index.ex:828
#: lib/who_need_help_web/live/request_live/index.ex:542
#: lib/who_need_help_web/live/request_live/index.ex:861
#, elixir-autogen, elixir-format
msgid "My requests"
msgstr "Мої запити"
#: lib/who_need_help_web/live/activity_live/index.ex:475
#: lib/who_need_help_web/live/activity_live/index.ex:507
#, elixir-autogen, elixir-format
msgid "Nearby activities"
msgstr "Активності поруч"
#: lib/who_need_help_web/live/activity_live/index.ex:765
#: lib/who_need_help_web/live/activity_live/index.ex:797
#, elixir-autogen, elixir-format
msgid "No activities yet"
msgstr "Активностей поки немає"
#: lib/who_need_help_web/live/activity_live/index.ex:651
#: lib/who_need_help_web/live/activity_live/index.ex:683
#, elixir-autogen, elixir-format
msgid "No open activities in this area"
msgstr "У цій області немає відкритих активностей"
#: lib/who_need_help_web/live/request_live/index.ex:852
#: lib/who_need_help_web/live/request_live/index.ex:885
#, elixir-autogen, elixir-format
msgid "No requests yet"
msgstr "Запитів поки немає"
#: lib/who_need_help_web/live/activity_live/index.ex:640
#: lib/who_need_help_web/live/activity_live/index.ex:672
#, elixir-autogen, elixir-format
msgid "Only activities from the selected map area will be loaded."
msgstr "Буде завантажено лише активності з вибраної області карти."
#: lib/who_need_help_web/live/activity_live/index.ex:723
#: lib/who_need_help_web/live/activity_live/index.ex:755
#, elixir-autogen, elixir-format
msgid "Open activity"
msgstr "Відкрити активність"
@ -5938,12 +5939,12 @@ msgstr "Відкрити активність"
msgid "Request form steps"
msgstr "Кроки створення запиту"
#: lib/who_need_help_web/live/request_live/index.ex:503
#: lib/who_need_help_web/live/request_live/index.ex:536
#, elixir-autogen, elixir-format
msgid "Request views"
msgstr "Розділи запитів"
#: lib/who_need_help_web/live/request_live/index.ex:854
#: lib/who_need_help_web/live/request_live/index.ex:887
#, elixir-autogen, elixir-format
msgid "Requests you publish or accept will appear here."
msgstr "Тут з’являться запити, які ви створили або прийняли."
@ -5968,7 +5969,7 @@ msgstr "Укажіть терміновість і час закриття за
msgid "Share only as much location detail as helpers need."
msgstr "Покажіть помічникам лише необхідну інформацію про місце."
#: lib/who_need_help_web/live/activity_live/index.ex:729
#: lib/who_need_help_web/live/activity_live/index.ex:761
#, elixir-autogen, elixir-format
msgid "The map is unavailable in this browser. Activity details remain usable."
msgstr "Карта недоступна в цьому браузері. Інформація про активності залишається доступною."
@ -5978,7 +5979,7 @@ msgstr "Карта недоступна в цьому браузері. Інфо
msgid "Timing"
msgstr "Час"
#: lib/who_need_help_web/live/request_live/index.ex:830
#: lib/who_need_help_web/live/request_live/index.ex:863
#, elixir-autogen, elixir-format
msgid "Track requests you created and requests you accepted as a helper."
msgstr "Стежте за створеними запитами й тими, які ви прийняли як помічник."
@ -6633,27 +6634,27 @@ msgstr "Що мають бачити люди до схвалення?"
msgid "Choose the meeting point on the map or use your current location."
msgstr "Оберіть місце зустрічі на карті або скористайтеся своїм поточним місцезнаходженням."
#: lib/who_need_help_web/live/activity_live/index.ex:555
#: lib/who_need_help_web/live/activity_live/index.ex:650
#: lib/who_need_help_web/live/activity_live/index.ex:757
#: lib/who_need_help_web/live/request_live/index.ex:600
#: lib/who_need_help_web/live/request_live/index.ex:695
#: lib/who_need_help_web/live/request_live/index.ex:844
#: lib/who_need_help_web/live/activity_live/index.ex:587
#: lib/who_need_help_web/live/activity_live/index.ex:682
#: lib/who_need_help_web/live/activity_live/index.ex:789
#: lib/who_need_help_web/live/request_live/index.ex:633
#: lib/who_need_help_web/live/request_live/index.ex:728
#: lib/who_need_help_web/live/request_live/index.ex:877
#, elixir-autogen, elixir-format
msgid "Loading results…"
msgstr "Завантажуємо результати…"
#: lib/who_need_help_web/live/activity_live/index.ex:726
#: lib/who_need_help_web/live/activity_live/index.ex:758
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching activities are listed beside the map."
msgstr "Досягнуто максимального масштабу. Відповідні заходи перелічено поруч із картою."
#: lib/who_need_help_web/live/request_live/index.ex:788
#: lib/who_need_help_web/live/request_live/index.ex:821
#, elixir-autogen, elixir-format
msgid "Maximum zoom reached. Matching requests are listed beside the map."
msgstr "Досягнуто максимального масштабу. Відповідні заявки перелічено поруч із картою."
#: lib/who_need_help_web/live/activity_live/index.ex:536
#: lib/who_need_help_web/live/activity_live/index.ex:568
#, elixir-autogen, elixir-format
msgid "%{count} activity in the selected map area"
msgid_plural "%{count} activities in the selected map area"
@ -6661,7 +6662,7 @@ msgstr[0] "%{count} подія у вибраній області карти"
msgstr[1] "%{count} події у вибраній області карти"
msgstr[2] "%{count} подій у вибраній області карти"
#: lib/who_need_help_web/live/request_live/index.ex:581
#: lib/who_need_help_web/live/request_live/index.ex:614
#, elixir-autogen, elixir-format
msgid "%{count} request in the selected map area"
msgid_plural "%{count} requests in the selected map area"
@ -6669,57 +6670,57 @@ msgstr[0] "%{count} заявка у вибраній області карти"
msgstr[1] "%{count} заявки у вибраній області карти"
msgstr[2] "%{count} заявок у вибраній області карти"
#: lib/who_need_help_web/live/activity_live/index.ex:561
#: lib/who_need_help_web/live/request_live/index.ex:606
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:639
#, elixir-autogen, elixir-format
msgid "Map moved. Results still show the previous area."
msgstr "Карту переміщено. Поки показано результати для попередньої області."
#: lib/who_need_help_web/live/activity_live/index.ex:579
#: lib/who_need_help_web/live/activity_live/index.ex:611
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show activities in this area”."
msgstr "Перемістіть або масштабуйте карту, потім натисніть «Показати події в цій області»."
#: lib/who_need_help_web/live/request_live/index.ex:624
#: lib/who_need_help_web/live/request_live/index.ex:657
#, elixir-autogen, elixir-format
msgid "Move or zoom the map, then choose “Show requests in this area”."
msgstr "Перемістіть або масштабуйте карту, потім натисніть «Показати заявки в цій області»."
#: lib/who_need_help_web/live/activity_live/index.ex:573
#: lib/who_need_help_web/live/request_live/index.ex:618
#: lib/who_need_help_web/live/activity_live/index.ex:605
#: lib/who_need_help_web/live/request_live/index.ex:651
#, elixir-autogen, elixir-format
msgid "Results update automatically after you stop moving the map."
msgstr "Результати оновляться автоматично, коли ви завершите переміщення карти."
#: lib/who_need_help_web/live/activity_live/index.ex:743
#: lib/who_need_help_web/live/activity_live/index.ex:775
#, elixir-autogen, elixir-format
msgid "Show activities in this area"
msgstr "Показати події в цій області"
#: lib/who_need_help_web/live/request_live/index.ex:800
#: lib/who_need_help_web/live/request_live/index.ex:833
#, elixir-autogen, elixir-format
msgid "Show requests in this area"
msgstr "Показати заявки в цій області"
#: lib/who_need_help_web/live/activity_live/index.ex:545
#: lib/who_need_help_web/live/request_live/index.ex:590
#: lib/who_need_help_web/live/activity_live/index.ex:577
#: lib/who_need_help_web/live/request_live/index.ex:623
#, elixir-autogen, elixir-format
msgid "Showing %{shown} of %{count} in the list."
msgstr "У списку показано %{shown} із %{count}."
#: lib/who_need_help_web/live/activity_live/index.ex:593
#: lib/who_need_help_web/live/request_live/index.ex:638
#: lib/who_need_help_web/live/activity_live/index.ex:625
#: lib/who_need_help_web/live/request_live/index.ex:671
#, elixir-autogen, elixir-format
msgid "Update results as map moves"
msgstr "Оновлювати результати під час переміщення карти"
#: lib/who_need_help_web/live/activity_live/index.ex:567
#: lib/who_need_help_web/live/request_live/index.ex:612
#: lib/who_need_help_web/live/activity_live/index.ex:599
#: lib/who_need_help_web/live/request_live/index.ex:645
#, elixir-autogen, elixir-format
msgid "Updating results for the visible map area…"
msgstr "Оновлюємо результати для видимої області карти…"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#: lib/who_need_help_web/controllers/support_html/received.html.heex:12
#, elixir-autogen, elixir-format
msgid "EMAIL CONFIRMATION REQUIRED"
msgstr "ПОТРІБНЕ ПІДТВЕРДЖЕННЯ EMAIL"
@ -6739,7 +6740,7 @@ msgstr "Очікуємо дозволу на геолокацію…"
msgid "Pending email verification"
msgstr "Очікує підтвердження email"
#: lib/who_need_help_web/controllers/support_html/received.html.heex:25
#: lib/who_need_help_web/controllers/support_html/received.html.heex:34
#, elixir-autogen, elixir-format
msgid "We saved pending request %{reference}. It is not in the support queue yet. Open the private link sent to the contact email to verify the address and submit the request for review."
msgstr "Ми зберегли запит %{reference}, що очікує підтвердження. Він ще не потрапив до черги підтримки. Відкрийте приватне посилання з листа, щоб підтвердити адресу та надіслати запит на розгляд."
@ -7804,7 +7805,7 @@ msgstr "У вас немає дозволу на цю дію. Для зміни
msgid "Your email was confirmed and the notice was sent for review."
msgstr "Ваш email підтверджено, повідомлення надіслано на перевірку."
#: lib/who_need_help_web/controllers/support_controller.ex:122
#: lib/who_need_help_web/controllers/support_controller.ex:128
#, elixir-autogen, elixir-format
msgid "Your email was confirmed and the request was sent to support."
msgstr "Ваш email підтверджено, звернення надіслано до підтримки."
@ -8002,7 +8003,7 @@ msgstr "Скопіюйте цю безпечну адресу та вставт
msgid "Confirm content-removal notice"
msgstr "Підтвердити повідомлення про видалення контенту"
#: lib/who_need_help_web/controllers/support_controller.ex:106
#: lib/who_need_help_web/controllers/support_controller.ex:112
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:9
#: lib/who_need_help_web/controllers/support_html/verify.html.heex:23
#, elixir-autogen, elixir-format
@ -8028,3 +8029,13 @@ msgstr "Якщо ви не надсилали це повідомлення, з
#, elixir-autogen, elixir-format
msgid "If you did not submit this request, close this page. Nothing will be sent to support."
msgstr "Якщо ви не надсилали це звернення, закрийте сторінку. До підтримки нічого не надійде."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:29
#, elixir-autogen, elixir-format
msgid "If that address belongs to a Who Need Help account, we sent a private confirmation link to the account email. No support request is created until that link is confirmed."
msgstr "Якщо ця адреса належить обліковому запису Who Need Help, ми надіслали приватне посилання для підтвердження на електронну пошту облікового запису. Звернення до підтримки буде створено лише після переходу за цим посиланням."
#: lib/who_need_help_web/controllers/support_html/received.html.heex:11
#, elixir-autogen, elixir-format
msgid "REQUEST CHECKED"
msgstr "ЗАПИТ ПЕРЕВІРЕНО"

View File

@ -11,3 +11,5 @@
20260801200302 application_safe additive generated public discovery coordinate columns
20260812120611 application_safe dropping the delivery-channel check allows inbox-only subscriptions that old code can still read safely
20260813194249 application_safe additive nullable inbound-provider identity columns and a partial unique index are ignored by the previous application
20260827173037 application_safe additive discovery rollup tables and maintenance triggers are ignored by the previous application while continuing to follow its writes
20260827180241 forward_only pending lifecycle uniqueness can reject duplicate account access or deletion requests that the previous application may still attempt to insert

1 # migration_version application_rollback_policy reason
11 20260801200302 application_safe additive generated public discovery coordinate columns
12 20260812120611 application_safe dropping the delivery-channel check allows inbox-only subscriptions that old code can still read safely
13 20260813194249 application_safe additive nullable inbound-provider identity columns and a partial unique index are ignored by the previous application
14 20260827173037 application_safe additive discovery rollup tables and maintenance triggers are ignored by the previous application while continuing to follow its writes
15 20260827180241 forward_only pending lifecycle uniqueness can reject duplicate account access or deletion requests that the previous application may still attempt to insert

View File

@ -0,0 +1,469 @@
defmodule WhoNeedHelp.Repo.Migrations.AddDiscoveryRollups do
use Ecto.Migration
@maximum_rollup_level 12
def up do
create table(:help_discovery_rollups, primary_key: false) do
add(:level, :smallint, null: false)
add(:cell_x, :integer, null: false)
add(:cell_y, :integer, null: false)
add(:category_id, :binary_id, null: false)
add(:urgency, :string, null: false)
add(:visible_until_hour, :utc_datetime, null: false)
add(:point_count, :bigint, null: false)
end
create(
constraint(:help_discovery_rollups, :help_discovery_rollups_level_range,
check: "level BETWEEN 0 AND #{@maximum_rollup_level}"
)
)
create(
constraint(:help_discovery_rollups, :help_discovery_rollups_non_negative_count,
check: "point_count >= 0"
)
)
create table(:activity_discovery_rollups, primary_key: false) do
add(:level, :smallint, null: false)
add(:cell_x, :integer, null: false)
add(:cell_y, :integer, null: false)
add(:category_id, :binary_id, null: false)
add(:visible_until_hour, :utc_datetime, null: false)
add(:point_count, :bigint, null: false)
end
create(
constraint(:activity_discovery_rollups, :activity_discovery_rollups_level_range,
check: "level BETWEEN 0 AND #{@maximum_rollup_level}"
)
)
create(
constraint(
:activity_discovery_rollups,
:activity_discovery_rollups_non_negative_count,
check: "point_count >= 0"
)
)
# The initial snapshot and trigger installation must describe one database
# state. Reads remain available, while writes to either discovery source wait
# until this migration transaction commits.
execute("LOCK TABLE help_requests, activities IN SHARE ROW EXCLUSIVE MODE")
execute(rebuild_help_rollups_sql())
execute(rebuild_activity_rollups_sql())
execute(validate_initial_rollups_sql())
create(
unique_index(
:help_discovery_rollups,
[:level, :cell_x, :cell_y, :category_id, :urgency, :visible_until_hour],
name: :help_discovery_rollups_identity
)
)
create(
index(
:help_discovery_rollups,
[:level, :cell_x, :cell_y, :visible_until_hour],
include: [:category_id, :urgency, :point_count],
name: :help_discovery_rollups_viewport
)
)
create(
index(
:help_discovery_rollups,
[:level, :category_id, :urgency, :cell_x, :cell_y, :visible_until_hour],
include: [:point_count],
name: :help_discovery_rollups_filtered_viewport
)
)
create(
unique_index(
:activity_discovery_rollups,
[:level, :cell_x, :cell_y, :category_id, :visible_until_hour],
name: :activity_discovery_rollups_identity
)
)
create(
index(
:activity_discovery_rollups,
[:level, :cell_x, :cell_y, :visible_until_hour],
include: [:category_id, :point_count],
name: :activity_discovery_rollups_viewport
)
)
create(
index(
:activity_discovery_rollups,
[:level, :category_id, :cell_x, :cell_y, :visible_until_hour],
include: [:point_count],
name: :activity_discovery_rollups_filtered_viewport
)
)
execute(help_trigger_function("insert", help_change_source("new_rows", 1)))
execute(help_trigger_function("delete", help_change_source("old_rows", -1)))
execute(
help_trigger_function(
"update",
help_change_source("new_rows", 1) <>
" UNION ALL " <>
help_change_source("old_rows", -1)
)
)
execute(activity_trigger_function("insert", activity_change_source("new_rows", 1)))
execute(activity_trigger_function("delete", activity_change_source("old_rows", -1)))
execute(
activity_trigger_function(
"update",
activity_change_source("new_rows", 1) <>
" UNION ALL " <>
activity_change_source("old_rows", -1)
)
)
execute("""
CREATE TRIGGER help_discovery_rollups_after_insert
AFTER INSERT ON help_requests
REFERENCING NEW TABLE AS new_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_help_discovery_rollups_insert()
""")
execute("""
CREATE TRIGGER help_discovery_rollups_after_delete
AFTER DELETE ON help_requests
REFERENCING OLD TABLE AS old_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_help_discovery_rollups_delete()
""")
execute("""
CREATE TRIGGER help_discovery_rollups_after_update
AFTER UPDATE ON help_requests
REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_help_discovery_rollups_update()
""")
execute("""
CREATE TRIGGER activity_discovery_rollups_after_insert
AFTER INSERT ON activities
REFERENCING NEW TABLE AS new_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_activity_discovery_rollups_insert()
""")
execute("""
CREATE TRIGGER activity_discovery_rollups_after_delete
AFTER DELETE ON activities
REFERENCING OLD TABLE AS old_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_activity_discovery_rollups_delete()
""")
execute("""
CREATE TRIGGER activity_discovery_rollups_after_update
AFTER UPDATE ON activities
REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows
FOR EACH STATEMENT EXECUTE FUNCTION wnh_activity_discovery_rollups_update()
""")
end
def down do
execute("DROP TRIGGER IF EXISTS activity_discovery_rollups_after_update ON activities")
execute("DROP TRIGGER IF EXISTS activity_discovery_rollups_after_delete ON activities")
execute("DROP TRIGGER IF EXISTS activity_discovery_rollups_after_insert ON activities")
execute("DROP TRIGGER IF EXISTS help_discovery_rollups_after_update ON help_requests")
execute("DROP TRIGGER IF EXISTS help_discovery_rollups_after_delete ON help_requests")
execute("DROP TRIGGER IF EXISTS help_discovery_rollups_after_insert ON help_requests")
for operation <- ~w(insert delete update) do
execute("DROP FUNCTION IF EXISTS wnh_activity_discovery_rollups_#{operation}()")
execute("DROP FUNCTION IF EXISTS wnh_help_discovery_rollups_#{operation}()")
end
drop(table(:activity_discovery_rollups))
drop(table(:help_discovery_rollups))
end
defp rebuild_help_rollups_sql do
"""
INSERT INTO help_discovery_rollups
(level, cell_x, cell_y, category_id, urgency, visible_until_hour, point_count)
SELECT
level,
#{cell_x_sql("request.public_longitude", "level")},
#{cell_y_sql("request.public_latitude", "level")},
request.category_id,
request.urgency,
date_trunc('hour', request.expires_at),
count(*)::bigint
FROM help_requests AS request
CROSS JOIN generate_series(0, #{@maximum_rollup_level}) AS level
WHERE #{eligible_help_sql("request")}
GROUP BY level, cell_x, cell_y, request.category_id, request.urgency,
date_trunc('hour', request.expires_at)
"""
end
defp rebuild_activity_rollups_sql do
"""
INSERT INTO activity_discovery_rollups
(level, cell_x, cell_y, category_id, visible_until_hour, point_count)
SELECT
level,
#{cell_x_sql("activity.public_longitude", "level")},
#{cell_y_sql("activity.public_latitude", "level")},
activity.category_id,
date_trunc('hour', least(activity.starts_at, activity.join_deadline)),
count(*)::bigint
FROM activities AS activity
CROSS JOIN generate_series(0, #{@maximum_rollup_level}) AS level
WHERE #{eligible_activity_sql("activity")}
GROUP BY level, cell_x, cell_y, activity.category_id,
date_trunc('hour', least(activity.starts_at, activity.join_deadline))
"""
end
defp help_change_source(relation, delta) do
"""
SELECT
#{delta}::bigint AS delta,
request.public_longitude,
request.public_latitude,
request.category_id,
request.urgency,
date_trunc('hour', request.expires_at) AS visible_until_hour
FROM #{relation} AS request
WHERE #{eligible_help_sql("request")}
"""
end
defp activity_change_source(relation, delta) do
"""
SELECT
#{delta}::bigint AS delta,
activity.public_longitude,
activity.public_latitude,
activity.category_id,
date_trunc('hour', least(activity.starts_at, activity.join_deadline)) AS visible_until_hour
FROM #{relation} AS activity
WHERE #{eligible_activity_sql("activity")}
"""
end
defp help_trigger_function(operation, changes_sql) do
"""
CREATE FUNCTION wnh_help_discovery_rollups_#{operation}()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
WITH changes AS (
#{changes_sql}
), expanded AS (
SELECT
changes.delta,
level,
#{cell_x_sql("changes.public_longitude", "level")},
#{cell_y_sql("changes.public_latitude", "level")},
changes.category_id,
changes.urgency,
changes.visible_until_hour
FROM changes
CROSS JOIN generate_series(0, #{@maximum_rollup_level}) AS level
), deltas AS (
SELECT
level,
cell_x,
cell_y,
category_id,
urgency,
visible_until_hour,
sum(delta)::bigint AS point_count
FROM expanded
GROUP BY level, cell_x, cell_y, category_id, urgency, visible_until_hour
HAVING sum(delta) <> 0
)
MERGE INTO help_discovery_rollups AS target
USING deltas AS source
ON target.level = source.level
AND target.cell_x = source.cell_x
AND target.cell_y = source.cell_y
AND target.category_id = source.category_id
AND target.urgency = source.urgency
AND target.visible_until_hour = source.visible_until_hour
WHEN MATCHED AND target.point_count + source.point_count > 0 THEN
UPDATE SET point_count = target.point_count + source.point_count
WHEN MATCHED THEN DELETE
WHEN NOT MATCHED AND source.point_count > 0 THEN
INSERT
(level, cell_x, cell_y, category_id, urgency, visible_until_hour, point_count)
VALUES
(source.level, source.cell_x, source.cell_y, source.category_id,
source.urgency, source.visible_until_hour, source.point_count);
RETURN NULL;
END
$function$
"""
end
defp activity_trigger_function(operation, changes_sql) do
"""
CREATE FUNCTION wnh_activity_discovery_rollups_#{operation}()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
WITH changes AS (
#{changes_sql}
), expanded AS (
SELECT
changes.delta,
level,
#{cell_x_sql("changes.public_longitude", "level")},
#{cell_y_sql("changes.public_latitude", "level")},
changes.category_id,
changes.visible_until_hour
FROM changes
CROSS JOIN generate_series(0, #{@maximum_rollup_level}) AS level
), deltas AS (
SELECT
level,
cell_x,
cell_y,
category_id,
visible_until_hour,
sum(delta)::bigint AS point_count
FROM expanded
GROUP BY level, cell_x, cell_y, category_id, visible_until_hour
HAVING sum(delta) <> 0
)
MERGE INTO activity_discovery_rollups AS target
USING deltas AS source
ON target.level = source.level
AND target.cell_x = source.cell_x
AND target.cell_y = source.cell_y
AND target.category_id = source.category_id
AND target.visible_until_hour = source.visible_until_hour
WHEN MATCHED AND target.point_count + source.point_count > 0 THEN
UPDATE SET point_count = target.point_count + source.point_count
WHEN MATCHED THEN DELETE
WHEN NOT MATCHED AND source.point_count > 0 THEN
INSERT (level, cell_x, cell_y, category_id, visible_until_hour, point_count)
VALUES
(source.level, source.cell_x, source.cell_y, source.category_id,
source.visible_until_hour, source.point_count);
RETURN NULL;
END
$function$
"""
end
defp eligible_help_sql(alias_name) do
"""
#{alias_name}.status = 'open'
AND #{alias_name}.hidden_at IS NULL
AND #{alias_name}.location_visibility <> 'hidden'
AND #{alias_name}.public_longitude IS NOT NULL
AND #{alias_name}.public_latitude IS NOT NULL
AND #{alias_name}.category_id IS NOT NULL
AND #{alias_name}.urgency IS NOT NULL
AND #{alias_name}.expires_at IS NOT NULL
"""
end
defp eligible_activity_sql(alias_name) do
"""
#{alias_name}.status = 'open'
AND #{alias_name}.hidden_at IS NULL
AND #{alias_name}.location_visibility = 'approximate_public'
AND #{alias_name}.public_longitude IS NOT NULL
AND #{alias_name}.public_latitude IS NOT NULL
AND #{alias_name}.category_id IS NOT NULL
AND #{alias_name}.starts_at IS NOT NULL
AND #{alias_name}.join_deadline IS NOT NULL
"""
end
defp validate_initial_rollups_sql do
"""
DO $validation$
DECLARE
expected_help bigint;
actual_help bigint;
expected_activities bigint;
actual_activities bigint;
BEGIN
SELECT count(*) INTO expected_help
FROM help_requests AS request
WHERE #{eligible_help_sql("request")};
SELECT coalesce(sum(point_count), 0) INTO actual_help
FROM help_discovery_rollups
WHERE level = 0;
IF expected_help <> actual_help THEN
RAISE EXCEPTION
'help discovery rollup validation failed: expected %, got %',
expected_help, actual_help;
END IF;
SELECT count(*) INTO expected_activities
FROM activities AS activity
WHERE #{eligible_activity_sql("activity")};
SELECT coalesce(sum(point_count), 0) INTO actual_activities
FROM activity_discovery_rollups
WHERE level = 0;
IF expected_activities <> actual_activities THEN
RAISE EXCEPTION
'activity discovery rollup validation failed: expected %, got %',
expected_activities, actual_activities;
END IF;
END
$validation$
"""
end
defp cell_x_sql(longitude, level) do
"""
least(
power(2, #{level})::bigint - 1,
greatest(0, floor(((#{longitude} + 180.0) / 360.0) * power(2, #{level})))::bigint
) AS cell_x
"""
end
defp cell_y_sql(latitude, level) do
"""
least(
power(2, #{level})::bigint - 1,
greatest(
0,
floor(
(
ln(
tan(
pi() / 4.0 +
radians(least(85.05112878, greatest(-85.05112878, #{latitude}))) / 2.0
)
) / pi() + 1.0
) / 2.0 * power(2, #{level})
)::bigint
)
) AS cell_y
"""
end
end

View File

@ -0,0 +1,11 @@
defmodule WhoNeedHelp.Repo.Migrations.AddPendingAccountLifecycleUniqueness do
use Ecto.Migration
def change do
create unique_index(:support_requests, [:requester_id, :kind],
name: :support_requests_one_pending_account_lifecycle_per_user_index,
where:
"requester_id IS NOT NULL AND contact_verified_at IS NULL AND status = 'pending_verification' AND kind IN ('account_access', 'account_deletion')"
)
end
end

View File

@ -463,7 +463,18 @@ defmodule WhoNeedHelp.ActivitiesTest do
assert cluster.hierarchy_level == 11
assert String.starts_with?(cluster.cluster_id, "activity:11:")
assert String.starts_with?(cluster.parent_cluster_id, "activity:10:")
assert cluster.expansion_zoom > 9
assert cluster.expansion_lookup
assert {:ok, expansion} =
Activities.map_cluster_expansion(
context.outsider_scope,
%{},
cluster.cluster_id
)
assert expansion.cluster_id == cluster.cluster_id
assert expansion.point_count == 3
assert expansion.zoom > 9
["activity", "11", cell_x, cell_y] = String.split(cluster.cluster_id, ":")
@ -472,10 +483,10 @@ defmodule WhoNeedHelp.ActivitiesTest do
assert_in_delta cluster.latitude, expected_latitude, 0.000_001
assert_in_delta cluster.longitude, expected_longitude, 0.000_001
assert_in_delta cluster.bounds.west, 30.52, 0.000_001
assert_in_delta cluster.bounds.east, 30.52, 0.000_001
assert_in_delta cluster.bounds.south, 50.45, 0.000_001
assert_in_delta cluster.bounds.north, 50.45, 0.000_001
assert_in_delta expansion.bounds.west, 30.52, 0.000_001
assert_in_delta expansion.bounds.east, 30.52, 0.000_001
assert_in_delta expansion.bounds.south, 50.45, 0.000_001
assert_in_delta expansion.bounds.north, 50.45, 0.000_001
assert Enum.any?(items, fn
%{
@ -565,6 +576,37 @@ defmodule WhoNeedHelp.ActivitiesTest do
assert Enum.sort(Enum.map(fixture_items, & &1.latitude)) == [50.451, 50.454]
end
test "map rollups follow activity coordinate changes and cancellation", context do
{:ok, activity} = Activities.create_activity(context.organizer_scope, context.attrs)
original_viewport = viewport!(30.50, 50.40, 30.60, 50.50, 9)
moved_viewport = viewport!(31.10, 51.10, 31.30, 51.30, 9)
original_items =
Activities.map_discovery_items(context.outsider_scope, %{}, original_viewport)
assert map_point_count(original_items) == 1
assert Enum.any?(original_items, &(&1.type == "activity" and &1.id == activity.id))
activity =
activity
|> Ecto.Changeset.change(location: %Geo.Point{coordinates: {31.2, 51.2}, srid: 4326})
|> Repo.update!()
assert Activities.map_discovery_items(context.outsider_scope, %{}, original_viewport) == []
moved_items =
Activities.map_discovery_items(context.outsider_scope, %{}, moved_viewport)
assert map_point_count(moved_items) == 1
assert Enum.any?(moved_items, &(&1.type == "activity" and &1.id == activity.id))
assert {:ok, _cancelled} =
Activities.cancel_activity(context.organizer_scope, activity.id)
assert Activities.map_discovery_items(context.outsider_scope, %{}, moved_viewport) == []
end
test "hidden activity is discoverable only through its public area description", context do
{:ok, hidden} =
Activities.create_activity(
@ -764,4 +806,6 @@ defmodule WhoNeedHelp.ActivitiesTest do
assert is_nil(restored.hidden_at)
assert {:ok, _activity} = Activities.get_activity(context.outsider_scope, activity.id)
end
defp map_point_count(items), do: Enum.sum(Enum.map(items, & &1.count))
end

View File

@ -580,7 +580,18 @@ defmodule WhoNeedHelp.MutualAidFlowTest do
assert cluster.hierarchy_level == 11
assert String.starts_with?(cluster.cluster_id, "request:11:")
assert String.starts_with?(cluster.parent_cluster_id, "request:10:")
assert cluster.expansion_zoom > viewport.zoom
assert cluster.expansion_lookup
assert {:ok, expansion} =
Help.map_cluster_expansion(
context.helper_scope,
%{},
cluster.cluster_id
)
assert expansion.cluster_id == cluster.cluster_id
assert expansion.point_count == 3
assert expansion.zoom > viewport.zoom
["request", "11", cell_x, cell_y] = String.split(cluster.cluster_id, ":")
@ -589,10 +600,10 @@ defmodule WhoNeedHelp.MutualAidFlowTest do
assert_in_delta cluster.latitude, expected_latitude, 0.000_001
assert_in_delta cluster.longitude, expected_longitude, 0.000_001
assert_in_delta cluster.bounds.west, 30.5234, 0.000_001
assert_in_delta cluster.bounds.east, 30.5235, 0.000_001
assert_in_delta cluster.bounds.south, 50.4501, 0.000_001
assert_in_delta cluster.bounds.north, 50.4501, 0.000_001
assert_in_delta expansion.bounds.west, 30.5234, 0.000_001
assert_in_delta expansion.bounds.east, 30.5235, 0.000_001
assert_in_delta expansion.bounds.south, 50.4501, 0.000_001
assert_in_delta expansion.bounds.north, 50.4501, 0.000_001
assert Enum.any?(items, fn
%{
@ -676,6 +687,34 @@ defmodule WhoNeedHelp.MutualAidFlowTest do
refute_in_delta item.longitude, 30.5267, 0.000_001
end
test "map rollups follow request coordinate changes and cancellation", context do
{:ok, request} = Help.create_request(context.requester_scope, context.request_attrs)
original_viewport = viewport!(30.50, 50.40, 30.60, 50.50, 9)
moved_viewport = viewport!(31.10, 51.10, 31.30, 51.30, 9)
original_items =
Help.map_discovery_items(context.helper_scope, %{}, original_viewport)
assert map_point_count(original_items) == 1
assert Enum.any?(original_items, &(&1.type == "request" and &1.id == request.id))
request =
request
|> Ecto.Changeset.change(location: %Geo.Point{coordinates: {31.2, 51.2}, srid: 4326})
|> Repo.update!()
assert Help.map_discovery_items(context.helper_scope, %{}, original_viewport) == []
moved_items = Help.map_discovery_items(context.helper_scope, %{}, moved_viewport)
assert map_point_count(moved_items) == 1
assert Enum.any?(moved_items, &(&1.type == "request" and &1.id == request.id))
assert {:ok, _cancelled} = Help.cancel_request(context.requester_scope, request.id)
assert Help.map_discovery_items(context.helper_scope, %{}, moved_viewport) == []
end
test "scale fixture requests keep distinct synthetic public map coordinates", context do
requests =
for {latitude, index} <- [{"50.451", 1}, {"50.454", 2}] do
@ -1292,4 +1331,6 @@ defmodule WhoNeedHelp.MutualAidFlowTest do
0 -> Enum.reverse(queries)
end
end
defp map_point_count(items), do: Enum.sum(Enum.map(items, & &1.count))
end

View File

@ -242,9 +242,9 @@ defmodule WhoNeedHelp.SupportAndContentRemovalTest do
assert {:ok, pending} =
Support.create_request(nil, %{
"kind" => "account_access",
"kind" => "technical_issue",
"contact_email" => "pending@example.com",
"subject" => "Pending account access request",
"subject" => "Pending technical support request",
"details" => "This public request must remain outside the operator queue."
})
@ -265,6 +265,67 @@ defmodule WhoNeedHelp.SupportAndContentRemovalTest do
assert Enum.map(Support.paginate_for_staff(moderator_scope).entries, & &1.id) == [verified.id]
end
test "anonymous account lifecycle intake creates no case or email for an unknown address" do
assert {:ok, :accepted} =
Support.create_request(nil, %{
"kind" => "account_access",
"contact_email" => "missing-account@example.com",
"subject" => "Recover account access",
"details" => "I need help recovering access to the account for this address."
})
assert Repo.aggregate(SupportRequest, :count) == 0
refute_enqueued(worker: SupportConfirmationWorker)
end
test "anonymous account lifecycle intake links one pending case to an unconfirmed account" do
user = unconfirmed_user_fixture(%{email: "Pending.Owner@Example.com"})
attrs = %{
"kind" => "account_deletion",
"contact_email" => " pending.owner@example.com ",
"subject" => "Delete my Who Need Help account",
"details" => "Please delete the account and its associated personal data."
}
assert {:ok, first} = Support.create_request(nil, attrs)
assert first.requester_id == user.id
assert first.contact_email == String.downcase(user.email)
assert first.status == :pending_verification
assert is_nil(first.contact_verified_at)
assert {:ok, second} =
Support.create_request(nil, %{
attrs
| "details" => "Please delete this account after I confirm ownership."
})
assert second.id == first.id
assert Repo.aggregate(
from(request in SupportRequest,
where:
request.requester_id == ^user.id and
request.kind == :account_deletion and
request.status == :pending_verification
),
:count
) == 1
assert_enqueued(
worker: SupportConfirmationWorker,
queue: :mail,
args: %{"request_id" => first.id}
)
assert {:ok, verified} =
Support.verify_by_confirmation_token(first.id, Support.confirmation_token(first))
assert verified.requester_id == user.id
assert verified.status == :open
assert verified.contact_verified_at
end
test "authenticated support uses the account email and staff moderation is audited" do
user = user_fixture()
assert_email_sent()

View File

@ -90,6 +90,44 @@ defmodule WhoNeedHelpWeb.SupportControllerTest do
assert page =~ "It is not in the support queue yet"
end
test "account lifecycle receipt is identical for matching and unknown addresses", %{
conn: conn
} do
user = unconfirmed_user_fixture(%{email: "lifecycle-owner@example.com"})
params = fn email ->
%{
"support_request" => %{
"kind" => "account_access",
"contact_email" => email,
"subject" => "Recover account access",
"details" => "I need help recovering access to the account for this address."
}
}
end
matching = post(conn, ~p"/support", params.("LIFECYCLE-OWNER@example.com"))
missing = post(recycle(conn), ~p"/support", params.("missing-owner@example.com"))
assert redirected_to(matching) == ~p"/support/received?flow=account"
assert redirected_to(missing) == ~p"/support/received?flow=account"
matching_page = matching |> recycle() |> get(redirected_to(matching)) |> html_response(200)
missing_page = missing |> recycle() |> get(redirected_to(missing)) |> html_response(200)
for page <- [matching_page, missing_page] do
assert page =~ "If that address belongs to a Who Need Help account"
assert page =~ "No support request is created until that link is confirmed"
refute page =~ "SUP-"
end
assert %SupportRequest{requester_id: requester_id} =
Repo.get_by(SupportRequest, kind: :account_access)
assert requester_id == user.id
assert Repo.aggregate(SupportRequest, :count) == 1
end
test "support intake enforces independent email and client IP limits", %{conn: conn} do
previous = Application.get_env(:who_need_help, :rate_limit_policies)