# Web UI Locale Utilities

This document describes the comprehensive locale utility system for the web UI, providing support for audio and subtitle language selection.

## Overview

The locale utilities (`pkg/web/locale_utils.go`) provide a rich set of functions for:
- Loading and searching language data from `locales.json`
- Filtering languages (common only, by search term, by country)
- Formatting language displays with flag emojis, country codes, and localized names
- Generating flag image URLs for web UI rendering

## Key Components

### LanguageOption Struct

The `LanguageOption` struct holds comprehensive language display data:

```go
type LanguageOption struct {
    Locale        string `json:"locale"`         // Full locale string (e.g., "ja-JP")
    LanguageName  string `json:"language_name"`  // English name (e.g., "Japanese")
    LanguageLocal string `json:"language_local"` // Native name (e.g., "日本語")
    FlagEmoji     string `json:"flag_emoji"`     // Flag emoji (e.g., "🇯🇵")
    CountryCode   string `json:"country_code"`   // ISO code (e.g., "JP")
    CountryName   string `json:"country_name"`   // Country name (e.g., "Japan")
    DisplayText   string `json:"display_text"`   // Formatted display text
}
```

### LanguageFilterOptions

Configure search/filter behavior:

```go
type LanguageFilterOptions struct {
    CommonOnly bool   // Show only common languages
    SearchTerm string // Search by language name or country code
    Limit      int    // Maximum results (0 = no limit)
}
```

## API Reference

### Core Functions

#### `LoadAllLanguages() ([]locale.LocaleEntry, error)`
Loads all language entries from embedded `locales.json`.

**Returns:**
- All locale entries from the JSON file
- Error if loading fails

#### `SearchLanguages(opts LanguageFilterOptions) ([]LanguageOption, error)`
Searches and filters languages based on provided options.

**Parameters:**
- `opts`: Filter options (common only, search term, limit)

**Returns:**
- Filtered and sorted language options
- Error if loading fails

**Example:**
```go
// Get first 10 common languages
opts := LanguageFilterOptions{
    CommonOnly: true,
    Limit: 10,
}
results, err := SearchLanguages(opts)

// Search for "Japanese" in all languages
opts := LanguageFilterOptions{
    SearchTerm: "Japanese",
}
results, err := SearchLanguages(opts)
```

#### `GetCommonLanguageOptions() ([]LanguageOption, error)`
Returns a list of common language options (en, ja, es, fr, de, zh, ko, it, pt, ru).

**Example:**
```go
options, err := GetCommonLanguageOptions()
for _, opt := range options {
    fmt.Printf("%s - %s\n", opt.DisplayText, opt.Locale)
}
```

#### `GetAllLanguageOptions() ([]LanguageOption, error)`
Returns all language options sorted alphabetically by language name.

**Example:**
```go
options, err := GetAllLanguageOptions()
fmt.Printf("Total languages: %d\n", len(options))
```

### Search & Filter Functions

#### `GetLanguagesByCountry(countryCode string) ([]LanguageOption, error)`
Returns all languages available for a specific country.

**Parameters:**
- `countryCode`: ISO country code (e.g., "JP", "US", "FR")

**Example:**
```go
// Get all languages spoken in Japan
options, err := GetLanguagesByCountry("JP")
for _, opt := range options {
    fmt.Printf("%s\n", opt.LanguageName)
}
```

#### `FindLanguageByLocale(localeStr string) (*LanguageOption, error)`
Finds a specific language option by locale string.

**Parameters:**
- `localeStr`: Full locale string (e.g., "ja-JP", "en-US")

**Returns:**
- Language option if found
- Error if not found

**Example:**
```go
opt, err := FindLanguageByLocale("ja-JP")
if err == nil {
    fmt.Printf("Found: %s\n", opt.DisplayText)
}
```

### Display Functions

#### `FormatLanguageDisplayEntry(entry *locale.LocaleEntry, region *locale.RegionEntry) string`
Formats a language with region as "🇯🇵 JP - 日本語 (Japanese)".

**Example:**
```go
entry := &locale.LocaleEntry{
    LanguageName:  "Japanese",
    LanguageLocal: "日本語",
    LanguageCode:  "ja",
}

region := &locale.RegionEntry{
    Locale:      "ja-JP",
    CountryCode: "JP",
    Flag:        "🇯🇵",
}

display := FormatLanguageDisplayEntry(entry, region)
// Output: "🇯🇵 JP - 日本語 (Japanese)"
```

#### `FormatLanguageDisplayBasic(langCode string, entry *locale.LocaleEntry, flagEmoji string) string`
Formats a language without region as "🇯🇵 - 日本語 (Japanese)".

**Example:**
```go
display := FormatLanguageDisplayBasic("ja", entry, "🇯🇵")
// Output: "🇯🇵 - 日本語 (Japanese)"
```

#### `GetFlagImageURL(localeStr string) string`
Returns the URL path for a flag image.

**Returns:** "/static/flags/JP.png" for "ja-JP" locale

**Example:**
```go
url := GetFlagImageURL("ja-JP")
// Output: "/static/flags/JP.png"
```

### Helper Functions

#### `IsCommonLanguage(languageCode string) bool`
Checks if a language code is in the common languages list.

**Returns:** true if language is common (en, ja, es, fr, de, zh, ko, it, pt, ru)

**Example:**
```go
if IsCommonLanguage("ja") {
    fmt.Println("Japanese is a common language")
}
```

#### `GetCommonLanguageCodes() []string`
Returns the list of common language codes.

**Returns:** []string{"en", "ja", "es", "fr", "de", "zh", "ko", "it", "pt", "ru"}

## Usage Examples

### Example 1: Audio Language Selector

```go
// Get all languages for audio track selection
options, err := GetAllLanguageOptions()
if err != nil {
    log.Fatal(err)
}

// Render in template
data := struct {
    AudioLanguages []LanguageOption
}{
    AudioLanguages: options,
}

// In HTML template:
// {{range .AudioLanguages}}
//   <option value="{{.Locale}}">{{.DisplayText}}</option>
// {{end}}
```

### Example 2: Common Languages Quick Select

```go
// Get common languages for quick selection
commonOpts, err := GetCommonLanguageOptions()
if err != nil {
    log.Fatal(err)
}

// Group by common category
common := struct {
    CommonLanguages []LanguageOption
    AllLanguages    []LanguageOption
}{
    CommonLanguages: commonOpts,
    AllLanguages:    options,
}
```

### Example 3: Search Functionality

```go
// Handle search query
searchTerm := r.URL.Query().Get("q")

opts := LanguageFilterOptions{
    SearchTerm: searchTerm,
    Limit:      50, // Limit results for performance
}

results, err := SearchLanguages(opts)
if err != nil {
    http.Error(w, err.Error(), http.StatusInternalServerError)
    return
}

// Return JSON response
json.NewEncoder(w).Encode(results)
```

### Example 4: Language by Country

```go
// Get all languages for a specific country
options, err := GetLanguagesByCountry("US")
if err != nil {
    log.Fatal(err)
}

// Display available languages for US
for _, opt := range options {
    fmt.Printf("%s (%s)\n", opt.LanguageName, opt.Locale)
}
```

## Common Use Cases

### Audio Language Selection

For selecting audio tracks in MPV configuration:
1. Use `GetAllLanguageOptions()` for complete list
2. Or use `GetCommonLanguageOptions()` for quick selection
3. Filter by search term for custom selection

### Subtitle Language Selection

For selecting subtitle language preferences:
1. Use same utilities as audio selection
2. May want to limit to 3-5 options for UI
3. Use `LanguageFilterOptions{Limit: 5}`

### Language Preference Page

For user language preference configuration:
1. Show common languages first (quick select)
2. Provide "More Languages" link to show all
3. Use country-based filtering for regional preferences

## Data Flow

```
locales.json (embedded)
    ↓
assets.ReadLocales()
    ↓
locale.LocaleEntry (internal format)
    ↓
LanguageOption (web UI format)
    ↓
Template / JSON API
    ↓
Browser display
```

## Notes

- All functions return data sorted alphabetically by language name
- Common languages match TUI implementation (en, ja, es, fr, de, zh, ko, it, pt, ru)
- Flag emojis are included in `LanguageOption` for emoji-capable browsers
- Flag image URLs are provided for compatibility with all browsers
- Native language names are included when available (e.g., "日本語" for Japanese)

## Testing

Comprehensive tests are provided in `pkg/web/locale_utils_test.go`:
- TestLanguageOption
- TestSearchLanguages_NoFilter
- TestSearchLanguages_CommonOnly
- TestSearchLanguages_SearchTerm
- TestSearchLanguages_Limit
- TestGetCommonLanguageOptions
- TestGetAllLanguageOptions
- TestFindLanguageByLocale
- TestFindLanguageByLocale_NotFound
- TestGetFlagImageURL
- TestFormatLanguageDisplayBasic
- TestGetLanguagesByCountry
- TestIsCommonLanguage
- TestGetCommonLanguageCodes

Run tests with:
```bash
go test ./pkg/web/... -v -run "Test.*Language"
```

## Comparison with TUI Implementation

| TUI Function | Web Equivalent | Notes |
|-------------|----------------|-------|
| `GetMajorLanguages()` | `GetCommonLanguageOptions()` | Returns LanguageOption vs LocaleEntry |
| Search functionality | `SearchLanguages()` | Web version supports filtering options |
| Format display | `FormatLanguageDisplayEntry()` | Both support flag + country code |
| - | `GetFlagImageURL()` | Web-specific for image rendering |
| - | `GetLanguagesByCountry()` | New web-specific function |
| - | `FindLanguageByLocale()` | New web-specific function |

## Future Enhancements

Potential future additions:
1. Language grouping by family (Germanic, Romance, etc.)
2. Regional variant grouping (en-US, en-GB, en-AU)
3. Language script detection (Latin, Cyrillic, Hanzi, etc.)
4. RTL language detection for proper UI layout
5. Language popularity/ranking for smart suggestions
