From 243b773e3985c27e7261e282aebd85f77d9456aa Mon Sep 17 00:00:00 2001
From: Graham McIntie
- The page you're looking for could not be found. + {t("The page you're looking for could not be found.")}
@@ -37,7 +37,7 @@ href="/" class="inline-flex items-center justify-center rounded-full py-3 px-6 text-sm font-semibold bg-blue-600 text-white hover:bg-blue-500 active:bg-blue-800 transition-colors" > - Go back home + {t("Go back home")} diff --git a/lib/towerops_web/controllers/error_html/500.html.heex b/lib/towerops_web/controllers/error_html/500.html.heex index 563bfd78..cf059885 100644 --- a/lib/towerops_web/controllers/error_html/500.html.heex +++ b/lib/towerops_web/controllers/error_html/500.html.heex @@ -3,7 +3,7 @@ -- We're working on fixing the problem. Please try again later. + {t("We're working on fixing the problem. Please try again later.")}
@@ -28,7 +28,7 @@ href="/" class="inline-flex items-center justify-center rounded-full py-3 px-6 text-sm font-semibold bg-blue-600 text-white hover:bg-blue-500 active:bg-blue-800 transition-colors" > - Go back home + {t("Go back home")} diff --git a/lib/towerops_web/controllers/invitation_controller.ex b/lib/towerops_web/controllers/invitation_controller.ex index 1cc18772..087c9c4a 100644 --- a/lib/towerops_web/controllers/invitation_controller.ex +++ b/lib/towerops_web/controllers/invitation_controller.ex @@ -7,7 +7,7 @@ defmodule ToweropsWeb.InvitationController do case Organizations.get_invitation_by_token(token) do nil -> conn - |> put_flash(:error, "This invitation is invalid or has expired.") + |> put_flash(:error, t("This invitation is invalid or has expired.")) |> redirect(to: ~p"/") invitation -> @@ -29,12 +29,12 @@ defmodule ToweropsWeb.InvitationController do case Organizations.accept_invitation(invitation, user.id) do {:ok, _membership} -> conn - |> put_flash(:info, "You've joined #{invitation.organization.name}!") + |> put_flash(:info, t("You've joined %{org}!", org: invitation.organization.name)) |> redirect(to: ~p"/orgs/#{invitation.organization.slug}/settings?tab=members") {:error, _changeset} -> conn - |> put_flash(:error, "Could not accept invitation. You may already be a member.") + |> put_flash(:error, t("Could not accept invitation. You may already be a member.")) |> redirect(to: ~p"/dashboard") end end diff --git a/lib/towerops_web/controllers/user_confirmation_controller.ex b/lib/towerops_web/controllers/user_confirmation_controller.ex index afb622a9..a8749fcb 100644 --- a/lib/towerops_web/controllers/user_confirmation_controller.ex +++ b/lib/towerops_web/controllers/user_confirmation_controller.ex @@ -30,12 +30,12 @@ defmodule ToweropsWeb.UserConfirmationController do case Accounts.confirm_user(token) do {:ok, _user} -> conn - |> put_flash(:info, "Email confirmed successfully. You may now log in.") + |> put_flash(:info, t("Email confirmed successfully. You may now log in.")) |> redirect(to: ~p"/users/log-in") :error -> conn - |> put_flash(:error, "Email confirmation link is invalid or has expired.") + |> put_flash(:error, t("Email confirmation link is invalid or has expired.")) |> redirect(to: ~p"/users/log-in") end end diff --git a/lib/towerops_web/controllers/user_confirmation_html/new.html.heex b/lib/towerops_web/controllers/user_confirmation_html/new.html.heex index 1c917119..6e565a61 100644 --- a/lib/towerops_web/controllers/user_confirmation_html/new.html.heex +++ b/lib/towerops_web/controllers/user_confirmation_html/new.html.heex @@ -1,15 +1,15 @@- <.link href={~p"/users/log-in"}>Log in - | <.link href={~p"/users/register"}>Register + <.link href={~p"/users/log-in"}>{t_auth("Log in")} + | <.link href={~p"/users/register"}>{t_auth("Register")}
- Enter the 6-digit code from your authenticator app, or use a recovery code (XXXX-XXXX format). + {t_auth("Enter the 6-digit code from your authenticator app, or use a recovery code (XXXX-XXXX format).")}
- Manage mobile devices that receive push notifications for alerts + {t_auth("Manage mobile devices that receive push notifications for alerts")}
- Add a mobile device to receive push notifications for alerts + {t_auth("Add a mobile device to receive push notifications for alerts")}
- {session.device_name || "Unknown Device"} + {session.device_name || t_auth("Unknown Device")}
{session.device_os} • {session.app_version}
- Last used {ToweropsWeb.TimeHelpers.format_date(session.last_used_at, "UTC")} + {t_auth("Last used %{date}", date: ToweropsWeb.TimeHelpers.format_date(session.last_used_at, "UTC"))}
- Enter the 6-digit code from your authenticator app. Recovery codes are not allowed for sensitive operations. + {t_auth("Enter the 6-digit code from your authenticator app. Recovery codes are not allowed for sensitive operations.")}
<%= if @search != "" do %> - Try adjusting your search terms or clearing the filters. + {t("Try adjusting your search terms or clearing the filters.")} <% else %> - Your network operations log is empty. Events will appear here in real time as config changes, alerts, device events, and syncs happen across your organization. + {t("Your network operations log is empty. Events will appear here in real time as config changes, alerts, device events, and syncs happen across your organization.")} <% end %>
- Agents across all organizations and cloud pollers + {t("Agents across all organizations and cloud pollers")}
System overview and recent activity
{@user_count}
<.link navigate={~p"/admin/users"} @@ -18,7 +18,7 @@{@org_count}
<.link navigate={~p"/admin/organizations"} @@ -33,7 +33,7 @@ <.icon name="hero-queue-list" class="w-5 h-5 inline mr-1" /> Oban Dashboard- Monitor background jobs and queues + {t("Monitor background jobs and queues")}
<.link navigate={~p"/admin/oban"} @@ -48,7 +48,7 @@ <.icon name="hero-chart-bar" class="w-5 h-5 inline mr-1" /> LiveDashboard- System metrics and performance + {t("System metrics and performance")}
<.link navigate={~p"/admin/dashboard"} @@ -63,7 +63,7 @@ <.icon name="hero-cpu-chip" class="w-5 h-5 inline mr-1" /> Job Monitoring- Real-time polling and discovery job monitoring + {t("Real-time polling and discovery job monitoring")}
<.link navigate={~p"/admin/monitoring"} @@ -78,7 +78,7 @@ <.icon name="hero-server" class="w-5 h-5 inline mr-1" /> All Agents- Agents across all organizations and cloud pollers + {t("Agents across all organizations and cloud pollers")}
<.link navigate={~p"/admin/agents"} @@ -91,7 +91,7 @@- Real-time monitoring of polling and discovery jobs + {t("Real-time monitoring of polling and discovery jobs")}
<%= if Map.get(@health_metrics, :avg_execution_time_seconds) do %> {Map.get(@health_metrics, :avg_execution_time_seconds) |> Float.round(1)}s <% else %> - N/A + {t("N/A")} <% end %>
last hour
{length(@active_jobs)}
@@ -162,13 +162,13 @@- Updates every 10 seconds + {t("Updates every 10 seconds")}
Manage organizations
- Manage IP allowlist and view denied IPs + {t("Manage IP allowlist and view denied IPs")}
Manage system users
- Update the agent name. The authentication token cannot be changed. + {t("Update the agent name. The authentication token cannot be changed.")}
- A descriptive name to identify this agent in your organization. + {t("A descriptive name to identify this agent in your organization.")}
Performance Impact
- When enabled, the server logs all SNMP data and messages for this agent. - This generates significant log volume and should only be enabled temporarily + {t("When enabled, the server logs all SNMP data and messages for this agent.")} + {t("This generates significant log volume and should only be enabled temporarily")} for troubleshooting.
- Enable verbose logging for troubleshooting SNMP discovery and polling issues. - Only organization members can toggle this setting. + {t("Enable verbose logging for troubleshooting SNMP discovery and polling issues.")} + {t("Only organization members can toggle this setting.")}
- Get started by creating your first remote agent. + {t("Get started by creating your first remote agent.")}
- Application-wide agents that can poll devices for any organization. Only visible and manageable by superadmins. + {t("Application-wide agents that can poll devices for any organization. Only visible and manageable by superadmins.")}
<.table id="cloud-pollers-table" rows={@streams.cloud_pollers} row_link={fn {_id, agent} -> ~p"/agents/#{agent.id}" end} > - <:col :let={{_id, agent}} label="Name"> + <:col :let={{_id, agent}} label={t("Name")}>- Fallback agent for organizations without a default agent configured. Devices with no assignment at any level will use this agent. + {t("Fallback agent for organizations without a default agent configured. Devices with no assignment at any level will use this agent.")}
<.form for={%{}} phx-change="update_selected_global_default" class="max-w-md">- Use the token and Docker Compose configuration below to deploy this agent. + {t("Use the token and Docker Compose configuration below to deploy this agent.")}
{if @uptime_percentage == 100.0, @@ -174,7 +174,7 @@ class="rounded-lg border border-gray-200 bg-white px-4 py-3 transition hover:shadow-sm dark:border-white/10 dark:bg-gray-800/50" > - Devices + {t("Devices")}
{@device_count} @@ -197,7 +197,7 @@ class="rounded-lg border border-gray-200 bg-white px-4 py-3 transition hover:shadow-sm dark:border-white/10 dark:bg-gray-800/50" > - Alerts + {t("Alerts")}
{format_number(@summary.subscribers.total)} @@ -238,7 +238,7 @@ ) ]}> - MRR at Risk + {t("MRR at Risk")}
- Sites + {t("Sites")}
{@sites_count} @@ -277,7 +277,7 @@ class="rounded-lg border border-gray-200 bg-white px-4 py-3 transition hover:shadow-sm dark:border-white/10 dark:bg-gray-800/50" > - Insights + {t("Insights")}
{@summary.insights.critical + @summary.insights.warning + @summary.insights.info} @@ -301,13 +301,13 @@ <% end %> <%!-- ═══════════════════════════════════════════════ - ACTIVE INCIDENTS (only when there ARE incidents) + {t("ACTIVE INCIDENTS (only when there ARE incidents)")} ═══════════════════════════════════════════════ --%> <%= if @active_incidents != [] do %>
You have {remaining} {if remaining == 1, do: "slot", else: "slots"} remaining. @@ -100,10 +100,10 @@
- Core device identification and location details. + {t("Core device identification and location details.")}
- A device with this IP address already exists: + {t("A device with this IP address already exists:")} <.link navigate={~p"/devices/#{@duplicate_device.id}"} class="font-medium underline hover:text-amber-900 dark:hover:text-amber-100" @@ -153,8 +153,8 @@
Non-routable IP address detected
- This IP address (private network or CGNAT range) cannot be reached from the cloud. - To monitor this device, assign it to a + {t("This IP address (private network or CGNAT range) cannot be reached from the cloud.")} + {t("To monitor this device, assign it to a")} <.link navigate={~p"/agents"} class="font-medium underline"> remote agent @@ -169,24 +169,24 @@ <.input field={@form[:site_id]} type="select" - label="Site (Optional)" + label={t("Site (Optional)")} prompt="No site (ungrouped)" options={Enum.map(@available_sites, &{&1.name, &1.id})} />
- Optionally group this device into a site (office, datacenter, etc.) + {t("Optionally group this device into a site (office, datacenter, etc.)")}
- Select a role manually or leave as auto-detect to infer from SNMP data. + {t("Select a role manually or leave as auto-detect to infer from SNMP data.")}
- Configure how and how often this device should be monitored. + {t("Configure how and how often this device should be monitored.")}
<.icon name="hero-exclamation-triangle" class="h-4 w-4" /> - Overriding + {t("Overriding")} site/organization defaults - this device is explicitly assigned
<% :site -> %> @@ -279,18 +279,18 @@ <% :global -> %><.icon name="hero-globe-alt" class="h-4 w-4" /> - Using global default cloud poller: + {t("Using global default cloud poller:")} {@effective_agent_name}
<% :none -> %><.icon name="hero-cloud" class="h-4 w-4" /> - No agent assigned - cloud polling + {t("No agent assigned - cloud polling")}
<% end %> <% else %>- Assign this device to a remote agent for local SNMP polling. Leave empty to inherit from site or organization defaults. + {t("Assign this device to a remote agent for local SNMP polling. Leave empty to inherit from site or organization defaults.")}
<% end %>- Choose monitoring mode and configure SNMP settings for detailed device information. + {t("Choose monitoring mode and configure SNMP settings for detailed device information.")}
- Monitor device availability with ICMP pings and collect detailed information via SNMP + {t("Monitor device availability with ICMP pings and collect detailed information via SNMP")} (interfaces, sensors, system info).
<% else %> @@ -367,7 +367,7 @@ <.input field={@form[:snmp_version]} type="select" - label="SNMP Version" + label={t("SNMP Version")} prompt="Inherit from site/organization" options={[{"v1", "1"}, {"v2c", "2c"}, {"v3", "3"}]} /> @@ -381,8 +381,8 @@ <.input field={@form[:snmp_community]} type="text" - label="Community String" - placeholder="Leave blank to inherit from site/organization" + label={t("Community String")} + placeholder={t("Leave blank to inherit from site/organization")} autocomplete="off" /> @@ -391,7 +391,7 @@ <% :device -> %><.icon name="hero-exclamation-triangle" class="h-4 w-4" /> - Overriding site/organization SNMP defaults + {t("Overriding")} site/organization SNMP defaults
<% :site -> %>@@ -418,7 +418,7 @@ <% :default -> %>
<.icon name="hero-information-circle" class="h-4 w-4" /> - Using default (v2c, no community set - configure at organization or site level) + {t("Using default (v2c, no community set - configure at organization or site level)")}
<% end %> <% end %> @@ -430,8 +430,8 @@ <.input field={@form[:snmpv3_username]} type="text" - label="Username" - placeholder="Leave blank to inherit from site/organization" + label={t("Username")} + placeholder={t("Leave blank to inherit from site/organization")} />- Testing SNMP credentials... + {t("Testing SNMP credentials...")}
- Connection successful! + {t("Connection successful!")}
{Map.get(@snmp_test_result, :message)} @@ -595,7 +595,7 @@
- Connection failed + {t("Connection failed")}
{Map.get(@snmp_test_result, :message)} @@ -620,16 +620,16 @@ >
- Configure MikroTik RouterOS API access. Works alongside SNMP for enhanced device management. SSH is used for device backups. + {t("Configure MikroTik RouterOS API access. Works alongside SNMP for enhanced device management. SSH is used for device backups.")}
<.icon name="hero-beaker" class="h-4 w-4 inline" /> - Experimental Feature: - MikroTik API integration is under active development. + {t("Experimental Feature:")} + {t("MikroTik API integration is under active development.")}
🚨 Critical Security Warning: - Plain API (port 8728) sends credentials unencrypted over the network. - This setting is blocked when using cloud pollers + {t("Plain API (port 8728) sends credentials unencrypted over the network.")} + {t("This setting is blocked when using cloud pollers")} and should only be used with local agents on trusted networks.
- Permanently delete this device and all its data. + {t("Permanently delete this device and all its data.")}
- Once you delete this device, there is no going back. All monitoring history and alerts will be permanently deleted. + {t("Once you delete this device, there is no going back. All monitoring history and alerts will be permanently deleted.")}
<.button phx-click="delete" - data-confirm="Are you sure you want to delete this device? All monitoring history and alerts will be permanently deleted." + data-confirm={t("Are you sure you want to delete this device? All monitoring history and alerts will be permanently deleted.")} variant="danger" > <.icon name="hero-trash" class="h-4 w-4" /> Delete Device diff --git a/lib/towerops_web/live/device_live/index.html.heex b/lib/towerops_web/live/device_live/index.html.heex index bd23ddbc..a6cda639 100644 --- a/lib/towerops_web/live/device_live/index.html.heex +++ b/lib/towerops_web/live/device_live/index.html.heex @@ -7,7 +7,7 @@- Sites help you organize devices by physical location. Create a site to assign your devices and keep things organized. + {t("Sites help you organize devices by physical location. Create a site to assign your devices and keep things organized.")}
- Get started by adding your first device. + {t("Get started by adding your first device.")}
- Devices will appear here as they are discovered via LLDP/CDP. + {t("Devices will appear here as they are discovered via LLDP/CDP.")}
- Showing + {t("Showing")} {(@pagination.page - 1) * @pagination.per_page + 1} @@ -650,7 +650,7 @@
- This device doesn't have any LLDP or CDP neighbors, or neighbor discovery hasn't run yet. + {t("This device doesn't have any LLDP or CDP neighbors, or neighbor discovery hasn't run yet.")}
- This device doesn't have any ARP entries, or ARP discovery hasn't run yet. + {t("This device doesn't have any ARP entries, or ARP discovery hasn't run yet.")}
- This device doesn't have any MAC forwarding entries, or MAC discovery hasn't run yet. + {t("This device doesn't have any MAC forwarding entries, or MAC discovery hasn't run yet.")}
- This device doesn't have any VLANs configured, or VLAN discovery hasn't run yet. + {t("This device doesn't have any VLANs configured, or VLAN discovery hasn't run yet.")}
- This device doesn't have any IP addresses discovered, or IP discovery hasn't run yet. + {t("This device doesn't have any IP addresses discovered, or IP discovery hasn't run yet.")}
@@ -1986,7 +1986,7 @@
<% else %>- Assign an agent to enable automatic backups. + {t("Assign an agent to enable automatic backups.")}
<% end %> @@ -1997,14 +1997,14 @@- Enable MikroTik API in device settings to enable configuration backups. + {t("Enable MikroTik API in device settings to enable configuration backups.")}
- Showing the most recent 100 events + {t("Showing the most recent 100 events")}
- Events will appear here as interface states change, speeds change, or other monitored changes occur. + {t("Events will appear here as interface states change, speeds change, or other monitored changes occur.")}
- Raw SNMP OID values collected during the last discovery run at + {t("Raw SNMP OID values collected during the last discovery run at")} <%= if @snmp_device.last_discovery_at do %> {ToweropsWeb.TimeHelpers.format_iso8601( @snmp_device.last_discovery_at, @@ -2096,20 +2096,20 @@ <%= if @snmp_device.raw_discovery_data do %>
| - Field + {t("Field")} | - OID + {t("OID")} | - Value + {t("Value")} |
|---|
| - OID + {t("OID")} | - Value + {t("Value")} |
|---|
| - Type + {t("Type")} | - Description + {t("Description")} | - OID + {t("OID")} | - Value + {t("Value")} | - State + {t("State")} |
|---|
diff --git a/lib/towerops_web/controllers/error_html/404.html.heex b/lib/towerops_web/controllers/error_html/404.html.heex index 134e68ba..69233a7a 100644 --- a/lib/towerops_web/controllers/error_html/404.html.heex +++ b/lib/towerops_web/controllers/error_html/404.html.heex @@ -3,7 +3,7 @@
-
+