Cross-Language Refactor Prompt for an Idiomatic Port, Not a Line Swap
A cross-language refactor prompt ports code idiomatically, flags non-translatable constructs, and locks a per-file output contract. Copy the structure.
Porting a module from Python to Go isn't translation. It's a rewrite that happens to share a spec. The cross-language refactor prompt that gets this right doesn't swap syntax line by line; it reads the module's intent and expresses it the way the target language actually wants, then flags the parts that don't translate at all.
The common tooling does the opposite. Paste a function, get the "same" function in another language, line for line. The output compiles. It also reads like Python wearing a Go costume: error handling shoehorned into try/except shapes, comprehensions faked with loops that miss the point. It works until it doesn't, and the bug is buried in a construct that never had a clean equivalent.
A reusable prompt fixes the altitude. It works at the module level with full context, not one orphaned function, and it tells you what it couldn't port cleanly instead of guessing.
Why a line-for-line port is a trap
Every language has constructs the others don't. Go's explicit error returns, Python's generators, Rust's borrow checker. A line swap maps each statement to its nearest neighbor, and the nearest neighbor is often wrong. The result is code that runs in the new language while thinking in the old one.
The opinionated bit. Most "AI code translation" is worse than useless for anything beyond a toy, because the failure is invisible. Bad translation doesn't crash. It compiles, passes a glance, and ships a subtle semantic drift, an off-by-one in how a concurrent loop behaves, an exception swallowed where the source would have propagated it. A port you can't trust is slower than rewriting by hand, because now you have to audit every line anyway.
So the prompt's value isn't speed. It's honesty about what it couldn't do.
What a cross-language refactor prompt does
A cross-language refactor prompt is a module-level porter that reads source code plus its context and returns idiomatic target code, a non-translatable list, and a per-file output contract. It ports intent, not syntax.
Run it to:
- Map the full scope of the port before any line changes
- Translate at the module level with surrounding context, not isolated functions
- Express the target language's idioms instead of mirroring the source
- Flag non-translatable constructs for a human decision
- Lock an output contract per file so each port is a reviewable unit
- Sweep call sites so callers of the ported code get updated too
The non-translatable list is the part naive tools hide.
Anatomy of the prompt
Variables
{{source_language}} → language porting from
{{target_language}} → language porting to
{{source_module}} → the module + its context
{{idiom_rules}} → target-language conventions to honor
Prompt
Role: you are a cross-language porter.
Task: port {{source_module}} from {{source_language}}
to {{target_language}} idiomatically.
Rules:
- Express intent in the target's idioms, not the source's.
- Flag any construct with no clean equivalent. Don't fake it.
- Output one file at a time with a clear contract.
Output contract
Return: ported file + non-translatable list + call-site notes.
1. Set the languages
{{source_language}} and {{target_language}} drive the idiom rules. The more specific the better; "Python 3.11 to Go 1.22" beats "Python to Go."
2. Supply module context
Paste the module into {{source_module}} with its imports and the types it touches. A function alone loses the context that makes the port correct.
3. Read the non-translatable list first
Before the ported code, read what the prompt flagged. Those are your decisions. A goroutine where the source was single-threaded isn't a translation; it's a design choice you have to make.
4. Port file by file
The per-file contract keeps each unit reviewable. Don't accept a 2,000-line blob; the prompt should hand you one file at a time.
The ported code is the easy output. The non-translatable list is the valuable one. When the prompt says "this generator has no direct equivalent, here are two options," that's the prompt doing its job. A port with an empty flag list on a non-trivial module is suspicious, not reassuring. It usually means the model faked something rather than admitting it couldn't.
Prompt-craft patterns for porting
Pass the module, not the function. Context is what makes a port idiomatic. A function ported in isolation loses the types and call patterns that should shape it. Give the model the surrounding module.
Make "flag, don't fake" a rule. Models default to helpfulness, which means they'll invent a translation for an untranslatable construct. State it: "if a construct has no clean equivalent, flag it for a human." Without the rule, you get confident wrong code.
Lock the contract per file. One giant output is unreviewable. A per-file contract turns the port into PR-sized units you can actually check.
Which model ports more honestly
Idiomatic porting is one of the few tasks where the models genuinely differ in character, not just capability. Claude tends to be more willing to flag a construct as non-translatable and stop, which is exactly the behavior you want. GPT-4o is more eager to produce a translation for everything, so the "flag, don't fake" rule has to be louder and restated near the end of the prompt.
| Behavior | Claude | ChatGPT (GPT-4o) |
|---|---|---|
| Flags untranslatable constructs | Readily, when asked | Tends to invent a translation unless the rule is explicit |
| Preserves target idioms | Strong | Strong, but sometimes mirrors source structure |
| Holds per-file contract on long modules | Reliable with a heading | Needs the contract restated on the final line |
The practical upshot: whichever model you pick, the non-translatable rule earns its place in the prompt. Don't assume the model will volunteer that it couldn't port something. It usually won't, because the training reward favors a confident answer over an honest "this needs a human." Pin the model version once a port reads correctly, and re-read the flag list after any model update. A porter that quietly got more confident is a porter that quietly got more wrong.
Variables you'll set
| Variable | Required | What it is |
|---|---|---|
{{source_language}} | Yes | Language porting from |
{{target_language}} | Yes | Language porting to |
{{source_module}} | Yes | The module and its context |
{{idiom_rules}} | Optional | Target conventions to honor |
Getting started
- Copy the structure into ChatGPT, Claude, or Gemini.
- Set
{{source_language}}and{{target_language}}with versions. - Paste the full module into
{{source_module}}, not a lone function. - Run it and read the non-translatable list before the ported code.
- Make a decision on each flagged construct.
- Accept the port file by file, reviewing each against its contract.
For a port that sweeps call sites and generates compatibility shims automatically, the Cross-Language Refactor Harness runs the full loop.
Browse the refactoring prompt packs →The Cross-Language Refactor Harness does this end-to-end: a {{source_language}} and {{target_language}} pair drives a call-site-sweep prompt so callers update with the port, a compatibility-guard step generates shims where callers can't change yet, and a verification-loop confirms the branch builds and tests before merge. It's part of The Complete AI Prompts Bundle, a one-time lifetime license to the whole catalog plus future packs, worth it if a port is one of several refactoring jobs you run.
A port often pairs with mechanical edits a codemod handles better. The Codemod Authoring Harness covers the within-language transforms a cross-language port leaves behind. Before a large port, the monorepo impact analysis prompt maps which packages the change reaches, and the framework migration prompt handles staged upgrades within one language. For build-versus-buy, read how to choose a reusable AI prompt pack.
See the codemod authoring pack →Common questions
What does a cross-language refactor prompt do that a translator doesn't?
Why does line-by-line code translation produce bad code?
How do you handle constructs that can't be translated?
Get the prompt packs this guide is built on
Ready-to-paste prompts with documented variables and worked examples for ChatGPT, Claude, and Gemini. One-time payment, own it forever.
More prompt guides

AI Prompt Packs vs Custom GPTs: What to Use for Repeated Work
The honest version of prompt pack vs custom GPT is a portability question, not a quality one. A Custom GPT is a configured ChatGPT that lives in OpenAI's platform and runs only there. A prompt pack is…

Best AI Prompt Packs for Coding Agents, Ranked by Job
Most coding-agent failures aren't model failures. They're missing-scaffolding failures: the agent commits a secret, edits a file it shouldn't, or sails through a review nobody actually ran. The fix us…

Codemod Authoring Prompt: Turn a Before/After Into an AST Transform
You can describe the refactor in one sentence: "rename this call, move the second argument into an options object." Doing it across 800 files by hand is a week of tedium and three subtle mistakes. A c…