diff --git a/lib/modules/maintenance/settings.ex b/lib/modules/maintenance/settings.ex index 1061e5c67..cc56d6d58 100644 --- a/lib/modules/maintenance/settings.ex +++ b/lib/modules/maintenance/settings.ex @@ -9,8 +9,20 @@ defmodule PhoenixKitWeb.Live.Modules.Maintenance.Settings do alias PhoenixKit.Modules.Maintenance alias PhoenixKit.Settings + alias PhoenixKit.Utils.Routes + + def mount(params, _session, socket) do + # Set locale for LiveView process FIRST - preserve from params or socket assigns + locale = params["locale"] || socket.assigns[:current_locale] + + if locale do + Gettext.put_locale(PhoenixKitWeb.Gettext, locale) + Process.put(:phoenix_kit_current_locale, locale) + end + + # Get current path for navigation (after locale is set) + current_path = Routes.path("/admin/settings/maintenance") - def mount(_params, _session, socket) do # Get current settings config = Maintenance.get_config() @@ -18,6 +30,8 @@ defmodule PhoenixKitWeb.Live.Modules.Maintenance.Settings do socket |> assign(:page_title, "Maintenance Mode Settings") |> assign(:project_title, Settings.get_setting("project_title", "PhoenixKit")) + |> assign(:current_path, current_path) + |> assign(:current_locale, locale) |> assign(:header, config.header) |> assign(:subtext, config.subtext) |> assign(:enabled, config.enabled) @@ -108,9 +122,9 @@ defmodule PhoenixKitWeb.Live.Modules.Maintenance.Settings do flash={@flash} phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]} page_title="{@project_title} - Maintenance Mode Settings" - current_path={@url_path} + current_path={@current_path} project_title={@project_title} - current_locale={assigns[:current_locale] || "en"} + current_locale={@current_locale} >
<%!-- Header Section --%> diff --git a/lib/phoenix_kit/modules/languages.ex b/lib/phoenix_kit/modules/languages.ex index 9c702ce6d..6720c870a 100644 --- a/lib/phoenix_kit/modules/languages.ex +++ b/lib/phoenix_kit/modules/languages.ex @@ -8,8 +8,8 @@ defmodule PhoenixKit.Modules.Languages do ## Language Structure Each language has the following structure: - - `code`: Language code (e.g., "en", "es", "fr") - - `name`: Full language name (e.g., "English", "Spanish", "French") + - `code`: Language code (e.g., "en-US", "es-ES", "fr-FR") + - `name`: Full language name (e.g., "English (United States)", "Spanish (Spain)", "French (France)") - `is_default`: Boolean indicating if this is the default language - `is_enabled`: Boolean indicating if this language is active @@ -52,22 +52,22 @@ defmodule PhoenixKit.Modules.Languages do # Get all languages languages = PhoenixKit.Modules.Languages.get_languages() - # => [%{code: "en", name: "English", is_default: true, is_enabled: true}, ...] + # => [%{code: "en-US", name: "English (United States)", is_default: true, is_enabled: true}, ...] # Get only enabled languages (most common use case) enabled_languages = PhoenixKit.Modules.Languages.get_enabled_languages() - # => [%{code: "en", name: "English", ...}, %{code: "es", name: "Spanish", ...}] + # => [%{code: "en-US", name: "English (United States)", ...}, %{code: "es-ES", name: "Spanish (Spain)", ...}] # Get a specific language by code - spanish = PhoenixKit.Modules.Languages.get_language("es") - # => %{code: "es", name: "Spanish", is_enabled: true} + spanish = PhoenixKit.Modules.Languages.get_language("es-ES") + # => %{code: "es-ES", name: "Spanish (Spain)", is_enabled: true} # Get just the language codes codes = PhoenixKit.Modules.Languages.get_enabled_language_codes() - # => ["en", "es", "fr"] + # => ["en-US", "es-ES", "fr-FR"] # Check if a language is valid and enabled - if PhoenixKit.Modules.Languages.language_enabled?("es") do + if PhoenixKit.Modules.Languages.language_enabled?("es-ES") do # Use Spanish language end @@ -79,14 +79,14 @@ defmodule PhoenixKit.Modules.Languages do { "languages": [ { - "code": "en", - "name": "English", + "code": "en-US", + "name": "English (United States)", "is_default": true, "is_enabled": true }, { - "code": "es", - "name": "Spanish", + "code": "es-ES", + "name": "Spanish (Spain)", "is_default": false, "is_enabled": true } @@ -119,14 +119,20 @@ defmodule PhoenixKit.Modules.Languages do %{code: "cs", name: "Czech", native: "Čeština", flag: "🇨🇿"}, %{code: "da", name: "Danish", native: "Dansk", flag: "🇩🇰"}, %{code: "nl", name: "Dutch", native: "Nederlands", flag: "🇳🇱"}, - %{code: "en", name: "English", native: "English", flag: "🇺🇸"}, + %{code: "en-US", name: "English (United States)", native: "English (US)", flag: "🇺🇸"}, + %{code: "en-GB", name: "English (United Kingdom)", native: "English (UK)", flag: "🇬🇧"}, + %{code: "en-CA", name: "English (Canada)", native: "English (CA)", flag: "🇨🇦"}, + %{code: "en-AU", name: "English (Australia)", native: "English (AU)", flag: "🇦🇺"}, %{code: "et", name: "Estonian", native: "Eesti", flag: "🇪🇪"}, %{code: "tl", name: "Filipino", native: "Filipino", flag: "🇵🇭"}, %{code: "fi", name: "Finnish", native: "Suomi", flag: "🇫🇮"}, - %{code: "fr", name: "French", native: "Français", flag: "🇫🇷"}, + %{code: "fr-FR", name: "French (France)", native: "Français (France)", flag: "🇫🇷"}, + %{code: "fr-CA", name: "French (Canada)", native: "Français (Canada)", flag: "🇨🇦"}, %{code: "gl", name: "Galician", native: "Galego", flag: "🏴"}, %{code: "ka", name: "Georgian", native: "ქართული", flag: "🇬🇪"}, - %{code: "de", name: "German", native: "Deutsch", flag: "🇩🇪"}, + %{code: "de-DE", name: "German (Germany)", native: "Deutsch (Deutschland)", flag: "🇩🇪"}, + %{code: "de-AT", name: "German (Austria)", native: "Deutsch (Österreich)", flag: "🇦🇹"}, + %{code: "de-CH", name: "German (Switzerland)", native: "Deutsch (Schweiz)", flag: "🇨🇭"}, %{code: "gu", name: "Gujarati", native: "ગુજરાતી", flag: "🇮🇳"}, %{code: "he", name: "Hebrew", native: "עברית", flag: "🇮🇱"}, %{code: "hi", name: "Hindi", native: "हिन्दी", flag: "🇮🇳"}, @@ -156,7 +162,8 @@ defmodule PhoenixKit.Modules.Languages do %{code: "no", name: "Norwegian", native: "Norsk", flag: "🇳🇴"}, %{code: "fa", name: "Persian", native: "فارسی", flag: "🇮🇷"}, %{code: "pl", name: "Polish", native: "Polski", flag: "🇵🇱"}, - %{code: "pt", name: "Portuguese", native: "Português", flag: "🇵🇹"}, + %{code: "pt-PT", name: "Portuguese (Portugal)", native: "Português (Portugal)", flag: "🇵🇹"}, + %{code: "pt-BR", name: "Portuguese (Brazil)", native: "Português (Brasil)", flag: "🇧🇷"}, %{code: "pa", name: "Punjabi", native: "ਪੰਜਾਬੀ", flag: "🇮🇳"}, %{code: "ro", name: "Romanian", native: "Română", flag: "🇷🇴"}, %{code: "ru", name: "Russian", native: "Русский", flag: "🇷🇺"}, @@ -165,7 +172,10 @@ defmodule PhoenixKit.Modules.Languages do %{code: "si", name: "Sinhala", native: "සිංහල", flag: "🇱🇰"}, %{code: "sk", name: "Slovak", native: "Slovenčina", flag: "🇸🇰"}, %{code: "sl", name: "Slovenian", native: "Slovenščina", flag: "🇸🇮"}, - %{code: "es", name: "Spanish", native: "Español", flag: "🇪🇸"}, + %{code: "es-ES", name: "Spanish (Spain)", native: "Español (España)", flag: "🇪🇸"}, + %{code: "es-MX", name: "Spanish (Mexico)", native: "Español (México)", flag: "🇲🇽"}, + %{code: "es-AR", name: "Spanish (Argentina)", native: "Español (Argentina)", flag: "🇦🇷"}, + %{code: "es-CO", name: "Spanish (Colombia)", native: "Español (Colombia)", flag: "🇨🇴"}, %{code: "sw", name: "Swahili", native: "Kiswahili", flag: "🇰🇪"}, %{code: "sv", name: "Swedish", native: "Svenska", flag: "🇸🇪"}, %{code: "ta", name: "Tamil", native: "தமிழ்", flag: "🇱🇰"}, @@ -183,8 +193,8 @@ defmodule PhoenixKit.Modules.Languages do @default_config %{ "languages" => [ %{ - "code" => "en", - "name" => "English", + "code" => "en-US", + "name" => "English (United States)", "is_default" => true, "is_enabled" => true } @@ -193,12 +203,37 @@ defmodule PhoenixKit.Modules.Languages do # Top 10 most common languages for permanent display in admin @top_10_languages [ - %{"code" => "en", "name" => "English", "is_default" => true, "is_enabled" => true}, - %{"code" => "es", "name" => "Spanish", "is_default" => false, "is_enabled" => true}, - %{"code" => "fr", "name" => "French", "is_default" => false, "is_enabled" => true}, - %{"code" => "de", "name" => "German", "is_default" => false, "is_enabled" => true}, + %{ + "code" => "en-US", + "name" => "English (United States)", + "is_default" => true, + "is_enabled" => true + }, + %{ + "code" => "es-ES", + "name" => "Spanish (Spain)", + "is_default" => false, + "is_enabled" => true + }, + %{ + "code" => "fr-FR", + "name" => "French (France)", + "is_default" => false, + "is_enabled" => true + }, + %{ + "code" => "de-DE", + "name" => "German (Germany)", + "is_default" => false, + "is_enabled" => true + }, %{"code" => "ja", "name" => "Japanese", "is_default" => false, "is_enabled" => true}, - %{"code" => "pt", "name" => "Portuguese", "is_default" => false, "is_enabled" => true}, + %{ + "code" => "pt-BR", + "name" => "Portuguese (Brazil)", + "is_default" => false, + "is_enabled" => true + }, %{"code" => "it", "name" => "Italian", "is_default" => false, "is_enabled" => true}, %{"code" => "ko", "name" => "Korean", "is_default" => false, "is_enabled" => true}, %{"code" => "ru", "name" => "Russian", "is_default" => false, "is_enabled" => true}, @@ -240,7 +275,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.enable_system() - {:ok, %{"languages" => [%{"code" => "en", ...}]}} + {:ok, %{"languages" => [%{"code" => "en-US", ...}]}} """ def enable_system do # Enable the system @@ -287,10 +322,10 @@ defmodule PhoenixKit.Modules.Languages do iex> PhoenixKit.Modules.Languages.get_config() %{ enabled: true, - languages: [%{"code" => "en", "name" => "English", ...}], + languages: [%{"code" => "en-US", "name" => "English (United States)", ...}], language_count: 1, enabled_count: 1, - default_language: %{"code" => "en", "name" => "English", ...} + default_language: %{"code" => "en-US", "name" => "English (United States)", ...} } """ def get_config do @@ -318,7 +353,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_languages() - [%{"code" => "en", "name" => "English", "is_default" => true, ...}] + [%{"code" => "en-US", "name" => "English (United States)", "is_default" => true, ...}] # When system is disabled: iex> PhoenixKit.Modules.Languages.get_languages() @@ -343,7 +378,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_enabled_languages() - [%{"code" => "en", "name" => "English", ...}] + [%{"code" => "en-US", "name" => "English (United States)", ...}] """ def get_enabled_languages do get_languages() @@ -359,7 +394,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_default_language() - %{"code" => "en", "name" => "English", "is_default" => true, ...} + %{"code" => "en-US", "name" => "English (United States)", "is_default" => true, ...} # When system is disabled: iex> PhoenixKit.Modules.Languages.get_default_language() @@ -381,8 +416,8 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.get_language("es") - %{"code" => "es", "name" => "Spanish", "is_enabled" => true} + iex> PhoenixKit.Modules.Languages.get_language("es-ES") + %{"code" => "es-ES", "name" => "Spanish (Spain)", "is_enabled" => true} iex> PhoenixKit.Modules.Languages.get_language("invalid") nil @@ -404,7 +439,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_language_codes() - ["en", "es", "fr"] + ["en-US", "es-ES", "fr-FR"] """ def get_language_codes do get_languages() @@ -419,7 +454,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_enabled_language_codes() - ["en", "es"] + ["en-US", "es-ES"] """ def get_enabled_language_codes do get_enabled_languages() @@ -435,21 +470,21 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.enabled_locale_codes() - ["en", "es", "fr"] + ["en-US", "es-ES", "fr-FR"] # When system is disabled: iex> PhoenixKit.Modules.Languages.enabled_locale_codes() - ["en"] + ["en-US"] """ def enabled_locale_codes do # Return enabled language codes from the frontend language module only # Admin navbar languages are managed separately in settings if enabled?() do codes = get_enabled_language_codes() - # Ensure we always have at least "en" as a fallback - if Enum.empty?(codes), do: ["en"], else: codes + # Ensure we always have at least "en-US" as a fallback + if Enum.empty?(codes), do: ["en-US"], else: codes else - ["en"] + ["en-US"] end end @@ -466,11 +501,11 @@ defmodule PhoenixKit.Modules.Languages do # When enabled (any number of languages) iex> PhoenixKit.Modules.Languages.get_display_languages() - [%{"code" => "en", "name" => "English", ...}] + [%{"code" => "en-US", "name" => "English (United States)", ...}] # When disabled iex> PhoenixKit.Modules.Languages.get_display_languages() - [%{"code" => "en", ...}, %{"code" => "es", ...}, ...] # Top 12 default + [%{"code" => "en-US", ...}, %{"code" => "es-ES", ...}, ...] # Top 12 default """ def get_display_languages do if enabled?() do @@ -507,7 +542,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.valid_language?("es") + iex> PhoenixKit.Modules.Languages.valid_language?("es-ES") true iex> PhoenixKit.Modules.Languages.valid_language?("invalid") @@ -524,7 +559,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.language_enabled?("es") + iex> PhoenixKit.Modules.Languages.language_enabled?("es-ES") true iex> PhoenixKit.Modules.Languages.language_enabled?("disabled_lang") @@ -547,7 +582,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_default_language_codes() - ["en", "es", "fr", "de", "pt", "it", "nl", "ru", "ja", "ko", "zh-CN", "ar"] + ["en-US", "es-ES", "fr-FR", "de-DE", "pt-BR", "it", "nl", "ru", "ja", "ko", "zh-CN", "ar"] """ def get_default_language_codes do @top_10_languages @@ -563,7 +598,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_available_languages() - [%{code: "en", name: "English", native: "English", flag: "🇺🇸"}, ...] + [%{code: "en-US", name: "English (United States)", native: "English (US)", flag: "🇺🇸"}, ...] """ def get_available_languages do @available_languages @@ -578,7 +613,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples iex> PhoenixKit.Modules.Languages.get_available_languages_for_selection() - [%{code: "es", name: "Spanish", native: "Español", flag: "🇪🇸"}, ...] + [%{code: "es-ES", name: "Spanish (Spain)", native: "Español (España)", flag: "🇪🇸"}, ...] """ def get_available_languages_for_selection do if enabled?() do @@ -598,8 +633,8 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.get_predefined_language("es") - %{code: "es", name: "Spanish", native: "Español", flag: "🇪🇸"} + iex> PhoenixKit.Modules.Languages.get_predefined_language("es-ES") + %{code: "es-ES", name: "Spanish (Spain)", native: "Español (España)", flag: "🇪🇸"} iex> PhoenixKit.Modules.Languages.get_predefined_language("invalid") nil @@ -617,10 +652,10 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.add_language("es") + iex> PhoenixKit.Modules.Languages.add_language("es-ES") {:ok, updated_config} - iex> PhoenixKit.Modules.Languages.add_language("en") # if already exists + iex> PhoenixKit.Modules.Languages.add_language("en-US") # if already exists {:error, "Language already exists"} iex> PhoenixKit.Modules.Languages.add_language("invalid") @@ -668,7 +703,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.update_language("es", %{name: "Español"}) + iex> PhoenixKit.Modules.Languages.update_language("es-ES", %{name: "Español"}) {:ok, updated_config} iex> PhoenixKit.Modules.Languages.update_language("nonexistent", %{name: "Test"}) @@ -694,10 +729,10 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.remove_language("es") + iex> PhoenixKit.Modules.Languages.remove_language("es-ES") {:ok, updated_config} - iex> PhoenixKit.Modules.Languages.remove_language("en") # if it's default + iex> PhoenixKit.Modules.Languages.remove_language("en-US") # if it's default {:error, "Cannot remove default language"} """ def remove_language(code) when is_binary(code) do @@ -735,7 +770,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.set_default_language("es") + iex> PhoenixKit.Modules.Languages.set_default_language("es-ES") {:ok, updated_config} iex> PhoenixKit.Modules.Languages.set_default_language("nonexistent") @@ -750,7 +785,7 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.enable_language("es") + iex> PhoenixKit.Modules.Languages.enable_language("es-ES") {:ok, updated_config} """ def enable_language(code) when is_binary(code) do @@ -764,10 +799,10 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.disable_language("es") + iex> PhoenixKit.Modules.Languages.disable_language("es-ES") {:ok, updated_config} - iex> PhoenixKit.Modules.Languages.disable_language("en") # if it's default + iex> PhoenixKit.Modules.Languages.disable_language("en-US") # if it's default {:error, "Cannot disable default language"} """ def disable_language(code) when is_binary(code) do @@ -788,10 +823,10 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.move_language_up("es") + iex> PhoenixKit.Modules.Languages.move_language_up("es-ES") {:ok, updated_config} - iex> PhoenixKit.Modules.Languages.move_language_up("en") # if first in array + iex> PhoenixKit.Modules.Languages.move_language_up("en-US") # if first in array {:error, "Language is already at the top"} """ def move_language_up(code) when is_binary(code) do @@ -835,10 +870,10 @@ defmodule PhoenixKit.Modules.Languages do ## Examples - iex> PhoenixKit.Modules.Languages.move_language_down("en") + iex> PhoenixKit.Modules.Languages.move_language_down("en-US") {:ok, updated_config} - iex> PhoenixKit.Modules.Languages.move_language_down("es") # if last in array + iex> PhoenixKit.Modules.Languages.move_language_down("es-ES") # if last in array {:error, "Language is already at the bottom"} """ def move_language_down(code) when is_binary(code) do diff --git a/lib/phoenix_kit/settings/settings.ex b/lib/phoenix_kit/settings/settings.ex index 25483d92d..3c8adc7db 100644 --- a/lib/phoenix_kit/settings/settings.ex +++ b/lib/phoenix_kit/settings/settings.ex @@ -740,30 +740,34 @@ defmodule PhoenixKit.Settings do ], "time_zone" => [ {"UTC-12 (Baker Island)", "-12"}, - {"UTC-11 (American Samoa)", "-11"}, - {"UTC-10 (Hawaii)", "-10"}, - {"UTC-9 (Alaska)", "-9"}, - {"UTC-8 (Pacific Time)", "-8"}, - {"UTC-7 (Mountain Time)", "-7"}, - {"UTC-6 (Central Time)", "-6"}, - {"UTC-5 (Eastern Time)", "-5"}, - {"UTC-4 (Atlantic Time)", "-4"}, - {"UTC-3 (Argentina)", "-3"}, - {"UTC-2 (Mid-Atlantic)", "-2"}, - {"UTC-1 (Cape Verde)", "-1"}, - {"UTC+0 (GMT/London)", "0"}, - {"UTC+1 (Central Europe)", "1"}, - {"UTC+2 (Eastern Europe)", "2"}, - {"UTC+3 (Moscow)", "3"}, - {"UTC+4 (Dubai)", "4"}, - {"UTC+5 (Pakistan)", "5"}, - {"UTC+6 (Bangladesh)", "6"}, - {"UTC+7 (Thailand)", "7"}, - {"UTC+8 (China/Singapore)", "8"}, - {"UTC+9 (Japan/Korea)", "9"}, - {"UTC+10 (Australia East)", "10"}, - {"UTC+11 (Solomon Islands)", "11"}, - {"UTC+12 (New Zealand)", "12"} + {"UTC-11 (Pago Pago, Niue)", "-11"}, + {"UTC-10 (Honolulu, Tahiti)", "-10"}, + {"UTC-9 (Anchorage, Juneau)", "-9"}, + {"UTC-8 (Los Angeles, Vancouver, Seattle)", "-8"}, + {"UTC-7 (Denver, Phoenix, Calgary)", "-7"}, + {"UTC-6 (Chicago, Mexico City, Guatemala)", "-6"}, + {"UTC-5 (New York, Toronto, Bogotá, Lima)", "-5"}, + {"UTC-4 (Halifax, Caracas, Santiago)", "-4"}, + {"UTC-3 (Buenos Aires, São Paulo, Montevideo)", "-3"}, + {"UTC-2 (South Georgia)", "-2"}, + {"UTC-1 (Azores, Cape Verde)", "-1"}, + {"UTC+0 (London, Dublin, Lisbon, Accra)", "0"}, + {"UTC+1 (Paris, Berlin, Rome, Madrid, Lagos)", "1"}, + {"UTC+2 (Kyiv, Athens, Helsinki, Cairo, Johannesburg)", "2"}, + {"UTC+3 (Istanbul, Riyadh, Nairobi, Baghdad, Moscow)", "3"}, + {"UTC+4 (Dubai, Baku, Tbilisi)", "4"}, + {"UTC+5 (Karachi, Tashkent, Yekaterinburg)", "5"}, + {"UTC+5:30 (Mumbai, Delhi, Kolkata, Colombo)", "5.5"}, + {"UTC+6 (Dhaka, Almaty, Bishkek)", "6"}, + {"UTC+7 (Bangkok, Jakarta, Ho Chi Minh City)", "7"}, + {"UTC+8 (Beijing, Singapore, Hong Kong, Perth)", "8"}, + {"UTC+9 (Tokyo, Seoul, Pyongyang)", "9"}, + {"UTC+9:30 (Adelaide, Darwin)", "9.5"}, + {"UTC+10 (Sydney, Melbourne, Brisbane)", "10"}, + {"UTC+11 (Honiara, Noumea)", "11"}, + {"UTC+12 (Auckland, Fiji, Wellington)", "12"}, + {"UTC+13 (Nuku'alofa, Apia)", "13"}, + {"UTC+14 (Kiritimati)", "14"} ], "date_format" => UtilsDate.get_date_format_options(), "time_format" => UtilsDate.get_time_format_options() diff --git a/lib/phoenix_kit/utils/routes.ex b/lib/phoenix_kit/utils/routes.ex index 42b90f945..3ab469fcb 100644 --- a/lib/phoenix_kit/utils/routes.ex +++ b/lib/phoenix_kit/utils/routes.ex @@ -23,7 +23,6 @@ defmodule PhoenixKit.Utils.Routes do case locale do :none -> "#{base_path}#{url_path}" - "en" -> "#{base_path}#{url_path}" locale_value -> "#{base_path}/#{locale_value}#{url_path}" end else diff --git a/lib/phoenix_kit_web/components/admin_nav.ex b/lib/phoenix_kit_web/components/admin_nav.ex index da24e0807..2eb566f24 100644 --- a/lib/phoenix_kit_web/components/admin_nav.ex +++ b/lib/phoenix_kit_web/components/admin_nav.ex @@ -44,6 +44,7 @@ defmodule PhoenixKitWeb.Components.AdminNav do attr(:nested, :boolean, default: false) attr(:disable_active, :boolean, default: false) attr(:exact_match_only, :boolean, default: false) + attr(:submenu_open, :boolean, default: false) def admin_nav_item(assigns) do active = @@ -64,10 +65,16 @@ defmodule PhoenixKitWeb.Components.AdminNav do navigate={@href} class={[ "flex items-center py-2 rounded-lg text-sm font-medium transition-colors group", - if(@active, - do: "bg-primary text-primary-content hover:bg-primary/90", - else: "text-base-content hover:bg-base-200 hover:text-primary" - ), + cond do + @active -> + "bg-primary text-primary-content hover:bg-primary/90" + + @submenu_open -> + "bg-base-200/50 text-base-content hover:bg-base-200 hover:text-primary" + + true -> + "text-base-content hover:bg-base-200 hover:text-primary" + end, if(@mobile, do: "w-full", else: ""), if(@nested, do: "pl-8 pr-3", else: "px-3") ]} @@ -131,6 +138,8 @@ defmodule PhoenixKitWeb.Components.AdminNav do <.icon name="hero-wrench-screwdriver" class="w-5 h-5" /> <% "storage" -> %> <.icon name="hero-folder" class="w-5 h-5" /> + <% "photo" -> %> + <.icon name="hero-photo" class="w-5 h-5" /> <% _ -> %> <.icon name="hero-squares-2x2" class="w-5 h-5" /> <% end %> @@ -588,7 +597,7 @@ defmodule PhoenixKitWeb.Components.AdminNav do end defp locale_candidate?(locale) do - String.length(locale) in 2..5 and Regex.match?(~r/^[a-z]{2}(?:-[A-Za-z0-9]{2,})?$/, locale) + String.length(locale) in 2..6 and Regex.match?(~r/^[a-z]{2}(?:-[A-Z]{2})?$/, locale) end # Helper function to get admin languages from settings diff --git a/lib/phoenix_kit_web/components/layout_wrapper.ex b/lib/phoenix_kit_web/components/layout_wrapper.ex index d061e75b2..d807153da 100644 --- a/lib/phoenix_kit_web/components/layout_wrapper.ex +++ b/lib/phoenix_kit_web/components/layout_wrapper.ex @@ -244,6 +244,15 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do label="Users" current_path={@current_path || ""} disable_active={true} + submenu_open={ + submenu_open?(@current_path, [ + "/admin/users", + "/admin/users/live_sessions", + "/admin/users/sessions", + "/admin/users/roles", + "/admin/users/referral-codes" + ]) + } /> <%= if submenu_open?(@current_path, ["/admin/users", "/admin/users/live_sessions", "/admin/users/sessions", "/admin/users/roles", "/admin/users/referral-codes"]) do %> @@ -309,6 +318,15 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do label="Emails" current_path={@current_path || ""} disable_active={true} + submenu_open={ + submenu_open?(@current_path, [ + "/admin/emails", + "/admin/emails/dashboard", + "/admin/modules/emails/templates", + "/admin/emails/queue", + "/admin/emails/blocklist" + ]) + } /> <%= if submenu_open?(@current_path, ["/admin/emails", "/admin/emails/dashboard", "/admin/modules/emails/templates", "/admin/emails/queue", "/admin/emails/blocklist"]) do %> @@ -365,6 +383,7 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do label="Entities" current_path={@current_path || ""} disable_active={true} + submenu_open={submenu_open?(@current_path, ["/admin/entities"])} /> <%= if submenu_open?(@current_path, ["/admin/entities"]) do %> @@ -405,6 +424,7 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do label="Blogging" current_path={@current_path || ""} exact_match_only={true} + submenu_open={submenu_open?(@current_path, ["/admin/blogging"])} /> <%= if submenu_open?(@current_path, ["/admin/blogging"]) do %> @@ -436,6 +456,21 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do label="Settings" current_path={@current_path || ""} disable_active={true} + submenu_open={ + submenu_open?(@current_path, [ + "/admin/settings", + "/admin/settings/users", + "/admin/settings/referral-codes", + "/admin/settings/emails", + "/admin/settings/languages", + "/admin/settings/entities", + "/admin/settings/media", + "/admin/settings/storage/dimensions", + "/admin/settings/maintenance", + "/admin/settings/blogging", + "/admin/settings/seo" + ]) + } /> <%= if submenu_open?(@current_path, ["/admin/settings", "/admin/settings/users", "/admin/settings/referral-codes", "/admin/settings/emails", "/admin/settings/languages", "/admin/settings/entities", "/admin/settings/media", "/admin/settings/storage/dimensions", "/admin/settings/maintenance", "/admin/settings/blogging", "/admin/settings/seo"]) do %> @@ -522,7 +557,7 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do <%!-- Media section with submenu --%> <.admin_nav_item href={Routes.locale_aware_path(assigns, "/admin/settings/media")} - icon="storage" + icon="photo" label="Media" current_path={@current_path || ""} nested={true} @@ -840,7 +875,10 @@ defmodule PhoenixKitWeb.Components.LayoutWrapper do end end - defp looks_like_locale?(locale), do: String.length(locale) <= 3 + defp looks_like_locale?(locale) do + # Match 2-letter codes (en, es) or regional variants (en-US, es-ES, zh-CN) + String.length(locale) <= 6 and String.match?(locale, ~r/^[a-z]{2}(-[A-Z]{2})?$/) + end defp path_matches_any?(normalized_path, paths) do Enum.any?(paths, fn path -> diff --git a/lib/phoenix_kit_web/live/modules/languages.ex b/lib/phoenix_kit_web/live/modules/languages.ex index c85e54e74..06804f4b6 100644 --- a/lib/phoenix_kit_web/live/modules/languages.ex +++ b/lib/phoenix_kit_web/live/modules/languages.ex @@ -39,6 +39,7 @@ defmodule PhoenixKitWeb.Live.Modules.Languages do |> assign(:language_count, length(display_languages)) |> assign(:enabled_count, Enum.count(display_languages, & &1["is_enabled"])) |> assign(:default_language, Enum.find(display_languages, & &1["is_default"])) + |> assign(:unknown_language_codes, get_unknown_language_codes(display_languages)) |> assign( :available_languages_for_selection, Languages.get_available_languages_for_selection() @@ -285,6 +286,7 @@ defmodule PhoenixKitWeb.Live.Modules.Languages do |> assign(:language_count, length(display_languages)) |> assign(:enabled_count, Enum.count(display_languages, & &1["is_enabled"])) |> assign(:default_language, Enum.find(display_languages, & &1["is_default"])) + |> assign(:unknown_language_codes, get_unknown_language_codes(display_languages)) end # Helper function to generate the language switcher code based on current settings @@ -308,4 +310,13 @@ defmodule PhoenixKitWeb.Live.Modules.Languages do nil -> "🌐" end end + + # Helper function to identify unknown/deprecated language codes + defp get_unknown_language_codes(languages) do + languages + |> Enum.map(& &1["code"]) + |> Enum.filter(fn code -> + Languages.get_predefined_language(code) == nil + end) + end end diff --git a/lib/phoenix_kit_web/live/modules/languages.html.heex b/lib/phoenix_kit_web/live/modules/languages.html.heex index 43871bddd..6cf65ff25 100644 --- a/lib/phoenix_kit_web/live/modules/languages.html.heex +++ b/lib/phoenix_kit_web/live/modules/languages.html.heex @@ -111,6 +111,9 @@ <%= if language["is_default"] do %> Default <% end %> + <%= if language["code"] in @unknown_language_codes do %> + Unknown + <% end %>
<%!-- Move buttons only in configured mode --%> @@ -170,8 +173,8 @@ <% end %> - <%!-- Remove Button (only in configured mode, and not the default language) --%> - <%= if @in_configured_mode and not language["is_default"] do %> + <%!-- Remove Button (show for unknown codes or in configured mode, but not for default language) --%> + <%= if (language["code"] in @unknown_language_codes and not language["is_default"]) or (@in_configured_mode and not language["is_default"]) do %>