> ## Documentation Index
> Fetch the complete documentation index at: https://docs.swiftaiboilerplate.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Localization Module

> Type-safe localization system with pluralization support for shipping globally-ready iOS apps

Ship globally from day one with a production-ready localization system featuring type-safe string keys and automatic pluralization support.

<Info>
  **Package location:** `Packages/Localization/`
</Info>

## What's new

* **v2.2** — Localized error surface: `AppError.localizedUserMessage` (en + es) lives here in Localization, now linked by the app target, FeatureSettings, and FeatureChat. All UI error call sites resolve user-facing copy through it.
* **v2.0** — `L10n.swift` is a root `enum L10n` plus one `L10n+<Namespace>.swift` per nested enum (`L10n+Auth.swift`, `L10n+Chat.swift`, `L10n+Settings.swift`, and so on). The public API is identical: `L10n.Auth.tagline`, `L10n.Chat.placeholder`, and every other call site compile unchanged.

## Overview

The Localization module provides compile-time safe string access, eliminating missing translation errors before they reach users.

<CardGroup cols={2}>
  <Card title="Type-Safe Strings" icon="shield-check">
    Compile-time safety catches missing translations
  </Card>

  <Card title="Pluralization" icon="list-ol">
    Automatic plural rules for every language
  </Card>

  <Card title="2 Languages Included" icon="globe">
    English and Spanish out of the box
  </Card>

  <Card title="100+ Strings" icon="message">
    Pre-localized Auth, Chat, Settings, Payments, Errors
  </Card>
</CardGroup>

## Quick Start

### Basic Usage

```swift theme={null}
import Localization

// Type-safe, autocomplete-friendly
Text(L10n.Auth.tagline)           // "Your AI assistant"
Text(L10n.Chat.placeholder)       // "Type a message..."
Text(L10n.Settings.theme)         // "Theme"

// Error messages that make sense
errorLabel.text = L10n.Error.networkOffline
// "You're offline. Please check your internet connection."
```

### Pluralization

Plural forms are driven by `Localizable.stringsdict`, so each language can define its own rules (English ships with `zero`/`one`/`other`; languages like Russian or Arabic can add their full form sets in their own `.stringsdict`):

```swift theme={null}
// English: "5 messages remaining" / "1 message remaining" / "No messages remaining"
Text(L10n.Chat.messagesRemaining(count))
```

## File Structure

```text theme={null}
Packages/Localization/
├── Package.swift
├── README.md
├── Sources/Localization/
│   ├── L10n.swift                # Root enum + locale utilities
│   ├── L10n+Auth.swift           # One file per namespace
│   ├── L10n+Chat.swift
│   ├── L10n+Settings.swift
│   ├── L10n+Payments.swift
│   ├── L10n+Onboarding.swift
│   ├── L10n+Profile.swift
│   ├── L10n+Theme.swift
│   ├── L10n+Common.swift
│   ├── L10n+Error.swift
│   ├── L10n+A11y.swift
│   ├── L10n+AppError.swift       # AppError.localizedUserMessage (v2.2)
│   ├── Localization.swift        # Module entry
│   └── Resources/
│       ├── en.lproj/             # English
│       │   ├── Localizable.strings
│       │   └── Localizable.stringsdict
│       └── es.lproj/             # Spanish
│           └── Localizable.strings
└── Tests/LocalizationTests/
    ├── L10nTests.swift
    └── L10nAppErrorTests.swift
```

## Adding New Languages

Adding a new language takes just minutes:

<Steps>
  <Step title="Copy existing language folder">
    ```bash theme={null}
    cd Packages/Localization/Sources/Localization/Resources
    cp -r en.lproj de.lproj
    ```
  </Step>

  <Step title="Translate strings">
    Edit `de.lproj/Localizable.strings` with German translations. Adapt the copied `Localizable.stringsdict` if the language needs different plural rules.
  </Step>

  <Step title="Build and test">
    Rebuild — the app automatically picks up new languages.
  </Step>
</Steps>

## Adding Custom Strings

### 1. Add to Localizable.strings

```text theme={null}
// en.lproj/Localizable.strings
"myFeature.title" = "My Feature";
"myFeature.subtitle" = "This is my new feature";
```

Add the same keys to every `.strings` file in `Resources/` (e.g. `es.lproj/`).

### 2. Add Type-Safe Key

Create a new `L10n+MyFeature.swift` extension (one namespace per file, matching the v2.0 layout):

```swift theme={null}
// L10n+MyFeature.swift
import Foundation

public extension L10n {
    enum MyFeature {
        public static var title: String {
            String(localized: "myFeature.title", bundle: bundle)
        }

        public static var subtitle: String {
            String(localized: "myFeature.subtitle", bundle: bundle)
        }
    }
}
```

### 3. Use in Your Views

```swift theme={null}
Text(L10n.MyFeature.title)
Text(L10n.MyFeature.subtitle)
```

## Pre-Localized Strings

The module includes 100+ pre-localized strings covering common app needs:

<AccordionGroup>
  <Accordion title="Authentication">
    * Sign in / Sign up labels
    * Password fields
    * Error messages
    * Social login buttons
    * Email confirmation
  </Accordion>

  <Accordion title="Chat">
    * Message placeholders
    * Send button
    * Typing indicators
    * Message status (sent, delivered, read)
    * Error states
  </Accordion>

  <Accordion title="Settings">
    * Section headers
    * Theme options
    * Account settings
    * Privacy options
    * About section
  </Accordion>

  <Accordion title="Payments">
    * Subscription labels
    * Price formatting
    * Purchase buttons
    * Restore purchases
    * Error messages
  </Accordion>

  <Accordion title="Errors">
    * Network errors
    * Authentication errors
    * Permission errors
    * Generic errors
    * Retry prompts
  </Accordion>
</AccordionGroup>

## Best Practices

<CardGroup cols={2}>
  <Card title="Always use L10n" icon="check">
    Never hardcode user-facing strings
  </Card>

  <Card title="Test with pseudolocalization" icon="flask">
    Catch layout issues early
  </Card>

  <Card title="Keep strings short" icon="compress">
    Some languages expand 30%+
  </Card>

  <Card title="Avoid string concatenation" icon="ban">
    Use string interpolation instead
  </Card>
</CardGroup>

## Testing

```swift theme={null}
func testLocalizationKeys() {
    // Verify all keys have translations
    XCTAssertFalse(L10n.Auth.tagline.isEmpty)
    XCTAssertFalse(L10n.Chat.placeholder.isEmpty)
    
    // Test pluralization
    XCTAssertEqual(L10n.Chat.messagesRemaining(0), "No messages remaining")
    XCTAssertEqual(L10n.Chat.messagesRemaining(1), "1 message remaining")
    XCTAssertEqual(L10n.Chat.messagesRemaining(5), "5 messages remaining")
}
```

## Related

<CardGroup cols={2}>
  <Card title="Quick Start" href="/pages/quickstart">
    Run the app before adding more languages
  </Card>

  <Card title="Architecture" href="/pages/architecture">
    Understand module boundaries
  </Card>

  <Card title="Accessibility Module" href="/pages/modules/accessibility">
    VoiceOver and Dynamic Type support
  </Card>

  <Card title="Design System" href="/pages/modules/design-system">
    UI tokens and components
  </Card>
</CardGroup>
