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

# Localization

> Customize UI strings and add language support to the social.plus UIKit

The social.plus UIKit ships with built-in English strings and a localization API that lets you add any language — or override individual strings — without forking the UIKit. English is the only built-in language. Any key missing from a custom locale bundle automatically resolves to its English value — no errors are thrown and no code changes are needed.

## Platform Implementation

Select your platform below for API details and integration code.

<Tabs>
  <Tab title="iOS (Swift)">
    ### How to Add a New Language

    #### Option A — Bundle-based `.lproj` files (recommended)

    Provide translations via standard iOS `.lproj` directories in your app bundle. The UIKit checks `Bundle.main` for `AmityLocalizable.strings` before falling back to its framework bundle — no code changes needed.

    ```text theme={null}
    MyApp/
    └── Resources/
        ├── en.lproj/AmityLocalizable.strings   ← English overrides (optional)
        └── ja.lproj/AmityLocalizable.strings   ← Japanese translations
    ```

    ```text theme={null}
    /* ja.lproj/AmityLocalizable.strings */
    "amity_common_button_cancel" = "キャンセル";
    "amity_common_button_delete" = "削除";
    "amity_social_button_comments" = "コメント";
    ```

    iOS automatically selects the correct `.lproj` folder based on the device language. This approach follows the standard iOS localization pattern and is well-suited for teams where translation stakeholders are non-technical — they only need to edit `.strings` files without touching application code.

    Use the English reference file [`AmityLocalizable.strings`](https://github.com/AmityCo/ASC-UIKit-iOS-OpenSource/blob/main/UpstraUIKit/AmityUIKit4/AmityUIKit4/Core/Localization/en.lproj/AmityLocalizable.strings) as the source of truth for all available keys.

    <Tip>
      **Generate translations with AI:** Download the English `.strings` file linked above and paste it into an AI assistant (ChatGPT, Claude, Copilot) with the prompt: *"Translate all values to \[language]. Keep all keys, format specifiers (`%@`, `%d`, `%s`), and file format unchanged."* This is a fast way to get a complete draft — have a native speaker review the output before shipping.
    </Tip>

    #### Option B — Programmatic via String Provider API

    Provide a `[String: String]` dictionary of translated keys and register it with each provider at runtime.

    <Steps>
      <Step title="Create a locale bundle">
        Create a dictionary with the translated keys. You only need to include keys you're translating — missing keys fall back to the built-in English values automatically.

        ```swift theme={null}
        struct MyJapaneseStrings {
            static let social: [String: String] = [
                "amity_social_button_comments": "コメント",
                "amity_social_button_delete_comment": "コメントを削除",
                "amity_social_button_edit_comment": "コメントを編集",
            ]

            static let common: [String: String] = [
                "amity_common_button_cancel": "キャンセル",
                "amity_common_button_done": "完了",
            ]

            static let chat: [String: String] = [
                "amity_chat_edit_message": "メッセージを編集",
            ]
        }
        ```
      </Step>

      <Step title="Register the locale bundle">
        Call `setLocale` on each provider — typically at app launch or in response to a user language-switch action:

        ```swift theme={null}
        AmityStringProvider.social.setLocale("ja", bundle: MyJapaneseStrings.social)
        AmityStringProvider.common.setLocale("ja", bundle: MyJapaneseStrings.common)
        AmityStringProvider.chat.setLocale("ja", bundle: MyJapaneseStrings.chat)
        ```

        To revert to the default English strings:

        ```swift theme={null}
        AmityStringProvider.social.deactivateLocale()
        AmityStringProvider.common.deactivateLocale()
        AmityStringProvider.chat.deactivateLocale()
        ```
      </Step>
    </Steps>

    #### Option C — Override individual keys

    To replace specific strings without changing the whole language, use `setOverrides()`. Overrides merge on top of any active locale.

    ```swift theme={null}
    AmityStringProvider.social.setOverrides([
        "amity_social_button_comments": "Replies",
        "amity_social_modal_dialog_generic_error": "Something went wrong. Please try again.",
    ])

    AmityStringProvider.common.setOverrides([
        "amity_common_button_cancel": "Dismiss",
    ])
    ```

    To clear overrides:

    ```swift theme={null}
    AmityStringProvider.social.clearOverrides()
    AmityStringProvider.common.clearOverrides()
    ```
  </Tab>

  <Tab title="Android (Kotlin)">
    ### How to Add a New Language

    #### Option A — Android resource files (recommended)

    Provide translations using standard Android resource directories in your **app module**. Since Android merges resources at build time, app-level strings override library-level strings automatically — no fork required.

    Add `values-<language-code>/strings.xml` files in your app module with the same `amity_*` resource names used by the UIKit:

    ```
    app/src/main/res/
    ├── values/strings.xml              ← your app's default strings (unchanged)
    └── values-ja/strings.xml           ← Japanese translations for UIKit keys
    ```

    ```xml theme={null}
    <!-- app/src/main/res/values-ja/strings.xml -->
    <resources>
        <string name="amity_common_button_cancel">キャンセル</string>
        <string name="amity_common_button_delete">削除</string>
        <string name="amity_social_button_comments">コメント</string>
    </resources>
    ```

    Android automatically selects the correct `values-<lang>/` folder based on the device language. This approach follows the standard Android localization pattern and is well-suited for teams where translation stakeholders are non-technical — they only need to edit XML files without touching application code.

    For the full key list, refer to the English default `strings.xml` files in the [Android UIKit open source repository](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Android-OpenSource):

    * [`social-compose/.../values/strings.xml`](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Android-OpenSource/blob/main/social-compose/src/main/res/values/strings.xml) (social keys)
    * [`common-compose/.../values/strings.xml`](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Android-OpenSource/blob/main/common-compose/src/main/res/values/strings.xml) (common keys)

    You can also refer to the comprehensive [`LOCALIZATION_GUIDE.md`](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Android-OpenSource/blob/main/LOCALIZATION_GUIDE.md) in the repository for detailed instructions and examples.

    <Tip>
      **Generate translations with AI:** Download the English `strings.xml` files linked above and paste them into an AI assistant (ChatGPT, Claude, Copilot) with the prompt: *"Translate all values to \[language]. Keep all keys, format specifiers (`%s`, `%d`, `%1$s`), and XML format unchanged."* This is a fast way to get a complete draft — have a native speaker review the output before shipping.
    </Tip>

    #### Option B — Locale bundle via String Provider API

    Provide a `Map<String, String>` of translated keys and register it with the provider at runtime.

    <Steps>
      <Step title="Initialize the providers">
        Call both providers in your `Application.onCreate()`:

        ```kotlin theme={null}
        class MyApplication : Application() {
            override fun onCreate() {
                super.onCreate()
                DefaultAmitySocialStringProvider.initialize(this)
                DefaultAmityCommonStringProvider.initialize(this)
            }
        }
        ```
      </Step>

      <Step title="Create a locale bundle">
        Create a Kotlin object (or a plain `Map<String, String>`) with the translated keys. You only need to include keys you're translating — missing keys fall back to the English `strings.xml` values automatically.

        ```kotlin theme={null}
        object MyJapaneseStrings {
            val social: Map<String, String> = mapOf(
                "amity_social_button_comments" to "コメント",
                "amity_social_button_delete_comment" to "コメントを削除",
                "amity_social_button_edit_comment" to "コメントを編集",
            )

            val common: Map<String, String> = mapOf(
                "amity_common_button_cancel" to "キャンセル",
                "amity_common_button_done" to "完了",
            )
        }
        ```
      </Step>

      <Step title="Register the locale bundle">
        Call `setLocale()` on both providers — typically in `Application.onCreate()` after initialization, or in response to a user language-switch action:

        ```kotlin theme={null}
        DefaultAmitySocialStringProvider.setLocale("ja", MyJapaneseStrings.social)
        DefaultAmityCommonStringProvider.setLocale("ja", MyJapaneseStrings.common)
        ```

        To revert to the default English resources:

        ```kotlin theme={null}
        DefaultAmitySocialStringProvider.getInstance().clearLocale()
        DefaultAmityCommonStringProvider.getInstance().clearLocale()
        ```
      </Step>
    </Steps>

    #### Option C — Override individual keys

    To replace specific strings without changing the whole language, use `setOverrides()`. Overrides merge on top of any active locale.

    ```kotlin theme={null}
    DefaultAmitySocialStringProvider.setOverrides(mapOf(
        "amity_social_button_comments" to "Replies",
        "amity_social_modal_dialog_generic_error" to "Something went wrong. Please try again.",
    ))

    DefaultAmityCommonStringProvider.setOverrides(mapOf(
        "amity_common_button_cancel" to "Dismiss",
    ))
    ```

    To clear overrides:

    ```kotlin theme={null}
    DefaultAmitySocialStringProvider.getInstance().clearOverrides()
    DefaultAmityCommonStringProvider.getInstance().clearOverrides()
    ```

    <Note>
      Social keys start with `amity_social_`; common keys start with `amity_common_`. When calling provider methods, use the correct provider for each key prefix.
    </Note>
  </Tab>

  <Tab title="Web (React)">
    ### How to Add a New Language

    <Steps>
      <Step title="Create a translation file">
        Create a flat JSON file with the keys you want to translate. You only need to include keys you're translating — missing keys automatically fall back to English.

        ```json theme={null}
        {
          "amity_common_button_cancel": "キャンセル",
          "amity_common_button_delete": "削除",
          "amity_social_button_block_user": "ユーザーをブロック"
        }
        ```
      </Step>

      <Step title="Register via localeMap">
        Pass the bundle via `localeMap` on `AmityUIKitProvider` so the UIKit auto-detects it from `navigator.language`:

        ```tsx theme={null}
        import jaLocale from './locales/ja.json';

        <AmityUIKitProvider
          localization={{
            localeMap: {
              ja: jaLocale,
            },
          }}
        >
          <App />
        </AmityUIKitProvider>
        ```

        The UIKit checks `navigator.language` — exact match first (e.g. `"ja"`), then language-prefix match (e.g. `"ja-JP"` → `"ja"`). Falls back to English if no match is found.
      </Step>

      <Step title="Verify coverage">
        Compare your translation file against [`en.json`](https://github.com/AmityCo/Amity-Social-Cloud-UIKit-Web-OpenSource/blob/master/src/v4/core/localization/defaults/en.json) to identify missing keys. Any untranslated key silently falls back to English — no errors are thrown.

        <Tip>
          **Generate translations with AI:** Download the `en.json` file linked above and paste it into an AI assistant (ChatGPT, Claude, Copilot) with the prompt: *"Translate all values to \[language]. Keep all keys, format specifiers (`%s`, `%d`), and JSON format unchanged."* This is a fast way to get a complete draft — have a native speaker review the output before shipping.
        </Tip>
      </Step>
    </Steps>

    ### Other Scenarios

    <AccordionGroup>
      <Accordion title="Override specific strings">
        Use the `overrides` prop to replace individual keys without providing a full locale bundle. Overrides merge on top of the active locale.

        ```tsx theme={null}
        <AmityUIKitProvider
          localization={{
            overrides: {
              'amity_common_button_cancel': 'Dismiss',
              'amity_social_button_delete_post_title': 'Remove this post?',
            },
          }}
        >
          <App />
        </AmityUIKitProvider>
        ```
      </Accordion>

      <Accordion title="Switch locale at runtime">
        `useLocale` controls the active locale. `useString` consumes strings and automatically re-renders all consumers when the locale changes.

        ```tsx theme={null}
        import { useLocale, useString } from '@amityco/ui-kit';
        import jaLocale from './locales/ja.json';

        function LanguageSwitcher() {
          const { setLocaleBundle, clearLocaleBundle } = useLocale();

          return (
            <>
              <button onClick={() => setLocaleBundle(jaLocale)}>日本語</button>
              <button onClick={() => clearLocaleBundle()}>English</button>
            </>
          );
        }

        // Any child component — automatically re-renders on locale change
        function CancelButton() {
          const label = useString('amity_common_button_cancel');
          return <button>{label}</button>;
        }
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>

<Info>
  **Version alignment:** New UIKit releases may introduce new localization keys for new UI components or features. When upgrading, re-generate your translation files from the open source reference file that matches your UIKit version to ensure no keys are missing. Untranslated keys fall back to English silently, but keeping your translation files up to date ensures a fully localized experience.
</Info>

## Migrating from `config.json` Text Overrides

<Warning>
  **`config.json` text overrides are deprecated for string customization.** If you previously used `config.json` to override UI strings (e.g. button labels, error messages), you should migrate those overrides to the localization API described above — even if you don't plan to add new languages.

  Existing `config.json` text overrides are still resolved gracefully for now, but this auto-resolution **may be removed in a future release**. New UI components and features will only support string customization through the localization system.

  `config.json` remains available for other configuration such as theme and UI element visibility — only string/text overrides are being deprecated.
</Warning>
