Packages

phoenix_kit

1.7.113
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit_web live modules languages.html.heex
Raw

lib/phoenix_kit_web/live/modules/languages.html.heex

<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="{@project_title} Languages"
current_path={@current_path}
project_title={@project_title}
current_locale={@current_locale}
>
<div
id="languages-content"
class="container flex flex-col mx-auto px-4 py-6"
phx-hook="PreserveScroll"
>
<.admin_page_header
back={PhoenixKit.Utils.Routes.path("/admin/modules")}
title="Languages"
subtitle="Manage available languages for your application"
/>
<%!-- Summary Section --%>
<div class="card bg-base-100 shadow-xl mb-6">
<div class="card-body">
<h3 class="card-title text-xl">{gettext("Summary")}</h3>
<%!-- Stats Row --%>
<div class="stats stats-vertical lg:stats-horizontal shadow bg-base-200 mt-2">
<div class="stat">
<div class="stat-title">{gettext("Languages Enabled")}</div>
<div class="stat-value text-primary">{@enabled_count}</div>
</div>
<div class="stat">
<div class="stat-title">{gettext("Countries Covered")}</div>
<div class="stat-value text-secondary">{@covered_count}</div>
</div>
</div>
<%= if @enabled_count > 0 do %>
<%!-- Enabled Languages List --%>
<div class="mt-4">
<div class="flex items-center justify-between mb-2">
<h4 class="font-semibold">{gettext("Enabled Languages")}</h4>
<div class="flex items-center gap-3">
<button
phx-click="toggle_reorder"
class={[
"btn btn-xs gap-1",
if(@show_reorder, do: "btn-error", else: "btn-ghost")
]}
>
<%= if @show_reorder do %>
<.icon name="hero-check" class="w-3 h-3" /> {gettext("Done")}
<% else %>
<.icon name="hero-arrows-up-down" class="w-3 h-3" /> {gettext("Reorder")}
<% end %>
</button>
<div class="flex items-center gap-3 text-xs text-base-content/60">
<span class="flex items-center gap-1">
<span class="badge badge-secondary badge-xs h-auto"></span> {gettext(
"Default"
)}
</span>
<span class="flex items-center gap-1">
<span class="badge badge-primary badge-xs h-auto"></span> {gettext("Enabled")}
</span>
</div>
</div>
</div>
<%= if @show_reorder do %>
<%!-- Draggable Reorder List --%>
<.draggable_list
id="language-reorder"
items={Enum.filter(@languages, & &1.is_enabled)}
item_id={& &1.code}
on_reorder="reorder_languages"
layout={:list}
gap="gap-2"
class="!flex-row flex-wrap"
item_class="pk-sortable-wiggle"
hide_source={true}
>
<:item :let={lang}>
<div class={[
"badge",
if(lang.code == @default_code,
do: "badge-secondary",
else: "badge-primary"
)
]}>
{lang.name}
</div>
</:item>
</.draggable_list>
<% else %>
<%!-- Static Badge List --%>
<div class="flex flex-wrap gap-2">
<%= for lang <- @languages |> Enum.filter(& &1.is_enabled) do %>
<div class="dropdown dropdown-hover">
<div
tabindex="0"
role="button"
class={[
"badge cursor-pointer",
if(lang.code == @default_code,
do: "badge-secondary",
else: "badge-primary"
)
]}
title={lang.code}
>
{lang.name}
</div>
<ul
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-40 border border-base-300"
>
<%= if lang.code != @default_code do %>
<li>
<button phx-click="set_default" phx-value-code={lang.code}>
<PhoenixKitWeb.Components.Core.Icons.icon_star class="w-4 h-4" />
{gettext("Set Default")}
</button>
</li>
<li>
<button
phx-click="toggle_language_availability"
phx-value-code={lang.code}
class="text-error"
>
<PhoenixKitWeb.Components.Core.Icons.icon_x class="w-4 h-4" /> {gettext(
"Disable"
)}
</button>
</li>
<% else %>
<li class="disabled">
<span class="text-base-content/60 text-sm">
{gettext("Default language")}
</span>
</li>
<% end %>
</ul>
</div>
<% end %>
</div>
<% end %>
</div>
<%!-- Covered Countries List --%>
<div class="mt-4">
<h4 class="font-semibold mb-2">{gettext("Countries Covered")}</h4>
<div class="flex flex-wrap gap-2">
<%= for {country, flag} <- @covered_countries do %>
<span class="badge badge-outline">{flag} {country}</span>
<% end %>
</div>
</div>
<% else %>
<p class="text-base-content/60 mt-4">{gettext("No languages enabled yet.")}</p>
<% end %>
</div>
</div>
<%!-- Languages Management Section --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<div class="mb-4">
<h3 class="card-title text-xl">{gettext("Available Languages")}</h3>
<p class="text-sm text-base-content/60 mt-1">
Enable languages for your application ({@enabled_count} enabled)
</p>
</div>
<%!-- Search Input --%>
<div class="mb-4">
<input
type="text"
placeholder="Search countries or languages..."
class="input input-bordered w-full"
phx-keyup="search_countries"
phx-debounce="150"
value={@search_query}
/>
</div>
<%!-- Languages List grouped by Continent -> Country --%>
<div class="space-y-4">
<%= for {continent, countries} <- filter_grouped_languages(@grouped_languages, @search_query) do %>
<details class="collapse collapse-arrow bg-base-300 rounded-lg">
<summary class="collapse-title font-bold text-lg py-3">
<span class="ml-2">{continent}</span>
<span class="badge badge-ghost badge-sm ml-2">
{count_covered_countries_in_continent(countries, @enabled_codes)}/{length(
countries
)} countries
</span>
</summary>
<div class="collapse-content px-2 pb-2">
<div class="space-y-2">
<%= for {country, country_flag, languages} <- countries do %>
<details class="collapse collapse-arrow bg-base-200 rounded-lg">
<summary class="collapse-title font-medium py-2">
<span class="text-lg">{country_flag}</span>
<span class="ml-2">{country}</span>
<span class="badge badge-ghost badge-xs ml-2">
{count_enabled(languages, @enabled_codes)}/{length(languages)}
</span>
</summary>
<div class="collapse-content px-2 pb-2">
<div class="space-y-1">
<%= for language <- languages do %>
<div class="flex items-center justify-between p-2 hover:bg-base-100 rounded-lg">
<div class="flex items-center gap-2 flex-1">
<span class="font-medium">
{language.native}
<span class="text-base-content/60">({language.name})</span>
</span>
<span class="badge badge-outline badge-xs h-auto">
{language.code}
</span>
<%= if language.code == @default_code do %>
<span class="badge badge-primary badge-xs h-auto">
{gettext("Default")}
</span>
<% end %>
</div>
<div class="flex items-center gap-2">
<%!-- Set Default Button (only for enabled, non-default languages) --%>
<%= if language.code in @enabled_codes and language.code != @default_code do %>
<button
class="btn btn-ghost btn-xs tooltip tooltip-bottom"
phx-click="set_default"
phx-value-code={language.code}
data-tip={gettext("Set Default")}
>
<.icon name="hero-star" class="w-4 h-4 hidden sm:inline" />
<span class="sm:hidden whitespace-nowrap">
{gettext("Set Default")}
</span>
</button>
<% end %>
<%!-- Enable/Disable Toggle --%>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={language.code in @enabled_codes}
phx-click="toggle_language_availability"
phx-value-code={language.code}
disabled={language.code == @default_code}
/>
</div>
</div>
<% end %>
</div>
</div>
</details>
<% end %>
</div>
</div>
</details>
<% end %>
</div>
</div>
</div>
<%!-- Help Section --%>
<div class="alert alert-info mt-6">
<PhoenixKitWeb.Components.Core.Icons.icon_info class="w-5 h-5" />
<div>
<h3 class="font-bold">{gettext("Language Configuration")}</h3>
<div class="text-sm space-y-1">
<p>• Toggle languages on/off to enable or disable them for your application</p>
<p>• The default language cannot be disabled and serves as the fallback</p>
<p>• Click "Set Default" on any enabled language to make it the default</p>
</div>
</div>
</div>
<%!-- Frontend Language Switcher Component Section --%>
<div class="card bg-base-100 shadow-xl mt-6">
<div class="card-body">
<h2 class="card-title text-xl mb-4">{gettext("Frontend Language Switcher")}</h2>
<p class="text-base-content/70 mb-6">
Configure and preview the language switcher component for your frontend application.
</p>
<%= if @ml_enabled and length(@languages) >= 1 do %>
<%!-- Two Column Layout: Settings | Preview --%>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 auto-rows-fr">
<%!-- Left Column: Settings --%>
<div class="lg:col-span-1 border border-base-200 rounded-lg p-4 flex flex-col">
<h3 class="font-bold mb-4">{gettext("Switcher Settings")}</h3>
<div class="space-y-4">
<%!-- Show Flags Toggle --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">{gettext("Show Flags")}</span>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={@switcher_show_flags}
phx-click="toggle_switcher_setting"
phx-value-setting="switcher_show_flags"
/>
</label>
</div>
<%!-- Show Language Names Toggle --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">{gettext("Show Names")}</span>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={@switcher_show_names}
phx-click="toggle_switcher_setting"
phx-value-setting="switcher_show_names"
/>
</label>
</div>
<%!-- Show Native Names Toggle --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">{gettext("Native Names")}</span>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={@switcher_show_native_names}
phx-click="toggle_switcher_setting"
phx-value-setting="switcher_show_native_names"
/>
</label>
</div>
<%!-- Go to Home Page Toggle --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">{gettext("Go to Home")}</span>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={@switcher_goto_home}
phx-click="toggle_switcher_setting"
phx-value-setting="switcher_goto_home"
/>
</label>
</div>
<%!-- Hide Current Language Toggle --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text">{gettext("Hide Current")}</span>
<input
type="checkbox"
class="toggle toggle-sm toggle-primary"
checked={@switcher_hide_current}
phx-click="toggle_switcher_setting"
phx-value-setting="switcher_hide_current"
/>
</label>
</div>
</div>
</div>
<%!-- Right Column: Preview and Code --%>
<div class="lg:col-span-2 space-y-4">
<%!-- Live Preview --%>
<div class="border border-base-200 rounded-lg p-4">
<h3 class="font-bold mb-3">{gettext("Live Preview")}</h3>
<div class="bg-base-200 rounded p-4 flex items-center justify-center min-h-24">
<.language_switcher_dropdown
current_locale={@current_locale}
show_flags={@switcher_show_flags}
show_names={@switcher_show_names}
show_native_names={@switcher_show_native_names}
_language_update_key={@language_count}
/>
</div>
</div>
<%!-- Generated Code --%>
<div class="border border-base-200 rounded-lg p-4">
<h3 class="font-bold mb-3">{gettext("Generated Code")}</h3>
<div class="text-xs text-base-content/60 bg-base-200 rounded p-3 font-mono overflow-x-auto">
<pre>{generate_switcher_code(@switcher_show_flags, @switcher_show_names, @switcher_goto_home, @switcher_hide_current, @switcher_show_native_names)}</pre>
</div>
<p class="text-xs text-base-content/60 mt-2">
Copy this code to your frontend application and customize as needed.
</p>
</div>
</div>
</div>
<%!-- Implementation Instructions --%>
<div class="alert alert-warning mt-6">
<PhoenixKitWeb.Components.Core.Icons.icon_warning class="w-5 h-5" />
<div>
<h3 class="font-bold">{gettext("Implementation Notes")}</h3>
<div class="text-sm space-y-1">
<p>
• Make sure <code class="bg-base-300 px-2 py-1 rounded">@current_locale</code>
is available in your assigns
</p>
<p>
• The component automatically fetches enabled languages from the Language Module
</p>
<p>• Only enabled languages will appear in the switcher</p>
<p>• Language switcher works with your existing route-based locale system</p>
</div>
</div>
</div>
<% else %>
<div class="alert alert-info">
<PhoenixKitWeb.Components.Core.Icons.icon_info class="w-5 h-5" />
<div>
<h3 class="font-bold">{gettext("Enable and Configure Languages")}</h3>
<p class="text-sm mt-2">
<%= if not @ml_enabled do %>
First, enable the Languages module using the toggle at the top, then add at least one language to see live previews of the language switcher component.
<% else %>
Add at least one language using the form above to see live previews of the language switcher component.
<% end %>
</p>
</div>
</div>
<% end %>
</div>
</div>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>