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

# Adapt Copy With Translations

> Customize and localize the text displayed by the Dynamic Swift SDK using the locale property on ClientProps.

The Dynamic Swift SDK lets you override almost any text it displays and add translations for additional languages. You pass a `locale` object through `ClientProps` when initializing the SDK.

## Quick override

Change UI text by overriding the copy key in `locale`. The object is keyed by language code, and each language value contains nested translation overrides that match the SDK's default English copy structure.

```swift theme={"system"}
import DynamicSDKSwift
import AnyCodableSwift

let locale: [String: Any] = [
    "en": [
        "dyn_widget": ["connect": "Sign in with wallet"],
        "dyn_login": [
            "title": ["all_wallet_list": "Choose a wallet"]
        ]
    ]
]

_ = DynamicSDK.initialize(
    props: ClientProps(
        environmentId: "your-environment-id",
        appName: "My App",
        appOrigin: "https://your-app.com",
        locale: AnyCodable(locale)
    )
)
```

<Tip>
  **Finding keys:** The Swift SDK renders UI inside a WebView. You can mirror the same `copykey` attribute names used in the web SDK. The nested object path matches the dot-separated key (for example, `dyn_login.title.all_wallet_list`).
</Tip>

## Supported languages

The top-level keys of `locale` must be one of the following language codes:

| Code | Language   |
| ---- | ---------- |
| `ar` | Arabic     |
| `da` | Danish     |
| `de` | German     |
| `en` | English    |
| `es` | Spanish    |
| `fi` | Finnish    |
| `fr` | French     |
| `he` | Hebrew     |
| `it` | Italian    |
| `ja` | Japanese   |
| `nl` | Dutch      |
| `pl` | Polish     |
| `pt` | Portuguese |
| `ru` | Russian    |
| `uk` | Ukrainian  |
| `zh` | Chinese    |

<Note>
  Any top-level language key that is not in the supported list is dropped. Other valid entries are still applied.
</Note>

## Full guide

In this guide we will override the "Select your wallet" text to "Find your favorite" in English and add an Italian translation. The key for that text is `dyn_login.title.all_wallet_list`.

```swift theme={"system"}
let locale: [String: Any] = [
    "en": [
        "dyn_login": [
            "title": [
                "all_wallet_list": "Find your favorite"
            ]
        ]
    ],
    "it": [
        "dyn_login": [
            "title": [
                "all_wallet_list": "Trova il tuo preferito"
            ]
        ]
    ]
]

_ = DynamicSDK.initialize(
    props: ClientProps(
        environmentId: "your-environment-id",
        appName: "My App",
        appOrigin: "https://your-app.com",
        locale: AnyCodable(locale)
    )
)
```

The SDK merges your overrides with the default English translations at runtime, so you only need to specify the keys you want to change.

### Translation structure

The `locale` value mirrors the SDK's translation resource. You can override nested objects arbitrarily deeply.

```swift theme={"system"}
let locale: [String: Any] = [
    "en": [
        "dyn_login": [
            "title": [
                "all": "Welcome",
                "all_wallet_list": "Find your favorite"
            ]
        ]
    ]
]
```

This is equivalent to the dot-separated path `dyn_login.title.all` and `dyn_login.title.all_wallet_list`.

### Adding a new language

To add a translation for a language that is not yet bundled, provide the same keys under that language code:

```swift theme={"system"}
let locale: [String: Any] = [
    "it": [
        "dyn_widget": ["connect": "Accedi"],
        "dyn_login": [
            "title": ["all_wallet_list": "Trova il tuo preferito"]
        ]
    ]
]
```

<Note>
  The SDK falls back to `en` for any key that is not provided in the chosen language. You do not need to mirror the entire translation tree.
</Note>

## Validation and sanitization

The `locale` object is sent to the webview controller through the SDK manifest. The webview validates the structure before applying it:

* The root value must be an object.
* Each top-level key must be a supported language code.
* The value for each language must be an object (translation overrides).
* Invalid top-level keys are dropped, and the rest of the object is still applied.
* If the root value is not an object, the whole locale is ignored.

For example, the following object keeps the valid `en` entry and drops the unsupported `xx` key:

```swift theme={"system"}
let locale: [String: Any] = [
    "en": [
        "dyn_widget": ["connect": "Sign in with wallet"]
    ],
    "xx": [
        "dyn_widget": ["connect": "Invalid language"]
    ]
]
```

When an invalid entry is dropped, the SDK instruments the event so you can detect it in your logs.

### Validation messages and form errors

You can also override validation copy. For example, the email and phone form validation keys live under `dyn_login`:

```swift theme={"system"}
let locale: [String: Any] = [
    "en": [
        "dyn_login": [
            "email_form": ["invalid_email": "Please enter a valid email address"],
            "phone_number_form": [
                "invalid_phone": "Please enter a valid phone number",
                "too_short": "Phone number is too short"
            ]
        ]
    ]
]
```

Other common validation keys include:

* `dyn_login.email_form.validation`
* `dyn_login.phone_number_form.validation`
* `dyn_login.phone_number_form.too_short`
* `dyn_active_wallet_info.testnet_warning`
* `dyn_send.error.invalid_balance`

## Runtime language changes

You can switch the active language at runtime after the SDK has initialized. Use the `LocaleLanguage` enum so only supported codes can be passed.

```swift theme={"system"}
import DynamicSDKSwift

try await DynamicSDK.shared?.locale.changeLanguage(.it)
```

The WebView loads the translations provided for that language and falls back to `en` for any missing keys.

## Complete example

```swift theme={"system"}
import DynamicSDKSwift
import AnyCodableSwift

let locale: [String: Any] = [
    "en": [
        "dyn_widget": ["connect": "Sign in with wallet"],
        "dyn_login": [
            "title": [
                "all": "Welcome",
                "all_wallet_list": "Find your favorite"
            ],
            "email_form": ["validation": "Email is not valid"],
            "phone_number_form": [
                "validation": "Phone number is not valid",
                "too_short": "Phone number is too short"
            ]
        ]
    ],
    "it": [
        "dyn_widget": ["connect": "Accedi con il portafoglio"],
        "dyn_login": [
            "title": [
                "all": "Benvenuto",
                "all_wallet_list": "Trova il tuo preferito"
            ]
        ]
    ]
]

_ = DynamicSDK.initialize(
    props: ClientProps(
        environmentId: "your-environment-id",
        appName: "My App",
        appOrigin: "https://your-app.com",
        locale: AnyCodable(locale)
    )
)
```

## Troubleshooting

* **Overrides do not appear**: Make sure the language code is supported (`LocaleLanguage` enum or a valid top-level key) and the key path matches the dot-separated copy key exactly.
* **Invalid language is ignored**: The webview controller drops unsupported top-level language keys. Check that you are using one of the 17 supported codes.
* **Entire locale is ignored**: If the root value is not a valid object, the whole locale is discarded. Ensure `locale` is wrapped in `AnyCodable` and the underlying value is a dictionary.
