Dlaczego mój program działa tylko w Polsce?! Czyli z lokalizacją na dobre i na złe

Może nie tylko w Polsce, ale na pewno nie w Stanach Zjednoczonych czy Wielkiej Brytanii. Kiedy decydujemy się na wystawienie naszej aplikacji na rynek międzynarodowy podejmujemy podstawową decyzję: czy nasza aplikacja będzie lokalizowana, czy „sztywno” anglojęzyczna. W drugim przypadku jesteśmy zwolnieni z tłumaczenia tekstów interfejsu oraz wyświetlania danych (takich jak data, czas, waluta) w formacie charakterystycznym dla danego regionu. Niestety nie możemy całkowicie zignorować kwestii lokalizowania, gdyż poskutkuje to niemałym zaskoczeniem. Na co więc należy zwrócić uwagę?

Przecinek czy kropka?

Najlepiej będzie jeżeli zobrazuję potencjalne zagrożenie na przykładzie. Przyjrzyjmy się poniższemu listingowi kodu:

float PI = 3.1415f;
if (!File.Exists("pi.txt"))
{
	using (StreamWriter sw = File.CreateText("pi.txt"))
	{
		sw.WriteLine(PI);
	}
}

using (StreamReader sr = new StreamReader("pi.txt"))
{
	PI = float.Parse(sr.ReadLine());
	Console.WriteLine(PI);
}

Zapisujemy do pliku pi.txt liczbę PI (o ile już taki plik nie istnieje). Następnie odczytujemy ją z pliku i wyświetlamy na ekranie. Nie zobaczymy nic zaskakującego:

Ok. Po pierwszym uruchomieniu mamy plik z danym. Przy każdym następnym będziemy tylko z niego odczytywać. Wszyscy się chyba zgodzimy, że ten prosty program konsolowy nie jest w ogóle ukierunkowany na lokalizację (zakładam, że sposób wyświetlania liczby jest nam obojętny). Czy oby na pewno?

Co się stanie na komputerze naszych kolegów zza oceanu, gdy przyślemy im nasz program wraz z plikiem pi.txt? Sprawdźmy!

Hmm… Nie ma już liczby 3.1415. Jest za to 31 415. Ach gdyby banki w ten sposób zapisywały saldo na koncie… Programu nie wysyłałem do Stanów Zjednoczonych, zmieniłem tylko ustawienia regionalne w systemie. Cóż więc się takiego stało?

Otóż w Stanach Zjednoczonych, Wielkiej Brytanii do oznaczenia części dziesiętnej liczby stosuje się znak ‚.’ (kropka). W Polsce natomiast jest to przecinek, który możemy ujrzeć w pliku PI. No dobrze, ale dlaczego zatem program się nie wysypał przy parsowaniu linii? Otóż przecinek w tych ustawieniach regionalnych jest traktowany jako separator „setek”. Znaczy się: w Polsce 1 000 000, w USA 1,000,000. Tak oto otrzymaliśmy 31415. Ta-dam!

Prosimy program o uniwersalny zapis…

Całe szczęście możemy łatwo zażegnać tego typu problemom. Rozwiązanie poniżej:

sw.WriteLine(PI.ToString( CultureInfo.InvariantCulture.NumberFormat));

PI = float.Parse(sr.ReadLine(), CultureInfo.InvariantCulture.NumberFormat);

Jedyne co musieliśmy zrobić to dodać dodatkowe informacje o kulturze i konkretnym formacie danych. Jako kulturę wybieramy InvarianCulture, który gwarantuje nam, że w każdym miejscu na ziemi nasz program będzie stosował taki sam format zapisu danych. W tym przypadku zapisujemy liczbę, więc wybieramy NumberFormat. InvariantCulture to poprostu „brane w ciemno” ustawienia English-United States.

Teraz jesteśmy gotowi!

Ze zdobytą dzisiaj wiedzą jesteśmy gotowi na podbój świata naszymi aplikacjami! Tak jak to w życiu programisty bywa: program zawsze najlepiej działa tam, gdzie był pisany. Czasem nawet tylko w wybrany dzień tygodnia, ale to już temat na inny artykuł 😉

Share

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Spam protection by WP Captcha-Free