Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ jobs:

- name: Every script parses
run: |
for f in scripts/*.mjs scripts/providers/*.mjs; do
for f in scripts/*.mjs scripts/providers/*.mjs bin/*.mjs; do
node --check "$f" || { echo "::error file=$f::syntax error"; exit 1; }
done
bash -n scripts/finalize.sh
echo "all scripts parse"

- name: Provider contract tests
- name: Contract tests (providers + CLI)
run: npm test

- name: Example config is valid JSON
Expand All @@ -46,6 +46,18 @@ jobs:
fi
echo "no key material found"

- name: Packaged CLI installs and scaffolds
run: |
npm pack --pack-destination /tmp
mkdir -p /tmp/cli-smoke && cd /tmp/cli-smoke
npm init -y > /dev/null
npm install --no-audit --no-fund --save-dev /tmp/claude-translator-*.tgz
./node_modules/.bin/claude-translator init
test -f scripts/i18n/extract.mjs || { echo "::error::init did not scaffold"; exit 1; }
test -f i18n.config.json || { echo "::error::init wrote no config"; exit 1; }
node -e "JSON.parse(require('fs').readFileSync('i18n.config.json','utf8'))"
echo "packaged CLI works"

- name: Config loader smoke test
run: |
mkdir -p /tmp/fixture/dist/about /tmp/fixture/dist/pricing
Expand Down
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ All notable changes to this project are documented here.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.0] — 2026-08-25

### Added

- **`npx claude-translator init`** — a scaffolder that replaces the four manual install
steps. Copies the pipeline into `scripts/i18n/` (or `--dir`), writes `i18n.config.json`,
declares `parse5`, and appends the derived `i18n/` paths to `.gitignore`. It never
overwrites without `--force` and prints every path it touched
- `--help`, `--version`, `--dir`, `--force`
- **12 CLI contract tests** (`npm test`) covering the refusal to install outside a Node
project, idempotency, `--force`, `--dir`, appending rather than replacing an existing
`.gitignore`, and that `package.json` "files" actually ships what `init` copies
- CI now packs the tarball, installs it into a scratch project and runs `init`, so a
broken published package fails the build rather than a user's first command

### Changed

- `parse5` moved from `dependencies` to `devDependencies`. Nothing in the published
package needs it at runtime — the CLI only copies files — so `npx` no longer downloads
it. A clone plus `npm install` is unaffected
- `package.json` gained a `files` allowlist, so the tarball carries the scripts,
references, `SKILL.md` and the example config, and nothing else

## [1.2.0] — 2026-08-25

Renamed to **Claude Translator**, and the translation step is no longer tied to one vendor.
Expand Down Expand Up @@ -106,6 +129,7 @@ into dozens of languages.
and cost, and adapting to other static site generators
- `SKILL.md`, so the repository can be installed directly as a Claude Code skill

[1.3.0]: https://github.com/ConveyThis/claude-translator/releases/tag/v1.3.0
[1.2.0]: https://github.com/ConveyThis/claude-translator/releases/tag/v1.2.0
[1.1.0]: https://github.com/ConveyThis/claude-translator/releases/tag/v1.1.0
[1.0.0]: https://github.com/ConveyThis/claude-translator/releases/tag/v1.0.0
40 changes: 31 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,15 @@ The builder restores the original tags by index.

```bash
# 1. Install into your project
git clone https://github.com/ConveyThis/claude-translator.git
cp -r claude-translator/scripts <your-project>/scripts/i18n
cd <your-project> && npm install --save-dev parse5
cd <your-project>
npx claude-translator init
npm install # parse5, the only dependency

# 2. Configure
cp ../claude-translator/i18n.config.example.json i18n.config.json
# 2. Configure — baseUrl, locales, provider
$EDITOR i18n.config.json

# 3. Provide your key (or skip entirely for a local model)
echo "ANTHROPIC_API_KEY=your-key-here" >> .env # make sure .env is gitignored
# 3. Provide your key (skip entirely for a local model)
echo "ANTHROPIC_API_KEY=your-key-here" >> .env # .gitignore this

# 4. Run
npm run build # your normal build
Expand All @@ -121,6 +120,29 @@ node scripts/i18n/audit-seo.mjs # full SEO audit

Deploy the resulting build directory exactly as you deploy it today.

`init` copies the pipeline into `scripts/i18n/`, writes a config, declares `parse5`, and adds
the derived `i18n/` paths to `.gitignore`. It **never overwrites anything without `--force`**
and prints every file it touched. `--dir <path>` puts the scripts somewhere else.

<details>
<summary>Installing without npx</summary>

```bash
git clone https://github.com/ConveyThis/claude-translator.git
cp -r claude-translator/scripts <your-project>/scripts/i18n
cp claude-translator/i18n.config.example.json <your-project>/i18n.config.json
cd <your-project> && npm install --save-dev parse5
```

Or run the scaffolder straight from the clone:
`node claude-translator/bin/claude-translator.mjs init`

</details>

The scripts are copied into your project rather than run from `node_modules` on purpose: they
resolve `parse5` and every relative path from the project they live in, they are short enough to
read, and this is AGPL software whose point is that you can change them.

---

## Configuration
Expand Down Expand Up @@ -340,8 +362,8 @@ git clone https://github.com/ConveyThis/claude-translator.git \
~/.claude/skills/claude-translator
```

Then ask Claude to "localize this site" and it will follow `SKILL.md`, including the
failure modes documented in `references/`.
Then ask Claude to "localize this site". It follows `SKILL.md`, including the failure modes in
`references/` and the routing rules for when this is the wrong tool entirely.

---

Expand Down
20 changes: 11 additions & 9 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ argument-hint: "[project-dir]"
license: AGPL-3.0
metadata:
author: ConveyThis
version: "1.2.0"
version: "1.3.0"
category: i18n
---

Expand Down Expand Up @@ -97,19 +97,21 @@ do not take the same parameters and guessing costs money.
## Setup

```bash
cp ~/.claude/skills/claude-translator/scripts/*.mjs <project>/scripts/
cp ~/.claude/skills/claude-translator/scripts/*.sh <project>/scripts/
cp ~/.claude/skills/claude-translator/i18n.config.example.json <project>/i18n.config.json
cd <project> && npm i -D parse5 # the only dependency
cd <project>
node ~/.claude/skills/claude-translator/bin/claude-translator.mjs init
npm install # parse5, the only dependency
```

That copies the pipeline into `scripts/i18n/`, writes `i18n.config.json`, declares
`parse5` and adds the derived paths to `.gitignore`. It never overwrites without
`--force`, so it is safe to re-run; `--dir <path>` puts the scripts elsewhere.

Scripts run **from inside the project** so `parse5` and relative paths resolve. Edit
`i18n.config.json` — five keys cover everything; see `i18n.config.example.json`.

Add to `.gitignore`: `i18n/source.json`, `i18n/manifest.json`, `i18n/segments/`,
`i18n/tm/*.failures.json`, `i18n/tm/*.review.json`, and `i18n` in `.prettierignore`.
**Commit `i18n/tm/{lang}.json`** — the memory is the asset; losing it means paying for a
full re-translation.
**Commit `i18n/tm/{lang}.json`.** The scaffolder deliberately does not ignore it: the
memory is the asset, and losing it means paying for a full re-translation. Everything
else under `i18n/` is derived and is ignored for you. Add `i18n` to `.prettierignore`.

## Pipeline

Expand Down
Loading
Loading