The currency symbol and currency format for this language code is displaying incorrectly when called through C# on a server.
ms-MY (Malay - Malaysian)
The language display on the control panel on the server has the currency symbol set to RM. While debugging the C# code, it has the currency code set to R.
I wrote up a mini console program locally to display the currency symbol for ms-MY and it shows up as RM.
If I change the formatting on the server. The code doesn't pick up the changes. Anyone knows if there are weird server caches or another place that language settings are stored?
I've checked the language registry key between the server and my local machine and they are the same. I tried recycling the application pool and it still doesn't work.
Pseudo Code on the server
foreach (CultureInfo c in CultureInfo.GetCultures(CultureTypes.InstalledWin32Cultures))
{
if (c.ThreeLetterISOLanguageName != "IVL")
{
r = new RegionInfo(c.LCID);
if (r.ISOCurrencySymbol == isoCurrencyCode)
{
ci = c;
FoundCode = true;
break;
}
}
}
Mini Console Code for testing locally.
decimal amount = 179835.00M ;
Console.WriteLine(amount.ToString("C", CultureInfo.CreateSpecificCulture("ms-my")));
Note when I add this to the watcher on the server code: CultureInfo.CreateSpecificCulture("ms-my"). The currency format display as R. But if I look at the watcher on my local console code nothing related to the server, it's set to RM
Related
I wrote some software that uses the output of system (powershell) commands, but did not foresee that the output would be different for languages other than English.
Is there a way to temporarily change the language in Powershell to English for just that one, single powershell session?
Notes
In case it is of significance, the particular powershell code I wish to run is netstat -n -a
I have come across some ways to change powershell language (e.g. here, here). But I want to be careful not to change it permanently! (that would be bad)
(a) For external programs such as netstat.exe, there is unfortunately no way (that I know of) to change the UI language in-session:
On Windows Server 2012 / Windows 8 and above, the Set-WinUILanguageOverride cmdlet allows you to (persistently) change the system-wide UI language for the current user, but that only takes effect in future logon sessions - that is, logging off and back on or a reboot are required.
As an aside: On Windows Server 2012 / Windows 8 and above, there is also the Set-Culture cmdlet, but its purpose is not to change the UI culture (display language), but only culture-specific settings such as date, number, and currency formats. It too changes the setting persistently for the current user, but only requires a new session (process) for the change to take effect.
(b) For PowerShell commands and .NET types, there is an in-session (non-persistent) solution - assuming the commands are culture-aware and come with localized strings:
Set [cultureinfo]::CurrentUICulture (temporarily) to the desired culture name (use [cultureinfo]::GetCultures('SpecificCultures') to see all predefined ones) ; e.g., [cultureinfo]::CurrentUICulture = 'en-US'
Complementarily, you may want to set [cultureinfo]::CurrentCulture (note the missing UI part) as well, which determines the culture-specific number, date, ... formatting.
In older versions of PowerShell / .NET, you'll have to set these properties on [System.Threading.Thread]::CurrentThread instead; e.g.,
[System.Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US'
See the bottom section for helper function Use-Culture that wraps this functionality for execution of code with a different culture temporarily in effect; here's an example call
with the culture-sensitive Get-LocalGroupMember cmdlet:
# Try with values other than "en-US", e.g. "fr-FR" to see localized
# values in the "ObjectClass" output column.
Use-Culture en-US { Get-LocalGroupMember Administrators }
An ad hoc example, if you don't want to define a helper function (only the UI culture is changed here):
& {
$prev=[cultureinfo]::CurrentUICulture
[cultureinfo]::CurrentUICulture='en-US'
Get-LocalGroupMember Administrators
[cultureinfo]::CurrentUICulture=$prev
}
Caveats:
PowerShell [Core] itself is not localized yet, as of v7.2.x; progress is being tracked in GitHub issue #666; however, the solution below does work with third-party modules that ship with localized messages and help content, as well as select Windows-specific modules that talk to platform APIs, such as the Microsoft.PowerShell.LocalAccounts module, whose Get-LocalGroupMember cmdlet was used in the example above.
Due to a bug in Windows PowerShell (PowerShell [Core] v6+ is not affected), in-session changes to [cultureinfo]::CurrentUICulture and [cultureinfo]::CurrentCulture are automatically reset at the command prompt, whenever a command finishes executing; however, for a given script the changes remain in effect for the entire script and its callees - see this answer.
Taking a step back:
I wrote some software that uses the output of system (powershell) commands, but did not foresee that the output would be different for languages other than English.
This is precisely why it's generally worth looking for PowerShell-native solutions as opposed to calling external programs:
Instead of having to parse - possibly localized - text, as with netstat.exe, for instance, PowerShell commands return objects whose properties you can robustly access in a culture-independent fashion.
Specifically, Mathias R. Jessen suggests looking at Get-NetTCPConnection as a PowerShell alternative to netstat.exe (available on Windows Server 2012 / Windows 8 and above).
Function Use-Culture's source code:
Note: The code was gratefully adapted from this venerable blog post; it is designed
# Runs a script block in the context of the specified culture, without changing
# the session's culture persistently.
# Handy for quickly testing the behavior of a command in the context of a different culture.
# Example:
# Use-Culture fr-FR { Get-Date }
function Use-Culture
{
param(
[Parameter(Mandatory)] [cultureinfo] $Culture,
[Parameter(Mandatory)] [scriptblock] $ScriptBlock
)
# Note: In Windows 10, a culture-info object can be created from *any* string.
# However, an identifier that does't refer to a *predefined* culture is
# reflected in .LCID containing 4096 (0x1000)
if ($Culture.LCID -eq 4096) { Throw "Unrecognized culture: $($Culture.DisplayName)" }
# Save the current culture / UI culture values.
$PrevCultures = [Threading.Thread]::CurrentThread.CurrentCulture, [Threading.Thread]::CurrentThread.CurrentUICulture
try {
# (Temporarily) set the culture and UI culture for the current thread.
[Threading.Thread]::CurrentThread.CurrentCulture = [Threading.Thread]::CurrentThread.CurrentUICulture = $Culture
# Now invoke the given code.
& $ScriptBlock
}
finally {
# Restore the previous culture / UI culture values.
[Threading.Thread]::CurrentThread.CurrentCulture = $PrevCultures[0]
[Threading.Thread]::CurrentThread.CurrentUICulture = $PrevCultures[1]
}
}
Original author of this code is #Scepticalist.
Run this from powershell console. It will change the culture to en-US for current session.
function Set-CultureWin([System.Globalization.CultureInfo] $culture) { [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture ; [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture } ; Set-CultureWin en-US ; [system.threading.thread]::currentthread.currentculture
Then you have to use the command Get-NetTCPConnection Instead of netstat. For its usage see https://learn.microsoft.com/en-us/powershell/module/nettcpip/get-nettcpconnection?view=win10-ps
What's going on:
I maintain a few small .NET applications for a local business. We've got one pair of apps that work in tandem: a "client manager" (C# / .NET 4.? / winforms) and a "label printer" (VB / .NET 2.0 / winforms).
I recently added a "Print Labels" button to the client manager. This opens the label printer & pre-populates the client's name from the client manager. Woohoo!
Unfortunately, only when the label printer is opened this way, dates print out in "dd/MM/yyyy" format, instead of "MM/dd/yyyy".
What I know:
Date is entered via a DateTime winforms input in the label printer that defaults to "Today".
We see the formatting bug whether the default date is left or is manually changed.
We don't send the date over from the client manager.
We use ".ToShortDateString" in the label printer app.
This never happened when opening the label printer by double-clicking the shortcut/EXE.
This only happens on our Windows 7 Panasonic Toughbook.
The date is wrong whether I print to our Dymo label printer or to PDF. (Thanks, #jdweng!)
Per the Task Manager, the label printer runs as the only local user no matter how I load it. (Thanks, #Polyfun!)
The label printer's CurrentCulture and CurrentUICulture are both en-US, no matter how I load it. (Thanks, #Jimi!)
The user profile uses M/d/yyyy via "Control Panel > Region". (Thanks, #Hans Passant!)
Relevant Code
Here's the C# code I'm using in the client manager to open the label printer app (comments added for clarity):
private void btnLabels_Click(object sender, EventArgs e)
{
// Set via a hybrid string/file input in the app's "Options" menu.
string labelAppLocation = Properties.Settings.Default.LabelAppLocation;
if (String.IsNullOrEmpty(labelAppLocation))
{
MessageBox.Show("We're not sure where your label printer app is located! Set this in \"Options >> Manage Lists >> Files\" and try again.");
}
else
{
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = labelAppLocation;
// This class has some formatting helpers for the
// client's name and other demographics we'd like to send later.
LabelArgs newLabelArgs = new LabelArgs();
newLabelArgs.Name = this.clientName.Text;
psi.Arguments = newLabelArgs.ToString();
p.StartInfo = psi;
p.Start();
}
}
And here's the VB code in the label printer where the date value gets added to the label:
Private Sub DrawItemLabel(ByVal e As System.Drawing.Printing.PrintPageEventArgs)
Dim g As Graphics = e.Graphics
'Custom font handler
Dim fonts As New ItemLabelFonts
'...set fonts, set other line items...
' `myDate` comes directly from a DateTime input's `.Value`.
Dim strMidLine As String = myDate.ToShortDateString & " " & myClientID & " " & myCounty
fonts.MiddleFont = ChooseMaxFontForWidth(strMidLine, fonts.MiddleFont, maxWidth, g)
'...do some math for spacing before drawing the label...
g.DrawString(myClientName, fonts.BottomFont, Brushes.Black, 0, bottomTop)
End Sub
What I think:
Maybe Process#Start() is losing the current culture and falling back to a dd/MM/yyyy default somewhere? (Confirmed not from user's "Region" settings)
Maybe .NET 4.x & .NET 2.0 aren't playing nicely?
Maybe the label printer behaves differently when passed arguments and I need to add a user profile or region through those? There's no logic in the form's Load hook to account for this.
What I've tried:
Checking the DateTime input's settings for a region fallback.
Changing my user's regional settings to see if I can "reset" the formatting.
Duplicating the behavior in Windows 10 & Windows XP (with no luck!)
Turning it off & back on again.
Poring over MSDN.
Why could opening an app via new Process().Start(); change its date formatting?
Success! I retargeted the label printer app from .NET 2.0 to .NET 4.0 (matching the client manager app), cleared out new warnings, and rebuilt the app. Running the v4.0 version of the label printer fixes the issue with no obvious side effects.
I should have done this sooner - I expected going from 2.0 to 4.0 to be a big task, but there were no build errors and the only warnings were implicit conversions. None of these affected Date variables, so I'm still unclear why the 2.0 version acted so strangely, but I'm glad to put this bug to bed. I don't intend to write any new .NET 2.0 projects anytime soon!
I think we're missing something for the Region/Date/Timezone format - somewhere hidden.
I've got a Powershell script to set the date to Australian. Here is the code and XML:
https://github.com/averkinderen/Azure/blob/master/101-ServerBuild/AURegion.xml
#Set Windows regional format (date/time etc.) to Australia - this applies to all users
# Set Locale, language etc.
& $env:SystemRoot\System32\control.exe "intl.cpl,,/f:`"C:\temp\AURegion.xml`""
# Set Timezone
& tzutil /s "AUS Eastern Standard Time"
# Set languages/culture
Set-Culture en-AU
$currentlist = Get-WinUserLanguageList
Write-Host "new lang" $currentlist.LanguageTag
Then I searched for an USA version and I found it here: https://poorerleno.blogspot.com/2018/07/remote-patching-1.html?_sm_au_=i7VM8snvHjkLnPvjBJ3vvK7RJCBJt
#Set Windows regional format (date/time etc.) to American - this applies to all users
if (!(test-path c:\temp)) {
New-Item c:\temp -ItemType Directory
}
[xml]$XmlDocument = invoke-webrequest -Uri https://raw.githubusercontent.com/poorleno1/systemlocale/master/USRegion.xml -UseBasicParsing | Select-Object -ExpandProperty content
$XmlDocument.Save("c:\temp\USRegion.xml")
# Set Locale, language etc.
& $env:SystemRoot\System32\control.exe "intl.cpl,,/f:`"C:\temp\USRegion.xml`""
# Set Timezone
& tzutil /s "Central European Standard Time"
# Set languages/culture
Set-Culture en-US
$currentlist = Get-WinUserLanguageList
Write-Host "new lang" $currentlist.LanguageTag
So I'am trying to add a new language, spesifically norwegian, to SpeechSynthesizer, but it doesn't seem to get installed.
Found this:
Add another voice into .NET Speech
(But here the problem is that Czech isn't supported)
I have installed the norwegian pack from here:
http://www.microsoft.com/en-us/download/details.aspx?id=27224
In my code I use this to check if it is installed:
foreach (var voice in speaker.GetInstalledVoices())
{
Console.WriteLine(voice.VoiceInfo.Description);
}
But it only outputs:
Microsoft Zira Desktop - English (United States)
Have checked the text-to-Speech tool were this is also the only option.
Have also tried to log off/log on and restart the computer.
Anyone know how to fix this?
You may need to add a Speech Language to Windows 10 and set your Locale, Country, Windows display language and Speech language so they are all aligned with one of Cortana's supported locale configurations.
To confirm the settings are set correctly:
Open Settings. Select Time& language, and then Region & Language.
Check the Language (set as default) setting for your Windows display language. If your desired language is not available, add your desired language:
Click Add Language.
Select your desired language from the list.
Select the desired locale, which is the language/country combination.
Click on the newly selected locale and select Options.
Under Download language pack, click Download.
Under Speech, click Download.
After the downloads are complete (this could take several minutes), return to the Time & Language settings.
Click on your new language and select Set as Default.
NOTE: IF you changed languages, you must sign out of your account and back in for the new setting to take effect.
Check the Country or region setting. Make sure the country selected corresponds with the Windows display language set in the Language setting.
Return to Settings and Time & language, and then select Speech. Check the Speech language setting, and make sure it’s aligned with the previous settings.
After you have correctly done the above, your language should appear in the SpeechSynthesizer.AllVoices collection. You should then be able to assign this voice to your SpeechSynthesizer instance's Voice property:
private async void SpeakText(MediaElement audioPlayer, string TTS)
{
SpeechSynthesizer ttssynthesizer = new SpeechSynthesizer();
//Set the Voice/Speaker to Spanish
using (var speaker = new SpeechSynthesizer())
{
speaker.Voice = (SpeechSynthesizer.AllVoices.First(x => x.Gender == VoiceGender.Female && x.Language.Contains("ES")) );
ttssynthesizer.Voice = speaker.Voice;
}
SpeechSynthesisStream ttsStream = await ttssynthesizer.SynthesizeTextToStreamAsync(TTS);
audioPlayer.SetSource(ttsStream, "");
}
http://answers.microsoft.com/en-us/windows/forum/windows_10-other_settings/speech-language-in-windows-10-home/3f04bc02-9953-40b1-951c-c1d262fc3f63?auth=1
I've localized my App in two languages (English and German) with the MulitlingualAppToolkit 4.0. English is the base language, while german is a translation based on the english one.
The translations are stored as resw-file inside folder "strings.en" and "strings.de".
In App.xaml.cs App() I set the culture like this:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = GetCurrentCulture();
CultureInfo.CurrentUICulture = GetCurrentCulture();
private CultureInfo GetCurrentCulture()
{
var cultureName = new DateTimeFormatter("longdate", new[] {"US"}).ResolvedLanguage;
return new CultureInfo(cultureName);
}
(I got this quiet weird way to the regional-culture in Windows 10 from this article https://www.pedrolamas.com/2015/11/02/cultureinfo-changes-in-uwp/ since I recognized that CultureInfo.CurrentCulture and CultureInfo.CurrentUICulture are always "en-EN" no matter what i configurate in my machines regional- and language-settings)
To check if PrimaryLanguageOverride works as expected, I added a TextBox by the name of tbTest on my first Page and a button linkt to this event:
private void Button_Click(object sender, RoutedEventArgs e)
{
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = tbTest.Text;
Frame.Navigate(this.GetType(), 0);
System.IO.File.AppendAllText(System.IO.Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "PrimaryLanguageOverride.txt"),
DateTime.Now + " - Actual PrimaryLanguageOverride:\n " + WIndows.Globalization.ApplicationLanguages.PrimaryLanguageOverride);
}
catch(Exception ex) { Helper.Log.LogUnhandledError(ex); }
}
Now comes the weird stuff:
When Debugging, or executing the App from my Development-Machine, everything works as expected, but when I make an appx-bundle and install it on another (Windows10-Desktop) device, the App does not recognize the its Language.
In my situation, the device is set to german, regional as well as its language. Also when using the test-procedure, it defenetively gets the string I set , as long as it's a valid culture-name, e.g.: "en-EN", "en-US", "de-DE", "de", "en" (all of these are working fine on my development machine) if it's an invalid string, I get an exception, with a log-entry in my unhandled-error-log. It refresh the Page, and even writes the new-set language in my PrimaryLanguageOverride-Log, but it doesn't change any text I did translate.
So my question is, is this a common Issue (since I recognized in UWP/Win10 the culture-system is a little messed up) or do I use the wrong procedure to override the App-Culture?
This is an issue with AppXBundling. When Installing bundles, it checks with the current OS for the installed Language packs and copies the relevant language resources from the bundle and omits the other language files. The objective of a single bundle is to copy necessary resources and build the application and therefore the languages which are not in the system are considered irrelevant. As a fix you could stop generating single bundles and create package for each CPU architecture. Check this for more info
I am currently working on a windows phone application that takes some information from the user and returns some other information based on the user input.
The application works great if the specific device has its region settings set to US. If the region settings of the device are set to Greek or German, some problems occur. For example, the US decimal point character "." is considered as "," and vice versa. As a result, all the calculations are false.
What I want to do is internationalize the application so that it works exactly the same no matter what the regional settings are. Is this possible?
If you want your app allways to show number and dates in one specify format you can force the app to allways run in one specify culture like this.
You just have to set the current thread of your app to one specify culture (add to the App.cs file)!
public App()
{
// Standard Silverlight initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
// Set the current thread to US!
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");