# Localization Service

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FWcNuHRCaG6qHC3xAgFU7%2FReference%20-%20Localization%20Service.png?alt=media&#x26;token=4a268efa-3732-4635-bc6f-94b815b5b11f" alt=""><figcaption></figcaption></figure>

**Audience:** IT admins. This page describes how the **localization service** works: how the **locale** is set, how it can be **overridden**, and how to **modify** UI text via localization configuration.

***

### Overview

Keeper Privilege Manager supports **multiple languages** for UI components (tray app, MFA/approval/justification dialogs, messages, etc.). The system:

* **Resolves the user’s locale** (system detection or an explicit override).
* **Stores the chosen locale** per user (via registration with the local service).
* **Serves localized strings** to each component by **culture** (e.g. `en_US`, `fr_FR`).
* **Allows customization** of text by editing **localization JSON files** or, where supported, via the **localization API**.

Locale is **per user** (or per session that registers). Each UI component requests strings for the **registered** culture so menus, dialogs, and notifications appear in the correct language.

***

### How the Locale is Set

#### Default Behavior (no override)

1. When the **KeeperClient** (tray) application starts, it determines the locale to use:
   * If no override is configured, it uses **system locale detection** (Windows display language, Linux `LANG`/locale, macOS preferences).
   * The result is normalized to a **culture code** such as `en_US`, `fr_FR`, `es_ES` (language\_REGION).
2. The client **registers** this locale with Keeper Privilege Manager by calling **`POST /api/Locale/Register`** with a JSON body such as `{ "Locale": "en_US" }`.
3. The service stores the **locale for that user** (or session). Other UI apps (KeeperMFA, KeeperApproval, KeeperJustification, KeeperMessage, etc.) that run in the same context use the **same registered locale** when they request localization data.
4. When a component needs strings (e.g. menu labels, dialog text), it calls **`GET /api/localization/{component}/{culture}`** (e.g. `GET /api/localization/KeeperClientLocales/en_US`). The **culture** comes from the registered locale, so all components stay in sync.

So by default: **system locale → register with KPM → all UIs use that culture** for localization.

#### Fallback

* If system detection fails, the client falls back to **en\_US**.
* If a requested culture is missing for a string, the service typically falls back to **en\_US** for that key, or the UI may show a fallback message (e.g. the `message` field in a toast).

***

### How the Locale Can Be Overwritten

You can **override** the system-detected locale so that the UI always uses a specific language, regardless of the OS display language.

#### Option 1: KeeperClient Plugin Setting (recommended)

The **KeeperClient** plugin supports a **LanguageOverride** setting in its **metadata**:

| Setting                       | Type   | Default     | Effect                                                    |
| ----------------------------- | ------ | ----------- | --------------------------------------------------------- |
| **metadata.LanguageOverride** | string | `"DEFAULT"` | Override UI language for the tray and related components. |

**Values:**

* **`"DEFAULT"`** (or empty/not set) — Use **system-detected** locale (behavior above).
* **A valid culture code** — Force that language, e.g. `"en_US"`, `"fr_FR"`, `"es_ES"`, `"de_DE"`, `"ja_JP"`, `"zh_CN"`.

**How to set it:**

1. **From the dashboard** — If your deployment supports configuration policy or plugin settings push, set **LanguageOverride** for the KeeperClient plugin to the desired culture code.
2. **On the endpoint** — Edit the KeeperClient plugin JSON (e.g. `Plugins/KeeperClient.json` or the path used in your install). Under `metadata`, add or change:

   ```
   "metadata": {
     "LanguageOverride": "fr_FR"
   }
   ```

   Then **restart the KeeperClient plugin** (or the agent) so it reloads settings. On next start, KeeperClient will read `LanguageOverride`, use `fr_FR` instead of system detection, and register that with `POST /api/Locale/Register`.

**Note:** If the value is not a valid culture code, the client logs a warning and falls back to system detection.

#### Option 2: Register Locale via API

An admin or a custom script can call **`POST /api/Locale/Register`** with a body like `{ "Locale": "fr_FR" }` (with appropriate auth and, typically, in the context of the target user/session). That **overwrites** the stored locale for that user so subsequent UI components will request strings for the new culture. This is advanced; usually you use the plugin setting or command-line override instead.

#### Summary

| Method                                       | Scope                                               | Persistence                                  |
| -------------------------------------------- | --------------------------------------------------- | -------------------------------------------- |
| **metadata.LanguageOverride** (KeeperClient) | All users on endpoints where this config is applied | Until config is changed and plugin restarted |
| **--language-override** (launch arg)         | Single process run                                  | That run only                                |
| **POST /api/Locale/Register**                | One user/session                                    | Until next register                          |

***

### How to Modify Text (localization configuration)

You can **change the text** that appears in the UI by editing **localization data**. The product uses **locale files** (JSON) that map **string keys** to **per-culture text**. You can edit these files directly or, where the product supports it, use the **localization API**.

#### Where Localization Data Lives

* **On the service (agent):** Localization JSON files are typically under the **Localization** directory of the Keeper Privilege Manager installation (exact path depends on deployment; e.g. `KeeperPrivilegeManager/Localization/`).
* **Component-specific files** — Each UI component has its own locale file (or shares one). Examples:
  * **LocaleValues.json** — Core/system strings.
  * **SharedLocales.json** — Shared strings (buttons, common labels, etc.).
  * **KeeperClientLocales.json** — Tray app (KeeperClient).
  * **KeeperMfaLocales.json** — MFA dialog.
  * **KeeperApprovalLocales.json** — Approval dialog.
  * **KeeperJustificationLocales.json** — Justification dialog.
  * **KeeperMessageLocales.json** — KeeperMessage dialogs.
  * **KeeperTrayLocales.json** — System tray.
  * **KeeperControlsLocales.json** — Controls UI.
  * **SudoWrapperLocales.json**, **DiagnosticToolLocales.json** — CLI/tool strings.

The **component name** in the API (`GET /api/localization/{component}/{culture}`) corresponds to these files (e.g. `KeeperClientLocales`, `SharedLocales`).

<mark style="color:$danger;">**WARNING:**</mark> localization files may be overwritten during upgrades.

#### JSON Structure of a Localization File

Each file is a JSON object where:

* **Key** = string id used in code or jobs (e.g. `kepm_kc_menu_settings`, `kepm_shared_button_ok`).
* **Value** = object mapping **culture code** to **display text**.

**Example:**

```
{
  "kepm_shared_button_ok": {
    "en_US": "OK",
    "fr_FR": "OK",
    "es_ES": "Aceptar",
    "de_DE": "OK"
  },
  "kepm_approval_title": {
    "en_US": "Approval Required",
    "fr_FR": "Approbation requise",
    "es_ES": "Aprobación requerida"
  }
}
```

* **Parameterized strings** use placeholders `{0}`, `{1}`, etc. Example: `"en_US": "Approval required for {0}"`. The application substitutes values at runtime.

**Culture codes** are in the form **language\_REGION** (e.g. `en_US`, `fr_FR`, `zh_CN`). The product supports many locales (e.g. en\_US, en\_GB, es\_ES, fr\_FR, de\_DE, it\_IT, pt\_BR, ja\_JP, ko\_KR, zh\_CN, zh\_TW, ru\_RU, and others). Add or edit the culture key that matches the locale you care about.

#### Modifying Text by Editing a Localization File

1. **Locate the correct file** — For tray/menu text, use **KeeperClientLocales.json** or **SharedLocales.json**. For MFA/approval/justification/message dialogs, use the corresponding component file (e.g. **KeeperMfaLocales.json**, **KeeperApprovalLocales.json**).
2. **Find the key** — Keys follow patterns like `kepm_kc_*` (KeeperClient), `kepm_shared_*` (shared), `kepm_kmfa_*` (MFA), `kepm_kapproval_*` (approval). Search the file for the key that corresponds to the text you want to change (or add a new key if you are extending; use the same structure as existing entries).
3. **Edit the value for the culture** — Change the string for the desired culture (e.g. `"en_US": "Your new text"`). You can add a new culture block if the file does not yet have that locale.
4. **Save the file** and **reload** so the service picks up changes:
   * **Restart the affected plugin** (e.g. KeeperClient) or **restart the agent**, and/or
   * If your deployment uses a **locale cache**, run the **locale-cache-cleanup** job (or equivalent) so the next request gets fresh data.

**Important:** Keep valid JSON (commas, quotes). Back up the file before editing. Avoid removing keys that are still referenced by the app, or the UI may show a missing-key placeholder.

#### Modifying Text via the Localization API (Admin)

The product exposes **Admin** endpoints to create, update, or delete localization strings:

| Method     | Path                              | Description                                                      |
| ---------- | --------------------------------- | ---------------------------------------------------------------- |
| **POST**   | `/api/localization/strings`       | Create a localization string (body: key and per-culture values). |
| **PUT**    | `/api/localization/strings/{key}` | Update an existing string.                                       |
| **DELETE** | `/api/localization/strings/{key}` | Delete a string.                                                 |

These typically operate on the **same data** that the service uses to answer `GET /api/localization/{component}/{culture}`. Whether they apply to file-based locale files or to a separate store depends on implementation; see product documentation or API docs. After changes, **restart the relevant UI** or **clear locale cache** so clients see updated text.

**Example (conceptual):** To change the English text for key `kepm_shared_button_ok`, you might send a PUT with a body that includes the updated `en_US` value. Exact request/response format follows the product’s API specification.

#### Adding a New Key or New Culture

* **New key:** In the appropriate JSON file, add a new top-level key with the same structure: key name → object with culture codes and strings. Use a consistent naming convention (e.g. `kepm_<component>_<description>`). If the UI or a job references this key (e.g. by `messageKey` in a toast), it will then show your text.
* **New culture:** Add a new property to existing (or new) key objects, e.g. `"pt_PT": "Texto em português"`. Ensure the locale is one the product supports (or document any custom codes your deployment uses).

#### Naming and Best Practices

* **Key naming** — Many keys use a prefix such as `kepm_shared_*`, `kepm_kc_*`, `kepm_kmfa_*`, etc. Keeping a similar style makes it easier to find and maintain entries.
* **Fallback** — Always provide at least **en\_US** so there is a default if a culture is missing.
* **Parameterized strings** — Use `{0}`, `{1}` for dynamic parts (e.g. file name, count); the app will substitute them in order.
* **Testing** — After changing a file or API, set the user’s locale (e.g. via **LanguageOverride**) to that culture and restart the UI to verify the new text.

***

### Locale Registration and Localization API Summary

| Item                 | Description                                                                                                                                                                                                                                                                    |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Set locale**       | System detection by default; optional override via **metadata.LanguageOverride** (KeeperClient) or **--language-override** or **POST /api/Locale/Register**.                                                                                                                   |
| **Overwrite locale** | Set **LanguageOverride** in KeeperClient plugin config to a culture code (or `DEFAULT`); restart plugin. Or use **POST /api/Locale/Register** for that user.                                                                                                                   |
| **Modify text**      | Edit the appropriate **Localization/\*.json** file (key → culture → text), or use **POST/PUT/DELETE /api/localization/strings** (Admin). Restart UI or clear locale cache after changes.                                                                                       |
| **Locale files**     | **LocaleValues**, **SharedLocales**, **KeeperClientLocales**, **KeeperMfaLocales**, **KeeperApprovalLocales**, **KeeperJustificationLocales**, **KeeperMessageLocales**, **KeeperTrayLocales**, **KeeperControlsLocales**, etc., under the service **Localization** directory. |
| **Structure**        | `"key": { "en_US": "text", "fr_FR": "text", ... }`; parameterized strings use `{0}`, `{1}`.                                                                                                                                                                                    |
