Scale map discovery and harden account lifecycle support
This commit is contained in:
parent
05dc9372e6
commit
01971f1bc4
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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,10 +542,11 @@ 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
|
||||
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
645
lib/who_need_help/discovery/rollup.ex
Normal file
645
lib/who_need_help/discovery/rollup.ex
Normal 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
|
||||
|
|
@ -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,9 +225,10 @@ 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)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
def received(conn, _params), do: redirect(conn, to: ~p"/support")
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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} ->
|
||||
|
|
|
|||
|
|
@ -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} ->
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 "ЗАПРОС ПРОВЕРЕН"
|
||||
|
|
|
|||
|
|
@ -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 "ЗАПИТ ПЕРЕВІРЕНО"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
469
priv/repo/migrations/20260827173037_add_discovery_rollups.exs
Normal file
469
priv/repo/migrations/20260827173037_add_discovery_rollups.exs
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user