All jobs

Translate a Nuxt App Into Another Language

Yes. An agent adds a locale to your Nuxt i18n app, translates every key in the source file, fixes the keys other locales are missing, and guards it all with a test.

Run this on RushIn a Project that has your repository.

What the agent does

The agent clones the repository into its own cloud sandbox and reads how translation is wired before it writes a word. In a Nuxt app like nuxt/movies, nuxt.config.ts loads @nuxtjs/i18n with strategy: 'no_prefix', langDir: 'internationalization', defaultLocale: 'en', browser detection with a cookie and an en fallback, and a locales list of fourteen entries from en to km, each with a code, a name in its own language and a file. i18n.config.ts sets fallbackLocale to en. app/components/LanguageSwitcher.vue renders a <select id="langSwitcher"> over locales and calls setLocale. The messages are flat JSON keyed by the English string itself: en.json has 49 keys such as Popular Movies, Type to search..., Search result for: {currentSearch} and {count} items, and components call them with $t('Home') and friends.

Before adding anything it compares the files, because a new locale copies the shape of the old ones. Twelve of the thirteen translations have all 49 keys. it.json has 45: Home, Movies, Search and TV Shows, the four navigation titles in app/components/NavBar.vue, are missing, so Italian users see the English fallback in the nav. de-DE.json has 49 entries but one of them is keyed Länge where en.json has Runtime, so $t('Runtime') falls back to English in German and the translation sits unused. The agent lists both findings in the pull request and fixes them in the same change, since the new locale would otherwise be the only complete one.

Then it adds the locale the prompt names: a new internationalization/<code>.json with every one of the 49 keys translated, placeholders such as {currentSearch}, {count} and {numberOfVideos} kept exactly, and the four strings that carry an ellipsis kept as three dots as the source does. It adds the entry to locales in nuxt.config.ts with the language's name written in that language, as the other entries are, so the switcher shows it the way a speaker expects. It does not add a prefix or change strategy, because the app chooses one URL for all languages and the existing end-to-end test depends on that.

To keep the files from drifting again it writes tests/unit/locales.test.ts, which vitest.config.ts already includes through **/tests/unit/**/*.test.ts: it reads every file in internationalization/, asserts its key set equals en.json's, and asserts every placeholder in a source string appears in the translation. That test fails on the repository as it is today and passes after the change. The agent runs pnpm test:unit, pnpm lint and pnpm typecheck, and because tests/e2e/homepage.spec.ts switches the language on a live page, it runs pnpm exec playwright test --project=Chrome to see that switching to the new code sets html lang and changes the visible strings.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Add a Dutch locale to this Nuxt app. Read nuxt.config.ts, i18n.config.ts, app/components/LanguageSwitcher.vue and every file in internationalization/ first. Compare each locale file's keys to en.json and report any missing or mismatched keys. Create internationalization/nl.json with every key of en.json translated, keeping placeholders exactly, add it to the locales list in nuxt.config.ts with its name written in Dutch, and fix the missing or mismatched keys you found in the other locale files without changing their existing translations. Add tests/unit/locales.test.ts that asserts every locale file has exactly en.json's keys and preserves its placeholders. Run pnpm test:unit, pnpm lint, pnpm typecheck and the Chrome Playwright project, and open a pull request listing what you added and what you fixed, marked for a native speaker to review.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request on its own branch that adds internationalization/nl.json and tests/unit/locales.test.ts, adds one entry to locales in nuxt.config.ts, adds four keys to it.json, and renames one key in de-DE.json from Länge to Runtime with its value unchanged. No component, page or other locale file changes. The description has three parts: the new locale and a table of its 49 strings for a reviewer who reads the language, the two fixes with the file and key named, and the test output.

A reviewer who speaks the language reads the table and corrects what a machine translation got wrong, which is why the pull request says so at the top rather than claiming fluency. Everyone else checks that the placeholders survived, that nuxt.config.ts gained one entry and nothing else, and that the new test fails on main and passes on the branch, which the session's transcript shows in that order.

The transcript also keeps the Playwright run where the switcher is set to the new code, so the reviewer can see the lang attribute and a translated heading without starting the app.

Run it on every Monday morning

Add an automation to the Project with a schedule trigger, a cron for Monday morning in your timezone, and a prompt that asks the agent to compare every locale file to en.json and open a pull request only when a key is missing or mismatched. Strings added to en.json during the week get their translations before anyone notices the fallback, and a week with no drift opens nothing.

For a new language on demand, a POST /o/{org}/sessions with this prompt and the language changed is the whole integration; a webhook_url on the API key receives run.completed with the session_url of the pull request.

The use case this job follows, with its automation and trigger: Hand off from your terminal.

Why run it on Rush?

Adding a language is forty-nine small decisions and a config edit, and the drift that makes the fourteenth file harder than the first is invisible until someone diffs key sets by hand. The agent does the diff first, in its own sandbox, fixes what it finds, writes the new file in the same shape and leaves a test so the next drift fails a build instead of a user.

The pull request separates what a native speaker must read from what anyone can check, and the transcript holds the test run, the lint and the browser switch. Several apps, or several languages, can run at once, each in its own sandbox and branch.

Frequently asked questions

Is the translation good enough to ship?

It is good enough to review, and the pull request says so at the top. The agent translates each string with its UI context, keeps placeholders and punctuation intact and matches the register of the other locale files, but a native speaker should read the table in the description before merging. That review is the one step this job cannot do for you.

Why did it change the German and Italian files when I asked for Dutch?

Because the comparison it ran first found them incomplete: it.json lacks the four navigation titles and de-DE.json keys one translation under the German word instead of the English source key, so both fall back to English in the UI. Fixing them is a key change, not a translation change, and it is listed separately in the pull request. Say so in the prompt if you want the new locale only.

Will the URLs change?

No. The app uses strategy: 'no_prefix', so every language lives at the same URL and the choice is stored in the i18n cookie. The agent adds the locale and leaves the strategy alone, which also keeps the existing Playwright language-switch test valid.

What stops the files from drifting again?

The new tests/unit/locales.test.ts, which Vitest already picks up from tests/unit/. It fails when any locale file is missing a key en.json has, has one it does not, or drops a placeholder, so the next string added to en.json without translations fails pnpm test:unit in the existing unit-test workflow.