Moving and renaming resource keys in a .resx file

I work on websites where we have several resource files that are localized in many languages. This makes operations like renaming a resource key and moving a resource key to a different file annoying since you must do it across several languages. To help with this I created a couple of PowerShell scripts to automate this process.

These PowerShell scripts assume your .resx files live in a folder named “Resources” but this can be easily changed.

RenameResource.ps1

param([String]$keyOld, [String]$keyNew)
if(-not $keyOld -or -not $keyOld) {
  echo "RenameResource.ps1 keyOld keyNew"
  return
}

$files=get-childitem Resources *.resx

foreach($file in $files) {
  $xml = [xml](Get-Content $file.FullName)
  $dataNode = $xml.root.data | Where-Object { $_.GetAttribute("name") -eq $keyOld }
  if ($dataNode -ne $null) {
    $dataNode.SetAttribute("name", $keyNew)
    $xml.Save($file.FullName)
  }
}

 

MoveResource.ps1

param([String]$resourceNameSource, [String]$resourceNameDestination, [string] $keyName)
if(-not $resourceNameSource -or -not $resourceNameDestination -or -not $keyName) {
  echo "MoveResource.ps1 resourceNameSource resourceNameDestination keyName"
  return
}

$sourceFiles = Get-ChildItem "Resources\$resourceNameSource*.resx"
$destFiles = Get-ChildItem "Resources\$resourceNameDestination*.resx"
$mapping = @{}

$sourceFiles | foreach {
  $parts = $_ -split "\."
  $list = New-Object "system.collections.arraylist"
  $list.Add($_) > $null
  if($parts.Length -eq 2) {
    $mapping["en-us"] = $list
  }
  else {
    $mapping[$parts[1]] = $list
  }
}

$destFiles | foreach {
  $parts = $_ -split "\."
  if($parts.Length -eq 2) {
    $mapping["en-us"].Add($_ ) > $null
  }
  else {
    $mapping[$parts[1]].Add($_ ) > $null
  }
}

foreach($pair in $mapping.Values) {
  $sourcePath = $pair[0]
  $destPath = $pair[1]
  $source = [xml](Get-Content $sourcePath)
  $dest = [xml](Get-Content $destPath)

  $keyNodeSource = $source.root.data | Where-Object { $_.GetAttribute("name") -eq $keyName }
  $keyNodeDest = $dest.root.data | Where-Object { $_.GetAttribute("name") -eq $keyName }
  if ($keyNodeSource -eq $null) {
      echo "Key does not exist in source"
      return;
  }
  if($keyNodeDest -ne $null) {
    echo "Key already exists in destination"
    return;
  }
  try
  {
    $newNode = $dest.ImportNode($keyNodeSource.Clone(), $true)
    $source.root.RemoveChild($keyNodeSource) > $null
    $dest.root.AppendChild($newNode) > $null
    $dest.Save($destPath)
    $source.Save($sourcePath)
  }
  catch {
    Write-Host "Error text: " $_
    return
  }
}

 

Usage

Renaming a resource key:

.\RenameResource.ps1 oldKey newKey

 

Moving a resource with key “keyName”  from a file named “ResourceFile1.resx” to “ResourceFile2.resx”:

.\MoveResource.ps1 ResourceFile1 ResourceFile2 keyName