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

# Source File

> How LazyLocales manages your source locale file and annotation syntax

Your **source file** is the JSON locale file that contains your original-language strings. LazyLocales uses a `.source.json` convention to separate the annotated source from the clean runtime file.

## The `.source.json` convention

When you run `lazylocales translate` for the first time, the CLI automatically renames your source file:

```
en.json  →  en.source.json
```

On every subsequent translate or push, a clean `en.json` is generated automatically — stripped of all annotations and ready for your i18n library.

```
locales/
├── en.source.json   ← your editable source (with annotations)
├── en.json           ← auto-generated clean copy (for runtime)
├── fr.json           ← AI-translated
├── de.json           ← AI-translated
└── es.json           ← AI-translated
```

<Info>
  The clean `en.json` is regenerated on every `translate` and `push` run. You should never edit it directly — always edit `en.source.json` instead.
</Info>

### Why two files?

Most i18n libraries (i18next, next-intl, vue-i18n) expect a plain JSON file with only key-value pairs. Annotation keys like `__context__` and `__lock__` would cause warnings or unexpected behavior at runtime. The `.source.json` convention keeps your annotations in a separate file that only the CLI reads, while the generated `en.json` stays clean for your app.

## Annotations

Annotations are special keys you add to your source file to control how the AI translates (or doesn't translate) specific strings. They are always stripped from the generated output files.

### Context (`__context__`)

Provide translation context by adding a `__context__` key next to any translation string. The key name format is `__context__` followed by the sibling key name.

```json en.source.json theme={null}
{
  "greeting": "Hello",
  "__context__greeting": "Informal greeting shown on the homepage hero section",

  "cta": "Get started",
  "__context__cta": "Call-to-action button, keep it short and punchy (max 2 words)"
}
```

Context annotations are sent to the AI model as hints. They help produce more accurate translations by telling the AI:

* **Where** the text appears in your UI
* **Tone** — formal, casual, technical, playful
* **Constraints** — character limits, line length, abbreviation rules
* **Terminology** — domain-specific terms, brand voice

Context keys work at any nesting level:

```json en.source.json theme={null}
{
  "nav": {
    "home": "Home",
    "__context__home": "Main navigation link — single word preferred"
  }
}
```

### Lock (`__lock__`)

Prevent a key from being translated by setting its `__lock__` sibling to `true` or `"true"`. Locked keys are copied verbatim from the source into every target locale file.

```json en.source.json theme={null}
{
  "brand": "LazyLocales",
  "__lock__brand": true,

  "product": {
    "name": "TranslateAI Pro",
    "__lock__name": true,
    "tagline": "Fast, accurate translations"
  }
}
```

In the output files (`de.json`, `fr.json`, etc.), `brand` will always be `"LazyLocales"` and `product.name` will always be `"TranslateAI Pro"` — they are never sent to the AI.

Lock annotations are useful for:

* **Brand names** and product names
* **Technical terms** that must stay in the source language
* **Constants** — error codes, identifiers, placeholder strings
* **Legal text** that requires exact wording

### Combining annotations

You can use both `__context__` and `__lock__` on the same key. For example, you might lock a key now but leave context for future reference:

```json en.source.json theme={null}
{
  "errorCode": "ERR_AUTH_FAILED",
  "__lock__errorCode": true,
  "__context__errorCode": "Internal error code, never translate"
}
```

## How annotations affect the diff

When you add, remove, or change a `__context__` or `__lock__` annotation, the CLI treats the associated key as **modified** — even if the value itself didn't change. This means:

* Adding `__context__greeting` will re-translate `greeting` in all target locales (with the new context).
* Adding `__lock__brand` will replace the translated `brand` with the source value in all target locales.
* Removing a `__lock__` will cause the key to be translated by AI on the next run.

## Full example

Here's a realistic source file with mixed annotations:

```json en.source.json theme={null}
{
  "common": {
    "appName": "LazyLocales",
    "__lock__appName": true,

    "cancel": "Cancel",
    "save": "Save",
    "__context__save": "Primary action button in forms — keep it short",

    "greeting": "Welcome back, {name}!",
    "__context__greeting": "Shown on dashboard after login. {name} is the user's first name."
  },
  "errors": {
    "notFound": "Page not found",
    "__lock__notFound": true,
    "__context__notFound": "HTTP 404 — locked because we want the English string everywhere",

    "serverError": "Something went wrong. Please try again.",
    "__context__serverError": "Generic fallback error — friendly, not technical"
  }
}
```

After running `lazylocales translate`, the generated `de.json` would look like:

```json de.json theme={null}
{
  "common": {
    "appName": "LazyLocales",
    "cancel": "Abbrechen",
    "save": "Speichern",
    "greeting": "Willkommen zurück, {name}!"
  },
  "errors": {
    "notFound": "Page not found",
    "serverError": "Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."
  }
}
```

Notice:

* `appName` and `notFound` are **locked** — copied verbatim from the source.
* `save` and `greeting` are translated with their **context** hints.
* All annotation keys are **stripped** — the output is clean JSON.
