🇧🇬 Български | 🇬🇧 English
A Visual Studio Code extension that shows your .resx localization resources (the same files Visual Studio uses for .NET projects) as one convenient table: key + one column per language, instead of opening and comparing several XML files by hand.
- What the extension does
- Installation
- Getting started
- Sidebar — file list
- Translation table
- Exporting and importing
- How files are grouped
- For translators (no coding experience needed)
- For C# / Visual Studio developers
- Developing the extension itself
- Roadmap
- License
- Visualizes every
.resxfile in a "family" (e.g.Strings.resx,Strings.bg.resx,Strings.de.resx) as one table: a row per key, a column per language. - In-place editing — you edit values directly in the table, and the extension writes them back into the correct
.resxfiles, preserving existing comments and formatting (it never rewrites the whole file). - Adding a new translation (new key) through a permanent "New key" row pinned to the top of the table.
- Deleting a key from every language at once, with a confirmation prompt first.
- Highlights missing/untranslated values in red, so you immediately see which translations are still missing.
- Per-column filtering (by key or by translated value); filters on different columns combine — you only see rows that match all of them at once.
- Export the table to CSV or JSON, and import translations back from a CSV/JSON file — validated before anything is written, with a review log if existing values got overwritten.
- Sidebar view in the Activity Bar with a tree of every
.resxfile in the project, grouped by folder and by "family" — check a box to open that file in a table. - Add a new language to an existing file family directly from the sidebar — pick from a list of common languages, or type any custom locale code (e.g.
pt-BR); the new file is created automatically with every key from the base file, ready to be translated. - Create a brand-new "master"
.resxfile at any time — the button is always available at the top of the sidebar, whether the project has no.resxfiles yet or already has plenty. - Auto-detects the base language (e.g. "en") from
.csproj/.vbproj(<NeutralLanguage>) orAssemblyInfo(NeutralResourcesLanguage) — the same settings your .NET project already uses. - Auto-refreshes — if a file is changed, added, or deleted on disk (e.g. via
git pullor another editor), the table and sidebar update themselves. - Each
.resx"family" opens in its own tab, so different tables never mix together.
Search for "ResXLocalizer" in the Extensions view (Ctrl+Shift+X) inside VS Code, or install it directly from its Marketplace page.
Useful if someone gave you a specific build directly (e.g. a pre-release), instead of installing through the Marketplace.
- Download the
resxlocalizer-X.X.X.vsixfile (X.X.X is the version number). - Open Visual Studio Code.
- In the icon bar on the left (Activity Bar), open Extensions (the icon looks like 4 little squares ▦), or press
Ctrl+Shift+X. - At the top-right of the Extensions panel, click the three-dot button
.... - Choose "Install from VSIX...".
- Point it at the downloaded
.vsixfile and confirm. - Once installation finishes, VS Code will offer to Reload (or "Restart Extensions") — click it.
Or, from the terminal:
code --install-extension resxlocalizer-0.0.1.vsixTip: whenever you install a newer version of the extension over an older one, always run Reload Window (
Ctrl+Shift+P→ "Developer: Reload Window") afterwards — otherwise VS Code may keep showing the old version in panels that are already open.
-
Open the project's workspace folder: File → Open Folder... and pick the project's root folder (the one that contains the
.csprojfile). -
A new icon — ResXLocalizer — appears in the Activity Bar on the left. Click it to open the sidebar panel.
-
The extension automatically scans the whole folder for
.resxfiles:-
If there are
.resxfiles already — you'll see a tree of folders and files (see the next section). -
If there are none yet — you'll just see a short message, plus the same "Create master .resx file" button described below:
Clicking it walks you through two simple steps: pick a folder, then type a name (e.g.
Strings) — the extension creates an empty, valid.resxfile (the same structure Visual Studio generates), ready for your first keys.
-
-
Check the box next to the files you want to see in a table (see below), or right-click a
.resxfile in the regular VS Code Explorer → "ResXLocalizer: Open Resx Table".
The "Create master .resx file" button at the top is always there, whether or not the project already has .resx files — use it any time you need to start a brand-new family (e.g. a Strings.resx for a new feature area), without it getting in the way of the tree below it.
Files are organized as a tree:
- Folder (📁) — matching the real folder structure of the project.
- Family (e.g.
LOGINPAGE) — every.resxfile with the same base name in that folder: the base (default) file plus its per-language variants. - Each file has a colored language badge:
- blue badge = the base ("master") file — the one with no language code in its name (
LoginPage.resx). If the project declares<NeutralLanguage>in its.csproj, the badge shows that exact language (e.g.en) instead of the generic "src". - grey badge = a specific translation (
bg,de,fr, ...).
- blue badge = the base ("master") file — the one with no language code in its name (
Checking a box opens the table with the selected files (or adds them to an already-open table for that family). If you only check a translation (e.g. bg), the base file gets checked automatically too — the table always shows at least the default column, for context.
"Add new" under each family adds a new language to it:
- Click "+ Add new".
- A list of common languages appears (English, Bulgarian, German, French...) — pick one with the mouse/arrow keys, or type your own code (e.g.
pt-BR,zh-Hant) if it isn't in the list. - The extension creates a new
.resxfile (e.g.LoginPage.pt-BR.resx) with every key from the base file, but with empty values — ready to be translated. - If the other files in the family already use a region-qualified format (e.g.
de-DEinstead of justde), the new file automatically follows the same format, for consistency.
The ⟳ (Refresh) button at the top of the panel reloads the list manually (you usually won't need it — the extension already watches the files automatically).
Each .resx family opens in its own tab as a table:
| Column | Content |
|---|---|
| Actions | Buttons to edit/delete that row |
| Key | The key's name (shared across all languages) |
| Default / language | One column per .resx file in the family |
- Click the ✏️ blue pencil at the start of the row → the row's cells become editable, and the icon turns into a 💾 green save icon.
- Change the text in any cell (directly, like a plain text field).
- Click the green icon again to save. The values are written back into each corresponding
.resxfile — the file's comments and formatting are left untouched; only the value changes.
Click the 🗑️ red trash icon next to the row → a confirmation dialog appears → once confirmed, the key is removed from every language file on that row.
There's always a special "New key" row pinned to the top of the table:
- Click its pencil icon to make it editable.
- Type the key's name into the first cell, and the values for each language.
- Click save. If the key field is empty, it's outlined in red and the save is rejected. If the key you typed already exists in the group, you'll be asked whether to overwrite its value.
A cell with no value (or only whitespace) is highlighted with a red accent on its left edge — you immediately see which language variants are still waiting for a translation.
Under every column header (except Actions) there's a Filter... field — type text and only rows whose value in that column contains it are shown (case-insensitive). Filters on different columns combine — for example, a filter of Login on Key plus error on BG shows only rows matching both conditions at once.
Two buttons sit above every table, at the top right, level with the table's title — a green Import button (↓ icon) and a blue Export button (↑ icon):
- Click Export.
- Choose CSV or JSON from the small picker that pops up.
- Pick where to save the file.
The exported file has one row per key, with a column per language (the base/default file's column is simply called default) — the exact same shape you see in the table. You can open it in Excel, Google Sheets, or hand it to a translation agency that doesn't use VS Code at all.
- Click Import.
- Pick a
.csvor.jsonfile — it doesn't have to come from this extension's own Export; any file with aKeycolumn/field and matching language columns works.
Before anything is written to your .resx files, the file is validated:
- it must parse correctly (valid CSV/JSON), with a
Keycolumn/field present on every row; - if any row is malformed or missing its key, the import is rejected entirely — a dialog lists every problem found, and nothing gets changed on disk.
Once validation passes:
- rows with a key that doesn't exist yet are added as new translations;
- rows with a key that already exists overwrite the existing value for that language — every such overwrite is recorded in a log;
- blank cells are skipped (an empty cell never erases an existing translation);
- columns that don't match any language file open in this table are simply ignored.
If any existing values were overwritten, a new tab opens automatically right after the import finishes, listing every overwritten key with its old and new value side by side — plus any warnings (e.g. a key repeated inside the imported file) — so you can review exactly what changed before trusting the result:
The extension recognizes files using .NET's resource-naming convention:
Strings.resx— the base ("neutral") file → shown as the default column.Strings.bg.resx— the Bulgarian variant.Strings.de-DE.resx— the German (Germany) variant, with a region.
Every file sharing the same base name (Strings) in the same folder forms one "family" and is shown together in one table. The keys shown are the union of the keys from every file in the group — so it's immediately obvious if a key only exists in some of the languages.
If your job is just to translate text, don't worry about the rest of this document — here's all you need:
- Open the project in VS Code (someone on the dev team has already set it up and given you a link/folder).
- Click the ResXLocalizer icon in the left-hand bar.
- Check the box next to your language (e.g.
bg) in the list — a table will open. - Look for rows highlighted in red — those are the missing translations.
- For each row: click the pencil ✏️, fill in the translation in your column, then click the save icon 💾 (it turns green while you're editing).
- Done — the change is saved automatically to the file. Nothing else is needed (no "Save As", no terminal).
You don't need to touch the Key column on existing rows, or delete files — just fill in the values in your own column.
If you're coming from Visual Studio and this extension is the first reason you're opening VS Code, here's a quick "dictionary" between the two environments:
| Visual Studio | VS Code + ResXLocalizer |
|---|---|
| Solution Explorer | Explorer panel (the files icon, top-left) |
Double-click a .resx → built-in Resource Designer |
Right-click a .resx → "ResXLocalizer: Open Resx Table", or check its box in the extension's sidebar |
Adding a new .resx for a new language by hand (copy/paste + rename) |
The "Add new" button in the sidebar — creates the file and fills in every key automatically |
<NeutralLanguage> in .csproj |
Detected automatically and shown as a badge on the base file |
For peace of mind: the extension never touches the project, its references, or the .csproj — it only reads and writes the .resx files themselves, preserving the XML structure that ResXFileCodeGenerator in Visual Studio expects. You can freely move the project between both editors — the files stay fully compatible with Visual Studio even after being edited through ResXLocalizer.
Because changes are minimal diffs in the XML itself (just a changed value, or one added <data> block), git diffs stay clean and easy to review in a pull request.
For anyone building or maintaining ResXLocalizer itself:
npm install— install dependencies.npm run watch— esbuild in watch mode (forF5debugging in an Extension Development Host).npm run check-types— TypeScript check with no emitted output.npm run lint— ESLint.npm run package— production build (invoked byvscode:prepublish).npm run vsix— package the extension into a.vsixfile (@vscode/vsce).npm run publish— publish the current version straight to the Marketplace (vsce publish); requires being logged in viavsce login <publisher>first.
For a map of the source code itself (folder layout, data flow, conventions worth knowing before changing something), see docs/ARCHITECTURE.md — useful for contributors and AI coding agents alike.
- Support for other localization formats (
.json,.po,.arb, ...)
ResXLocalizer is distributed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
In short (full terms are in LICENSE):
- ✅ You're free to use it, modify/extend it, and share it with others — both in its original and in a modified form.
- ✅ The only requirement is giving credit to the original source (author + a link to the license), and that a modified version must be shared under the same license.
- ❌ It (or a modified version of it) may not be sold, rented out/subscribed to, or otherwise used for commercial gain.
Full legal license text: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode Human-readable summary: https://creativecommons.org/licenses/by-nc-sa/4.0/



