# Film and TV Resolvers

> **Relevant source files**
> * [ArWikiCats/new_resolvers/__init__.py](../ArWikiCats/new_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/countries_names_resolvers/__init__.py](../ArWikiCats/new_resolvers/countries_names_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/countries_names_with_sports/__init__.py](../ArWikiCats/new_resolvers/countries_names_with_sports/__init__.py)
> * [ArWikiCats/new_resolvers/countries_names_with_sports/p17_bot_sport.py](../ArWikiCats/new_resolvers/countries_names_with_sports/p17_bot_sport.py)
> * [ArWikiCats/new_resolvers/countries_names_with_sports/p17_sport_to_move_under.py](../ArWikiCats/new_resolvers/countries_names_with_sports/p17_sport_to_move_under.py)
> * [ArWikiCats/new_resolvers/films_resolvers/__init__.py](../ArWikiCats/new_resolvers/films_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py)
> * [ArWikiCats/new_resolvers/jobs_resolvers/__init__.py](../ArWikiCats/new_resolvers/jobs_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/jobs_resolvers/relegin_jobs_new.py](../ArWikiCats/new_resolvers/jobs_resolvers/relegin_jobs_new.py)
> * [ArWikiCats/new_resolvers/nationalities_resolvers/__init__.py](../ArWikiCats/new_resolvers/nationalities_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/__init__.py](../ArWikiCats/new_resolvers/sports_resolvers/__init__.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/countries_names_and_sports.py](../ArWikiCats/new_resolvers/sports_resolvers/countries_names_and_sports.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/nationalities_and_sports.py](../ArWikiCats/new_resolvers/sports_resolvers/nationalities_and_sports.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/pre_defined.py](../ArWikiCats/new_resolvers/sports_resolvers/pre_defined.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/raw_sports.py](../ArWikiCats/new_resolvers/sports_resolvers/raw_sports.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/raw_sports_with_suffixes.py](../ArWikiCats/new_resolvers/sports_resolvers/raw_sports_with_suffixes.py)
> * [ArWikiCats/new_resolvers/sports_resolvers/sport_lab_nat.py](../ArWikiCats/new_resolvers/sports_resolvers/sport_lab_nat.py)
> * [ArWikiCats/new_resolvers/teams_mappings_ends.py](../ArWikiCats/new_resolvers/teams_mappings_ends.py)
> * [examples/data/endings.json](../examples/data/endings.json)
> * [examples/data/novels.json](../examples/data/novels.json)
> * [examples/data/television series.json](../examples/data/television series.json)

## Purpose and Scope

The Film and TV Resolvers subsystem translates English Wikipedia categories for films, television series, and related media into Arabic. This resolver handles categories combining nationality, genre, time periods, and media types (e.g., "2010 American action films" → "أفلام حركة أمريكية في 2010"). The system manages 13,146 film/TV entries with gender-specific handling and nationality placeholder patterns.

For job-related resolvers (including sports-related jobs), see [Job Resolvers](18.Job-Resolvers.md). For nationality-based categories without media types, see [Nationality Resolvers](16.Nationality-Resolvers.md). For time pattern resolution, see [Time Pattern Resolvers](15.Time-Pattern-Resolvers.md)

## Resolution Architecture

The film and TV resolver system operates as part of the main resolver chain with priority 7 (after jobs, sports, nationalities, and countries but before relations and languages). The system uses a multi-stage resolution process combining direct lookups, time-based patterns, and template-based formatters.

### Resolver Flow Diagram

```mermaid
flowchart TD

Input["Input Category<br/>e.g., '2010 american action films'"]
MainEntry["main_films_resolvers()<br/>ArWikiCats/new_resolvers/films_resolvers/init.py:38"]
Normalize["Normalize<br/>- Strip whitespace<br/>- Lowercase<br/>- Remove 'category:' prefix"]
LegacyCheck["legacy_label_check()<br/>Check for numeric/legacy labels"]
TimeFilms["get_films_key_tyty_new_and_time()<br/>Time-based film patterns"]
TVKeys["TELEVISION_KEYS lookup<br/>Direct TV dictionary"]
FilmsKeys["Films_key_CAO lookup<br/>Direct films dictionary"]
PatternFilms["get_films_key_tyty_new()<br/>Pattern-based resolution"]
LegacyResult["Result?"]
TimeResult["Result?"]
TVResult["Result?"]
FilmsResult["Result?"]
PatternResult["Result?"]
Output["Arabic Category<br/>تصنيف:أفلام حركة أمريكية في 2010"]
EmptyResult["Empty String"]

Input --> MainEntry
MainEntry --> Normalize
Normalize --> LegacyCheck
LegacyCheck --> LegacyResult
LegacyResult --> Output
LegacyResult --> TimeFilms
TimeFilms --> TimeResult
TimeResult --> Output
TimeResult --> TVKeys
TVKeys --> TVResult
TVResult --> Output
TVResult --> FilmsKeys
FilmsKeys --> FilmsResult
FilmsResult --> Output
FilmsResult --> PatternFilms
PatternFilms --> PatternResult
PatternResult --> Output
PatternResult --> EmptyResult
```

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/__init__.py L37-L66](../ArWikiCats/new_resolvers/films_resolvers/__init__.py#L37-L66)

## Main Entry Point

The `main_films_resolvers()` function serves as the orchestrator for all film and television category resolution. It implements a waterfall pattern where each resolver is tried in sequence until one returns a non-empty result.

```mermaid
flowchart TD

A["normalize<br/>category"]
B["legacy_label_check"]
C["get_films_key_tyty_new_and_time"]
D["TELEVISION_KEYS"]
E["Films_key_CAO"]
F["get_films_key_tyty_new"]
Output["Return Result"]

B --> Output
C --> Output
D --> Output
E --> Output
F --> Output

subgraph main_films_resolvers ["main_films_resolvers"]
    A
    B
    C
    D
    E
    F
    A --> B
    B --> C
    C --> D
    D --> E
    E --> F
end
```

The function performs these operations:

1. **Normalization**: Strips whitespace, converts to lowercase, removes "category:" prefix
2. **Legacy check**: Returns numeric categories as-is, maps "people" to "أشخاص"
3. **Time-based**: Handles year/decade + film/TV combinations
4. **Direct lookups**: Queries pre-compiled dictionaries for exact matches
5. **Pattern matching**: Uses template-based formatters for complex patterns

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/__init__.py L18-L66](../ArWikiCats/new_resolvers/films_resolvers/__init__.py#L18-L66)

## Legacy Label Checker

The `legacy_label_check()` function handles two special cases that don't require full template processing:

| Input Pattern | Output | Description |
| --- | --- | --- |
| `^\d+$` | Same number | Numeric categories (e.g., "2010") |
| `people` | `أشخاص` | Generic people category |

This early check avoids unnecessary processing for categories that are already in their final form or need simple direct translation.

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/__init__.py L18-L34](../ArWikiCats/new_resolvers/films_resolvers/__init__.py#L18-L34)

## Template System Architecture

The core of the film resolver system is a sophisticated template engine that combines nationality data with film/TV genre keys to generate Arabic translations. The system uses dual-bot architecture with separate handling for nationality+genre patterns versus genre-only patterns.

### Bot Configuration Diagram

```mermaid
flowchart TD

BuildTV["_build_television_cao()<br/>Build TV/Film dictionaries"]
FormattedData["formatted_data<br/>{nat_en} {film_key} films<br/>{nat_en} television series"]
TVData["_data from _build_television_cao()<br/>Nationality + Genre patterns"]
OtherData["other_formatted_data<br/>{film_key} films<br/>animated television series"]
TVDataNoNat["data_no_nats<br/>Genre-only patterns"]
NatWomen["Nat_women<br/>Female nationality forms"]
FilmKeys["film_keys_for_female<br/>13,146 genre entries"]
DoubleBot["format_films_country_data()<br/>MultiDataFormatterDataDouble<br/>Handles nat + genre"]
SimpleBot["format_multi_data()<br/>MultiDataFormatterBase<br/>Handles genre only"]
PutLabelLast["put_label_last set<br/>low-budget, supernatural,<br/>christmas, lgbtq-related,<br/>upcoming"]
Output["double_bot, bot"]

DoubleBot --> Output
SimpleBot --> Output

subgraph subGraph4 ["_make_bot() Configuration"]
    BuildTV
    PutLabelLast
    BuildTV --> FormattedData
    BuildTV --> TVData
    BuildTV --> OtherData
    BuildTV --> TVDataNoNat
    FormattedData --> DoubleBot
    TVData --> DoubleBot
    OtherData --> DoubleBot
    TVDataNoNat --> DoubleBot
    NatWomen --> DoubleBot
    FilmKeys --> DoubleBot
    FormattedData --> SimpleBot
    OtherData --> SimpleBot
    NatWomen --> SimpleBot
    FilmKeys --> SimpleBot
    DoubleBot --> PutLabelLast

subgraph subGraph3 ["Formatter Bots"]
    DoubleBot
    SimpleBot
end

subgraph subGraph2 ["Data Sources"]
    NatWomen
    FilmKeys
end

subgraph subGraph1 ["Dictionary 2: Genre Only"]
    OtherData
    TVDataNoNat
end

subgraph subGraph0 ["Dictionary 1: With Nationalities"]
    FormattedData
    TVData
end
end
```

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L154-L260](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L154-L260)

## Television CAO Dictionary Builder

The `_build_television_cao()` function constructs two complementary translation dictionaries for television and film categories. "CAO" likely stands for "Characters And Others" based on the pattern types it handles.

### Pattern Categories

The builder creates patterns for:

1. **Base suffixes**: characters, title cards, video covers, posters, images
2. **Genre categories**: 27 media types including: * Television: series, episodes, programs, shows, miniseries * Film: films, film characters, film series * Other: novels, novellas, comics, video games, web series
3. **Compound patterns**: Genre + suffix combinations (e.g., "television series characters")

### Dictionary Structure

| Dictionary | Purpose | Example Pattern | Example Output |
| --- | --- | --- | --- |
| `data` | With nationality placeholder | `{nat_en} {film_key} films` | `أفلام {film_ar} {nat_ar}` |
| `data_no_nats` | Without nationality | `{film_key} films` | `أفلام {film_ar}` |

The function generates 100+ pattern combinations by cross-multiplying:

* 5 base suffixes × 27 genre categories = 135 compound patterns
* Plus standalone genre patterns
* Plus nationality-genre combinations

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L27-L151](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L27-L151)

## Placeholder System

The film resolver uses a multi-placeholder template system that allows flexible composition of nationality, genre, and descriptor elements.

### Placeholder Types

| Placeholder | Purpose | Example Input | Example Value |
| --- | --- | --- | --- |
| `{nat_en}` | English nationality | "american" | Looked up in Nat_women |
| `{nat_ar}` | Arabic nationality | Result | "أمريكية" |
| `{film_key}` | English genre key | "action" | Looked up in film_keys_for_female |
| `{film_ar}` | Arabic genre value | Result | "حركة" |

### Template Examples

```mermaid
flowchart TD

Input3["british television series"]
Template3["{nat_en} television series"]
Arabic3["مسلسلات تلفزيونية {nat_ar}"]
Output3["مسلسلات تلفزيونية بريطانية"]
Input2["horror films"]
Template2["{film_key} films"]
Arabic2["أفلام {film_ar}"]
Output2["أفلام رعب"]
Input1["american action films"]
Template1["{nat_en} {film_key} films"]
Arabic1["أفلام {film_ar} {nat_ar}"]
Output1["أفلام حركة أمريكية"]

subgraph subGraph2 ["Example 3: TV Series"]
    Input3
    Template3
    Arabic3
    Output3
    Input3 --> Template3
    Template3 --> Arabic3
    Arabic3 --> Output3
end

subgraph subGraph1 ["Example 2: Genre Only"]
    Input2
    Template2
    Arabic2
    Output2
    Input2 --> Template2
    Template2 --> Arabic2
    Arabic2 --> Output2
end

subgraph subGraph0 ["Example 1: Nationality + Genre"]
    Input1
    Template1
    Arabic1
    Output1
    Input1 --> Template1
    Template1 --> Arabic1
    Arabic1 --> Output1
end
```

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L171-L260](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L171-L260)

## Gender-Specific Handling

The film resolver system includes sophisticated gender handling for film genres, as Arabic translation requires grammatically gendered forms. This is implemented through `film_keys_for_female`, which provides feminine forms for genre descriptors.

### Gender Data Structure

The system uses feminine forms by default from `film_keys_for_female`, then selectively overrides specific entries:

```mermaid
flowchart TD

BaseData["film_keys_for_female<br/>Base dictionary with<br/>feminine forms"]
Remove1["Remove 'television'<br/>Avoid conflicts"]
Override1["Override 'superhero'<br/>superhero → أبطال خارقين<br/>(special plural form)"]
FinalData["data_list2<br/>Final genre dictionary"]
FormatBot["format_films_country_data()"]

FinalData --> FormatBot

subgraph subGraph0 ["Gender Data Pipeline"]
    BaseData
    Remove1
    Override1
    FinalData
    BaseData --> Remove1
    Remove1 --> Override1
    Override1 --> FinalData
end
```

### Special Genre Handling

| Genre Key | Arabic Value | Notes |
| --- | --- | --- |
| action | حركة | Feminine form for "films" (أفلام) |
| drama | درامية | Feminine adjective |
| horror | رعب | Masculine noun (no gender change) |
| superhero | أبطال خارقين | Plural form (overridden) |
| upcoming | قادمة | Feminine participle |

### Label Positioning

The `put_label_last` set controls word order for specific genres where the Arabic translation should appear after the main noun rather than before:

```
put_label_last = {
    "low-budget",
    "supernatural",
    "christmas",
    "lgbtq-related",
    "upcoming",
}
```

This affects patterns like:

* "upcoming films" → "أفلام قادمة" (not "قادمة أفلام")
* "low-budget films" → "أفلام قليلة التكلفة" (not "قليلة التكلفة أفلام")

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L208-L247](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L208-L247)

## Key Normalization

The `fix_keys()` function applies specific text replacements to handle multi-word terms that need to be treated as single units during pattern matching.

### Normalization Rules

| Original | Normalized | Reason |
| --- | --- | --- |
| `saudi arabian` | `saudiarabian` | Prevent word boundary issues |
| `children's animated adventure television` | `children's-animated-adventure-television` | Treat as single compound key |
| `children's animated superhero` | `children's-animated-superhero` | Treat as single compound key |

The function also applies standard normalization (lowercase, strip whitespace) before these specific fixes.

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L263-L287](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L263-L287)

## Formatter Bot Architecture

The system creates two separate formatter instances to handle different complexity levels:

### Dual-Bot Structure

```mermaid
flowchart TD

DB_Config["Configuration"]
DB_NatList["data_list: Nat_women<br/>Nationality translations"]
DB_FilmList["data_list2: film_keys_for_female<br/>Genre translations"]
DB_Formatted["formatted_data<br/>Patterns with both placeholders"]
DB_Other["other_formatted_data<br/>Patterns with single placeholder"]
DB_Type["Type: MultiDataFormatterDataDouble<br/>Handles nationality+genre pairs"]
DB_Populate["Populates film-country patterns"]
SB_Config["Configuration"]
SB_NatList["data_list: Nat_women"]
SB_FilmList["data_list2: film_keys_for_female"]
SB_Formatted["formatted_data<br/>Same patterns"]
SB_Other["other_formatted_data<br/>Same patterns"]
SB_Type["Type: MultiDataFormatterBase<br/>Standard multi-element"]
Usage["_get_films_key_tyty_new()"]
Try1["First attempt"]
Try2["Fallback"]

DB_Type --> Usage
SB_Type --> Usage
Usage --> Try1
Usage --> Try2

subgraph subGraph1 ["Bot 2: format_multi_data()"]
    SB_Config
    SB_NatList
    SB_FilmList
    SB_Formatted
    SB_Other
    SB_Type
    SB_Config --> SB_Type
    SB_NatList --> SB_Type
    SB_FilmList --> SB_Type
    SB_Formatted --> SB_Type
    SB_Other --> SB_Type
end

subgraph subGraph0 ["Bot 1: format_films_country_data()"]
    DB_Config
    DB_NatList
    DB_FilmList
    DB_Formatted
    DB_Other
    DB_Type
    DB_Populate
    DB_Config --> DB_Type
    DB_NatList --> DB_Type
    DB_FilmList --> DB_Type
    DB_Formatted --> DB_Type
    DB_Other --> DB_Type
    DB_Type --> DB_Populate
end
```

The dual-bot architecture provides:

1. **Primary bot**: Standard multi-element formatter for most patterns
2. **Fallback bot**: Enhanced double formatter with film-country pattern population for complex cases

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L234-L260](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L234-L260), [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L290-L307](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L290-L307)

## Resolution Entry Point

The `_get_films_key_tyty_new()` function implements the actual resolution logic using the configured bots.

### Resolution Process

```mermaid
sequenceDiagram
  participant Input Category
  participant fix_keys()
  participant LRU Cache
  participant bot.search_all()
  participant double_bot.search_all()
  participant Arabic Result

  Input Category->>fix_keys(): "american action films"
  fix_keys()->>LRU Cache: "american action films"
  loop [Bot1 finds match]
    LRU Cache->>Arabic Result: Return cached result
    LRU Cache->>bot.search_all(): Attempt resolution
    bot.search_all()->>Arabic Result: Return result
    bot.search_all()->>double_bot.search_all(): Fallback
    double_bot.search_all()->>Arabic Result: Return result or ""
  end
```

The function:

1. Normalizes input with `fix_keys()`
2. Checks 10,000-entry LRU cache
3. Tries standard bot first
4. Falls back to double bot for complex patterns
5. Returns empty string if both fail

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L290-L307](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L290-L307)

## Example Translations

### Television Series Examples

From the test data, the resolver handles complex television category patterns:

| English Category | Arabic Translation |
| --- | --- |
| 2010 Swedish television series | مسلسلات تلفزيونية سويدية في 2010 |
| British police procedural television series | مسلسلات تلفزيونية إجراءات الشرطة بريطانية |
| American animated television series about children | مسلسلات تلفزيونية رسوم متحركة أمريكية عن أطفال |
| 2010 Japanese television series debuts | مسلسلات تلفزيونية يابانية بدأ عرضها في 2010 |
| Nigerian television series title cards | بطاقات عنوان مسلسلات تلفزيونية نيجيرية |

**Sources:** [examples/data/television L1-L56](../examples/data/television series.json#L1-L56)

### Endings Pattern Examples

The resolver also handles "endings" patterns for television series:

| English Category | Arabic Translation |
| --- | --- |
| 2010 Brazilian television series endings | مسلسلات تلفزيونية برازيلية انتهت في 2010 |
| 2010s Indonesian television series endings | مسلسلات تلفزيونية إندونيسية انتهت في عقد 2010 |
| 21st-century Chilean television series endings | مسلسلات تلفزيونية تشيلية انتهت في القرن 21 |

**Sources:** [examples/data/endings.json L1-L32](../examples/data/endings.json#L1-L32)

## Integration with Resolver Chain

The film resolver integrates into the main resolver chain at priority level 7, positioned after more specific resolvers to avoid conflicts:

### Resolver Priority Context

```mermaid
flowchart TD

Priority1["1. Time ResolversYears, decades, centuries"]
Priority2["2. Pattern ResolversRegex-based"]
Priority3["3. Jobs ResolversOccupations"]
Priority4["4. Time + Jobs"]
Priority5["5. Sports Resolvers"]
Priority6["6. Nationalities"]
Priority7["7. Countries"]
Priority8["8. Films ResolversTHIS SUBSYSTEM"]
Priority9["9. Relations"]
Priority10["10. Countries+Sports"]

Priority1 --> Priority2
Priority2 --> Priority3
Priority3 --> Priority4
Priority4 --> Priority5
Priority5 --> Priority6
Priority6 --> Priority7
Priority7 --> Priority8
Priority8 --> Priority9
Priority9 --> Priority10
```

This positioning ensures:

* Job titles are resolved first (e.g., "film director" goes to jobs, not films)
* Nationality patterns are resolved first (e.g., "American people" goes to nationalities)
* Film/TV categories get processed after more specific patterns have been tried
* The system serves as a catch-all for media-related categories

**Sources:** [ArWikiCats/new_resolvers/__init__.py L37-L98](../ArWikiCats/new_resolvers/__init__.py#L37-L98)

## Data Sources

The film resolver depends on several translation data sources:

| Data Source | Type | Purpose | Size |
| --- | --- | --- | --- |
| `Nat_women` | dict | Female nationality forms | ~843 entries |
| `film_keys_for_female` | dict | Female genre descriptors | 13,146 entries |
| `TELEVISION_KEYS` | dict | Direct TV lookups | Unknown |
| `Films_key_CAO` | dict | Direct film lookups | Unknown |

These are imported from the `translations` module and represent pre-compiled lookup tables built from the JSON data sources in the `jsons/media/` directory.

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L14-L22](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L14-L22)

## Caching Strategy

The film resolver implements aggressive caching at multiple levels:

| Cache Location | Size | Purpose |
| --- | --- | --- |
| `main_films_resolvers()` | 10,000 entries | Top-level category caching |
| `_get_films_key_tyty_new()` | 10,000 entries | Pattern resolution caching |
| `get_films_key_tyty_new()` | 10,000 entries | Public API caching |
| `_make_bot()` | 1 entry (singleton) | Bot instance caching |
| `_build_television_cao()` | Implicit | Dictionary construction caching |
| `fix_keys()` | Implicit | Normalization caching |

All caches use `functools.lru_cache` for automatic LRU eviction when capacity is reached. The singleton bot cache ensures the expensive formatter construction happens only once per process.

**Sources:** [ArWikiCats/new_resolvers/films_resolvers/__init__.py L37](../ArWikiCats/new_resolvers/films_resolvers/__init__.py#L37), [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L154](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L154), [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L290](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L290), [ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py L310](../ArWikiCats/new_resolvers/films_resolvers/resolve_films_labels.py#L310)
