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

# Configuration File

> Complete reference for the .gleef/config.json configuration file

The `.gleef/config.json` file controls how Gleef CLI processes your localization files. This file is created automatically by `gleef init` but can be customized for complex project setups.

## Configuration Location

The configuration file is always located at:

```
your-project/
└── .gleef/
    └── config.json
```

This file should be committed to version control so your team shares the same configuration.

## Basic Configuration Structure

```json theme={null}
{
  "localeFilePatterns": [
    "src/locales/{locale}.json",
    "public/i18n/{locale}/{feature}.json"
  ],
  "formatOptions": {
    "json": {
      "nested": true
    },
    "xml": {
      "nested": false
    }
  },
  "customLocaleNames": {
    "en-US": "english",
    "fr-FR": "french"
  },
  "prependNamespaceToKeys": false
}
```

## Configuration Properties

### localeFilePatterns

**Type:** `string[]`\
**Required:** Yes

Defines placeholder patterns that match your localization files. Each pattern **must** include the `{locale}` placeholder.

```json5 theme={null}
{
  "localeFilePatterns": [
    "src/locales/{locale}.json",              // Simple locale files
    "public/i18n/{locale}/{feature}.json",    // Namespaced by feature
    "assets/strings/{locale}.strings",        // iOS strings files
    "config/locales/{feature}.{locale}.yml"   // Feature-first naming
  ]
}
```

**Placeholder Syntax:**

| Placeholder   | Description                       | Example                       |
| ------------- | --------------------------------- | ----------------------------- |
| `{locale}`    | **Required** - Locale identifier  | `en`, `fr-FR`, `es-ES`        |
| `{feature}`   | Optional - Feature/namespace name | `common`, `auth`, `dashboard` |
| `{namespace}` | Optional - Alternative to feature | `header`, `footer`, `modal`   |

**Pattern Examples:**

| Pattern                           | Matches                                          | Structure                 |
| --------------------------------- | ------------------------------------------------ | ------------------------- |
| `src/{locale}.json`               | `src/en.json`, `src/fr.json`                     | Simple structure          |
| `locales/{locale}/{feature}.json` | `locales/en/common.json`, `locales/fr/auth.json` | Locale-first namespacing  |
| `i18n/{feature}.{locale}.json`    | `i18n/common.en.json`, `i18n/auth.fr.json`       | Feature-first namespacing |
| `assets/{locale}/strings.xml`     | `assets/en/strings.xml`, `assets/fr/strings.xml` | Folder-based locales      |

### formatOptions

**Type:** `object`\
**Required:** No

Controls how different file formats are processed and generated.

```json theme={null}
{
  "formatOptions": {
    "json": {
      "nested": true
    },
    "xml": {
      "nested": false
    },
    "yaml": {
      "nested": true
    }
  }
}
```

**Format-Specific Options:**

#### JSON Options

* `nested` (boolean): Use nested object structure vs flat keys

#### XML Options

* `nested` (boolean): Use nested elements vs flat structure

#### YAML Options

* `nested` (boolean): Use nested structure vs flat keys

#### Strings Options

None

### customLocaleNames

**Type:** `object`
**Required:** No

Maps your company's locale codes to the actual file or folder names in your project when they don't match.

```json theme={null}
{
  "customLocaleNames": {
    "en-US": "english",
    "fr-FR": "french",
    "es-ES": "spanish",
    "zh-CN": "chinese-simplified"
  }
}
```

**Use Cases:**

* Legacy naming conventions that can't be changed
* Simplified locale names (`fr` instead of `fr-FR`)
* Descriptive filenames in existing projects
* Platform-specific naming requirements (iOS: `en.lproj`)

**How it works:**

* Company locale `"fr-FR"` maps to file/folder name `"french"`
* Pattern `src/{locale}.json` resolves to `src/french.json`
* Gleef treats this file as containing `fr-FR` translations

### prependNamespaceToKeys

**Type:** `boolean`
**Required:** No
**Default:** `false`

Automatically prepends the namespace/file name to translation keys when pushing to Gleef's remote storage. This is useful when you have multiple namespace files per locale and want to keep keys unique across files remotely while maintaining simple keys locally.

```json theme={null}
{
  "prependNamespaceToKeys": true
}
```

**How it works:**

When enabled, translation keys are transformed before being sent to Gleef:

**Local file structure:**

```
locales/
  en/
    auth.json    → { "loginButton": "Log In" }
    common.json  → { "loginButton": "Sign In" }
```

Without `prependNamespaceToKeys` (default):

* Both files have key `loginButton`
* Conflict: Remote storage can't distinguish between them

With `prependNamespaceToKeys: true`:

* `auth.json` → Remote key: `auth.loginButton`
* `common.json` → Remote key: `common.loginButton`
* No conflict: Keys are unique remotely

**Use Cases:**

* Projects with multiple namespace files per locale
* Preventing key naming conflicts across different feature files
* Maintaining simple local key names while having unique remote keys
* Working with modular translation architectures

**Important:**

* Keys are only transformed for remote storage - local files remain unchanged
* When pulling translations, namespace prefixes are automatically stripped
* Works seamlessly with the `--namespace` flag for filtering

### placeholderTransformation

**Type:** `string | "default" | "none"`
**Required:** No
**Default:** `"none"` (transformation disabled)

Automatically converts placeholders between platform-specific formats and Gleef's universal ICU MessageFormat. This enables seamless cross-platform development where different platforms use different placeholder syntaxes.

```json theme={null}
{
  "placeholderTransformation": "default"
}
```

**Configuration Options:**

| Value       | Description                                               |
| ----------- | --------------------------------------------------------- |
| `"none"`    | Disabled - No transformation (default)                    |
| `"default"` | Use smart defaults based on file extension                |
| `"ios"`     | Force iOS format (`%@`, `%d`, `%1$@`)                     |
| `"android"` | Force Android format (`%s`, `%d`, `%1$s`)                 |
| `"printf"`  | Force printf format (`%s`, `%d`, `%f`)                    |
| `"icu"`     | Force ICU MessageFormat (`{variable}`, `{count:integer}`) |

**Default Format Mappings:**

When using `"default"`, file extensions automatically determine the format:

| File Extension  | Platform Format   | Example Placeholder             |
| --------------- | ----------------- | ------------------------------- |
| `.json`         | ICU MessageFormat | `{userName}`, `{count:integer}` |
| `.strings`      | iOS               | `%@`, `%d`, `%1$@`              |
| `.xml`          | Android           | `%s`, `%d`, `%1$s`              |
| `.yaml`, `.yml` | printf            | `%s`, `%d`, `%f`                |

**How it works:**

Gleef stores all translations using ICU MessageFormat internally. When you push/pull:

* **Push:** Converts your platform format → ICU format for remote storage
* **Pull:** Converts ICU format → your platform format for local files

**Platform Format Examples:**

<CodeGroup>
  ```swift iOS (.strings) theme={null}
  // Local file format
  "greeting" = "Hello %@, you have %d messages";
  "profile" = "Welcome back, %1$@! Last login: %2$@";

  // Stored in Gleef as ICU
  "greeting" = "Hello {variable}, you have {variable2:integer} messages";
  "profile" = "Welcome back, {variable@1}! Last login: {variable@2}";
  ```

  ```xml Android (strings.xml) theme={null}
  <!-- Local file format -->
  <string name="greeting">Hello %s, you have %d messages</string>
  <string name="profile">Welcome back, %1$s! Last login: %2$s</string>

  <!-- Stored in Gleef as ICU -->
  <string name="greeting">Hello {variable}, you have {variable2:integer} messages</string>
  <string name="profile">Welcome back, {variable@1}! Last login: {variable@2}</string>
  ```

  ```json Web (JSON with ICU) theme={null}
  // Local file format (no transformation needed)
  {
    "greeting": "Hello {userName}, you have {count:integer} messages",
    "profile": "Welcome back, {userName}! Last login: {lastLogin}"
  }

  // Already in ICU format - stored as-is
  ```

  ```yaml Backend (YAML with printf) theme={null}
  # Local file format
  greeting: "Hello %s, you have %d messages"
  profile: "Welcome back, %s! Last login: %s"

  # Stored in Gleef as ICU
  greeting: "Hello {variable}, you have {variable2:integer} messages"
  profile: "Welcome back, {variable}! Last login: {variable2}"
  ```
</CodeGroup>

**Use Cases:**

**Cross-Platform Projects:**

```json theme={null}
{
  "localeFilePatterns": [
    "src/web/{locale}.json",
    "ios/Resources/{locale}.lproj/Localizable.strings",
    "android/app/res/values-{locale}/strings.xml"
  ],
  "placeholderTransformation": "default"
}
```

With this configuration:

* Web JSON files use `{userName}` syntax (ICU)
* iOS strings use `%@` syntax (iOS format)
* Android XML uses `%s` syntax (Android format)
* All convert to ICU when stored in Gleef
* Each pulls back in its native format

**Forcing a Specific Format:**

```json theme={null}
{
  "localeFilePatterns": [
    "locales/{locale}.json"
  ],
  "placeholderTransformation": "android"
}
```

This forces JSON files to use Android placeholder syntax (`%s`, `%d`) instead of the default ICU format.

**Type Annotations:**

Placeholders can include type information for better validation:

| Type    | iOS        | Android | ICU                  |
| ------- | ---------- | ------- | -------------------- |
| String  | `%@`       | `%s`    | `{variable}`         |
| Integer | `%d`, `%i` | `%d`    | `{variable:integer}` |
| Float   | `%f`       | `%f`    | `{variable:float}`   |

**Positional Arguments:**

Reorder placeholders in translations using positional markers:

| Format  | Syntax         | Example                                  |
| ------- | -------------- | ---------------------------------------- |
| iOS     | `%1$@`         | `%1$@ logged in at %2$@`                 |
| Android | `%1$s`         | `%1$s logged in at %2$s`                 |
| ICU     | `{variable@1}` | `{variable@1} logged in at {variable@2}` |

**Important Notes:**

* Transformation happens automatically during push/pull operations
* Local files always maintain their native platform format
* Translators see the universal ICU format in Gleef's platform
* Conversion is deterministic and reversible

## Advanced Configuration Examples

### Multi-Module Project

<CodeGroup>
  ```json Configuration theme={null}
  {
    "localeFilePatterns": [
      "apps/web/src/locales/{locale}.json",
      "apps/mobile/assets/i18n/{locale}.json", 
      "packages/shared/locales/{locale}/{feature}.json"
    ],
    "formatOptions": {
      "json": {
        "nested": true
      }
    }
  }
  ```

  ```bash File Structure theme={null}
  apps/
  ├── web/src/locales/
  │   ├── en.json
  │   └── fr.json
  ├── mobile/assets/i18n/
  │   ├── en.json
  │   └── fr.json
  packages/shared/locales/
  ├── en/
  │   ├── common.json
  │   └── auth.json
  └── fr/
      ├── common.json
      └── auth.json
  ```
</CodeGroup>

### Cross-Platform Project

<CodeGroup>
  ```json Configuration theme={null}
  {
    "localeFilePatterns": [
      "src/web/{locale}.json",
      "ios/MyApp/{locale}.lproj/Localizable.strings",
      "android/app/src/main/res/values-{locale}/strings.xml"
    ],
    "formatOptions": {
      "json": {
        "nested": true
      },
      "xml": {
        "nested": false
      }
    },
    "customLocaleNames": {
      "en-US": "en",
      "fr-FR": "fr",
      "es-ES": "es"
    },
    "placeholderTransformation": "default"
  }
  ```

  ```bash File Structure theme={null}
  src/web/
  ├── en.json
  ├── fr.json
  └── es.json
  ios/MyApp/
  ├── en.lproj/
  │   └── Localizable.strings
  ├── fr.lproj/
  │   └── Localizable.strings
  └── es.lproj/
      └── Localizable.strings
  android/app/src/main/res/
  ├── values-en/
  │   └── strings.xml
  ├── values-fr/
  │   └── strings.xml
  └── values-es/
      └── strings.xml
  ```
</CodeGroup>

### Namespace-Organized Project

<CodeGroup>
  ```json Configuration theme={null}
  {
    "localeFilePatterns": [
      "i18n/{feature}.{locale}.yml",
      "locales/{locale}/{feature}.json"
    ],
    "formatOptions": {
      "json": {
        "nested": true
      },
      "yaml": {
        "nested": true
      }
    }
  }
  ```

  ```bash File Structure theme={null}
  i18n/
  ├── common.en.yml
  ├── common.fr.yml
  ├── auth.en.yml
  └── auth.fr.yml
  locales/
  ├── en/
  │   ├── dashboard.json
  │   └── settings.json
  └── fr/
      ├── dashboard.json
      └── settings.json
  ```
</CodeGroup>

### Namespace Project with Key Prepending

<CodeGroup>
  ```json Configuration theme={null}
  {
    "localeFilePatterns": [
      "locales/{locale}/{feature}.json"
    ],
    "formatOptions": {
      "json": {
        "nested": true
      }
    },
    "prependNamespaceToKeys": true
  }
  ```

  ```bash File Structure theme={null}
  locales/
  ├── en/
  │   ├── auth.json       → { "loginButton": "Log In", "signupButton": "Sign Up" }
  │   ├── common.json     → { "loginButton": "Sign In", "cancel": "Cancel" }
  │   └── dashboard.json  → { "welcome": "Welcome" }
  └── fr/
      ├── auth.json       → { "loginButton": "Se connecter", "signupButton": "S'inscrire" }
      ├── common.json     → { "loginButton": "Connexion", "cancel": "Annuler" }
      └── dashboard.json  → { "welcome": "Bienvenue" }
  ```

  ```json Remote Keys (with prependNamespaceToKeys) theme={null}
  {
    "en": {
      "auth.loginButton": "Log In",
      "auth.signupButton": "Sign Up",
      "common.loginButton": "Sign In",
      "common.cancel": "Cancel",
      "dashboard.welcome": "Welcome"
    }
  }
  ```
</CodeGroup>

This configuration solves the duplicate key problem where `loginButton` appears in both `auth.json` and `common.json`. With `prependNamespaceToKeys: true`, they become unique remote keys: `auth.loginButton` and `common.loginButton`.

## File Structure Examples

### Nested JSON (Default)

**Configuration:**

```json theme={null}
{
  "formatOptions": {
    "json": {
      "nested": true
    }
  }
}
```

**Output:**

```json theme={null}
{
  "auth": {
    "login": {
      "title": "Sign In",
      "email": "Email Address",
      "password": "Password"
    }
  },
  "navigation": {
    "home": "Home",
    "about": "About"
  }
}
```

### Flat JSON

**Configuration:**

```json theme={null}
{
  "formatOptions": {
    "json": {
      "nested": false
    }
  }
}
```

**Output:**

```json theme={null}
{
  "auth.login.title": "Sign In",
  "auth.login.email": "Email Address", 
  "auth.login.password": "Password",
  "navigation.home": "Home",
  "navigation.about": "About"
}
```

### XML Structure

**Configuration:**

```json theme={null}
{
  "formatOptions": {
    "xml": {
      "nested": false
    }
  }
}
```

**Output:**

```xml theme={null}
<?xml version="1.0" encoding="UTF-8"?>
<resources>
  <string name="auth_login_title">Sign In</string>
  <string name="auth_login_email">Email Address</string>
  <string name="navigation_home">Home</string>
</resources>
```

## Configuration Validation

### Common Validation Errors

**Missing Locale Placeholder:**

```
Error: No {locale} placeholder found in pattern: src/translations/*.json
```

**No Files Matched:**

```
Warning: Pattern 'locales/{locale}.json' matched no files. Check your file structure.
```

**Invalid Pattern Syntax:**

```
Error: File path structure doesn't match pattern: src/en/common.json vs src/{locale}.json
```

**Locale Mapping Issues:**

```
Warning: Some translations for locale 'fr' have been generated but not written locally.
Check your customLocaleNames configuration.
```

## Troubleshooting

### Configuration Issues

**No files detected:**

* Check pattern syntax
* Verify file paths are correct
* Test patterns with file system tools

**Wrong files included:**

* Add exclusion patterns
* Make patterns more specific
* Check for conflicting patterns

**Format errors:**

* Validate JSON syntax
* Check property names and values
* Review format-specific options

### Recovery

**Reset configuration:**

```bash theme={null}
rm -rf .gleef/
gleef init
```

## Next Steps

<CardGroup cols={2}>
  <Card title="File Patterns" icon="folder" href="/cli/configuration/file-patterns">
    Learn advanced file pattern matching techniques
  </Card>

  <Card title="Format Options" icon="file-code" href="/cli/configuration/format-options">
    Master format-specific configuration options
  </Card>
</CardGroup>
