diff --git a/lib/aprsme/convert.ex b/lib/aprsme/convert.ex index 80381c0..c38eb7c 100644 --- a/lib/aprsme/convert.ex +++ b/lib/aprsme/convert.ex @@ -9,4 +9,47 @@ defmodule Aprsme.Convert do @spec speed(number(), :knots, :mph) :: float() def speed(value, :knots, :mph), do: Float.round(value * 1.15077945, 2) + + # Weather unit conversions + @doc """ + Converts Fahrenheit to Celsius + """ + def f_to_c(fahrenheit) when is_number(fahrenheit) do + (fahrenheit - 32) * 5 / 9 + end + + @doc """ + Converts Celsius to Fahrenheit + """ + def c_to_f(celsius) when is_number(celsius) do + celsius * 9 / 5 + 32 + end + + @doc """ + Converts mph to km/h + """ + def mph_to_kph(mph) when is_number(mph) do + mph * 1.60934 + end + + @doc """ + Converts km/h to mph + """ + def kph_to_mph(kph) when is_number(kph) do + kph / 1.60934 + end + + @doc """ + Converts inches to mm + """ + def inches_to_mm(inches) when is_number(inches) do + inches * 25.4 + end + + @doc """ + Converts mm to inches + """ + def mm_to_inches(mm) when is_number(mm) do + mm / 25.4 + end end diff --git a/lib/aprsme_web/live/map_live/callsign_view.ex b/lib/aprsme_web/live/map_live/callsign_view.ex index 1dd5242..7f61989 100644 --- a/lib/aprsme_web/live/map_live/callsign_view.ex +++ b/lib/aprsme_web/live/map_live/callsign_view.ex @@ -329,7 +329,8 @@ defmodule AprsmeWeb.MapLive.CallsignView do socket = assign(socket, visible_packets: updated_visible_packets) # Live packets are always the most recent for their callsign - packet_data = PacketUtils.build_packet_data(packet, true) + locale = Map.get(socket.assigns, :locale, "en") + packet_data = PacketUtils.build_packet_data(packet, true, locale) socket = if packet_data, @@ -355,7 +356,9 @@ defmodule AprsmeWeb.MapLive.CallsignView do end defp handle_replay_packet(packet, socket) do - case PacketUtils.build_packet_data(packet) do + locale = Map.get(socket.assigns, :locale, "en") + + case PacketUtils.build_packet_data(packet, false, locale) do nil -> handle_invalid_replay_packet(socket) packet_data -> handle_valid_replay_packet(packet, packet_data, socket) end @@ -814,7 +817,8 @@ defmodule AprsmeWeb.MapLive.CallsignView do end defp build_single_historical_packet_data(packet, index, callsign) do - case PacketUtils.build_packet_data(packet) do + # Note: We don't have access to locale here, so we'll use default "en" + case PacketUtils.build_packet_data(packet, false, "en") do nil -> nil @@ -847,7 +851,8 @@ defmodule AprsmeWeb.MapLive.CallsignView do defp push_latest_marker(socket, latest_packet) do if latest_packet do - packet_data = PacketUtils.build_packet_data(latest_packet, true) + locale = Map.get(socket.assigns, :locale, "en") + packet_data = PacketUtils.build_packet_data(latest_packet, true, locale) if packet_data, do: {push_event(socket, "new_packet", packet_data), true}, @@ -992,7 +997,8 @@ defmodule AprsmeWeb.MapLive.CallsignView do if Map.get(socket.assigns, :latest_marker_pushed, false) do socket else - packet_data = PacketUtils.build_packet_data(packet, true) + locale = Map.get(socket.assigns, :locale, "en") + packet_data = PacketUtils.build_packet_data(packet, true, locale) if packet_data, do: push_event(socket, "new_packet", packet_data), else: socket end end diff --git a/lib/aprsme_web/live/map_live/index.ex b/lib/aprsme_web/live/map_live/index.ex index 0abbf77..a1279b1 100644 --- a/lib/aprsme_web/live/map_live/index.ex +++ b/lib/aprsme_web/live/map_live/index.ex @@ -144,9 +144,11 @@ defmodule AprsmeWeb.MapLive.Index do end) |> Map.new() + locale = Map.get(socket.assigns, :locale, "en") + visible_packets_list = filtered_packets - |> Enum.map(fn {_callsign, packet} -> PacketUtils.build_packet_data(packet) end) + |> Enum.map(fn {_callsign, packet} -> PacketUtils.build_packet_data(packet, false, locale) end) |> Enum.filter(& &1) socket = assign(socket, visible_packets: filtered_packets) @@ -398,7 +400,8 @@ defmodule AprsmeWeb.MapLive.Index do new_visible_packets = Map.put(socket.assigns.visible_packets, callsign_key, packet) # Live packets are always the most recent for their callsign - marker_data = PacketUtils.build_packet_data(packet, true) + locale = Map.get(socket.assigns, :locale, "en") + marker_data = PacketUtils.build_packet_data(packet, true, locale) socket = if marker_data do @@ -1046,7 +1049,8 @@ defmodule AprsmeWeb.MapLive.Index do # Only show as red dot if it's not the most recent position is_most_recent = index == 0 - packet_data = PacketUtils.build_packet_data(packet, is_most_recent) + # Note: We don't have access to locale here, so we'll use default "en" + packet_data = PacketUtils.build_packet_data(packet, is_most_recent, "en") if packet_data do packet_data diff --git a/lib/aprsme_web/live/map_live/packet_utils.ex b/lib/aprsme_web/live/map_live/packet_utils.ex index 0684ec8..616407a 100644 --- a/lib/aprsme_web/live/map_live/packet_utils.ex +++ b/lib/aprsme_web/live/map_live/packet_utils.ex @@ -137,24 +137,25 @@ defmodule AprsmeWeb.MapLive.PacketUtils do Map.get(data_extended, to_string(key)) || "N/A" end - def build_packet_data(packet, is_most_recent_for_callsign) when is_boolean(is_most_recent_for_callsign) do + def build_packet_data(packet, is_most_recent_for_callsign, locale \\ "en") + when is_boolean(is_most_recent_for_callsign) do {lat, lon, data_extended} = MapHelpers.get_coordinates(packet) callsign = generate_callsign(packet) if lat && lon && callsign != "" && callsign != nil do - packet_data = build_packet_map(packet, lat, lon, data_extended) + packet_data = build_packet_map(packet, lat, lon, data_extended, locale) Map.put(packet_data, "is_most_recent_for_callsign", is_most_recent_for_callsign) end end def build_packet_data(packet) do - build_packet_data(packet, false) + build_packet_data(packet, false, "en") end - defp build_packet_map(packet, lat, lon, data_extended) do + defp build_packet_map(packet, lat, lon, data_extended, locale) do data_extended = data_extended || %{} packet_info = extract_packet_info(packet, data_extended) - popup = build_popup_content(packet, packet_info, lat, lon) + popup = build_popup_content(packet, packet_info, lat, lon, locale) build_packet_result(packet, packet_info, lat, lon, popup) end @@ -171,9 +172,9 @@ defmodule AprsmeWeb.MapLive.PacketUtils do } end - defp build_popup_content(packet, packet_info, lat, lon) do + defp build_popup_content(packet, packet_info, lat, lon, locale) do if packet_info.is_weather_packet do - build_weather_popup_html(packet, packet_info.callsign) + build_weather_popup_html(packet, packet_info.callsign, locale) else build_standard_popup_html(packet_info, lat, lon) end @@ -197,11 +198,27 @@ defmodule AprsmeWeb.MapLive.PacketUtils do |> IO.iodata_to_binary() end - defp build_weather_popup_html(packet, sender) do + defp build_weather_popup_html(packet, sender, locale) do received_at = get_received_at(packet) timestamp_dt = TimeHelpers.to_datetime(received_at) cache_buster = System.system_time(:millisecond) + # Get weather data and convert units based on locale + temperature_raw = get_weather_field(packet, :temperature) + wind_speed_raw = get_weather_field(packet, :wind_speed) + wind_gust_raw = get_weather_field(packet, :wind_gust) + rain_1h_raw = get_weather_field(packet, :rain_1h) + rain_24h_raw = get_weather_field(packet, :rain_24h) + rain_since_midnight_raw = get_weather_field(packet, :rain_since_midnight) + + # Convert units if the values are numbers + {temperature, temp_unit} = convert_temperature(temperature_raw, locale) + {wind_speed, wind_unit} = convert_wind_speed(wind_speed_raw, locale) + {wind_gust, gust_unit} = convert_wind_speed(wind_gust_raw, locale) + {rain_1h, rain_unit} = convert_rain(rain_1h_raw, locale) + {rain_24h, rain_unit} = convert_rain(rain_24h_raw, locale) + {rain_since_midnight, rain_unit} = convert_rain(rain_since_midnight_raw, locale) + %{ callsign: sender, comment: nil, @@ -209,15 +226,19 @@ defmodule AprsmeWeb.MapLive.PacketUtils do cache_buster: cache_buster, weather: true, weather_link: true, - temperature: get_weather_field(packet, :temperature), + temperature: temperature, + temp_unit: temp_unit, humidity: get_weather_field(packet, :humidity), wind_direction: get_weather_field(packet, :wind_direction), - wind_speed: get_weather_field(packet, :wind_speed), - wind_gust: get_weather_field(packet, :wind_gust), + wind_speed: wind_speed, + wind_unit: wind_unit, + wind_gust: wind_gust, + gust_unit: gust_unit, pressure: get_weather_field(packet, :pressure), - rain_1h: get_weather_field(packet, :rain_1h), - rain_24h: get_weather_field(packet, :rain_24h), - rain_since_midnight: get_weather_field(packet, :rain_since_midnight) + rain_1h: rain_1h, + rain_24h: rain_24h, + rain_since_midnight: rain_since_midnight, + rain_unit: rain_unit } |> PopupComponent.popup() |> Safe.to_iodata() @@ -259,4 +280,23 @@ defmodule AprsmeWeb.MapLive.PacketUtils do true -> nil end end + + # Weather unit conversion helpers + defp convert_temperature(value, locale) when is_number(value) do + AprsmeWeb.WeatherUnits.format_temperature(value, locale) + end + + defp convert_temperature(value, _locale), do: {value, "°F"} + + defp convert_wind_speed(value, locale) when is_number(value) do + AprsmeWeb.WeatherUnits.format_wind_speed(value, locale) + end + + defp convert_wind_speed(value, _locale), do: {value, "mph"} + + defp convert_rain(value, locale) when is_number(value) do + AprsmeWeb.WeatherUnits.format_rain(value, locale) + end + + defp convert_rain(value, _locale), do: {value, "in"} end diff --git a/lib/aprsme_web/live/map_live/popup_component.ex b/lib/aprsme_web/live/map_live/popup_component.ex index 863ae16..b2635d0 100644 --- a/lib/aprsme_web/live/map_live/popup_component.ex +++ b/lib/aprsme_web/live/map_live/popup_component.ex @@ -5,6 +5,8 @@ defmodule AprsmeWeb.MapLive.PopupComponent do import AprsmeWeb.TimeHelpers import Gettext + alias AprsmeWeb.WeatherUnits + def popup(assigns) do ~H"""
@@ -36,16 +38,16 @@ defmodule AprsmeWeb.MapLive.PopupComponent do <% end %> <%= if @weather do %>
- {gettext(AprsmeWeb.Gettext, "Temperature:")} {@temperature}°F
+ {gettext(AprsmeWeb.Gettext, "Temperature:")} {@temperature}{@temp_unit}
{gettext(AprsmeWeb.Gettext, "Humidity:")} {@humidity}%
- {gettext(AprsmeWeb.Gettext, "Wind:")} {@wind_direction}° {gettext(AprsmeWeb.Gettext, "at")} {@wind_speed} mph, {gettext( + {gettext(AprsmeWeb.Gettext, "Wind:")} {@wind_direction}° {gettext(AprsmeWeb.Gettext, "at")} {@wind_speed} {@wind_unit}, {gettext( AprsmeWeb.Gettext, "gusts to" - )} {@wind_gust} mph
+ )} {@wind_gust} {@gust_unit}
{gettext(AprsmeWeb.Gettext, "Pressure:")} {@pressure} hPa
- {gettext(AprsmeWeb.Gettext, "Rain (1h):")} {@rain_1h} in.
- {gettext(AprsmeWeb.Gettext, "Rain (24h):")} {@rain_24h} in.
- {gettext(AprsmeWeb.Gettext, "Rain (since midnight):")} {@rain_since_midnight} in.
+ {gettext(AprsmeWeb.Gettext, "Rain (1h):")} {@rain_1h} {@rain_unit}
+ {gettext(AprsmeWeb.Gettext, "Rain (24h):")} {@rain_24h} {@rain_unit}
+ {gettext(AprsmeWeb.Gettext, "Rain (since midnight):")} {@rain_since_midnight} {@rain_unit}
<% end %>
""" diff --git a/lib/aprsme_web/live/weather_live/callsign_view.ex b/lib/aprsme_web/live/weather_live/callsign_view.ex index 29c6d6f..3fc42e6 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.ex +++ b/lib/aprsme_web/live/weather_live/callsign_view.ex @@ -7,6 +7,7 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do alias Aprsme.Packets alias AprsmeWeb.MapLive.PacketUtils + alias AprsmeWeb.WeatherUnits @impl true def mount(%{"callsign" => callsign}, _session, socket) do @@ -22,6 +23,10 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do {start_time, end_time} = default_time_range() weather_history = get_weather_history(normalized_callsign, start_time, end_time) + # Get locale from socket assigns (set by LocaleHook) + locale = Map.get(socket.assigns, :locale, "en") + unit_labels = WeatherUnits.unit_labels(locale) + weather_history_json = weather_history |> Enum.map(fn pkt -> @@ -30,36 +35,44 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do calc_dew_point(pkt.temperature, pkt.humidity) end + # Convert units based on locale + {temp_value, _} = WeatherUnits.format_temperature(pkt.temperature, locale) + {dew_value, _} = if dew_point, do: WeatherUnits.format_temperature(dew_point, locale), else: {nil, nil} + {wind_speed_value, _} = WeatherUnits.format_wind_speed(pkt.wind_speed, locale) + {rain_1h_value, _} = WeatherUnits.format_rain(pkt.rain_1h, locale) + {rain_24h_value, _} = WeatherUnits.format_rain(pkt.rain_24h, locale) + {rain_since_midnight_value, _} = WeatherUnits.format_rain(pkt.rain_since_midnight, locale) + %{ timestamp: pkt.received_at, - temperature: pkt.temperature, - dew_point: dew_point, + temperature: temp_value, + dew_point: dew_value, humidity: pkt.humidity, pressure: pkt.pressure, wind_direction: pkt.wind_direction, - wind_speed: pkt.wind_speed, - rain_1h: pkt.rain_1h, - rain_24h: pkt.rain_24h, - rain_since_midnight: pkt.rain_since_midnight, + wind_speed: wind_speed_value, + rain_1h: rain_1h_value, + rain_24h: rain_24h_value, + rain_since_midnight: rain_since_midnight_value, luminosity: pkt.luminosity } end) |> Jason.encode!() - # Add chart labels for translation + # Add chart labels for translation with locale-aware units chart_labels = %{ - temp_title: gettext("Temperature & Dew Point (°F)"), - temp_label: gettext("Temperature (°F)"), - dew_label: gettext("Dew Point (°F)"), + temp_title: gettext("Temperature & Dew Point (%{unit})", unit: unit_labels.temperature), + temp_label: gettext("Temperature (%{unit})", unit: unit_labels.temperature), + dew_label: gettext("Dew Point (%{unit})", unit: unit_labels.temperature), 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)"), + wind_title: gettext("Wind (%{unit})", unit: unit_labels.wind_speed), + wind_label: gettext("Wind Speed (%{unit})", unit: unit_labels.wind_speed), + gust_label: gettext("Wind Gust (%{unit})", unit: unit_labels.wind_speed), time: gettext("Time"), - degf: gettext("°F"), + degf: unit_labels.temperature, percent: gettext("%"), mb: gettext("mb") } @@ -83,6 +96,9 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do {start_time, end_time} = default_time_range() weather_history = get_weather_history(socket.assigns.callsign, start_time, end_time) + # Get locale from socket assigns + locale = Map.get(socket.assigns, :locale, "en") + weather_history_json = weather_history |> Enum.map(fn pkt -> @@ -91,17 +107,25 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do calc_dew_point(pkt.temperature, pkt.humidity) end + # Convert units based on locale + {temp_value, _} = WeatherUnits.format_temperature(pkt.temperature, locale) + {dew_value, _} = if dew_point, do: WeatherUnits.format_temperature(dew_point, locale), else: {nil, nil} + {wind_speed_value, _} = WeatherUnits.format_wind_speed(pkt.wind_speed, locale) + {rain_1h_value, _} = WeatherUnits.format_rain(pkt.rain_1h, locale) + {rain_24h_value, _} = WeatherUnits.format_rain(pkt.rain_24h, locale) + {rain_since_midnight_value, _} = WeatherUnits.format_rain(pkt.rain_since_midnight, locale) + %{ timestamp: pkt.received_at, - temperature: pkt.temperature, - dew_point: dew_point, + temperature: temp_value, + dew_point: dew_value, humidity: pkt.humidity, pressure: pkt.pressure, wind_direction: pkt.wind_direction, - wind_speed: pkt.wind_speed, - rain_1h: pkt.rain_1h, - rain_24h: pkt.rain_24h, - rain_since_midnight: pkt.rain_since_midnight, + wind_speed: wind_speed_value, + rain_1h: rain_1h_value, + rain_24h: rain_24h_value, + rain_since_midnight: rain_since_midnight_value, luminosity: pkt.luminosity } end) @@ -128,6 +152,9 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do {start_time, end_time} = default_time_range() weather_history = get_weather_history(socket.assigns.callsign, start_time, end_time) + # Get locale from socket assigns + locale = Map.get(socket.assigns, :locale, "en") + weather_history_json = weather_history |> Enum.map(fn pkt -> @@ -136,17 +163,25 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do calc_dew_point(pkt.temperature, pkt.humidity) end + # Convert units based on locale + {temp_value, _} = WeatherUnits.format_temperature(pkt.temperature, locale) + {dew_value, _} = if dew_point, do: WeatherUnits.format_temperature(dew_point, locale), else: {nil, nil} + {wind_speed_value, _} = WeatherUnits.format_wind_speed(pkt.wind_speed, locale) + {rain_1h_value, _} = WeatherUnits.format_rain(pkt.rain_1h, locale) + {rain_24h_value, _} = WeatherUnits.format_rain(pkt.rain_24h, locale) + {rain_since_midnight_value, _} = WeatherUnits.format_rain(pkt.rain_since_midnight, locale) + %{ timestamp: pkt.received_at, - temperature: pkt.temperature, - dew_point: dew_point, + temperature: temp_value, + dew_point: dew_value, humidity: pkt.humidity, pressure: pkt.pressure, wind_direction: pkt.wind_direction, - wind_speed: pkt.wind_speed, - rain_1h: pkt.rain_1h, - rain_24h: pkt.rain_24h, - rain_since_midnight: pkt.rain_since_midnight, + wind_speed: wind_speed_value, + rain_1h: rain_1h_value, + rain_24h: rain_24h_value, + rain_since_midnight: rain_since_midnight_value, luminosity: pkt.luminosity } end) @@ -220,4 +255,44 @@ defmodule AprsmeWeb.WeatherLive.CallsignView do _ -> value end end + + @doc """ + Formats weather values with appropriate units based on locale. + """ + def format_weather_value(packet, key, locale) do + value = PacketUtils.get_weather_field(packet, key) + + case {key, value} do + {:temperature, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_temperature(value, locale) + "#{converted_value}#{unit}" + + {:wind_speed, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_wind_speed(value, locale) + "#{converted_value} #{unit}" + + {:wind_gust, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_wind_speed(value, locale) + "#{converted_value} #{unit}" + + {:rain_1h, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_rain(value, locale) + "#{converted_value} #{unit}" + + {:rain_24h, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_rain(value, locale) + "#{converted_value} #{unit}" + + {:rain_since_midnight, value} when is_number(value) -> + {converted_value, unit} = WeatherUnits.format_rain(value, locale) + "#{converted_value} #{unit}" + + _ -> + case value do + "N/A" -> "N/A" + nil -> "N/A" + _ -> "#{value}" + end + end + end end diff --git a/lib/aprsme_web/live/weather_live/callsign_view.html.heex b/lib/aprsme_web/live/weather_live/callsign_view.html.heex index b130702..2dc5b57 100644 --- a/lib/aprsme_web/live/weather_live/callsign_view.html.heex +++ b/lib/aprsme_web/live/weather_live/callsign_view.html.heex @@ -96,7 +96,7 @@
{gettext("Temperature")}
- {PacketUtils.get_weather_field(@weather_packet, :temperature)}°F + {format_weather_value(@weather_packet, :temperature, @locale)}
@@ -108,16 +108,17 @@
{gettext("Wind")}
- {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {PacketUtils.get_weather_field( + {PacketUtils.get_weather_field(@weather_packet, :wind_direction)}° @ {format_weather_value( @weather_packet, - :wind_speed - )} mph + :wind_speed, + @locale + )}
{gettext("Gusts")}
- {PacketUtils.get_weather_field(@weather_packet, :wind_gust)} mph + {format_weather_value(@weather_packet, :wind_gust, @locale)}
@@ -129,19 +130,19 @@
{gettext("Rain (1h)")}
- {get_weather_field_zero(@weather_packet, :rain_1h)} in + {format_weather_value(@weather_packet, :rain_1h, @locale)}
{gettext("Rain (24h)")}
- {get_weather_field_zero(@weather_packet, :rain_24h)} in + {format_weather_value(@weather_packet, :rain_24h, @locale)}
{gettext("Rain (since midnight)")}
- {get_weather_field_zero(@weather_packet, :rain_since_midnight)} in + {format_weather_value(@weather_packet, :rain_since_midnight, @locale)}
diff --git a/lib/aprsme_web/weather_units.ex b/lib/aprsme_web/weather_units.ex new file mode 100644 index 0000000..86173cd --- /dev/null +++ b/lib/aprsme_web/weather_units.ex @@ -0,0 +1,98 @@ +defmodule AprsmeWeb.WeatherUnits do + @moduledoc """ + Handles weather unit conversions and formatting based on locale. + Supports imperial (US) and metric (international) units. + """ + + alias Aprsme.Convert + + @doc """ + Determines the unit system based on locale. + Returns :imperial for US, :metric for most other countries. + """ + def unit_system(locale) when is_binary(locale) do + case locale do + # Default to imperial for English + "en" -> :imperial + # Spanish-speaking countries mostly use metric + "es" -> :metric + # Germany uses metric + "de" -> :metric + # France uses metric + "fr" -> :metric + # Default to metric for unknown locales + _ -> :metric + end + end + + @doc """ + Converts temperature from Fahrenheit to Celsius if needed. + Returns the temperature in the appropriate unit for the locale. + """ + def format_temperature(temp, locale) when is_number(temp) do + case unit_system(locale) do + :imperial -> {temp, "°F"} + :metric -> {Convert.f_to_c(temp), "°C"} + end + end + + def format_temperature(temp, _locale), do: {temp, "°F"} + + @doc """ + Converts wind speed from mph to km/h if needed. + Returns the wind speed in the appropriate unit for the locale. + """ + def format_wind_speed(speed, locale) when is_number(speed) do + case unit_system(locale) do + :imperial -> {speed, "mph"} + :metric -> {Convert.mph_to_kph(speed), "km/h"} + end + end + + def format_wind_speed(speed, _locale), do: {speed, "mph"} + + @doc """ + Converts rain from inches to mm if needed. + Returns the rain amount in the appropriate unit for the locale. + """ + def format_rain(rain, locale) when is_number(rain) do + case unit_system(locale) do + :imperial -> {rain, "in"} + :metric -> {Convert.inches_to_mm(rain), "mm"} + end + end + + def format_rain(rain, _locale), do: {rain, "in"} + + @doc """ + Formats pressure (keeps hPa for all locales as it's standard). + """ + def format_pressure(pressure, _locale) when is_number(pressure) do + {pressure, "hPa"} + end + + def format_pressure(pressure, _locale), do: {pressure, "hPa"} + + @doc """ + Gets the appropriate unit labels for the locale. + """ + def unit_labels(locale) do + case unit_system(locale) do + :imperial -> + %{ + temperature: "°F", + wind_speed: "mph", + rain: "in", + pressure: "hPa" + } + + :metric -> + %{ + temperature: "°C", + wind_speed: "km/h", + rain: "mm", + pressure: "hPa" + } + end + end +end