# Verify Language Switch

Prove a language switch translates what the user sees, keeps what they had already...

- Repository: https://github.com/reticlehq/reticle (1299 stars)
- Category: Engineering
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add reticlehq/reticle --skill verify-language-switch -g -a claude-code -y`
Codex: `npx skills add reticlehq/reticle --skill verify-language-switch -g -a codex -y`
Cursor: `npx skills add reticlehq/reticle --skill verify-language-switch -g -a cursor -y`
Gemini CLI: `npx skills add reticlehq/reticle --skill verify-language-switch -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add reticlehq/reticle`

## Description

Prove a language switch translates what the user sees, keeps what they had already typed, and is still in force after a reload. Use when i18n, a locale picker, a language menu or translation files were added or changed, when a string is suspected of staying in the old language or showing a raw translation key, or when a user reports losing their form or their language choice after switching or refreshing.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# A translated heading is not a translated page

Clicking the language menu and seeing one word change proves one string was wired up. It does not prove the rest of the page followed, that the field the user was in the middle of filling still holds what they typed, or that the choice outlives a refresh. Those are three separate bugs. Each ships regularly, and glancing at the page after the click catches none of them.

**Reticle** can prove all three in the running app, with no test code. Not set up? Follow the [`reticle`](https://github.com/reticlehq/reticle/blob/main/skills/reticle/SKILL.md) skill: it installs Reticle, asks the user before `init` changes the app's files, and proves one flow.

## Before you start

- **Confirm the session can observe:** `reticle_session({ action: "list" })`. A hidden or throttled tab can accept a click and render nothing. If it is not healthy, report the run as **blocked**, not passed.
- **Take the expected strings from the app, not from your head.** Open its translation files (`locales/`, `messages/`, `i18n/`) and copy the target-language value for each string you will assert on. A translation you guessed can fail on a correct app, and one you half-remember can pass on a wrong one.
- **Pick strings that are not already on the page.** A language menu that lists "Español" satisfies `{ kind: "text", contains: "Español" }` before you click, and the verdict comes back `already_true`. Assert on the translated heading or a nav label instead, and `scope` the predicate to the region it lives in.

## 1. Note what is on screen, and type something

```
reticle_look({ action: "page", sessionId })
```

Write down two or three visible strings in the current language from **different regions** of the page: the heading, a nav label, a button. One string proves one component; two regions prove the switch reached the page.

Then type a value into a form field, so step 3 has something to find:

The rest: https://github.com/reticlehq/reticle/blob/HEAD/skills/verify-language-switch/SKILL.md
