If you’ve been running your NopCommerce store for years, chances are you’ve made many custom tweaks to your locale string resources. Because of that, importing a new language pack can feel risky — one click and you might overwrite dozens or even hundreds of translations you carefully adjusted over time.
The official recommendation from NopCommerce is to export your current locale resources, compare them manually with the new language pack using tools like WinMerge, and then copy the differences one by one.
This approach works, but it’s slow and error-prone, especially if your store has thousands of entries.
To make this process easier and safer, I created a simple PowerShell script that compares two XML files and tells you exactly what changed — without the need for manual diff tools.
What the Script Does
The script compares two XML files:
-
old.xml — your current locale string resources
-
new.xml — the newest language pack for your NopCommerce version
It matches entries by their Name attribute and generates three clear output files:
added.xml
Contains resources that exist in the new language pack but are missing from your current one.
removed.xml
Contains resources that exist in your current installation but are no longer present in the new language pack.
changed.xml
Contains resources that exist in both files but have different values (your custom translation vs. the updated one).
This gives you a clean overview of everything that changed — without modifying anything in your store.
Want an Even Easier Solution? Try EasyTranslate
If you’re open to spending a small budget to simplify this task further, take a look at my EasyTranslate plugin.
With EasyTranslate, you can:
-
See missing and untranslated locale resources directly in the NopCommerce admin panel
-
Translate them instantly using the Google Translation API
-
Export them as XML if you prefer manual editing
-
Detect untranslated content across your entire store
(catalog, blog posts, news, topics — anything translatable) -
Translate all this content with Google in just a few clicks
For stores with many languages, EasyTranslate saves hours of manual work.
How to Use the PowerShell Script (Windows)
Follow these steps to safely compare your current translations with the newest language pack.
1. Install PowerShell
Most Windows installations already have it. If not, download it from Microsoft.
2. Download the Script
Download nop-lang-compare.ps1 and place it in your working folder.

3. Open PowerShell in Your Working Folder
You have two options:
Option A: Using the cd command
Option B: Using File Explorer (easier)
Open your folder → click in the address bar → type powershell → press Enter.
PowerShell will open directly in that folder.
4. Export Your Current Locale Resources
In NopCommerce Admin:
Configuration → Languages → select a language → Export Resources
Move the downloaded XML file into your working folder and rename it to:
5. Download the Newest Language Pack
Go to the official translations page on the NopCommerce website and download the newest pack for your version.
Place the file in your working folder and rename it to:
6. Confirm All Files Are Present
In PowerShell, run:
You should see:
-
nop-lang-compare.ps1
-
old.xml
-
new.xml

7. Run the Script
Execute:

The script will create:
-
added.xml
-
removed.xml
-
changed.xml
in the same folder.
What to Do With the Results
✔ Import added.xml
Safe to import — it only adds missing items.
✔ Review changed.xml
Decide which values you want to keep:
-
If the entry contains your custom translation → delete that entry from changed.xml
-
If you want the new translation → leave it as is
Save the file and import it. Only the entries that remain will be updated.
✔ Normally ignore removed.xml
It’s only for reference.
You usually don’t need to import removed entries back into your store.
nop-lang-compare.ps1
# Determine output directory (directory where this script is located)
$OutDir = $PSScriptRoot
# Load XML files
[xml]$old = Get-Content "old.xml"
[xml]$new = Get-Content "new.xml"
# Build hashtable: Name -> Trimmed Value
$oldMap = @{}
$newMap = @{}
foreach ($n in $old.Language.LocaleResource) {
$oldMap[$n.Name] = $n.Value.Trim()
}
foreach ($n in $new.Language.LocaleResource) {
$newMap[$n.Name] = $n.Value.Trim()
}
# Helper function to create an XML document with resources
function New-LangXml {
param ($resources)
$xml = New-Object System.Xml.XmlDocument
$decl = $xml.CreateXmlDeclaration("1.0", "utf-8", $null)
$xml.AppendChild($decl) | Out-Null
$root = $xml.CreateElement("Language")
$root.SetAttribute("Name", "Diff")
$root.SetAttribute("SupportedVersion", "1.0")
$xml.AppendChild($root) | Out-Null
foreach ($r in $resources) {
$node = $xml.CreateElement("LocaleResource")
$node.SetAttribute("Name", $r.Name)
$valueNode = $xml.CreateElement("Value")
$valueNode.InnerText = $r.Value
$node.AppendChild($valueNode) | Out-Null
$root.AppendChild($node) | Out-Null
}
return $xml
}
# --- Determine ADDED ---
$added = @()
foreach ($key in $newMap.Keys) {
if (-not $oldMap.ContainsKey($key)) {
$added += [pscustomobject]@{
Name = $key
Value = $newMap[$key]
}
}
}
# --- Determine REMOVED ---
$removed = @()
foreach ($key in $oldMap.Keys) {
if (-not $newMap.ContainsKey($key)) {
$removed += [pscustomobject]@{
Name = $key
Value = $oldMap[$key]
}
}
}
# --- Determine CHANGED ---
$changed = @()
foreach ($key in $oldMap.Keys) {
if ($newMap.ContainsKey($key) -and $oldMap[$key] -ne $newMap[$key]) {
$changed += [pscustomobject]@{
Name = $key
Value = $newMap[$key] # store NEW trimmed value
}
}
}
# Save XML diff files to the script’s folder
(New-LangXml $added).Save( (Join-Path $OutDir "added.xml") )
(New-LangXml $removed).Save( (Join-Path $OutDir "removed.xml") )
(New-LangXml $changed).Save( (Join-Path $OutDir "changed.xml") )
Write-Host "Created added.xml, removed.xml, changed.xml in $OutDir" -ForegroundColor Green
