# Fix the angular ngx-translate pipe missing key error

## TL;DR

The translate pipe prints the key because the loader never delivered that translation, so check the loader path and that setDefaultLang ran. Confirm the JSON is reachable at the URL the TranslateHttpLoader builds, then make sure use() is called with a language that has the key. Most cases are a wrong assets path.

## The error

```text
Missing translation for "HOME.TITLE" in language "es"
{{ 'HOME.TITLE' | translate }} renders HOME.TITLE
```

## Fix it

### Step 1: Check the URL the loader requests

```bash
grep -rn "TranslateHttpLoader" src/app/app.module.js | head -3
```

Expected: You see the prefix and suffix, usually ./assets/i18n/ plus .json.

### Step 2: Fetch that URL directly

```bash
curl -s -o /dev/null -w "%{http_code}" YOUR_HOST/assets/i18n/es.json
```

Expected: 200 means the file is served, 404 means the path is wrong.

### Step 3: Confirm the key exists in the file

```bash
node -e "const j=require('./src/assets/i18n/es.json'); console.log(j.HOME && j.HOME.TITLE ? 'key present' : 'key missing')"
```

Expected: You know whether it is a path problem or a content problem.

### Step 4: Verify setDefaultLang and use ran at startup

```bash
grep -rn "setDefaultLang\|.use(" src/app/app.component.js | head -5
```

Expected: The default language is set and use() is called before first render.

## When to use this

- The ngx-translate pipe renders the key instead of the translation
- The console logs missing translation for a key

## When NOT to use this

- The key translates but shows the wrong language, check the active language
- You use a custom loader, verify the loader not the path

## Tool and version compatibility

- @ngx-translate/core v13/v14/v15, @ngx-translate/http-loader
- Angular 12 through 18

## Variant phrasings

### missing key only after lazy module loads

The lazy module never called the loader for its language. Share one TranslateService instance or reload translations on module init.

### key missing in tests only

Tests need TranslateModule.forRoot with a fake loader. Without it the pipe has no translations at all.

## Why it happens

The pipe asks the TranslateService for the key in the active language. If the HTTP loader 404d, the language was never activated, or the key is absent from the JSON, the service returns the key itself and logs the miss.

## Edge cases

- Nested keys need the full path, HOME.TITLE will not match a flat home.title key
- A trailing slash mismatch in the loader prefix 404s every language
- setDefaultLang only sets the fallback, use() activates the language

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Pz-ua5Ylpby8URZENHCbwA
