diff --git a/app/Helpers/translation_helpers.php b/app/Helpers/translation_helpers.php index 36fad85..ed76ea9 100644 --- a/app/Helpers/translation_helpers.php +++ b/app/Helpers/translation_helpers.php @@ -222,6 +222,93 @@ if (!function_exists('get_translation_status_color')) { } } +if (!function_exists('flag_emoji_from_country_code')) { + /** + * Build a flag emoji from a two-letter country/region code (e.g. TR → 🇹🇷). + */ + function flag_emoji_from_country_code(string $countryCode): string + { + $countryCode = strtoupper(substr($countryCode, 0, 2)); + $flag = ''; + + for ($i = 0; $i < strlen($countryCode); $i++) { + $flag .= mb_chr(127397 + ord($countryCode[$i])); + } + + return $flag; + } +} + +if (!function_exists('country_code_from_flag_emoji')) { + /** + * Extract a two-letter code from a flag emoji (e.g. 🇬🇧 → GB). + */ + function country_code_from_flag_emoji(?string $flag): ?string + { + if (empty($flag)) { + return null; + } + + $code = ''; + + foreach (mb_str_split($flag) as $char) { + $ord = mb_ord($char); + + if ($ord >= 0x1F1E6 && $ord <= 0x1F1FF) { + $code .= chr(ord('A') + ($ord - 0x1F1E6)); + } + } + + return strlen($code) === 2 ? $code : null; + } +} + +if (!function_exists('resolve_language_flag')) { + /** + * Resolve flag emoji for a language (stored flag or generated from code). + */ + function resolve_language_flag(Language|string $language): string + { + if (is_string($language)) { + $language = Language::findByCode($language); + } + + if (! $language) { + return '🌐'; + } + + if (! empty($language->flag) && $language->flag !== '🌐') { + return $language->flag; + } + + return flag_emoji_from_country_code($language->code); + } +} + +if (!function_exists('get_language_short_code')) { + /** + * Short display code for language (from flag region, e.g. GB, TR, SE). + */ + function get_language_short_code(Language|string $language): string + { + if (is_string($language)) { + $model = Language::findByCode($language); + + return $model ? get_language_short_code($model) : strtoupper($language); + } + + $fromFlag = country_code_from_flag_emoji($language->flag); + + if ($fromFlag) { + return $fromFlag; + } + + $fromResolved = country_code_from_flag_emoji(resolve_language_flag($language)); + + return $fromResolved ?: strtoupper($language->code); + } +} + if (!function_exists('get_language_flag')) { /** * Get language flag emoji or icon @@ -229,7 +316,8 @@ if (!function_exists('get_language_flag')) { function get_language_flag(string $languageCode): string { $language = Language::findByCode($languageCode); - return $language ? ($language->flag ?? '🌐') : '🌐'; + + return $language ? resolve_language_flag($language) : '🌐'; } } diff --git a/resources/views/components/custom/language-selector.blade.php b/resources/views/components/custom/language-selector.blade.php index 69db859..0cb495e 100644 --- a/resources/views/components/custom/language-selector.blade.php +++ b/resources/views/components/custom/language-selector.blade.php @@ -8,42 +8,48 @@ $currentLanguage = $languages->firstWhere('code', $currentLang); $languageCollapseId = 'offcanvas-language-collapse'; + $languageLabel = static function ($language): string { + return $language->native_name ?: $language->name ?: strtoupper($language->code); + }; + + $languageFlag = static function ($language): string { + return resolve_language_flag($language); + }; + $wrapperClass = $variant === 'offcanvas' ? 'language-select-offcanvas w-full' : 'navbar-other !ml-5 header-language-desktop !hidden lg:!flex xl:!flex shrink-0'; - $linkClass = 'nav-link dropdown-item dropdown-toggle xl:!text-[.85rem] lg:!text-[.85rem] max-lg:!text-[1.05rem]'; + $linkClass = 'nav-link dropdown-item dropdown-toggle language-select__trigger xl:!text-[.85rem] lg:!text-[.85rem] max-lg:!text-[1.05rem] !normal-case'; @endphp @if($variant === 'offcanvas')
merge(['class' => $wrapperClass]) }}>
-