Skip to content

Key Locking for JSON and YAML

Lingo.dev allows you to lock specific translation keys to prevent them from being modified during the translation process. This is particularly useful for maintaining consistent values across all locales where certain content should remain the same regardless of language.

Note: Key locking is currently supported only for JSON and YAML formats.

When to use key locking

  • URLs, email addresses, or other technical identifiers
  • Configuration values that should be identical across all languages

Configuration

To lock keys in your JSON or YAML translation files, add the lockedKeys array to your bucket configuration in i18n.json:

json
{
  "buckets": {
    "json": {
      "include": ["locales/[locale].json"],
      "lockedKeys": [
        "app/version",
        "config/apiEndpoint",
        "branding/productName"
      ]
    },
    "yaml": {
      "include": ["translations/[locale].yml"],
      "lockedKeys": ["contact/email", "site/domain"]
    }
  }
}

How it works

When Lingo.dev processes your translations:

  1. Keys specified in the lockedKeys array will retain their original values from the source locale
  2. These values will not be sent to the translation engine
  3. During both normal translation and cache restoration, locked keys will preserve their values

Nested objects and arrays

Key locking works with nested structures using path notation with forward slash (/) separators:

json
{
  "lockedKeys": [
    "level1/level2/level3/lockedValue",
    "settings/advanced/apiKeys/0",
    "configuration/endpoints/auth"
  ]
}

Important: The separator for nested keys is forward slash (/), not dot (.). This is because many applications use dots in key names for namespacing.

This allows you to:

  • Lock deeply nested object properties
  • Lock specific array elements (using numeric indices)
  • Lock entire object subtrees (all properties under a path)

Example

Consider this source JSON file (en.json):

json
{
  "welcome": "Welcome to our application",
  "config": {
    "api.url": "https://api.example.com",
    "version": "1.2.3"
  },
  "branding": {
    "name": "TechApp",
    "slogan": "Technology made simple"
  }
}

With this configuration:

json
{
  "buckets": {
    "json": {
      "include": ["locales/[locale].json"],
      "lockedKeys": ["config/api.url", "branding/name"]
    }
  }
}

When translating to Spanish, the resulting es.json would be:

json
{
  "welcome": "Bienvenido a nuestra aplicación",
  "config": {
    "api.url": "https://api.example.com",
    "version": "1.2.3"
  },
  "branding": {
    "name": "TechApp",
    "slogan": "Tecnología simplificada"
  }
}

Notice that config/api.url and branding/name remain unchanged from the source file, while other content is translated. Note how we used the forward slash (/) in the lockedKeys path even though the original key uses a dot.