The Multilingual User Interface (MUI) in SharePoint 2010 makes it possible to set language dependent titles and descriptions for your fields, lists, content types and web sites. The list of all affected types and properties as well as a short introduction of MUI can be read on MSDN.
As you can read there, the localization of these objects is done through the SPUserResource class and its Value property, that gets / sets the localized value based on the CurrentUICulture property of the Thread.CurrentThread object. It means that instead of calling a method with a CultureInfo parameter to get / set for example a field title, you should first set the CurrentUICulture to the CultureInfo you would like to work with:
Thread.CurrentThread.CurrentUICulture = yourCulture;
Then get / set the Title property of your SPField object as you did in WSS 3.0:
field.Title = title;
The above procedure shows it is pretty straightforward in C#, but recently I had to do something similar using PowerShell. I found it to be not trivial, and would like to share the lessons I’ve learnt.
My first approach was based on this post to simply set the CurrentUICulture as I did using C#, but it does not work for me. After setting the CurrentUICulture to German (de-DE) I tried to get its value in the next command, but it was still (or again?) English (en-US), so when I set the Title, it was set for English, not for German.
The solution for this issue can be to run the second command in the same line like this:
[Threading.Thread]::CurrentThread.CurrentCulture = $culture;[Threading.Thread]::CurrentThread.CurrentCulture
But the above format is not so nice and hard to use and read if you need to work with a lot of fields / languages.
I found the following Using-Culture function for PowerShell on Stack Overflow:
function Using-Culture (
[System.Globalization.CultureInfo] $culture = (throw "USAGE: Using-Culture -Culture culture -Script {…}"),
[ScriptBlock]
$script = (throw "USAGE: Using-Culture -Culture culture -Script {…}"))
{
$OldCulture = [Threading.Thread]::CurrentThread.CurrentCulture
$OldUICulture = [Threading.Thread]::CurrentThread.CurrentUICulture
try {
[Threading.Thread]::CurrentThread.CurrentCulture = $culture
[Threading.Thread]::CurrentThread.CurrentUICulture = $culture
Invoke-Command $script
}
finally {
[Threading.Thread]::CurrentThread.CurrentCulture = $OldCulture
[Threading.Thread]::CurrentThread.CurrentUICulture = $OldUICulture
}
}
Using this function, it was easy to query the field titles (in this case for all fields with English Title begins with “title”):
$web = Get-SPWeb http://SP2010
$fields = $web.Fields
$fields | Where-Object { $_.Title -like "title*" } | ForEach-Object { Using-Culture de-DE { $_.TitleResource.Value } }
Or a more compact version of the last line:
$fields | ? { $_.Title -like "title*" } | % { Using-Culture de-DE { $_.TitleResource.Value } }
My first approach to set the value for multiple fields was the next one:
$fields | ? { $_.Title -like "title*" } | % { Using-Culture de-DE { $_.TitleResource.Value = "Titel"; $_.Update("True") } }
But it resulted the following error:
An error occurred while enumerating through a collection: Collection was modified; enumeration operation may not execute..
To create a solution for this task I assembled first a new array of fields using the IDs of matching fields, then iterated through this array, set the field title and updated the field:
$fields | ? { $_.Title -like "title*" } | % { $web.Fields[$_.Id] } | % { Using-Culture de-DE { $_.TitleResource.Value = "Titel"; $_.Update("True") } }
Thanks for the post. Your code works great for me on fields that don’t already have a resource string defined in their CAML XML declaration in a feature. On the other hand, when the field is defined in a feature CAML XML your code doesn’t work. For one reason I can’t modify the feature so I’m trying to override this resource string using your technique to set the TitleResource. It appears to work when I inspect the value right after setting it and updating the field and web. But once I release the SPField instance and get it again the TitleResource is back to its original value. Any thoughts on what might be the cause of this?
Comment by JohnC — June 6, 2012 @ 12:16
You could use TitleResource.GetValueForUICulture() method for this:
$_.TitleResource.GetValueForUICulture($web.UICulture)
Comment by Anders Rask — July 25, 2012 @ 11:44
Thanks for clear description, it was very useful for me.
Comment by Ivan Krupsky — March 6, 2015 @ 20:09