en español
This commit is contained in:
parent
1406ae97f0
commit
fc449ed5f9
31 changed files with 3087 additions and 206 deletions
|
|
@ -59,6 +59,16 @@ function unregisterChartInstance(el: HTMLElement) {
|
|||
}
|
||||
}
|
||||
|
||||
function getLabels(el: HTMLElement) {
|
||||
const raw = el.getAttribute('data-chart-labels');
|
||||
if (!raw) return {};
|
||||
try {
|
||||
return JSON.parse(raw);
|
||||
} catch {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// All hooks are typed as 'any' for LiveView context compatibility
|
||||
export const WeatherChartHooks: Record<string, Hook> = {
|
||||
ChartJSTempChart: {
|
||||
|
|
@ -83,6 +93,7 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
const self = this as any;
|
||||
if (self.chart) self.chart.destroy();
|
||||
const data: WeatherHistoryDatum[] = JSON.parse(self.el.dataset.weatherHistory!);
|
||||
const labels = getLabels(self.el);
|
||||
const times = data.map(d => new Date(d.timestamp));
|
||||
const temps = data.map(d => d.temperature);
|
||||
const dews = data.map(d => d.dew_point);
|
||||
|
|
@ -94,20 +105,20 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
data: {
|
||||
labels: times,
|
||||
datasets: [
|
||||
{ label: 'Temperature (°F)', data: temps, borderColor: 'red', backgroundColor: 'rgba(255, 0, 0, 0.1)', tension: 0.1, pointRadius: 0 },
|
||||
{ label: 'Dew Point (°F)', data: dews, borderColor: 'blue', backgroundColor: 'rgba(0, 0, 255, 0.1)', tension: 0.1, pointRadius: 0 }
|
||||
{ label: labels.temp_label || 'Temperature (°F)', data: temps, borderColor: 'red', backgroundColor: 'rgba(255, 0, 0, 0.1)', tension: 0.1, pointRadius: 0 },
|
||||
{ label: labels.dew_label || 'Dew Point (°F)', data: dews, borderColor: 'blue', backgroundColor: 'rgba(0, 0, 255, 0.1)', tension: 0.1, pointRadius: 0 }
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: { display: true, text: 'Temperature & Dew Point (°F)', color: colors.text },
|
||||
title: { display: true, text: labels.temp_title || 'Temperature & Dew Point (°F)', color: colors.text },
|
||||
legend: { labels: { color: colors.text } }
|
||||
},
|
||||
scales: {
|
||||
x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } },
|
||||
y: { title: { display: true, text: '°F', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }
|
||||
x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: labels.time || 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } },
|
||||
y: { title: { display: true, text: labels.degf || '°F', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -135,6 +146,7 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
const self = this as any;
|
||||
if (self.chart) self.chart.destroy();
|
||||
const data: WeatherHistoryDatum[] = JSON.parse(self.el.dataset.weatherHistory!);
|
||||
const labels = getLabels(self.el);
|
||||
const times = data.map(d => new Date(d.timestamp));
|
||||
const humidity = data.map(d => d.humidity);
|
||||
const colors = getThemeColors();
|
||||
|
|
@ -142,12 +154,12 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
if (!canvas) return;
|
||||
self.chart = new window.Chart(canvas, {
|
||||
type: 'line',
|
||||
data: { labels: times, datasets: [{ label: 'Humidity (%)', data: humidity, borderColor: 'green', backgroundColor: 'rgba(0, 255, 0, 0.1)', tension: 0.1, pointRadius: 0 }] },
|
||||
data: { labels: times, datasets: [{ label: labels.humidity_label || 'Humidity (%)', data: humidity, borderColor: 'green', backgroundColor: 'rgba(0, 255, 0, 0.1)', tension: 0.1, pointRadius: 0 }] },
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: { title: { display: true, text: 'Humidity (%)', color: colors.text }, legend: { labels: { color: colors.text } } },
|
||||
scales: { x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }, y: { title: { display: true, text: '%', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } } }
|
||||
plugins: { title: { display: true, text: labels.humidity_title || 'Humidity (%)', color: colors.text }, legend: { labels: { color: colors.text } } },
|
||||
scales: { x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: labels.time || 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }, y: { title: { display: true, text: labels.percent || '%', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } } }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -174,6 +186,7 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
const self = this as any;
|
||||
if (self.chart) self.chart.destroy();
|
||||
const data: WeatherHistoryDatum[] = JSON.parse(self.el.dataset.weatherHistory!);
|
||||
const labels = getLabels(self.el);
|
||||
const times = data.map(d => new Date(d.timestamp));
|
||||
const pressure = data.map(d => d.pressure);
|
||||
const colors = getThemeColors();
|
||||
|
|
@ -181,12 +194,12 @@ export const WeatherChartHooks: Record<string, Hook> = {
|
|||
if (!canvas) return;
|
||||
self.chart = new window.Chart(canvas, {
|
||||
type: 'line',
|
||||
data: { labels: times, datasets: [{ label: 'Pressure (mb)', data: pressure, borderColor: 'purple', backgroundColor: 'rgba(128, 0, 128, 0.1)', tension: 0.1, pointRadius: 0 }] },
|
||||
data: { labels: times, datasets: [{ label: labels.pressure_label || 'Pressure (mb)', data: pressure, borderColor: 'purple', backgroundColor: 'rgba(128, 0, 128, 0.1)', tension: 0.1, pointRadius: 0 }] },
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: { title: { display: true, text: 'Pressure (mb)', color: colors.text }, legend: { labels: { color: colors.text } } },
|
||||
scales: { x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }, y: { title: { display: true, text: 'mb', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } } }
|
||||
plugins: { title: { display: true, text: labels.pressure_title || 'Pressure (mb)', color: colors.text }, legend: { labels: { color: colors.text } } },
|
||||
scales: { x: { type: 'time', time: { displayFormats: { hour: 'HH:mm', minute: 'HH:mm' } }, title: { display: true, text: labels.time || 'Time', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } }, y: { title: { display: true, text: labels.mb || 'mb', color: colors.text }, ticks: { color: colors.text }, grid: { color: colors.grid } } }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ config :aprsme, AprsmeWeb.Endpoint,
|
|||
pubsub_server: Aprsme.PubSub,
|
||||
live_view: [signing_salt: "ees098qG"]
|
||||
|
||||
# Configure Gettext
|
||||
config :aprsme, AprsmeWeb.Gettext,
|
||||
locales: ~w(en es),
|
||||
default_locale: "en"
|
||||
|
||||
# Configure Oban for background jobs
|
||||
config :aprsme, Oban,
|
||||
repo: Aprsme.Repo,
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ defmodule Aprsme.Application do
|
|||
defp migrate do
|
||||
auto_migrate = Application.get_env(:aprsme, :auto_migrate, true)
|
||||
do_migrate(auto_migrate)
|
||||
|
||||
# Gettext translations are automatically compiled during Mix compilation
|
||||
rescue
|
||||
error ->
|
||||
require Logger
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ defmodule Aprsme.DeviceIdentification do
|
|||
@moduledoc """
|
||||
Handles APRS device identification based on the APRS device identification database.
|
||||
"""
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ defmodule Aprsme.DeviceIdentification do
|
|||
"""
|
||||
@spec identify_device(String.t()) :: String.t()
|
||||
def identify_device(symbols) do
|
||||
Enum.find_value(@device_patterns, "Unknown", fn {regex, name} ->
|
||||
Enum.find_value(@device_patterns, gettext("Unknown"), fn {regex, name} ->
|
||||
if Regex.match?(regex, symbols) do
|
||||
name
|
||||
end
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ defmodule Aprsme.Release do
|
|||
deployed_at = init()
|
||||
Logger.info("Deployment timestamp: #{deployed_at}")
|
||||
|
||||
# Gettext translations are automatically compiled during Mix compilation
|
||||
|
||||
# Run migrations
|
||||
{:ok, _, _} = Ecto.Migrator.with_repo(Aprsme.Repo, &Ecto.Migrator.run(&1, :up, all: true))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ defmodule AprsmeWeb.Api.V1.FallbackController do
|
|||
See `Phoenix.Controller.action_fallback/1` for more details.
|
||||
"""
|
||||
use AprsmeWeb, :controller
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
alias AprsmeWeb.Api.V1.ErrorJSON
|
||||
|
||||
|
|
@ -53,7 +54,7 @@ defmodule AprsmeWeb.Api.V1.FallbackController do
|
|||
conn
|
||||
|> put_status(:request_timeout)
|
||||
|> put_view(json: ErrorJSON)
|
||||
|> render(:error, message: "Request timeout")
|
||||
|> render(:error, message: gettext("Request timeout"))
|
||||
end
|
||||
|
||||
# Default fallback for unexpected errors
|
||||
|
|
@ -64,9 +65,9 @@ defmodule AprsmeWeb.Api.V1.FallbackController do
|
|||
|> render(:"500")
|
||||
end
|
||||
|
||||
defp format_error_message(:not_found), do: "Resource not found"
|
||||
defp format_error_message(:unauthorized), do: "Unauthorized access"
|
||||
defp format_error_message(:forbidden), do: "Access forbidden"
|
||||
defp format_error_message(:bad_request), do: "Bad request"
|
||||
defp format_error_message(reason), do: "An error occurred: #{reason}"
|
||||
defp format_error_message(:not_found), do: gettext("Resource not found")
|
||||
defp format_error_message(:unauthorized), do: gettext("Unauthorized access")
|
||||
defp format_error_message(:forbidden), do: gettext("Access forbidden")
|
||||
defp format_error_message(:bad_request), do: gettext("Bad request")
|
||||
defp format_error_message(reason), do: gettext("An error occurred: %{reason}", reason: reason)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ defmodule AprsmeWeb.Api.V1.ChangesetJSON do
|
|||
@moduledoc """
|
||||
Renders changeset errors for API v1.
|
||||
"""
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
@doc """
|
||||
Renders changeset errors.
|
||||
|
|
@ -9,7 +10,7 @@ defmodule AprsmeWeb.Api.V1.ChangesetJSON do
|
|||
def render("error.json", %{changeset: changeset}) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Validation failed",
|
||||
message: gettext("Validation failed"),
|
||||
code: "validation_error",
|
||||
details: translate_errors(changeset)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
@moduledoc """
|
||||
Renders error responses for API v1.
|
||||
"""
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
def render("error.json", %{message: message}) do
|
||||
%{
|
||||
|
|
@ -15,7 +16,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("404.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Resource not found",
|
||||
message: gettext("Resource not found"),
|
||||
code: "not_found"
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +25,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("500.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Internal server error",
|
||||
message: gettext("Internal server error"),
|
||||
code: "internal_server_error"
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +34,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("422.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Unprocessable entity",
|
||||
message: gettext("Unprocessable entity"),
|
||||
code: "unprocessable_entity"
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +43,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("400.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Bad request",
|
||||
message: gettext("Bad request"),
|
||||
code: "bad_request"
|
||||
}
|
||||
}
|
||||
|
|
@ -51,7 +52,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("401.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Unauthorized",
|
||||
message: gettext("Unauthorized"),
|
||||
code: "unauthorized"
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +61,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("403.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Forbidden",
|
||||
message: gettext("Forbidden"),
|
||||
code: "forbidden"
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +70,7 @@ defmodule AprsmeWeb.Api.V1.ErrorJSON do
|
|||
def render("408.json", _assigns) do
|
||||
%{
|
||||
error: %{
|
||||
message: "Request timeout",
|
||||
message: gettext("Request timeout"),
|
||||
code: "request_timeout"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule AprsmeWeb.AboutLive do
|
||||
@moduledoc false
|
||||
use AprsmeWeb, :live_view
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
@impl true
|
||||
def mount(_params, _session, socket) do
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div class="container mx-auto max-w-2xl py-12">
|
||||
<div class="card bg-base-100 shadow-xl mb-8">
|
||||
<div class="card-body prose max-w-none">
|
||||
<h2 class="card-title text-3xl">Under heavy construction</h2>
|
||||
<h2 class="card-title text-3xl">{gettext("Under heavy construction")}</h2>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
</p>
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
|
||||
</p>
|
||||
<div class="bg-base-200 p-6 rounded-lg mb-8">
|
||||
<h4 class="text-lg font-semibold mb-3">Built with Modern Technologies</h4>
|
||||
<h4 class="text-lg font-semibold mb-3">{gettext("Built with Modern Technologies")}</h4>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<span class="badge badge-primary">Elixir</span>
|
||||
<span class="badge badge-success">Phoenix</span>
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
<span class="badge badge-error">Tailwind CSS</span>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="text-2xl font-semibold mb-4">Join Our Community</h3>
|
||||
<h3 class="text-2xl font-semibold mb-4">{gettext("Join Our Community")}</h3>
|
||||
<p>
|
||||
Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus.
|
||||
</p>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-1.447-.894L15 4m0 13V4m-6 3l6-3"
|
||||
/>
|
||||
</svg>
|
||||
Explore the Map
|
||||
{gettext("Explore the Map")}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="mt-6 bg-white shadow-sm rounded-lg overflow-hidden">
|
||||
<div class="px-4 py-2 bg-gray-50 border-b border-gray-200 flex items-center justify-between">
|
||||
<span class="text-xs text-gray-500">
|
||||
Auto-refreshes every 5 seconds
|
||||
{gettext("Auto-refreshes every 5 seconds")}
|
||||
</span>
|
||||
<%= if @loading do %>
|
||||
<span class="flex items-center text-xs text-blue-600">
|
||||
|
|
@ -32,12 +32,12 @@
|
|||
>
|
||||
</path>
|
||||
</svg>
|
||||
Updating...
|
||||
{gettext("Updating...")}
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<.table id="bad_packets" rows={@bad_packets}>
|
||||
<:col :let={bad_packet} label="Attempted At">
|
||||
<:col :let={bad_packet} label={gettext("Attempted At")}>
|
||||
<span class="text-sm text-gray-900">
|
||||
{Calendar.strftime(
|
||||
bad_packet.attempted_at || bad_packet.inserted_at,
|
||||
|
|
@ -45,17 +45,17 @@
|
|||
)}
|
||||
</span>
|
||||
</:col>
|
||||
<:col :let={bad_packet} label="Error Type">
|
||||
<:col :let={bad_packet} label={gettext("Error Type")}>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
|
||||
{bad_packet.error_type || "Unknown"}
|
||||
{bad_packet.error_type || gettext("Unknown")}
|
||||
</span>
|
||||
</:col>
|
||||
<:col :let={bad_packet} label="Error Message">
|
||||
<:col :let={bad_packet} label={gettext("Error Message")}>
|
||||
<span class="text-sm text-red-600 font-mono">
|
||||
{bad_packet.error_message || "No error message"}
|
||||
{bad_packet.error_message || gettext("No error message")}
|
||||
</span>
|
||||
</:col>
|
||||
<:col :let={bad_packet} label="Raw Packet">
|
||||
<:col :let={bad_packet} label={gettext("Raw Packet")}>
|
||||
<div class="max-w-md">
|
||||
<div class="text-xs font-mono text-gray-700 break-all">
|
||||
<%= if is_binary(bad_packet.raw_packet) do %>
|
||||
|
|
@ -81,8 +81,8 @@
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">No bad packets</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">All packets are parsing successfully!</p>
|
||||
<h3 class="mt-2 text-sm font-medium text-gray-900">{gettext("No bad packets")}</h3>
|
||||
<p class="mt-1 text-sm text-gray-500">{gettext("All packets are parsing successfully!")}</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule AprsmeWeb.InfoLive.Show do
|
||||
@moduledoc false
|
||||
use AprsmeWeb, :live_view
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
alias Aprsme.Packets
|
||||
alias AprsmeWeb.MapLive.PacketUtils
|
||||
|
|
@ -273,38 +274,38 @@ defmodule AprsmeWeb.InfoLive.Show do
|
|||
# WIDE digipeaters
|
||||
String.starts_with?(element, "WIDE") ->
|
||||
case element do
|
||||
"WIDE1-1" -> "WIDE1-1 (Wide area digipeater, 1 hop)"
|
||||
"WIDE2-1" -> "WIDE2-1 (Wide area digipeater, 2 hops)"
|
||||
"WIDE3-1" -> "WIDE3-1 (Wide area digipeater, 3 hops)"
|
||||
"WIDE4-1" -> "WIDE4-1 (Wide area digipeater, 4 hops)"
|
||||
"WIDE5-1" -> "WIDE5-1 (Wide area digipeater, 5 hops)"
|
||||
"WIDE6-1" -> "WIDE6-1 (Wide area digipeater, 6 hops)"
|
||||
"WIDE7-1" -> "WIDE7-1 (WIDE area digipeater, 7 hops)"
|
||||
"WIDE1-2" -> "WIDE1-2 (Wide area digipeater, 1 hop, 2nd attempt)"
|
||||
"WIDE2-2" -> "WIDE2-2 (Wide area digipeater, 2 hops, 2nd attempt)"
|
||||
_ -> "WIDE digipeater (#{element})"
|
||||
"WIDE1-1" -> gettext("WIDE1-1 (Wide area digipeater, 1 hop)")
|
||||
"WIDE2-1" -> gettext("WIDE2-1 (Wide area digipeater, 2 hops)")
|
||||
"WIDE3-1" -> gettext("WIDE3-1 (Wide area digipeater, 3 hops)")
|
||||
"WIDE4-1" -> gettext("WIDE4-1 (Wide area digipeater, 4 hops)")
|
||||
"WIDE5-1" -> gettext("WIDE5-1 (Wide area digipeater, 5 hops)")
|
||||
"WIDE6-1" -> gettext("WIDE6-1 (Wide area digipeater, 6 hops)")
|
||||
"WIDE7-1" -> gettext("WIDE7-1 (WIDE area digipeater, 7 hops)")
|
||||
"WIDE1-2" -> gettext("WIDE1-2 (Wide area digipeater, 1 hop, 2nd attempt)")
|
||||
"WIDE2-2" -> gettext("WIDE2-2 (Wide area digipeater, 2 hops, 2nd attempt)")
|
||||
_ -> gettext("WIDE digipeater (%{element})", element: element)
|
||||
end
|
||||
|
||||
# TRACE digipeaters
|
||||
String.starts_with?(element, "TRACE") ->
|
||||
case element do
|
||||
"TRACE1-1" -> "TRACE1-1 (Trace digipeater, 1 hop)"
|
||||
"TRACE2-1" -> "TRACE2-1 (Trace digipeater, 2 hops)"
|
||||
"TRACE3-1" -> "TRACE3-1 (Trace digipeater, 3 hops)"
|
||||
"TRACE4-1" -> "TRACE4-1 (Trace digipeater, 4 hops)"
|
||||
"TRACE5-1" -> "TRACE5-1 (Trace digipeater, 5 hops)"
|
||||
"TRACE6-1" -> "TRACE6-1 (Trace digipeater, 6 hops)"
|
||||
"TRACE7-1" -> "TRACE7-1 (Trace digipeater, 7 hops)"
|
||||
_ -> "TRACE digipeater (#{element})"
|
||||
"TRACE1-1" -> gettext("TRACE1-1 (Trace digipeater, 1 hop)")
|
||||
"TRACE2-1" -> gettext("TRACE2-1 (Trace digipeater, 2 hops)")
|
||||
"TRACE3-1" -> gettext("TRACE3-1 (Trace digipeater, 3 hops)")
|
||||
"TRACE4-1" -> gettext("TRACE4-1 (Trace digipeater, 4 hops)")
|
||||
"TRACE5-1" -> gettext("TRACE5-1 (Trace digipeater, 5 hops)")
|
||||
"TRACE6-1" -> gettext("TRACE6-1 (Trace digipeater, 6 hops)")
|
||||
"TRACE7-1" -> gettext("TRACE7-1 (Trace digipeater, 7 hops)")
|
||||
_ -> gettext("TRACE digipeater (%{element})", element: element)
|
||||
end
|
||||
|
||||
# RELAY digipeaters
|
||||
String.starts_with?(element, "RELAY") ->
|
||||
case element do
|
||||
"RELAY" -> "RELAY (Relay digipeater)"
|
||||
"RELAY-1" -> "RELAY-1 (Relay digipeater, 1 hop)"
|
||||
"RELAY-2" -> "RELAY-2 (Relay digipeater, 2 hops)"
|
||||
_ -> "RELAY digipeater (#{element})"
|
||||
"RELAY" -> gettext("RELAY (Relay digipeater)")
|
||||
"RELAY-1" -> gettext("RELAY-1 (Relay digipeater, 1 hop)")
|
||||
"RELAY-2" -> gettext("RELAY-2 (Relay digipeater, 2 hops)")
|
||||
_ -> gettext("RELAY digipeater (%{element})", element: element)
|
||||
end
|
||||
|
||||
# qAC (APRS-IS connection)
|
||||
|
|
@ -466,22 +467,22 @@ defmodule AprsmeWeb.InfoLive.Show do
|
|||
# TCPIP digipeaters
|
||||
String.starts_with?(element, "TCPIP") ->
|
||||
case element do
|
||||
"TCPIP" -> "TCPIP (Internet gateway)"
|
||||
"TCPIP*" -> "TCPIP* (Internet gateway, no forward)"
|
||||
_ -> "TCPIP gateway (#{element})"
|
||||
"TCPIP" -> gettext("TCPIP (Internet gateway)")
|
||||
"TCPIP*" -> gettext("TCPIP* (Internet gateway, no forward)")
|
||||
_ -> gettext("TCPIP gateway (%{element})", element: element)
|
||||
end
|
||||
|
||||
# Generic callsign with SSID (likely a digipeater)
|
||||
Regex.match?(~r/^[A-Z0-9]+-\d+$/, element) ->
|
||||
"#{element} (Digipeater)"
|
||||
gettext("%{element} (Digipeater)", element: element)
|
||||
|
||||
# Generic callsign without SSID
|
||||
Regex.match?(~r/^[A-Z0-9]+$/, element) ->
|
||||
"#{element} (Station)"
|
||||
gettext("%{element} (Station)", element: element)
|
||||
|
||||
# Default case
|
||||
true ->
|
||||
"#{element} (Unknown)"
|
||||
gettext("%{element} (Unknown)", element: element)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-center">
|
||||
<h1 class="text-xl font-bold leading-7 sm:truncate sm:text-2xl">
|
||||
APRS Station
|
||||
{gettext("APRS Station")}
|
||||
</h1>
|
||||
<div class="ml-3 flex items-center space-x-3">
|
||||
<span class="badge badge-primary">
|
||||
|
|
@ -64,11 +64,11 @@
|
|||
<div class="mt-3 flex md:ml-4 md:mt-0">
|
||||
<div class="flex space-x-2">
|
||||
<.link navigate={~p"/packets/#{@callsign}"} class="btn btn-outline btn-sm">
|
||||
View packets
|
||||
{gettext("View packets")}
|
||||
</.link>
|
||||
<%= if @has_weather_packets do %>
|
||||
<.link navigate={~p"/weather/#{@callsign}"} class="btn btn-primary btn-sm">
|
||||
Weather charts
|
||||
{gettext("Weather charts")}
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
@ -106,19 +106,19 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h3 class="text-sm font-medium">Position Information</h3>
|
||||
<h3 class="text-sm font-medium">{gettext("Position Information")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<dl class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Location</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Location")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{@packet.lat || ""}, {@packet.lon || ""}
|
||||
</dd>
|
||||
</div>
|
||||
<%= if @packet.lat && @packet.lon do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Grid Square</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Grid Square")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
<%= case Gridsquare.encode(@packet.lon, @packet.lat) do %>
|
||||
<% %Gridsquare.EncodeResult{grid_reference: grid_ref} -> %>
|
||||
|
|
@ -130,7 +130,7 @@
|
|||
</div>
|
||||
<% end %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Last Position</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Last Position")}</dt>
|
||||
<dd class="mt-1 text-sm">
|
||||
<%= if @packet.received_at do %>
|
||||
<div class="font-semibold">
|
||||
|
|
@ -140,25 +140,25 @@
|
|||
{Calendar.strftime(@packet.received_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
</div>
|
||||
<% else %>
|
||||
<span class="opacity-70">Unknown</span>
|
||||
<span class="opacity-70">{gettext("Unknown")}</span>
|
||||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
<%= if @packet.altitude do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Altitude</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Altitude")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">{@packet.altitude} ft</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if @packet.course do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Course</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Course")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">{@packet.course}°</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<%= if @packet.speed do %>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Speed</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Speed")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">{@packet.speed} MPH</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
@ -186,12 +186,12 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h3 class="text-sm font-medium">Device Information</h3>
|
||||
<h3 class="text-sm font-medium">{gettext("Device Information")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<dl class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Device</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Device")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
<%= if @packet.device_model || @packet.device_vendor do %>
|
||||
{[
|
||||
|
|
@ -206,25 +206,25 @@
|
|||
<% end %>
|
||||
<% else %>
|
||||
<span class="opacity-70 font-mono">
|
||||
{@packet.device_identifier || "Unknown"}
|
||||
{@packet.device_identifier || gettext("Unknown")}
|
||||
</span>
|
||||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Path</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Path")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">{@packet.path || ""}</dd>
|
||||
</div>
|
||||
<%= if @packet.path && @packet.path != "" do %>
|
||||
<div class="col-span-2">
|
||||
<dt class="text-xs font-medium opacity-70">Decoded Path</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Decoded Path")}</dt>
|
||||
<dd class="mt-1 text-sm">
|
||||
{decode_aprs_path(@packet.path)}
|
||||
</dd>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="col-span-2">
|
||||
<dt class="text-xs font-medium opacity-70">Raw Packet</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Raw Packet")}</dt>
|
||||
<dd class="mt-1 text-xs font-mono break-all">
|
||||
<%= if is_binary(@packet.raw_packet) do %>
|
||||
{Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)}
|
||||
|
|
@ -259,7 +259,7 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h3 class="text-sm font-medium">Other SSIDs</h3>
|
||||
<h3 class="text-sm font-medium">{gettext("Other SSIDs")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
|
|
@ -267,13 +267,13 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Callsign
|
||||
{gettext("Callsign")}
|
||||
</th>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Distance & Direction
|
||||
{gettext("Distance & Direction")}
|
||||
</th>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Last Heard
|
||||
{gettext("Last Heard")}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -377,7 +377,7 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h3 class="text-sm font-medium">Stations Near Current Position</h3>
|
||||
<h3 class="text-sm font-medium">{gettext("Stations Near Current Position")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
|
|
@ -385,13 +385,13 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Callsign
|
||||
{gettext("Callsign")}
|
||||
</th>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Distance & Course
|
||||
{gettext("Distance & Course")}
|
||||
</th>
|
||||
<th class="text-xs font-medium uppercase tracking-wider">
|
||||
Last Heard
|
||||
{gettext("Last Heard")}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
@ -466,9 +466,9 @@
|
|||
d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423L16.5 15.75l.394 1.183a2.25 2.25 0 001.423 1.423L19.5 18.75l-1.183.394a2.25 2.25 0 00-1.423 1.423z"
|
||||
/>
|
||||
</svg>
|
||||
<h3 class="mt-2 text-sm font-semibold">No data available</h3>
|
||||
<h3 class="mt-2 text-sm font-semibold">{gettext("No data available")}</h3>
|
||||
<p class="mt-1 text-sm opacity-70">
|
||||
No recent packet data available for this callsign.
|
||||
{gettext("No recent packet data available for this callsign.")}
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
|
|
|||
25
lib/aprsme_web/live/locale_hook.ex
Normal file
25
lib/aprsme_web/live/locale_hook.ex
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
defmodule AprsmeWeb.LocaleHook do
|
||||
@moduledoc """
|
||||
LiveView hook for setting locale based on Accept-Language header.
|
||||
This ensures that LiveView updates maintain the correct locale.
|
||||
"""
|
||||
import Phoenix.Component
|
||||
|
||||
@supported_locales ["en", "es"]
|
||||
|
||||
def on_mount(:set_locale, _params, session, socket) do
|
||||
locale = get_locale_from_session(session) || "en"
|
||||
Gettext.put_locale(AprsmeWeb.Gettext, locale)
|
||||
{:cont, assign(socket, locale: locale)}
|
||||
end
|
||||
|
||||
defp get_locale_from_session(session) do
|
||||
case session do
|
||||
%{"locale" => locale} when locale in @supported_locales ->
|
||||
locale
|
||||
|
||||
_ ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -607,7 +607,11 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
>
|
||||
</div>
|
||||
|
||||
<button class="locate-button" phx-click="locate_me" title="Find my location">
|
||||
<button
|
||||
class="locate-button"
|
||||
phx-click="locate_me"
|
||||
title={Gettext.gettext(AprsmeWeb.Gettext, "Find my location")}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="20"
|
||||
|
|
@ -629,7 +633,11 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
<button
|
||||
class={["slideover-toggle", if(@slideover_open, do: "slideover-open", else: "slideover-closed")]}
|
||||
phx-click="toggle_slideover"
|
||||
title={if @slideover_open, do: "Hide controls", else: "Show controls"}
|
||||
title={
|
||||
if @slideover_open,
|
||||
do: Gettext.gettext(AprsmeWeb.Gettext, "Hide controls"),
|
||||
else: Gettext.gettext(AprsmeWeb.Gettext, "Show controls")
|
||||
}
|
||||
>
|
||||
<%= if @slideover_open do %>
|
||||
<svg
|
||||
|
|
@ -704,7 +712,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
<button
|
||||
class="lg:hidden text-white hover:text-slate-200 transition-colors"
|
||||
phx-click="toggle_slideover"
|
||||
title="Close controls"
|
||||
title={Gettext.gettext(AprsmeWeb.Gettext, "Close controls")}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -736,7 +744,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Search Callsign</span>
|
||||
<span>{Gettext.gettext(AprsmeWeb.Gettext, "Search Callsign")}</span>
|
||||
</label>
|
||||
<form phx-submit="search_callsign" class="flex space-x-2">
|
||||
<input
|
||||
|
|
@ -744,14 +752,14 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
name="callsign"
|
||||
value={@overlay_callsign}
|
||||
phx-change="update_callsign"
|
||||
placeholder="Enter callsign..."
|
||||
placeholder={Gettext.gettext(AprsmeWeb.Gettext, "Enter callsign...")}
|
||||
class="flex-1 px-4 py-3 border border-slate-300 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm uppercase placeholder-slate-400 transition-all duration-200 hover:border-slate-400"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
class="px-6 py-3 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-xl hover:from-indigo-700 hover:to-purple-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 transition-all duration-200 text-sm font-semibold shadow-lg hover:shadow-xl"
|
||||
>
|
||||
Search
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "Search")}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -772,19 +780,31 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Trail Duration</span>
|
||||
<span>{Gettext.gettext(AprsmeWeb.Gettext, "Trail Duration")}</span>
|
||||
</label>
|
||||
<form phx-change="update_trail_duration" class="relative">
|
||||
<select
|
||||
name="trail_duration"
|
||||
class="w-full px-4 py-3 border border-slate-300 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm bg-white text-gray-900 appearance-none transition-all duration-200 hover:border-slate-400"
|
||||
>
|
||||
<option value="1" selected={@trail_duration == "1"}>1 Hour</option>
|
||||
<option value="6" selected={@trail_duration == "6"}>6 Hours</option>
|
||||
<option value="12" selected={@trail_duration == "12"}>12 Hours</option>
|
||||
<option value="24" selected={@trail_duration == "24"}>24 Hours</option>
|
||||
<option value="48" selected={@trail_duration == "48"}>48 Hours</option>
|
||||
<option value="168" selected={@trail_duration == "168"}>1 Week</option>
|
||||
<option value="1" selected={@trail_duration == "1"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "1 Hour")}
|
||||
</option>
|
||||
<option value="6" selected={@trail_duration == "6"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "6 Hours")}
|
||||
</option>
|
||||
<option value="12" selected={@trail_duration == "12"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "12 Hours")}
|
||||
</option>
|
||||
<option value="24" selected={@trail_duration == "24"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "24 Hours")}
|
||||
</option>
|
||||
<option value="48" selected={@trail_duration == "48"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "48 Hours")}
|
||||
</option>
|
||||
<option value="168" selected={@trail_duration == "168"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "1 Week")}
|
||||
</option>
|
||||
</select>
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
|
||||
<svg
|
||||
|
|
@ -815,18 +835,28 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Historical Data</span>
|
||||
<span>{Gettext.gettext(AprsmeWeb.Gettext, "Historical Data")}</span>
|
||||
</label>
|
||||
<form phx-change="update_historical_hours" class="relative">
|
||||
<select
|
||||
name="historical_hours"
|
||||
class="w-full px-4 py-3 border border-slate-300 rounded-xl shadow-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 text-sm bg-white text-gray-900 appearance-none transition-all duration-200 hover:border-slate-400"
|
||||
>
|
||||
<option value="1" selected={@historical_hours == "1"}>1 Hour</option>
|
||||
<option value="3" selected={@historical_hours == "3"}>3 Hours</option>
|
||||
<option value="6" selected={@historical_hours == "6"}>6 Hours</option>
|
||||
<option value="12" selected={@historical_hours == "12"}>12 Hours</option>
|
||||
<option value="24" selected={@historical_hours == "24"}>24 Hours</option>
|
||||
<option value="1" selected={@historical_hours == "1"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "1 Hour")}
|
||||
</option>
|
||||
<option value="3" selected={@historical_hours == "3"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "3 Hours")}
|
||||
</option>
|
||||
<option value="6" selected={@historical_hours == "6"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "6 Hours")}
|
||||
</option>
|
||||
<option value="12" selected={@historical_hours == "12"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "12 Hours")}
|
||||
</option>
|
||||
<option value="24" selected={@historical_hours == "24"}>
|
||||
{Gettext.gettext(AprsmeWeb.Gettext, "24 Hours")}
|
||||
</option>
|
||||
</select>
|
||||
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
|
||||
<svg
|
||||
|
|
@ -857,7 +887,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="font-medium">Navigation</span>
|
||||
<span class="font-medium">{Gettext.gettext(AprsmeWeb.Gettext, "Navigation")}</span>
|
||||
</div>
|
||||
<.navigation variant={:vertical} class="text-sm" />
|
||||
</div>
|
||||
|
|
@ -873,7 +903,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
|||
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="font-medium">Last Deploy</span>
|
||||
<span class="font-medium">{Gettext.gettext(AprsmeWeb.Gettext, "Last Deploy")}</span>
|
||||
</div>
|
||||
<div class="text-xs text-slate-500">
|
||||
<div class="font-mono">{time_ago_in_words(@deployed_at)}</div>
|
||||
|
|
|
|||
|
|
@ -3,19 +3,24 @@ defmodule AprsmeWeb.MapLive.PopupComponent do
|
|||
use Phoenix.Component
|
||||
|
||||
import AprsmeWeb.TimeHelpers
|
||||
import Gettext
|
||||
|
||||
def popup(assigns) do
|
||||
~H"""
|
||||
<div class="aprs-popup" data-timestamp={@cache_buster}>
|
||||
<div class="aprs-callsign">
|
||||
<strong><.link navigate={"/#{@callsign}"}>{@callsign}</.link></strong>
|
||||
<.link navigate={"/info/#{@callsign}"} class="aprs-info-link">info</.link>
|
||||
<.link navigate={"/info/#{@callsign}"} class="aprs-info-link">
|
||||
{gettext(AprsmeWeb.Gettext, "info")}
|
||||
</.link>
|
||||
<%= if @weather_link do %>
|
||||
<.link navigate={"/weather/#{@callsign}"} class="aprs-info-link">weather charts</.link>
|
||||
<.link navigate={"/weather/#{@callsign}"} class="aprs-info-link">
|
||||
{gettext(AprsmeWeb.Gettext, "weather charts")}
|
||||
</.link>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= if @weather do %>
|
||||
<div class="aprs-comment">Weather Report</div>
|
||||
<div class="aprs-comment">{gettext(AprsmeWeb.Gettext, "Weather Report")}</div>
|
||||
<% else %>
|
||||
<%= if @comment != "" do %>
|
||||
<div class="aprs-comment">{@comment}</div>
|
||||
|
|
@ -30,11 +35,17 @@ defmodule AprsmeWeb.MapLive.PopupComponent do
|
|||
</div>
|
||||
<% end %>
|
||||
<%= if @weather do %>
|
||||
<hr style="margin-top: 4px; margin-bottom: 4px;" /> Temperature: {@temperature}°F<br />
|
||||
Humidity: {@humidity}%<br />
|
||||
Wind: {@wind_direction}° at {@wind_speed} mph, gusts to {@wind_gust} mph<br />
|
||||
Pressure: {@pressure} hPa<br /> Rain (1h): {@rain_1h} in.<br />
|
||||
Rain (24h): {@rain_24h} in.<br /> Rain (since midnight): {@rain_since_midnight} in.<br />
|
||||
<hr style="margin-top: 4px; margin-bottom: 4px;" />
|
||||
{gettext(AprsmeWeb.Gettext, "Temperature:")} {@temperature}°F<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Humidity:")} {@humidity}%<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Wind:")} {@wind_direction}° {gettext(AprsmeWeb.Gettext, "at")} {@wind_speed} mph, {gettext(
|
||||
AprsmeWeb.Gettext,
|
||||
"gusts to"
|
||||
)} {@wind_gust} mph<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Pressure:")} {@pressure} hPa<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Rain (1h):")} {@rain_1h} in.<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Rain (24h):")} {@rain_24h} in.<br />
|
||||
{gettext(AprsmeWeb.Gettext, "Rain (since midnight):")} {@rain_since_midnight} in.<br />
|
||||
<% end %>
|
||||
</div>
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule AprsmeWeb.PacketsLive.Index do
|
||||
@moduledoc false
|
||||
use AprsmeWeb, :live_view
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
alias Aprsme.EncodingUtils
|
||||
alias AprsmeWeb.Endpoint
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@
|
|||
<table class="table table-zebra">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Sender</th>
|
||||
<th>SSID</th>
|
||||
<th>Base Callsign</th>
|
||||
<th>Data Type</th>
|
||||
<th>Symbol</th>
|
||||
<th>Path</th>
|
||||
<th>Latitude</th>
|
||||
<th>Longitude</th>
|
||||
<th>Device</th>
|
||||
<th>{gettext("Sender")}</th>
|
||||
<th>{gettext("SSID")}</th>
|
||||
<th>{gettext("Base Callsign")}</th>
|
||||
<th>{gettext("Data Type")}</th>
|
||||
<th>{gettext("Symbol")}</th>
|
||||
<th>{gettext("Path")}</th>
|
||||
<th>{gettext("Latitude")}</th>
|
||||
<th>{gettext("Longitude")}</th>
|
||||
<th>{gettext("Device")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -161,8 +161,8 @@
|
|||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-lg font-medium mb-2">No packets</h3>
|
||||
<p class="opacity-70">Packets will appear here as they are received.</p>
|
||||
<h3 class="text-lg font-medium mb-2">{gettext("No packets")}</h3>
|
||||
<p class="opacity-70">{gettext("Packets will appear here as they are received.")}</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<div class="flex justify-between items-center mb-6">
|
||||
<h1 class="card-title text-3xl">APRS.me System Status</h1>
|
||||
<h1 class="card-title text-3xl">{gettext("APRS.me System Status")}</h1>
|
||||
<div class="text-sm opacity-70">
|
||||
Last updated:
|
||||
{gettext("Last updated:")}
|
||||
<span class="font-mono">{Calendar.strftime(@current_time, "%H:%M:%S UTC")}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -65,9 +65,11 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
/>
|
||||
</svg>
|
||||
<div>
|
||||
<h3 class="font-bold">APRS-IS Connection Issue</h3>
|
||||
<h3 class="font-bold">{gettext("APRS-IS Connection Issue")}</h3>
|
||||
<div class="text-xs">
|
||||
The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance.
|
||||
{gettext(
|
||||
"The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance."
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -75,50 +77,52 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
|
||||
<!-- APRS-IS Connection Status -->
|
||||
<div class="mb-8">
|
||||
<h2 class="text-xl font-semibold mb-4">APRS-IS Connection</h2>
|
||||
<h2 class="text-xl font-semibold mb-4">{gettext("APRS-IS Connection")}</h2>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Status:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">{gettext("Status:")}</span>
|
||||
<%= if @aprs_status.connected do %>
|
||||
<div class="badge badge-success gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Connected
|
||||
{gettext("Connected")}
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="badge badge-error gap-1">
|
||||
<div class="w-2 h-2 bg-current rounded-full"></div>
|
||||
Disconnected
|
||||
{gettext("Disconnected")}
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Server:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">{gettext("Server:")}</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.server}:{@aprs_status.port}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Login ID:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">{gettext("Login ID:")}</span>
|
||||
<span class="text-sm font-mono">{@aprs_status.login_id}</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Connected Since:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Connected Since:")}
|
||||
</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.connected_at do %>
|
||||
{Calendar.strftime(@aprs_status.connected_at, "%Y-%m-%d %H:%M:%S UTC")}
|
||||
<% else %>
|
||||
<span class="opacity-50">Not connected</span>
|
||||
<span class="opacity-50">{gettext("Not connected")}</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Uptime:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">{gettext("Uptime:")}</span>
|
||||
<span class={[
|
||||
"text-sm font-medium",
|
||||
if(@aprs_status.connected, do: "text-success", else: "text-error")
|
||||
|
|
@ -128,7 +132,7 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
</div>
|
||||
|
||||
<div class="flex items-center col-span-2">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Filter:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">{gettext("Filter:")}</span>
|
||||
<div class="badge badge-outline font-mono">
|
||||
{@aprs_status.filter}
|
||||
</div>
|
||||
|
|
@ -138,42 +142,52 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
<!-- Packet Statistics -->
|
||||
<div class="divider"></div>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium mb-3">Packet Statistics</h3>
|
||||
<h3 class="text-sm font-medium mb-3">{gettext("Packet Statistics")}</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Total Packets:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Total Packets:")}
|
||||
</span>
|
||||
<span class="text-sm font-mono">
|
||||
{format_number(@aprs_status.packet_stats.total_packets)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Sec:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Packets/Sec:")}
|
||||
</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Packets/Min:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Packets/Min:")}
|
||||
</span>
|
||||
<span class="text-sm font-mono">
|
||||
{@aprs_status.packet_stats.packets_per_second * 60}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Last Packet:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Last Packet:")}
|
||||
</span>
|
||||
<span class="text-sm">
|
||||
<%= if @aprs_status.packet_stats.last_packet_at do %>
|
||||
{format_time_ago(@aprs_status.packet_stats.last_packet_at)}
|
||||
<% else %>
|
||||
<span class="opacity-50">None</span>
|
||||
<span class="opacity-50">{gettext("None")}</span>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<span class="text-sm font-medium opacity-70 mr-2">Stored Packets:</span>
|
||||
<span class="text-sm font-medium opacity-70 mr-2">
|
||||
{gettext("Stored Packets:")}
|
||||
</span>
|
||||
<span class="text-sm font-mono">
|
||||
{format_number(@aprs_status.stored_packet_count)}
|
||||
</span>
|
||||
|
|
@ -184,7 +198,7 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
<!-- Health Score -->
|
||||
<div class="divider"></div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm font-medium opacity-70">Connection Health:</span>
|
||||
<span class="text-sm font-medium opacity-70">{gettext("Connection Health:")}</span>
|
||||
<div class="flex items-center">
|
||||
<div class="rating rating-sm mr-2">
|
||||
<%= for i <- 1..5 do %>
|
||||
|
|
@ -259,7 +273,7 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
Process.send_after(self(), :refresh_status, @refresh_interval)
|
||||
end
|
||||
|
||||
def format_uptime(seconds) when seconds <= 0, do: "Not connected"
|
||||
def format_uptime(seconds) when seconds <= 0, do: gettext("Not connected")
|
||||
|
||||
def format_uptime(seconds) do
|
||||
days = div(seconds, 86_400)
|
||||
|
|
@ -291,12 +305,12 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
|
||||
def get_health_description(score, connected) do
|
||||
case {score, connected} do
|
||||
{1, false} -> "Disconnected - Connection issues detected"
|
||||
{2, true} -> "Recently connected - Monitoring stability"
|
||||
{3, true} -> "Good - Connection stable for less than 1 hour"
|
||||
{4, true} -> "Very good - Connection stable for less than 1 day"
|
||||
{5, true} -> "Excellent - Long-term stable connection"
|
||||
_ -> "Unknown status"
|
||||
{1, false} -> gettext("Disconnected - Connection issues detected")
|
||||
{2, true} -> gettext("Recently connected - Monitoring stability")
|
||||
{3, true} -> gettext("Good - Connection stable for less than 1 hour")
|
||||
{4, true} -> gettext("Very good - Connection stable for less than 1 day")
|
||||
{5, true} -> gettext("Excellent - Long-term stable connection")
|
||||
_ -> gettext("Unknown status")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -304,10 +318,10 @@ defmodule AprsmeWeb.StatusLive.Index do
|
|||
diff_seconds = DateTime.diff(DateTime.utc_now(), datetime)
|
||||
|
||||
cond do
|
||||
diff_seconds < 60 -> "#{diff_seconds} seconds ago"
|
||||
diff_seconds < 3600 -> "#{div(diff_seconds, 60)} minutes ago"
|
||||
diff_seconds < 86_400 -> "#{div(diff_seconds, 3600)} hours ago"
|
||||
true -> "#{div(diff_seconds, 86_400)} days ago"
|
||||
diff_seconds < 60 -> gettext("%{count} seconds ago", count: diff_seconds)
|
||||
diff_seconds < 3600 -> gettext("%{count} minutes ago", count: div(diff_seconds, 60))
|
||||
diff_seconds < 86_400 -> gettext("%{count} hours ago", count: div(diff_seconds, 3600))
|
||||
true -> gettext("%{count} days ago", count: div(diff_seconds, 86_400))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
defmodule AprsmeWeb.WeatherLive.CallsignView do
|
||||
@moduledoc false
|
||||
use AprsmeWeb, :live_view
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
import Phoenix.LiveView, only: [push_event: 3, connected?: 1]
|
||||
|
||||
|
|
@ -45,6 +46,24 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
|
|||
end)
|
||||
|> Jason.encode!()
|
||||
|
||||
# Add chart labels for translation
|
||||
chart_labels = %{
|
||||
temp_title: gettext("Temperature & Dew Point (°F)"),
|
||||
temp_label: gettext("Temperature (°F)"),
|
||||
dew_label: gettext("Dew Point (°F)"),
|
||||
humidity_title: gettext("Humidity (%)"),
|
||||
humidity_label: gettext("Humidity (%)"),
|
||||
pressure_title: gettext("Pressure (mb)"),
|
||||
pressure_label: gettext("Pressure (mb)"),
|
||||
wind_title: gettext("Wind (mph)"),
|
||||
wind_label: gettext("Wind Speed (mph)"),
|
||||
gust_label: gettext("Wind Gust (mph)"),
|
||||
time: gettext("Time"),
|
||||
degf: gettext("°F"),
|
||||
percent: gettext("%"),
|
||||
mb: gettext("mb")
|
||||
}
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:callsign, normalized_callsign)
|
||||
|
|
@ -52,6 +71,7 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do
|
|||
|> assign(:page_title, "Weather for #{normalized_callsign}")
|
||||
|> assign(:weather_history, weather_history)
|
||||
|> assign(:weather_history_json, weather_history_json)
|
||||
|> assign(:chart_labels, chart_labels)
|
||||
|
||||
{:ok, socket}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<div class="py-4 md:flex md:items-center md:justify-between">
|
||||
<div class="flex items-center">
|
||||
<h1 class="text-xl font-bold leading-7 sm:truncate sm:text-2xl">
|
||||
Weather Station
|
||||
{gettext("Weather Station")}
|
||||
</h1>
|
||||
<div class="ml-3 flex items-center space-x-3">
|
||||
<span class="badge badge-primary">
|
||||
|
|
@ -40,13 +40,13 @@
|
|||
<div class="mt-3 flex md:ml-4 md:mt-0">
|
||||
<div class="flex space-x-2">
|
||||
<.link navigate={~p"/info/#{@callsign}"} class="btn btn-outline btn-sm">
|
||||
View info
|
||||
{gettext("View info")}
|
||||
</.link>
|
||||
<.link navigate={~p"/packets/#{@callsign}"} class="btn btn-outline btn-sm">
|
||||
View packets
|
||||
{gettext("View packets")}
|
||||
</.link>
|
||||
<.link navigate={~p"/#{@callsign}"} class="btn btn-primary btn-sm">
|
||||
View on map
|
||||
{gettext("View on map")}
|
||||
</.link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -76,12 +76,12 @@
|
|||
</svg>
|
||||
</div>
|
||||
<div class="ml-2">
|
||||
<h3 class="text-sm font-medium">Weather Details</h3>
|
||||
<h3 class="text-sm font-medium">{gettext("Weather Details")}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<dl class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Last WX report</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Last WX report")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
<%= if dt do %>
|
||||
{Calendar.strftime(dt, "%Y-%m-%d %H:%M:%S UTC")} ({AprsmeWeb.TimeHelpers.time_ago_in_words(
|
||||
|
|
@ -89,24 +89,24 @@
|
|||
)})<br />
|
||||
<%!-- <span class="text-xs text-gray-500">{Calendar.strftime(dt, "%Y-%m-%d %H:%M:%S %Z")} local time at {Map.get(@weather_packet, :region) || Map.get(@weather_packet, "region") || "Unknown location"} [?]</span> --%>
|
||||
<% else %>
|
||||
Unknown
|
||||
{gettext("Unknown")}
|
||||
<% end %>
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Temperature</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Temperature")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :temperature)}°F
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Humidity</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Humidity")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :humidity)}%
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Wind</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Wind")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {PacketUtils.get_weather_field(
|
||||
@weather_packet,
|
||||
|
|
@ -115,37 +115,37 @@
|
|||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Gusts</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Gusts")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :wind_gust)} mph
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Pressure</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Pressure")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{PacketUtils.get_weather_field(@weather_packet, :pressure)} hPa
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Rain (1h)</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (1h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{get_weather_field_zero(@weather_packet, :rain_1h)} in
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Rain (24h)</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (24h)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{get_weather_field_zero(@weather_packet, :rain_24h)} in
|
||||
</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt class="text-xs font-medium opacity-70">Rain (since midnight)</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Rain (since midnight)")}</dt>
|
||||
<dd class="mt-1 text-sm font-semibold">
|
||||
{get_weather_field_zero(@weather_packet, :rain_since_midnight)} in
|
||||
</dd>
|
||||
</div>
|
||||
<div class="col-span-2">
|
||||
<dt class="text-xs font-medium opacity-70">Raw Packet</dt>
|
||||
<dt class="text-xs font-medium opacity-70">{gettext("Raw Packet")}</dt>
|
||||
<dd class="mt-1 text-xs font-mono break-all">
|
||||
<%= if is_binary(@weather_packet.raw_packet) do %>
|
||||
{Aprsme.EncodingUtils.sanitize_string(@weather_packet.raw_packet)}
|
||||
|
|
@ -156,18 +156,20 @@
|
|||
</div>
|
||||
</dl>
|
||||
<div class="mt-2 text-xs opacity-70">
|
||||
<strong>Raw comment:</strong> {@weather_packet.comment || @weather_packet["comment"]}
|
||||
<strong>{gettext("Raw comment")}:</strong> {@weather_packet.comment ||
|
||||
@weather_packet["comment"]}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<h3 class="text-sm font-medium mb-2">Weather History Graphs</h3>
|
||||
<h3 class="text-sm font-medium mb-2">{gettext("Weather History Graphs")}</h3>
|
||||
<%= if Enum.any?(@weather_history, &(not is_nil(Map.get(&1, :temperature, nil)))) do %>
|
||||
<div
|
||||
id="temp-chart"
|
||||
phx-hook="ChartJSTempChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
@ -179,6 +181,7 @@
|
|||
id="humidity-chart"
|
||||
phx-hook="ChartJSHumidityChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
@ -190,6 +193,7 @@
|
|||
id="pressure-chart"
|
||||
phx-hook="ChartJSPressureChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
@ -201,6 +205,7 @@
|
|||
id="wind-chart"
|
||||
phx-hook="ChartJSWindChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
@ -212,6 +217,7 @@
|
|||
id="rain-chart"
|
||||
phx-hook="ChartJSRainChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
@ -223,6 +229,7 @@
|
|||
id="luminosity-chart"
|
||||
phx-hook="ChartJSLuminosityChart"
|
||||
data-weather-history={@weather_history_json}
|
||||
data-chart-labels={Jason.encode!(@chart_labels)}
|
||||
class="bg-base-200 rounded-lg p-4 mb-4"
|
||||
style="height:250px;"
|
||||
>
|
||||
|
|
|
|||
53
lib/aprsme_web/plugs/set_locale.ex
Normal file
53
lib/aprsme_web/plugs/set_locale.ex
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
defmodule AprsmeWeb.Plugs.SetLocale do
|
||||
@moduledoc """
|
||||
A plug that sets the locale based on the Accept-Language header.
|
||||
Falls back to English if the requested locale is not available.
|
||||
"""
|
||||
import Plug.Conn
|
||||
|
||||
@supported_locales ["en", "es"]
|
||||
|
||||
def init(opts), do: opts
|
||||
|
||||
def call(conn, _opts) do
|
||||
locale = get_locale_from_header(conn) || "en"
|
||||
IO.puts("DEBUG: SetLocale - Final locale: #{locale}")
|
||||
Gettext.put_locale(AprsmeWeb.Gettext, locale)
|
||||
# Store locale in session for LiveView to access
|
||||
conn = put_session(conn, :locale, locale)
|
||||
conn
|
||||
end
|
||||
|
||||
defp get_locale_from_header(conn) do
|
||||
case get_req_header(conn, "accept-language") do
|
||||
[accept_language | _] ->
|
||||
IO.puts("DEBUG: SetLocale - Accept-Language header: #{inspect(accept_language)}")
|
||||
parse_accept_language(accept_language)
|
||||
|
||||
_ ->
|
||||
IO.puts("DEBUG: SetLocale - No Accept-Language header found")
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_accept_language(accept_language) do
|
||||
accept_language
|
||||
|> String.split(",")
|
||||
|> Enum.map(&parse_language_tag/1)
|
||||
|> Enum.find(&supported_locale?/1)
|
||||
end
|
||||
|
||||
defp parse_language_tag(tag) do
|
||||
tag
|
||||
|> String.trim()
|
||||
|> String.split(";")
|
||||
|> List.first()
|
||||
|> String.split("-")
|
||||
|> List.first()
|
||||
|> String.downcase()
|
||||
end
|
||||
|
||||
defp supported_locale?(locale) do
|
||||
locale in @supported_locales
|
||||
end
|
||||
end
|
||||
|
|
@ -12,6 +12,7 @@ defmodule AprsmeWeb.Router do
|
|||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :fetch_current_user
|
||||
plug AprsmeWeb.Plugs.SetLocale
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
|
@ -30,7 +31,7 @@ defmodule AprsmeWeb.Router do
|
|||
|
||||
live_dashboard "/dashboard", metrics: AprsmeWeb.Telemetry
|
||||
|
||||
live_session :regular_pages do
|
||||
live_session :regular_pages, on_mount: [{AprsmeWeb.LocaleHook, :set_locale}] do
|
||||
live "/status", StatusLive.Index, :index
|
||||
live "/packets", PacketsLive.Index, :index
|
||||
live "/packets/:callsign", PacketsLive.CallsignView, :index
|
||||
|
|
@ -73,7 +74,7 @@ defmodule AprsmeWeb.Router do
|
|||
pipe_through [:browser, :redirect_if_user_is_authenticated]
|
||||
|
||||
live_session :redirect_if_user_is_authenticated,
|
||||
on_mount: [{AprsmeWeb.UserAuth, :redirect_if_user_is_authenticated}] do
|
||||
on_mount: [{AprsmeWeb.UserAuth, :redirect_if_user_is_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
|
||||
live "/users/register", UserRegistrationLive, :new
|
||||
live "/users/log_in", UserLoginLive, :new
|
||||
live "/users/reset_password", UserForgotPasswordLive, :new
|
||||
|
|
@ -87,7 +88,7 @@ defmodule AprsmeWeb.Router do
|
|||
pipe_through [:browser, :require_authenticated_user]
|
||||
|
||||
live_session :require_authenticated_user,
|
||||
on_mount: [{AprsmeWeb.UserAuth, :ensure_authenticated}] do
|
||||
on_mount: [{AprsmeWeb.UserAuth, :ensure_authenticated}, {AprsmeWeb.LocaleHook, :set_locale}] do
|
||||
live "/users/settings", UserSettingsLive, :edit
|
||||
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
|
||||
end
|
||||
|
|
@ -99,7 +100,7 @@ defmodule AprsmeWeb.Router do
|
|||
delete "/users/log_out", UserSessionController, :delete
|
||||
|
||||
live_session :current_user,
|
||||
on_mount: [{AprsmeWeb.UserAuth, :mount_current_user}] do
|
||||
on_mount: [{AprsmeWeb.UserAuth, :mount_current_user}, {AprsmeWeb.LocaleHook, :set_locale}] do
|
||||
live "/users/confirm/:token", UserConfirmationLive, :edit
|
||||
live "/users/confirm", UserConfirmationInstructionsLive, :new
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ defmodule AprsmeWeb.TimeHelpers do
|
|||
@moduledoc """
|
||||
Shared helpers for formatting time and dates in the web layer.
|
||||
"""
|
||||
use Gettext, backend: AprsmeWeb.Gettext
|
||||
|
||||
@doc """
|
||||
Returns a human-readable string for how long ago the given DateTime was.
|
||||
|
|
@ -10,22 +11,22 @@ defmodule AprsmeWeb.TimeHelpers do
|
|||
now = DateTime.utc_now()
|
||||
diff_seconds = DateTime.diff(now, datetime, :second)
|
||||
|
||||
format_time_diff(diff_seconds) <> " ago"
|
||||
format_time_diff(diff_seconds) <> " " <> gettext("ago")
|
||||
end
|
||||
|
||||
defp format_time_diff(seconds) when seconds < 60, do: "less than a minute"
|
||||
defp format_time_diff(seconds) when seconds < 120, do: "1 minute"
|
||||
defp format_time_diff(seconds) when seconds < 3600, do: "#{div(seconds, 60)} minutes"
|
||||
defp format_time_diff(seconds) when seconds < 7200, do: "1 hour"
|
||||
defp format_time_diff(seconds) when seconds < 86_400, do: "#{div(seconds, 3600)} hours"
|
||||
defp format_time_diff(seconds) when seconds < 172_800, do: "1 day"
|
||||
defp format_time_diff(seconds) when seconds < 2_592_000, do: "#{div(seconds, 86_400)} days"
|
||||
defp format_time_diff(seconds) when seconds < 5_184_000, do: "1 month"
|
||||
defp format_time_diff(seconds) when seconds < 60, do: gettext("less than a minute")
|
||||
defp format_time_diff(seconds) when seconds < 120, do: gettext("1 minute")
|
||||
defp format_time_diff(seconds) when seconds < 3600, do: gettext("%{count} minutes", count: div(seconds, 60))
|
||||
defp format_time_diff(seconds) when seconds < 7200, do: gettext("1 hour")
|
||||
defp format_time_diff(seconds) when seconds < 86_400, do: gettext("%{count} hours", count: div(seconds, 3600))
|
||||
defp format_time_diff(seconds) when seconds < 172_800, do: gettext("1 day")
|
||||
defp format_time_diff(seconds) when seconds < 2_592_000, do: gettext("%{count} days", count: div(seconds, 86_400))
|
||||
defp format_time_diff(seconds) when seconds < 5_184_000, do: gettext("1 month")
|
||||
|
||||
defp format_time_diff(seconds) when seconds < 31_536_000, do: "#{div(seconds, 2_592_000)} months"
|
||||
defp format_time_diff(seconds) when seconds < 31_536_000, do: gettext("%{count} months", count: div(seconds, 2_592_000))
|
||||
|
||||
defp format_time_diff(seconds) when seconds < 63_072_000, do: "1 year"
|
||||
defp format_time_diff(seconds), do: "#{div(seconds, 31_536_000)} years"
|
||||
defp format_time_diff(seconds) when seconds < 63_072_000, do: gettext("1 year")
|
||||
defp format_time_diff(seconds), do: gettext("%{count} years", count: div(seconds, 31_536_000))
|
||||
|
||||
@doc """
|
||||
Converts various timestamp formats into a standard DateTime object.
|
||||
|
|
|
|||
815
priv/gettext/default.pot
Normal file
815
priv/gettext/default.pot
Normal file
|
|
@ -0,0 +1,815 @@
|
|||
## This file is a PO Template file.
|
||||
##
|
||||
## "msgid"s here are often extracted from source code.
|
||||
## Add new messages manually only if they're dynamic
|
||||
## messages that can't be statically extracted.
|
||||
##
|
||||
## Run "mix gettext.extract" to bring this file up to
|
||||
## date. Leave "msgstr"s empty as changing them here has no
|
||||
## effect: edit them in PO (.po) files instead.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:570
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:117
|
||||
#: lib/aprsme_web/components/core_components.ex:202
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:310
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:309
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} months"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} seconds ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:29
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} years"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:477
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Digipeater)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:481
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Station)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:485
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Unknown)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 hour"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 minute"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 year"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection Issue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS.me System Status"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Access forbidden"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:85
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All packets are parsing successfully!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "An error occurred: %{reason}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempted At"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-refreshes every 5 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:71
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Bad request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:110
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected Since:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:187
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connection Health:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected - Connection issues detected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Excellent - Long-term stable connection"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:131
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Filter:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forbidden"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Good - Connection stable for less than 1 hour"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Internal server error"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Packet:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last updated:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Login ID:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No bad packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No error message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:170
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:115
|
||||
#: lib/aprsme_web/live/status_live/index.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not connected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:141
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packet Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Min:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Sec:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:305
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY (Relay digipeater)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-1 (Relay digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-2 (Relay digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:58
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:227
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:148
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw Packet"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Recently connected - Monitoring stability"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:57
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request timeout"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:68
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:98
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Server:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Status:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:176
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stored Packets:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:470
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP (Internet gateway)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:472
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP gateway (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP* (Internet gateway, no forward)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:292
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE1-1 (Trace digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:293
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE2-1 (Trace digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE3-1 (Trace digipeater, 3 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE4-1 (Trace digipeater, 4 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE5-1 (Trace digipeater, 5 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE6-1 (Trace digipeater, 6 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE7-1 (Trace digipeater, 7 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:144
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Total Packets:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:69
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized access"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme/device_identification.ex:56
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:50
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:143
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:209
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown status"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unprocessable entity"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Updating..."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uptime:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/changeset_json.ex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Validation failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Very good - Connection stable for less than 1 day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:286
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:277
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-1 (Wide area digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:284
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-2 (Wide area digipeater, 1 hop, 2nd attempt)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-1 (Wide area digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:285
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-2 (Wide area digipeater, 2 hops, 2nd attempt)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:279
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE3-1 (Wide area digipeater, 3 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:280
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE4-1 (Wide area digipeater, 4 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:281
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE5-1 (Wide area digipeater, 5 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:282
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE6-1 (Wide area digipeater, 6 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:283
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE7-1 (WIDE area digipeater, 7 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "less than a minute"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Gusts"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:103
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Humidity"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last WX report"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:124
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Pressure"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (1h)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:136
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (24h)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:142
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (since midnight)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:159
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw comment"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View info"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:49
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View on map"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:67
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Details"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather History Graphs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Station"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS Station"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Altitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Base Callsign"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Built with Modern Technologies"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:270
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:388
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Callsign"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:155
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Course"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decoded Path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:194
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:189
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:391
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Course"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:273
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Direction"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Explore the Map"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Grid Square"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Join Our Community"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:276
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:394
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Heard"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:133
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Position"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Latitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:15
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Longitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:469
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No data available"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:164
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No recent packet data available for this callsign."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other SSIDs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets will appear here as they are received."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:215
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Position Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SSID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sender"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:380
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stations Near Current Position"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Symbol"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Under heavy construction"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:71
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather charts"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Dew Point (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:54
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Humidity (%)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:56
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:57
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Pressure (mb)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:51
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature & Dew Point (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Gust (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:59
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Speed (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "mb"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "°F"
|
||||
msgstr ""
|
||||
815
priv/gettext/en/LC_MESSAGES/default.po
Normal file
815
priv/gettext/en/LC_MESSAGES/default.po
Normal file
|
|
@ -0,0 +1,815 @@
|
|||
## "msgid"s in this file come from POT (.pot) files.
|
||||
###
|
||||
### Do not add, change, or remove "msgid"s manually here as
|
||||
### they're tied to the ones in the corresponding POT file
|
||||
### (with the same domain).
|
||||
###
|
||||
### Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
### to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: en\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:570
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Actions"
|
||||
msgstr "Actions"
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:117
|
||||
#: lib/aprsme_web/components/core_components.ex:202
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr "close"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days"
|
||||
msgstr "%{count} days"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:310
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days ago"
|
||||
msgstr "%{count} days ago"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours"
|
||||
msgstr "%{count} hours"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:309
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours ago"
|
||||
msgstr "%{count} hours ago"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes"
|
||||
msgstr "%{count} minutes"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes ago"
|
||||
msgstr "%{count} minutes ago"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} months"
|
||||
msgstr "%{count} months"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} seconds ago"
|
||||
msgstr "%{count} seconds ago"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:29
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} years"
|
||||
msgstr "%{count} years"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:477
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Digipeater)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:481
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Station)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:485
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Unknown)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 hour"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 minute"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 month"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 year"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection Issue"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS.me System Status"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Access forbidden"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:85
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All packets are parsing successfully!"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "An error occurred: %{reason}"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempted At"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-refreshes every 5 seconds"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:71
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Bad request"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:110
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected Since:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:187
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connection Health:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected - Connection issues detected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Excellent - Long-term stable connection"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:131
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Filter:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forbidden"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Good - Connection stable for less than 1 hour"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Internal server error"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Packet:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last updated:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Login ID:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No bad packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No error message"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:170
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "None"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:115
|
||||
#: lib/aprsme_web/live/status_live/index.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not connected"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:141
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packet Statistics"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Min:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Sec:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:305
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY (Relay digipeater)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-1 (Relay digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-2 (Relay digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:58
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:227
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:148
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw Packet"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Recently connected - Monitoring stability"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:57
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request timeout"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:68
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource not found"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:98
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Server:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Status:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:176
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stored Packets:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:470
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP (Internet gateway)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:472
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP gateway (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP* (Internet gateway, no forward)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:292
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE1-1 (Trace digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:293
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE2-1 (Trace digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE3-1 (Trace digipeater, 3 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE4-1 (Trace digipeater, 4 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE5-1 (Trace digipeater, 5 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE6-1 (Trace digipeater, 6 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE7-1 (Trace digipeater, 7 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:144
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Total Packets:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:69
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized access"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme/device_identification.ex:56
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:50
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:143
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:209
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown status"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unprocessable entity"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Updating..."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uptime:"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/changeset_json.ex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Validation failed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Very good - Connection stable for less than 1 day"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:286
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE digipeater (%{element})"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:277
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-1 (Wide area digipeater, 1 hop)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:284
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-2 (Wide area digipeater, 1 hop, 2nd attempt)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-1 (Wide area digipeater, 2 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:285
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-2 (Wide area digipeater, 2 hops, 2nd attempt)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:279
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE3-1 (Wide area digipeater, 3 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:280
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE4-1 (Wide area digipeater, 4 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:281
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE5-1 (Wide area digipeater, 5 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:282
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE6-1 (Wide area digipeater, 6 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:283
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE7-1 (WIDE area digipeater, 7 hops)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "less than a minute"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Gusts"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:103
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Humidity"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last WX report"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:124
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Pressure"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (1h)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:136
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (24h)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:142
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (since midnight)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:159
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw comment"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View info"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:49
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View on map"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:67
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Details"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather History Graphs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Station"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS Station"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Altitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Base Callsign"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Built with Modern Technologies"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:270
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:388
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Callsign"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:155
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Course"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data Type"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decoded Path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:194
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:189
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:391
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Course"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:273
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Direction"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Explore the Map"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Grid Square"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Join Our Community"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:276
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:394
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Heard"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:133
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Position"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Latitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Location"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:15
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Longitude"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:469
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No data available"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:164
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No packets"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No recent packet data available for this callsign."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other SSIDs"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets will appear here as they are received."
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:215
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Path"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Position Information"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SSID"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sender"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Speed"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:380
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stations Near Current Position"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Symbol"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Under heavy construction"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:71
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Weather charts"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Dew Point (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:54
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Humidity (%)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:56
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:57
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Pressure (mb)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:51
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature & Dew Point (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:52
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Temperature (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Time"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Gust (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:59
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Speed (mph)"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ago"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "mb"
|
||||
msgstr ""
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "°F"
|
||||
msgstr ""
|
||||
|
|
@ -12,15 +12,15 @@ msgstr ""
|
|||
|
||||
## From Ecto.Changeset.cast/4
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
msgstr "can't be blank"
|
||||
|
||||
## From Ecto.Changeset.unique_constraint/3
|
||||
msgid "has already been taken"
|
||||
msgstr ""
|
||||
msgstr "has already been taken"
|
||||
|
||||
## From Ecto.Changeset.put_change/3
|
||||
msgid "is invalid"
|
||||
msgstr ""
|
||||
msgstr "is invalid"
|
||||
|
||||
## From Ecto.Changeset.validate_acceptance/3
|
||||
msgid "must be accepted"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
## Run `mix gettext.extract` to bring this file up to
|
||||
## date. Leave `msgstr`s empty as changing them here has no
|
||||
## effect: edit them in PO (`.po`) files instead.
|
||||
|
||||
## From Ecto.Changeset.cast/4
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
|
|
|
|||
905
priv/gettext/es/LC_MESSAGES/default.po
Normal file
905
priv/gettext/es/LC_MESSAGES/default.po
Normal file
|
|
@ -0,0 +1,905 @@
|
|||
## "msgid"s in this file come from POT (.pot) files.
|
||||
###
|
||||
### Do not add, change, or remove "msgid"s manually here as
|
||||
### they're tied to the ones in the corresponding POT file
|
||||
### (with the same domain).
|
||||
###
|
||||
### Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
### to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:570
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Actions"
|
||||
msgstr "Acciones"
|
||||
|
||||
#: lib/aprsme_web/components/core_components.ex:117
|
||||
#: lib/aprsme_web/components/core_components.ex:202
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "close"
|
||||
msgstr "cerrar"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:23
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days"
|
||||
msgstr "%{count} días"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:310
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} days ago"
|
||||
msgstr "hace %{count} días"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours"
|
||||
msgstr "%{count} horas"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:309
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} hours ago"
|
||||
msgstr "hace %{count} horas"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes"
|
||||
msgstr "%{count} minutos"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} minutes ago"
|
||||
msgstr "hace %{count} minutos"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:26
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} months"
|
||||
msgstr "%{count} meses"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} seconds ago"
|
||||
msgstr "hace %{count} segundos"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:29
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{count} years"
|
||||
msgstr "%{count} años"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:477
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Digipeater)"
|
||||
msgstr "%{element} (Digipeater)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:481
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Station)"
|
||||
msgstr "%{element} (Estación)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:485
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%{element} (Unknown)"
|
||||
msgstr "%{element} (Desconocido)"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:22
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 day"
|
||||
msgstr "1 día"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:20
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 hour"
|
||||
msgstr "1 hora"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:18
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 minute"
|
||||
msgstr "1 minuto"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:24
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 month"
|
||||
msgstr "1 mes"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 year"
|
||||
msgstr "1 año"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:78
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection"
|
||||
msgstr "Conexión APRS-IS"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:68
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS-IS Connection Issue"
|
||||
msgstr "Problema de Conexión APRS-IS"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:44
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS.me System Status"
|
||||
msgstr "Estado del Sistema APRS.me"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Access forbidden"
|
||||
msgstr "Acceso prohibido"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:85
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "All packets are parsing successfully!"
|
||||
msgstr "¡Todos los paquetes se están analizando correctamente!"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:72
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "An error occurred: %{reason}"
|
||||
msgstr "Ocurrió un error: %{reason}"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:40
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Attempted At"
|
||||
msgstr "Intentado En"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Auto-refreshes every 5 seconds"
|
||||
msgstr "Se actualiza automáticamente cada 5 segundos"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:71
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Bad request"
|
||||
msgstr "Solicitud incorrecta"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:87
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected"
|
||||
msgstr "Conectado"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:110
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connected Since:"
|
||||
msgstr "Conectado Desde:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:187
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Connection Health:"
|
||||
msgstr "Estado de la Conexión:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected"
|
||||
msgstr "Desconectado"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Disconnected - Connection issues detected"
|
||||
msgstr "Desconectado - Problemas de conexión detectados"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Message"
|
||||
msgstr "Mensaje de Error"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:48
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Error Type"
|
||||
msgstr "Tipo de Error"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Excellent - Long-term stable connection"
|
||||
msgstr "Excelente - Conexión estable a largo plazo"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:131
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Filter:"
|
||||
msgstr "Filtro:"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Forbidden"
|
||||
msgstr "Prohibido"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Good - Connection stable for less than 1 hour"
|
||||
msgstr "Bueno - Conexión estable por menos de 1 hora"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:28
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Internal server error"
|
||||
msgstr "Error interno del servidor"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Packet:"
|
||||
msgstr "Último Paquete:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last updated:"
|
||||
msgstr "Última actualización:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:105
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Login ID:"
|
||||
msgstr "ID de Inicio de Sesión:"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No bad packets"
|
||||
msgstr "No hay paquetes malos"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No error message"
|
||||
msgstr "Sin mensaje de error"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:170
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "None"
|
||||
msgstr "Ninguno"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:115
|
||||
#: lib/aprsme_web/live/status_live/index.ex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Not connected"
|
||||
msgstr "No conectado"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:141
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packet Statistics"
|
||||
msgstr "Estadísticas de Paquetes"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:158
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Min:"
|
||||
msgstr "Paquetes/Min:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:151
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets/Sec:"
|
||||
msgstr "Paquetes/Seg:"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:305
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY (Relay digipeater)"
|
||||
msgstr "RELAY (Digipeater de retransmisión)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:308
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY digipeater (%{element})"
|
||||
msgstr "Digipeater RELAY (%{element})"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:306
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-1 (Relay digipeater, 1 hop)"
|
||||
msgstr "RELAY-1 (Digipeater de retransmisión, 1 salto)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:307
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "RELAY-2 (Relay digipeater, 2 hops)"
|
||||
msgstr "RELAY-2 (Digipeater de retransmisión, 2 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:58
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:227
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:148
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw Packet"
|
||||
msgstr "Paquete Sin Procesar"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Recently connected - Monitoring stability"
|
||||
msgstr "Recientemente conectado - Monitoreando estabilidad"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:57
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:73
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Request timeout"
|
||||
msgstr "Tiempo de espera de la solicitud"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:68
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:19
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Resource not found"
|
||||
msgstr "Recurso no encontrado"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:98
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Server:"
|
||||
msgstr "Servidor:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:83
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Status:"
|
||||
msgstr "Estado:"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:176
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stored Packets:"
|
||||
msgstr "Paquetes Almacenados:"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:470
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP (Internet gateway)"
|
||||
msgstr "TCPIP (Puerta de enlace de Internet)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:472
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP gateway (%{element})"
|
||||
msgstr "Puerta de enlace TCPIP (%{element})"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TCPIP* (Internet gateway, no forward)"
|
||||
msgstr "TCPIP* (Puerta de enlace de Internet, sin reenvío)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE digipeater (%{element})"
|
||||
msgstr "Digipeater TRACE (%{element})"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:292
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE1-1 (Trace digipeater, 1 hop)"
|
||||
msgstr "TRACE1-1 (Digipeater de rastreo, 1 salto)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:293
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE2-1 (Trace digipeater, 2 hops)"
|
||||
msgstr "TRACE2-1 (Digipeater de rastreo, 2 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:294
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE3-1 (Trace digipeater, 3 hops)"
|
||||
msgstr "TRACE3-1 (Digipeater de rastreo, 3 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:295
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE4-1 (Trace digipeater, 4 hops)"
|
||||
msgstr "TRACE4-1 (Digipeater de rastreo, 4 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:296
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE5-1 (Trace digipeater, 5 hops)"
|
||||
msgstr "TRACE5-1 (Digipeater de rastreo, 5 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE6-1 (Trace digipeater, 6 hops)"
|
||||
msgstr "TRACE6-1 (Digipeater de rastreo, 6 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:298
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "TRACE7-1 (Trace digipeater, 7 hops)"
|
||||
msgstr "TRACE7-1 (Digipeater de rastreo, 7 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:70
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "The system is currently disconnected from the APRS-IS network. This may be due to network issues or server maintenance."
|
||||
msgstr "El sistema está actualmente desconectado de la red APRS-IS. Esto puede deberse a problemas de red o mantenimiento del servidor."
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:144
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Total Packets:"
|
||||
msgstr "Total de Paquetes:"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized"
|
||||
msgstr "No autorizado"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/fallback_controller.ex:69
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unauthorized access"
|
||||
msgstr "Acceso no autorizado"
|
||||
|
||||
#: lib/aprsme/device_identification.ex:56
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:50
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:143
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:209
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:92
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown"
|
||||
msgstr "Desconocido"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:299
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unknown status"
|
||||
msgstr "Estado desconocido"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/error_json.ex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Unprocessable entity"
|
||||
msgstr "Entidad no procesable"
|
||||
|
||||
#: lib/aprsme_web/live/bad_packets_live/index.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Updating..."
|
||||
msgstr "Actualizando..."
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Uptime:"
|
||||
msgstr "Tiempo de Actividad:"
|
||||
|
||||
#: lib/aprsme_web/controllers/api/v1/json/changeset_json.ex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Validation failed"
|
||||
msgstr "Validación fallida"
|
||||
|
||||
#: lib/aprsme_web/live/status_live/index.ex:297
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Very good - Connection stable for less than 1 day"
|
||||
msgstr "Muy bueno - Conexión estable por menos de 1 día"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:286
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE digipeater (%{element})"
|
||||
msgstr "Digipeater WIDE (%{element})"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:277
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-1 (Wide area digipeater, 1 hop)"
|
||||
msgstr "WIDE1-1 (Digipeater de área amplia, 1 salto)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:284
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE1-2 (Wide area digipeater, 1 hop, 2nd attempt)"
|
||||
msgstr "WIDE1-2 (Digipeater de área amplia, 1 salto, 2º intento)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:278
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-1 (Wide area digipeater, 2 hops)"
|
||||
msgstr "WIDE2-1 (Digipeater de área amplia, 2 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:285
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE2-2 (Wide area digipeater, 2 hops, 2nd attempt)"
|
||||
msgstr "WIDE2-2 (Digipeater de área amplia, 2 saltos, 2º intento)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:279
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE3-1 (Wide area digipeater, 3 hops)"
|
||||
msgstr "WIDE3-1 (Digipeater de área amplia, 3 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:280
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE4-1 (Wide area digipeater, 4 hops)"
|
||||
msgstr "WIDE4-1 (Digipeater de área amplia, 4 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:281
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE5-1 (Wide area digipeater, 5 hops)"
|
||||
msgstr "WIDE5-1 (Digipeater de área amplia, 5 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:282
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE6-1 (Wide area digipeater, 6 hops)"
|
||||
msgstr "WIDE6-1 (Digipeater de área amplia, 6 saltos)"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.ex:283
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "WIDE7-1 (WIDE area digipeater, 7 hops)"
|
||||
msgstr "WIDE7-1 (Digipeater de área amplia, 7 saltos)"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:17
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "less than a minute"
|
||||
msgstr "menos de un minuto"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Gusts"
|
||||
msgstr "Ráfagas"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:103
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Humidity"
|
||||
msgstr "Humedad"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:84
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last WX report"
|
||||
msgstr "Último reporte WX"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:124
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Pressure"
|
||||
msgstr "Presión"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:130
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (1h)"
|
||||
msgstr "Lluvia (1h)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:136
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (24h)"
|
||||
msgstr "Lluvia (24h)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:142
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Rain (since midnight)"
|
||||
msgstr "Lluvia (desde medianoche)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:159
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Raw comment"
|
||||
msgstr "Comentario crudo"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:97
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature"
|
||||
msgstr "Temperatura"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:43
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View info"
|
||||
msgstr "Ver información"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:49
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View on map"
|
||||
msgstr "Ver en mapa"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:67
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:46
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "View packets"
|
||||
msgstr "Ver paquetes"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:79
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Details"
|
||||
msgstr "Detalles del Clima"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather History Graphs"
|
||||
msgstr "Gráficos del Historial del Clima"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Weather Station"
|
||||
msgstr "Estación Meteorológica"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind"
|
||||
msgstr "Viento"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:27
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "APRS Station"
|
||||
msgstr "Estación APRS"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:149
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Altitude"
|
||||
msgstr "Altitud"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:10
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Base Callsign"
|
||||
msgstr "Indicativo Base"
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Built with Modern Technologies"
|
||||
msgstr "Construido con Tecnologías Modernas"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:270
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:388
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Callsign"
|
||||
msgstr "Indicativo"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:155
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Course"
|
||||
msgstr "Rumbo"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:11
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Data Type"
|
||||
msgstr "Tipo de Datos"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:220
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Decoded Path"
|
||||
msgstr "Ruta Decodificada"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:194
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:16
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device"
|
||||
msgstr "Dispositivo"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:189
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Device Information"
|
||||
msgstr "Información del Dispositivo"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:391
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Course"
|
||||
msgstr "Distancia y Rumbo"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:273
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Distance & Direction"
|
||||
msgstr "Distancia y Dirección"
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:35
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Explore the Map"
|
||||
msgstr "Explorar el Mapa"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:121
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Grid Square"
|
||||
msgstr "Cuadrícula"
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:21
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Join Our Community"
|
||||
msgstr "Únete a Nuestra Comunidad"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:276
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:394
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Heard"
|
||||
msgstr "Último Escuchado"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:133
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Position"
|
||||
msgstr "Última Posición"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Latitude"
|
||||
msgstr "Latitud"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:114
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Location"
|
||||
msgstr "Ubicación"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:15
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Longitude"
|
||||
msgstr "Longitud"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:469
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No data available"
|
||||
msgstr "No hay datos disponibles"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:164
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "No packets"
|
||||
msgstr "No hay paquetes"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:471
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "No recent packet data available for this callsign."
|
||||
msgstr "No hay datos de paquetes recientes disponibles para este indicativo."
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:262
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Other SSIDs"
|
||||
msgstr "Otros SSIDs"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:165
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Packets will appear here as they are received."
|
||||
msgstr "Los paquetes aparecerán aquí a medida que sean recibidos."
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:215
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:13
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Path"
|
||||
msgstr "Ruta"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:109
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Position Information"
|
||||
msgstr "Información de Posición"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:9
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "SSID"
|
||||
msgstr "SSID"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:8
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Sender"
|
||||
msgstr "Remitente"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:161
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Speed"
|
||||
msgstr "Velocidad"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:380
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Stations Near Current Position"
|
||||
msgstr "Estaciones Cerca de la Posición Actual"
|
||||
|
||||
#: lib/aprsme_web/live/packets_live/index.html.heex:12
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Symbol"
|
||||
msgstr "Símbolo"
|
||||
|
||||
#: lib/aprsme_web/live/about_live.html.heex:4
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Under heavy construction"
|
||||
msgstr "En construcción intensiva"
|
||||
|
||||
#: lib/aprsme_web/live/info_live/show.html.heex:71
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
msgid "Weather charts"
|
||||
msgstr "Gráficos del clima"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:63
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "%"
|
||||
msgstr "%"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:53
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Dew Point (°F)"
|
||||
msgstr "Punto de Rocío (°F)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:54
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:55
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Humidity (%)"
|
||||
msgstr "Humedad (%)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:56
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:57
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Pressure (mb)"
|
||||
msgstr "Presión (mb)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:51
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature & Dew Point (°F)"
|
||||
msgstr "Temperatura y Punto de Rocío (°F)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:52
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Temperature (°F)"
|
||||
msgstr "Temperatura (°F)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:61
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Time"
|
||||
msgstr "Tiempo"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:58
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind (mph)"
|
||||
msgstr "Viento (mph)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:60
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Gust (mph)"
|
||||
msgstr "Ráfaga de Viento (mph)"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:59
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Wind Speed (mph)"
|
||||
msgstr "Velocidad del Viento (mph)"
|
||||
|
||||
#: lib/aprsme_web/time_helpers.ex:14
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "ago"
|
||||
msgstr "hace"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:64
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "mb"
|
||||
msgstr "mb"
|
||||
|
||||
#: lib/aprsme_web/live/weather_live/callsign_view.ex:62
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "°F"
|
||||
msgstr "°F"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:611
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Find my location"
|
||||
msgstr "Encontrar mi ubicación"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:633
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Hide controls"
|
||||
msgstr "Ocultar controles"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:633
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Show controls"
|
||||
msgstr "Mostrar controles"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:670
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Close controls"
|
||||
msgstr "Cerrar controles"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:690
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search Callsign"
|
||||
msgstr "Buscar Indicativo"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:695
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Enter callsign..."
|
||||
msgstr "Ingrese indicativo..."
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:700
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Search"
|
||||
msgstr "Buscar"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:710
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Trail Duration"
|
||||
msgstr "Duración del Rastro"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:715
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 Hour"
|
||||
msgstr "1 Hora"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:716
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "6 Hours"
|
||||
msgstr "6 Horas"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:717
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "12 Hours"
|
||||
msgstr "12 Horas"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:718
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "24 Hours"
|
||||
msgstr "24 Horas"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:719
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "48 Hours"
|
||||
msgstr "48 Horas"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:720
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "1 Week"
|
||||
msgstr "1 Semana"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:730
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Historical Data"
|
||||
msgstr "Datos Históricos"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:735
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "3 Hours"
|
||||
msgstr "3 Horas"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:750
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Navigation"
|
||||
msgstr "Navegación"
|
||||
|
||||
#: lib/aprsme_web/live/map_live/index.ex:760
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Last Deploy"
|
||||
msgstr "Último Despliegue"
|
||||
102
priv/gettext/es/LC_MESSAGES/errors.po
Normal file
102
priv/gettext/es/LC_MESSAGES/errors.po
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
## "msgid"s in this file come from POT (.pot) files.
|
||||
###
|
||||
### Do not add, change, or remove "msgid"s manually here as
|
||||
### they're tied to the ones in the corresponding POT file
|
||||
### (with the same domain).
|
||||
###
|
||||
### Use "mix gettext.extract --merge" or "mix gettext.merge"
|
||||
### to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
msgid "can't be blank"
|
||||
msgstr "no puede estar en blanco"
|
||||
|
||||
msgid "has already been taken"
|
||||
msgstr "ya ha sido tomado"
|
||||
|
||||
msgid "is invalid"
|
||||
msgstr "no es válido"
|
||||
|
||||
msgid "must be accepted"
|
||||
msgstr "debe ser aceptado"
|
||||
|
||||
msgid "has invalid format"
|
||||
msgstr "tiene formato inválido"
|
||||
|
||||
msgid "has an invalid entry"
|
||||
msgstr "tiene una entrada inválida"
|
||||
|
||||
msgid "is reserved"
|
||||
msgstr "está reservado"
|
||||
|
||||
msgid "does not match confirmation"
|
||||
msgstr "no coincide con la confirmación"
|
||||
|
||||
msgid "is still associated with this entry"
|
||||
msgstr "todavía está asociado con esta entrada"
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr "todavía están asociados con esta entrada"
|
||||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
msgstr[0] "debe tener %{count} elemento"
|
||||
msgstr[1] "debe tener %{count} elementos"
|
||||
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
msgstr[0] "debe ser %{count} carácter"
|
||||
msgstr[1] "debe ser %{count} caracteres"
|
||||
|
||||
msgid "should be %{count} byte(s)"
|
||||
msgid_plural "should be %{count} byte(s)"
|
||||
msgstr[0] "debe ser %{count} byte"
|
||||
msgstr[1] "debe ser %{count} bytes"
|
||||
|
||||
msgid "should have at least %{count} item(s)"
|
||||
msgid_plural "should have at least %{count} item(s)"
|
||||
msgstr[0] "debe tener al menos %{count} elemento"
|
||||
msgstr[1] "debe tener al menos %{count} elementos"
|
||||
|
||||
msgid "should be at least %{count} character(s)"
|
||||
msgid_plural "should be at least %{count} character(s)"
|
||||
msgstr[0] "debe ser al menos %{count} carácter"
|
||||
msgstr[1] "debe ser al menos %{count} caracteres"
|
||||
|
||||
msgid "should be at least %{count} byte(s)"
|
||||
msgid_plural "should be at least %{count} byte(s)"
|
||||
msgstr[0] "debe ser al menos %{count} byte"
|
||||
msgstr[1] "debe ser al menos %{count} bytes"
|
||||
|
||||
msgid "should have at most %{count} item(s)"
|
||||
msgid_plural "should have at most %{count} item(s)"
|
||||
msgstr[0] "debe tener como máximo %{count} elemento"
|
||||
msgstr[1] "debe tener como máximo %{count} elementos"
|
||||
|
||||
msgid "should be at most %{count} character(s)"
|
||||
msgid_plural "should be at most %{count} character(s)"
|
||||
msgstr[0] "debe ser como máximo %{count} carácter"
|
||||
msgstr[1] "debe ser como máximo %{count} caracteres"
|
||||
|
||||
msgid "should be at most %{count} byte(s)"
|
||||
msgid_plural "should be at most %{count} byte(s)"
|
||||
msgstr[0] "debe ser como máximo %{count} byte"
|
||||
msgstr[1] "debe ser como máximo %{count} bytes"
|
||||
|
||||
msgid "must be less than %{number}"
|
||||
msgstr "debe ser menor que %{number}"
|
||||
|
||||
msgid "must be greater than %{number}"
|
||||
msgstr "debe ser mayor que %{number}"
|
||||
|
||||
msgid "must be less than or equal to %{number}"
|
||||
msgstr "debe ser menor o igual a %{number}"
|
||||
|
||||
msgid "must be greater than or equal to %{number}"
|
||||
msgstr "debe ser mayor o igual a %{number}"
|
||||
|
||||
msgid "must be equal to %{number}"
|
||||
msgstr "debe ser igual a %{number}"
|
||||
54
test/aprsme_web/plugs/set_locale_test.exs
Normal file
54
test/aprsme_web/plugs/set_locale_test.exs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
defmodule AprsmeWeb.Plugs.SetLocaleTest do
|
||||
use AprsmeWeb.ConnCase
|
||||
|
||||
alias AprsmeWeb.Plugs.SetLocale
|
||||
|
||||
test "sets Spanish locale when Accept-Language header contains es", %{conn: conn} do
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(store: :cookie, key: "_aprs_key", signing_salt: "test"))
|
||||
|> fetch_session()
|
||||
|> put_req_header("accept-language", "es-ES,es;q=0.9,en;q=0.8")
|
||||
|> SetLocale.call([])
|
||||
|
||||
assert Gettext.get_locale(AprsmeWeb.Gettext) == "es"
|
||||
end
|
||||
|
||||
test "sets English locale when Accept-Language header contains en", %{conn: conn} do
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(store: :cookie, key: "_aprs_key", signing_salt: "test"))
|
||||
|> fetch_session()
|
||||
|> put_req_header("accept-language", "en-US,en;q=0.9,es;q=0.8")
|
||||
|> SetLocale.call([])
|
||||
|
||||
assert Gettext.get_locale(AprsmeWeb.Gettext) == "en"
|
||||
end
|
||||
|
||||
test "falls back to English when Accept-Language header contains unsupported locale", %{conn: conn} do
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(store: :cookie, key: "_aprs_key", signing_salt: "test"))
|
||||
|> fetch_session()
|
||||
|> put_req_header("accept-language", "fr-FR,fr;q=0.9,en;q=0.8")
|
||||
|> SetLocale.call([])
|
||||
|
||||
assert Gettext.get_locale(AprsmeWeb.Gettext) == "en"
|
||||
end
|
||||
|
||||
test "falls back to English when no Accept-Language header is present", %{conn: conn} do
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(store: :cookie, key: "_aprs_key", signing_salt: "test"))
|
||||
|> fetch_session()
|
||||
|> SetLocale.call([])
|
||||
|
||||
assert Gettext.get_locale(AprsmeWeb.Gettext) == "en"
|
||||
end
|
||||
|
||||
test "prefers first supported locale in Accept-Language header", %{conn: conn} do
|
||||
conn
|
||||
|> Plug.Session.call(Plug.Session.init(store: :cookie, key: "_aprs_key", signing_salt: "test"))
|
||||
|> fetch_session()
|
||||
|> put_req_header("accept-language", "fr-FR,es-ES,en-US;q=0.9")
|
||||
|> SetLocale.call([])
|
||||
|
||||
assert Gettext.get_locale(AprsmeWeb.Gettext) == "es"
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue