Skip navigation
All Places > PI Developers Club > Blog > Author: aduhig

PI Developers Club

1 Post authored by: aduhig

A while ago I was asked by our Japan team, "Hey Alex, do you have a Japanese version of our training Microsoft Azure VMs we can use for customer classes in Japan?"


... well, no, I didn't. So I decided to make some. I installed some Japanese Windows and Office language packs and PI System MUIs on our normal training template, moved it over to Japan and it worked great. Then I thought, "Why just Japanese? Couldn't I just do this for every language?". So I did. The end product means that students taking our training classes will be able to log in to their system in any language supported on the PI System, not just English.


There are a few traps, so thought I'd post about it here and hopefully help someone else that deals with many systems with many languages and locales. In my scenario, I was trying to configure a group of machines in an isolated domain so that they are able to be logged in with different accounts, and show the user a different language UI with each. For example, if a user logs in to the PI Server machine in the training environment with the Student01 account, they get an English PI and Windows UI. If they log in with fr-Student01 they get French, and with ja-Student01 they get Japanese. The steps I took to do this are approximately as follows:


  1. Start with an already configured PI System Client or Server Machine
  2. Install Windows and Microsoft Office language packs for each supported language
  3. Run the appropriate PI System MUI (Multilingual User Interface) products that correspond to the installed PI System software
  4. Configure new AD OUs for each language, and put new language specific accounts in each. Set up GPOs for each OU locking the user interface to the appropriate language.
  5. Establish startup scripts for all users, or on specific machines. This is the interesting bit, and something that my audience here may be interested in. There were a few difficulties I found when doing this. Specifically:
    1. The PI System MUI products don't seem to look at the user's language context to determine the language to display. They look at the machine language context. The user can change their language manually though, using the PI Language Settings Tool. I want to automate this.
    2. Older PI System UIs (Like the old Tag Search) do not use Unicode text. For these to be displayed properly in languages that use non-Latin characters, you need to change the whole system locale and reboot.


The commenting in my PowerShell script below should be of help for anyone else doing something like this. The below script runs for each user when they log in to a training account on each machine:


#Script written by Alex Duhig
#This is a startup script written to ease management of localized training VMs. Our training VMs can be logged in to with a range of accounts,
#each corresponding with a different language and region. The script detects the language of the user account according to a naming prefix,
#(i.e. de-Student01 = German) then configures time zones, the PI Language Setting tool and the Windows System Locale. Actual languages displayed
#on each account are not configured in this script, this is intended to be handled by Group Policy. 
#This script requires at least Windows 2012R2 or Windows 8.

#The below code gets administrator mode if it doesn't already have it and restarts the script.
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {   
  $arguments = "& '" + $myinvocation.mycommand.definition + "'"
  Start-Process powershell -Verb runAs -ArgumentList $arguments

#Find the current username, and the two letter language prefix if one exists.
$CurrentUser = [Environment]::UserName
$UserPrefix = $CurrentUser.substring(0,2)

#Extract user language from username (or assume english if no defined prefix)
IF (($UserPrefix -eq "de") -or ($UserPrefix -eq "es") -or ($UserPrefix -eq "fr") -or ($UserPrefix -eq "ja") -or `
   ($UserPrefix -eq "ko") -or ($UserPrefix -eq "pt") -or ($UserPrefix -eq "ru") -or ($UserPrefix -eq "zh")) {
    $UserLanguage = $UserPrefix
    $UserLanguage = "en"
Write-Host "User name is " $CurrentUser
Write-Host "User Language is " $UserLanguage

#The language prefixes need to be matched to a user locale. Our training classes are most commonly taught in these locales, so we'll 
#use them:
SWITCH ($UserLanguage) {
    "de"{$UserLocale = "de-DE"}
    "en"{$UserLocale = "en-US"}
    "es"{$UserLocale = "es-MX"}
    "fr"{$UserLocale = "fr-CA"}
    "ja"{$UserLocale = "ja-JP"}
    "ko"{$UserLocale = "ko-KR"}
    "pt"{$UserLocale = "pt-BR"}
    "ru"{$UserLocale = "ru-RU"}
    "zh"{$UserLocale = "zh-CN"}
Write-Host "User Locale is " $UserLocale

#Change the user locale so it matches their prefix
Set-Culture $UserLocale
Set-WinUserLanguageList -LanguageList (New-WinUserLanguageList $UserLocale) -Force

#Our training classes occur all over the world. A lot of languages are shared by multiple countries, and we'll leave them in UTC.
#However, it makes sense to change a few languages to a specific time zone. The following code changes the Time Zone Based on the 
#user language.
$PrevTimeZone = invoke-command {tzutil /g}
Write-Host "Current TimeZone: " $PrevTimeZone
SWITCH ($UserLanguage) {
    "de"{Invoke-Command {tzutil /s "W. Europe Standard Time"}}
    "en"{Invoke-Command {tzutil /s "UTC"}}
    "es"{Invoke-Command {tzutil /s "UTC"}}
    "fr"{Invoke-Command {tzutil /s "UTC"}}
    "ja"{Invoke-Command {tzutil /s "Tokyo Standard Time"}}
    "ko"{Invoke-Command {tzutil /s "Korea Standard Time"}}
    "pt"{Invoke-Command {tzutil /s "E. South America Standard Time"}}
    "ru"{Invoke-Command {tzutil /s "Russian Standard Time"}}
    "zh"{Invoke-Command {tzutil /s "China Standard Time"}}
$NewTimeZone = invoke-command {tzutil /g}
Write-Host "New Timezone: " $NewTimeZone

#The PI System MUIs sometimes don't detect the language of the user. Causes of this are usually linked to the OS being in a different language 
#than the current user. The below code works around this, and configures the registry manually for the user that has logged in.
#The below switch statement maps language prefixes to the numbers the PI System MUI uses in the registry.
SWITCH ($UserLanguage) {
    "de"{$UserSelectedDisplayLanguage = 7}
    "en"{$UserSelectedDisplayLanguage = 9}
    "es"{$UserSelectedDisplayLanguage = 10}
    "fr"{$UserSelectedDisplayLanguage = 12}
    "ja"{$UserSelectedDisplayLanguage = 17}
    "ko"{$UserSelectedDisplayLanguage = 18}
    "pt"{$UserSelectedDisplayLanguage = 22}
    "ru"{$UserSelectedDisplayLanguage = 25}
    "zh"{$UserSelectedDisplayLanguage = 4}
#When the PI Language Settings Tool is used to change language settings for a user, it uses a couple of registry keys. The below code changes
#these keys without input from a user. The "Set-ItemProperty" cmdlets are there in case the settings already exist.
New-Item -Path HKCU:\Software\PISystem\Common -Force | Out-Null
New-ItemProperty -Path HKCU:\Software\PISystem\Common -Name "IsPerUserLanguage" -Value 1 -PropertyType DWORD -Force | Out-Null
New-ItemProperty -Path HKCU:\Software\PISystem\Common -Name "UserSelectedDisplayLanguage" -Value $UserSelectedDisplayLanguage -PropertyType DWORD -Force | Out-Null
Set-ItemProperty -Path HKCU:\Software\PISystem\Common -Name "IsPerUserLanguage" -Value 1 -Force | Out-Null
Set-ItemProperty -Path HKCU:\Software\PISystem\Common -Name "UserSelectedDisplayLanguage" -Value $UserSelectedDisplayLanguage -Force | Out-Null

#Some older PI System products (Like the PI Tag Search GUI in PI ProcessBook) do not support Unicode languages, and rely on the locale of the 
#windows system to display characters properly. This is only a problem with non-Latin-character languages such as Japanese, Korean, Russian 
#and Chinese. The below code changes the system locale, but only bothers rebooting the machine if this login or the last login had a 
#non-Latin-character language. If everything is Latin, no reboot (or locale change at all really) should be needed.
$PreviousLocale = Get-WinSystemLocale
Write-Host "Previous Locale was " $PreviousLocale
Write-Host "Current User's Locale is " $UserLocale
IF ($PreviousLocale -ne $UserLocale) {
  Set-WinSystemLocale $UserLocale
        IF (($UserLocale -eq "ja-JP") -or ($UserLocale -eq "ko-KR") -or ($UserLocale -eq "ru-RU") -or ($UserLocale -eq "zh-CN") -or`
            ($PreviousLocale -eq "ja-JP") -or ($PreviousLocale -eq "ko-KR") -or ($PreviousLocale -eq "ru-RU") -or ($PreviousLocale -eq "zh-CN")) {
            Write-Host "Computer Locale has been changed, rebooting in 20 seconds"
            Sleep 20


Hopefully this is useful to someone, somewhere, sometime. Enjoy!



Filter Blog

By date: By tag: