Skip to main content
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

{
  "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.
{
  "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:
PlaceholderDescriptionExample
{locale}Required - Locale identifieren, fr-FR, es-ES
{feature}Optional - Feature/namespace namecommon, auth, dashboard
{namespace}Optional - Alternative to featureheader, footer, modal
Pattern Examples:
PatternMatchesStructure
src/{locale}.jsonsrc/en.json, src/fr.jsonSimple structure
locales/{locale}/{feature}.jsonlocales/en/common.json, locales/fr/auth.jsonLocale-first namespacing
i18n/{feature}.{locale}.jsoni18n/common.en.json, i18n/auth.fr.jsonFeature-first namespacing
assets/{locale}/strings.xmlassets/en/strings.xml, assets/fr/strings.xmlFolder-based locales

formatOptions

Type: object
Required: No
Controls how different file formats are processed and generated.
{
  "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.
{
  "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.
{
  "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.
{
  "placeholderTransformation": "default"
}
Configuration Options:
ValueDescription
"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 ExtensionPlatform FormatExample Placeholder
.jsonICU MessageFormat{userName}, {count:integer}
.stringsiOS%@, %d, %1$@
.xmlAndroid%s, %d, %1$s
.yaml, .ymlprintf%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:
// 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}";
Use Cases: Cross-Platform Projects:
{
  "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:
{
  "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:
TypeiOSAndroidICU
String%@%s{variable}
Integer%d, %i%d{variable:integer}
Float%f%f{variable:float}
Positional Arguments: Reorder placeholders in translations using positional markers:
FormatSyntaxExample
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

{
  "localeFilePatterns": [
    "apps/web/src/locales/{locale}.json",
    "apps/mobile/assets/i18n/{locale}.json", 
    "packages/shared/locales/{locale}/{feature}.json"
  ],
  "formatOptions": {
    "json": {
      "nested": true
    }
  }
}

Cross-Platform Project

{
  "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"
}

Namespace-Organized Project

{
  "localeFilePatterns": [
    "i18n/{feature}.{locale}.yml",
    "locales/{locale}/{feature}.json"
  ],
  "formatOptions": {
    "json": {
      "nested": true
    },
    "yaml": {
      "nested": true
    }
  }
}

Namespace Project with Key Prepending

{
  "localeFilePatterns": [
    "locales/{locale}/{feature}.json"
  ],
  "formatOptions": {
    "json": {
      "nested": true
    }
  },
  "prependNamespaceToKeys": true
}
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:
{
  "formatOptions": {
    "json": {
      "nested": true
    }
  }
}
Output:
{
  "auth": {
    "login": {
      "title": "Sign In",
      "email": "Email Address",
      "password": "Password"
    }
  },
  "navigation": {
    "home": "Home",
    "about": "About"
  }
}

Flat JSON

Configuration:
{
  "formatOptions": {
    "json": {
      "nested": false
    }
  }
}
Output:
{
  "auth.login.title": "Sign In",
  "auth.login.email": "Email Address", 
  "auth.login.password": "Password",
  "navigation.home": "Home",
  "navigation.about": "About"
}

XML Structure

Configuration:
{
  "formatOptions": {
    "xml": {
      "nested": false
    }
  }
}
Output:
<?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:
rm -rf .gleef/
gleef init

Next Steps