Rename to Claude Translator and unlock any translation provider - #2
Merged
Merged
Conversation
Two names for one thing (repo claude-translator, skill static-site-localization) was a split I introduced and it was wrong. The product is Claude Translator throughout: skill, package, generator tag and landing-page URL. "static-site localization" survives as the descriptive subtitle, because it is the phrase people search when they have never heard of us. Providers The translation step no longer assumes Google. scripts/providers/ holds three adapters — anthropic, gemini, openai — each owning only how to build a request and how to read a response. Everything that made translate.mjs worth keeping stayed put and now applies to all of them: network-error retry, HTTP backoff, halving a batch that was refused or truncated, placeholder validation, memory checkpointing. The openai adapter is the one that matters most. /v1/chat/completions is spoken by OpenAI, Azure, Groq, DeepSeek, Mistral, OpenRouter, Together and Fireworks — and by Ollama, LM Studio and vLLM, so setting apiBaseUrl to localhost runs the whole pipeline on your own hardware with no key and no request leaving the machine. Anything not on that list is a .mjs file with two exports; references/providers.md documents the interface. Claude is now the default, on claude-haiku-4-5 — the tier priced for bulk segment translation. It is roughly 10x the previous Gemini default, which references/throughput-and-cost.md now states plainly with a per-provider table and the one-line change back. Burying that would be worse than the cost itself. Things that would have bitten - A config from 1.0/1.1 pins a Gemini model and has no provider key. Changing the default would have sent a Gemini model id to Anthropic. The provider is now inferred from the model id, so those configs are untouched; only a config naming neither gets the new default. - Claude tiers do not take the same parameters. Haiku rejects output_config.effort outright, and the tiers that accept it run adaptive thinking by default — a translation run would have quietly paid for reasoning it has no use for. The adapter carries a capability table and pins low effort where it applies. - Small and local models emit fenced JSON and often reject response_format entirely. The parser strips fences; the JSON mode degrades json_schema -> json_object -> prompt only rather than failing the run. - apiBaseUrl is a separate key from baseUrl. Sharing one would have meant pointing at a local model also rewrote every canonical and hreflang URL. - The generator tag changed, and verify.mjs gate 2 matches its prefix. Gate 2 now accepts the 1.1 name too, so a locale directory built by the previous release still verifies after upgrading. Cost is reported only when a rate is genuinely known — from config or the provider's own table — instead of a hardcoded guess at somebody else's price list. Token counts are always printed. Verified without spending anything: 20 contract tests assert each adapter's exact request shape, usage normalisation and split-triggering behaviour (npm test, no network, now in CI). Beyond that, all six gates pass with the new tag and still fail on injected markup, a foreign generator tag, a duplicate of our own, and an old-plus-new pair; provider resolution was exercised across six configs; and a custom adapter plus a deliberately picky OpenAI-compatible server drove full runs over real HTTP, including the double JSON-mode fallback with placeholders intact. No live call was made to Anthropic, Google or OpenAI — no credentials on this machine. The request shapes are asserted against their documented contracts, not against the live services. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two follow-ups from the last release, plus the launch blocker.
claude-translator+ skillstatic-site-localizationwas a split I introduced and it was wrong. Everything now says Claude Translator; "static-site localization" survives as the descriptive subtitle, because it is the phrase people search when they have never heard of us.translate.mjshardcoded Google's endpoint, so "why can I only use Gemini?" was the first question any reviewer would ask.Providers
scripts/providers/holds three adapters —anthropic,gemini,openai— each owning only how to build a request and how to read a response. Everything that madetranslate.mjsworth keeping stayed put and now applies to all of them: network-error retry, HTTP backoff, halving a batch that was refused or truncated, placeholder validation, memory checkpointing.The
openaiadapter is the one that matters./v1/chat/completionsis spoken by OpenAI, Azure, Groq, DeepSeek, Mistral, OpenRouter, Together and Fireworks — and by Ollama, LM Studio and vLLM:{ "provider": "openai", "apiBaseUrl": "http://localhost:11434/v1", "model": "qwen2.5:14b" }No key, no quota, nothing leaves the machine. Anything not on that list is a
.mjsfile with two exports — see the newreferences/providers.md.Claude is now the default, on
claude-haiku-4-5. That is ~10x the previous Gemini default, andreferences/throughput-and-cost.mdnow says so plainly with a per-provider table and the one-line change back. Burying it would be worse than the cost.Five things that would have bitten
providerkey — the new default would have sent a Gemini model id to Anthropic. The provider is now inferred from the model id, so those configs are untouched. Only a config naming neither gets the new default.output_config.effort; the tiers that accept it run adaptive thinking by default, which a translation run has no use for but is billed for. The adapter carries a capability table and pins low effort where it applies.response_formatoutright. The parser strips fences; the JSON mode degradesjson_schema→json_object→ prompt-only instead of failing.apiBaseUrlis deliberately a different key frombaseUrl(the site's origin). Sharing one would have meant pointing at a local model also rewrote every canonical, hreflang and sitemap URL.Verification
20 contract tests (
npm test— no network, no key, now in CI) assert each adapter's exact URL, headers, body shape, usage normalisation and split-triggering behaviour. Beyond that:claude-*inference, explicit localopenai, unknown provider, missing key