Files
takeone-youtube-clone/app/Data/CountryLanguages.php
T
ghassanandClaude Opus 4.7 2d33e39b9b Add AI translation for comments and video descriptions
Comments get a Translate button that calls the active LLM provider in Admin → AI
settings. Each commenter shows a small country flag inferred from their
video_views + profile_visits history (falls back to users.nationality); that
inferred country drives the language hint passed to the LLM so Portuguese
"Linda, linda, linda" translates to "Beautiful" instead of pass-through.

Description boxes get a line-paired translation grid: a shared Translate button
flips #vdbDescSplit into a two-column CSS grid where every source line sits
next to its translation on the same row. Backend splits by newline and asks
the LLM for a JSON map keyed by index so counts always match.

LlmLyricsService now has translate() + translateLines() with echo-retry (if the
model returns the input unchanged while source != target, retry once with a
stronger directive) and keeps the Ollama model resident via keep_alive=1h.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-10-02 12:18:20 +03:00

51 lines
2.2 KiB
PHP

<?php
namespace App\Data;
class CountryLanguages
{
private const MAP = [
'AE' => 'ar', 'AF' => 'ps', 'AL' => 'sq', 'AM' => 'hy', 'AO' => 'pt',
'AR' => 'es', 'AT' => 'de', 'AU' => 'en', 'AZ' => 'az',
'BA' => 'bs', 'BD' => 'bn', 'BE' => 'nl', 'BG' => 'bg', 'BH' => 'ar',
'BO' => 'es', 'BR' => 'pt', 'BY' => 'be',
'CA' => 'en', 'CH' => 'de', 'CL' => 'es', 'CN' => 'zh', 'CO' => 'es',
'CR' => 'es', 'CU' => 'es', 'CZ' => 'cs',
'DE' => 'de', 'DK' => 'da', 'DO' => 'es', 'DZ' => 'ar',
'EC' => 'es', 'EE' => 'et', 'EG' => 'ar', 'ES' => 'es', 'ET' => 'am',
'FI' => 'fi', 'FR' => 'fr',
'GB' => 'en', 'GE' => 'ka', 'GR' => 'el', 'GT' => 'es',
'HK' => 'zh', 'HN' => 'es', 'HR' => 'hr', 'HU' => 'hu',
'ID' => 'id', 'IE' => 'en', 'IL' => 'he', 'IN' => 'hi', 'IQ' => 'ar',
'IR' => 'fa', 'IS' => 'is', 'IT' => 'it',
'JO' => 'ar', 'JP' => 'ja',
'KE' => 'sw', 'KG' => 'ky', 'KH' => 'km', 'KR' => 'ko', 'KW' => 'ar',
'KZ' => 'kk',
'LA' => 'lo', 'LB' => 'ar', 'LK' => 'si', 'LT' => 'lt', 'LU' => 'fr',
'LV' => 'lv', 'LY' => 'ar',
'MA' => 'ar', 'MD' => 'ro', 'ME' => 'sr', 'MK' => 'mk', 'MM' => 'my',
'MN' => 'mn', 'MT' => 'mt', 'MX' => 'es', 'MY' => 'ms',
'NG' => 'en', 'NI' => 'es', 'NL' => 'nl', 'NO' => 'no', 'NP' => 'ne',
'NZ' => 'en',
'OM' => 'ar',
'PA' => 'es', 'PE' => 'es', 'PH' => 'tl', 'PK' => 'ur', 'PL' => 'pl',
'PR' => 'es', 'PS' => 'ar', 'PT' => 'pt', 'PY' => 'es',
'QA' => 'ar',
'RO' => 'ro', 'RS' => 'sr', 'RU' => 'ru',
'SA' => 'ar', 'SD' => 'ar', 'SE' => 'sv', 'SG' => 'en', 'SI' => 'sl',
'SK' => 'sk', 'SO' => 'so', 'SV' => 'es', 'SY' => 'ar',
'TH' => 'th', 'TJ' => 'tg', 'TN' => 'ar', 'TR' => 'tr', 'TW' => 'zh',
'TZ' => 'sw',
'UA' => 'uk', 'UG' => 'en', 'US' => 'en', 'UY' => 'es', 'UZ' => 'uz',
'VE' => 'es', 'VN' => 'vi',
'YE' => 'ar',
'ZA' => 'en', 'ZW' => 'en',
];
public static function primary(?string $iso2): ?string
{
if (! $iso2) return null;
return self::MAP[strtoupper($iso2)] ?? null;
}
}