Jak poprawnie zlokalizować liczby?

38

O jakich zastrzeżeniach powinienem pamiętać podczas lokalizowania liczb w aplikacji front-end?

Przykład: w brazylijskim portugalskim (pt-BR) dzielimy tysiące kropkami i dziesiętnymi przecinkami. W amerykańskim angielskim (en-US) jest inaczej. W pt-BR przedstawiamy cyfry oddzielone tysiącami, takie same jak w en-US. Ale czytając o indyjskim angielskim (en-IN) dzisiaj spotkałem ten klejnot:

Indyjski system numeracji jest preferowany do grupowania cyfr. Liczby mniejsze niż 100 000/100 000 są pisane słowami lub wypowiadane tak, jak w języku angielskim standardowym. Liczby w tym i powyżej 100 000/100 000 są wyrażone w podzbiorze indyjskiego systemu numeracji.

https://en.wikipedia.org/wiki/Indian_English#Numbering_system

Co znaczy:

1000000 units in pt-BR are formatted 1.000.000
1000000 units in en-US are formatted 1,000,000
1000000 units in en-IN are formatted 10,00,000

Oprócz przecinków, kropek i innych specyficznych separatorów wydaje się, że maskowanie jest również ważnym problemem.

Jakie inne zastrzeżenia powinienem znać podczas lokalizowania liczb w mojej aplikacji front-end? Zwłaszcza jeśli wyświetlam liczby zestawom znaków spoza alfabetu łacińskiego?

Machado
źródło
3
Staje się jeszcze bardziej interesujący w przypadku pieniędzy! :-)
Stephan Bijzitter
4
Nie mówiąc o marsjańskim systemie numeracji, który ma podstawę 6 (dwa razy 3 palce) ;-) Ale Japończyk ma również dziwność: człowiek = 10.000 napisany jako 1.0000, oku = 100.000.000 napisany w Japonii jako 1.0000.0000 i chō. .. zgadnij
qwerty_so
6
Dlaczego musisz się tym martwić? Czy nie możesz przestrzegać ustawień systemu operacyjnego?
Jan Doggen,
3
@ JanDoggen, ponieważ jest to jeden z interesujących problemów w dziedzinie inżynierii oprogramowania: „jak prawidłowo prezentować dane ludziom”. To, o co powinienem się martwić, projektując system, jest domeną tego pytania. I nawet nie mówię o pieniądzach, jak powiedział nasz przyjaciel Stephan, ani o dacie i godzinie. Tylko surowe liczby.
Machado,
5
@ JanDoggen, staje się to znacznie bardziej skomplikowane, gdy mamy do czynienia z oprogramowaniem online. Użytkownik może przebywać w Indiach na komputerze w języku angielskim w USA, ale czyta stronę internetową w języku portugalskim brazylijskim. Twój serwer może być chiński. Twoja aplikacja musi zrozumieć, czego chce użytkownik, bez względu na to, jakiego systemu operacyjnego używa lub gdzie znajduje się Twój serwer. Twoje 1 000,00 dolarów stanie się 67,545,00 rupiami: amerykańską walutą przeliczoną według lokalnego kursu walutowego, ale wyświetloną w formacie portugalskim.
noderman

Odpowiedzi:

87

Większość języków programowania i struktur ma już rozsądny, działający mechanizm, którego można użyć do tego celu.

Na przykład ekosystem C # ma przestrzeń nazw System.Globalization , która pozwala określić Cultureżądane:

Console.WriteLine(myMoneyValue.ToString("C", "en-US"));

To nie jest coś, co chcesz na nowo wynaleźć. Skorzystaj z funkcji internacjonalizacji zapewnianych przez ulubiony język lub środowisko.

Robert Harvey
źródło
2
Zdaję sobie sprawę z System.Globalization i innych frameworków, które obsługują dla mnie tego rodzaju złożoność. Nie wiem, jakie problemy rozwiązują. Na przykład kilka aplikacji, które widzę, używa określonego maskowania na ToString, takich jak .ToString („#, ## 0,00”, ustawienia regionalne), ale ta maska ​​sama w sobie jest nieprawidłowa, jeśli pokazuję ten numer Hindusowi. Poza tym „nie używaj konkretnych masek”, o czym jeszcze powinienem wiedzieć?
Machado,
7
Nic, o czym wiem. Jeśli używasz frameworka właściwie, powinien on po prostu działać. Istnieją pewne konkretne przypadki problemów z internacjonalizacją, ale tworzenie ich wyczerpującej listy nie jest tutaj czymś, co robimy. Zobacz ten przykład .
Robert Harvey,
5
To jedyna poprawna odpowiedź: ustaw swoje ustawienia regionalne, a następnie prześlij wartości przez warstwę i18n przed wyświetleniem użytkownikowi i pozwól autorom frameworka sobie z tym poradzić. Dotyczy to liczb, wartości walutowych, przetłumaczonych ciągów, dat, wszystkiego.
2
Idealna odpowiedź. „Nie wymyślaj na nowo koła” to coś, co zawsze należy brać pod uwagę przy rozwiązywaniu typowych problemów takich jak ten. Szkoda, że ​​nie mogę głosować więcej niż raz.
BgrWorker,
3
@Machado "Na przykład kilka aplikacji, które widzę, używa określonego maskowania w ToString, takich jak .ToString (" #, ## 0,00 ", ustawienia regionalne), ale ta maska ​​sama w sobie jest nieprawidłowa, jeśli pokazuję ten numer Hindusowi . ” - Może to nie być jasne, ale zwróć uwagę, że pozycja ,ciągu formatu jest w dużej mierze nieistotna i „#, 0,00” miałby ten sam efekt. ,oznacza po prostu „użyj separatorów grup liczb w sposób określony przez ustawienia regionalne”.
hvd,
23

Kilka doskonałych odpowiedzi już tutaj, ale nie wspomniały o jednej rzeczy, która moim zdaniem jest ważna, aby nie zapomnieć: upewnij się, że wszędzie tam, gdzie ma miejsce formatowanie liczb, jest jasne (lub można kontrolować), do czego służy wyjście:

  • w przypadku interfejsu użytkownika należy zastosować zlokalizowane formatowanie

  • gdy numer ma zostać zapisany do pliku lub wysłany przez sieć lub inną formę, w której numer jest potrzebny w formie do odczytu maszynowego , upewnij się, że nie jest sformatowany zgodnie z bieżącą kulturą, ale zgodnie ze stałym ustawieniem (na przykład w środowisku .NET użyj InvariantCulture).

W przeciwnym razie występują problemy, gdy liczby są zapisywane lub wysyłane za pomocą kultury A oraz czytane lub odbierane za pomocą kultury B.

Z mojego doświadczenia wynika, że ​​jest to jedna z największych przeszkód w prawidłowej lokalizacji liczb: próbując scentralizować formatowanie i konwersję liczb, ludzie zaczynają tworzyć ogólne funkcje wielokrotnego użytku do formatowania, a następnie zaczynają z nich korzystać w całym miejsce. Jednak gdy tylko liczby będą potrzebne w formacie łańcucha odczytywalnym maszynowo w innym miejscu programu, potrzebne są dwa warianty: formatowanie zlokalizowane i formatowanie nielokalizowane. Wprowadza to wysokie ryzyko pomieszania dwóch form konwersji (szczególnie, gdy programiści i maszyny testujące mają swoje domyślne ustawienia regionalne podobne do „ustalonego” ustawienia używanego do formatowania innego niż interfejs użytkownika, ale część bazy użytkowników tego nie zrobiła).

Dodatek: ten problem może stać się naprawdę paskudny w sytuacjach, w których wcześniej nie jest jasne, czy numer zostanie przetworzony przez maszynę, czy przez człowieka (lub jedno i drugie) później. Na przykład jako część wyniku pliku dziennika. W takich przypadkach prawdopodobnie najlepiej trzymać się „neutralnego” standardu, w którym nie stosuje się separatora oprócz kropki jako separatora dziesiętnego.

Doktor Brown
źródło
2
Co gorsza, wiele współczesnych języków programowania ma oczywiste / domyślne funkcje w standardowej bibliotece „zlokalizowane”. Jeśli więc programista nie wie ani nie dba o lokalizację, wynikowa aplikacja może być raczej niefunkcjonalna niż po prostu brzydka w obcych systemach.
Peter Green,
4
Nie zgadzam się na równie złe. Narzędzie, które nie przestrzega lokalnych konwencji numerycznych w interfejsie użytkownika, nadal będzie przydatne. Narzędzie, które nie odczytuje własnych plików danych lub nie komunikuje się z serwerem z powodu niezgodności konwencji numerycznych, jest znacznie bardziej prawdopodobne, że będzie bezużyteczne.
Peter Green,
5
Anegdota: Separator dziesiętny en-ZA zmienił się między Win 7 a Win 8. Poprzednio lokalnie przechowywane wartości zaczęły się nie deserializować
Caleth
1
@PeterGreen: narzędzie, które w swoim interfejsie użytkownika nie przestrzega lokalnych konwencji numerycznych, może być nadal użyteczne lub może być całkowicie bezużyteczne w niektórych przypadkach użycia. Byłbym bardzo ostrożny przy przyjmowaniu takich założeń. Powodem, dla którego tylu programistów błędnie lokalizuje liczby, jest właśnie to - przyjmowanie tego rodzaju założeń.
Doc Brown,
1
@DocBrown Mam najstraszniejszy starszy kod do utrzymania, który cierpi z powodu zlokalizowanych procedur parsowania liczb całkowitych / zmiennopozycyjnych w bibliotece standardowej. Myślę, że można śmiało powiedzieć, że program napisany bez dbałości o lokalizację, gdy domyślne procedury dla tych zadań nie są zlokalizowane, może nie nadawać się do użycia w niektórych sytuacjach, ale jeśli domyślne procedury zostaną zlokalizowane, program zawsze zostanie zepsuty, gdy tylko się pojawi. wykonywane na komputerze, na którym globalne ustawienia narodowe nie są językiem angielskim.
Sebastian Redl,
9

Właściwa lokalizacja jest dość trudna. Większość ekosystemów programistycznych próbuje rozwiązań dla lokalizacji, ale z mojego doświadczenia wynika, że ​​wszystkie są mniej lub bardziej zepsute. Proponuję zatem:

  • Nie próbuj automatyzować lokalizacji. Nie zawsze będzie działać. Trudno jest dostrzec problemy i frustrujące dla użytkowników.

  • Bądź spójny: nie mieszaj różnych języków i konwencji formatowania, np. Separatory dziesiętne w stylu brazylijskim w tekście angielskim.

  • Jawnie obsługuje dany zestaw ustawień narodowych. Współpracuj z tłumaczami, aby znaleźć odpowiednie formatowanie dat i liczb. Najprawdopodobniej skończysz tworzenie własnego zestawu narzędzi lokalizacyjnych, chociaż większość (ale nie wszystkie) problemy można przekazać do istniejącej biblioteki.

  • Twórz proste opcje formatowania konfigurowane przez każdego użytkownika: formaty dat i godzin, separatory dziesiętne, preferowana waluta,…. Jest to szczególnie przydatne dla podróżników, emigrantów lub innych osób, które muszą mieszać wiele lokalizacji lub kultur niezależnie od języka.

amon
źródło
18
Należy również pamiętać, że duża liczba użytkowników nie znosi konwencji, która jest uważana za „poprawną dla ich ustawień regionalnych”, uważa ją za obrzydliwą starszą praktykę i nie chce żadnego grupowania ani innego rodzaju grupowania. W związku z tym prawdopodobnie powinny istnieć opcje wyłączenia lub ręcznego zastąpienia.
R ..
2

Ważna uwaga: powinieneś zdecydować, ile wystarczy. Ponieważ jeśli pójdziesz do króliczej nory, próbując perfekcyjnie zlokalizować, stanie się to coraz bardziej złożone.

Wybierz typową etykietę, na przykład „Wybrałeś n elementów”. Czyta się źle, jeśli wybrano tylko jeden element. Brzydkim, ale pragmatycznym rozwiązaniem jest napisanie „Wybrałeś n elementów”. Ale jeśli chcesz to zrobić poprawnie, potrzebujesz dwóch różnych tekstów w zależności od n. Jeśli spróbujesz to zrobić w wielu lokalizacjach, szybko stanie się to naprawdę skomplikowane, ponieważ różne języki mają inną gramatykę. Niektóre języki mają różne koniugacje dla jednego, dwóch i wielu przedmiotów i tak dalej. Z tego powodu znani ludzie zawsze będą narzekać, że istniejące ramy lokalizacyjne są niewystarczające.

Ale musisz wybrać swoje bitwy i zdecydować, jaki poziom wyrafinowania jest wystarczający. Do wielu celów wystarczy standardowa biblioteka lokalizacji do formatowania liczb i dat.

JacquesB
źródło
Rozwiązuje to ICU (MessageFormat). Wadą jest to, że przyjęcie OIOM w wielu językach jest wciąż słabe. Deweloper musi jednak odpowiednio skonstruować komunikat. To naprawdę więcej niż aspekt techniczny. userguide.icu-project.org/formatparse/messages
noderman
Rozwiązuje to również bardziej dostępna funkcja ngettext w GNU gettext, ale wydaje się, że klasa MessageFormat rozwiązuje dodatkowe problemy, których ngettext nie rozwiązuje.
hvd,
2

Nie możesz być świadomy wszystkich zastrzeżeń dotyczących języków. Mówisz o liczbach, ale są też liczby mnogie, rodzaje, zestawienia. Musisz wiedzieć, że istnieją i polegać na rozległej pracy wykonanej przez inne osoby, w szczególności na projektach OIOM i CLDR.

Większość współczesnych języków implementuje niektóre lub wszystkie funkcje tych projektów, ale nawet jeśli tego nie zrobią, czytanie o tych projektach da ci dobry pomysł na to, czego szukać.

http://site.icu-project.org

http://cldr.unicode.org

Aktualizacja

Narzędzie ankiety CLDR zapewnia dostęp do wszystkich wzorców. To pokaże, jak sformatować liczbę w określonym języku i regionie. Na przykład portugalski (Portugalia):

http://st.unicode.org/cldr-apps/v#/pt_PT/Number_Formatting_Patterns/

A jeśli naprawdę chcesz sprawdzić wszystkie dane (i być może je wykorzystać), możesz pobrać CLDR w formacie JSON z GitHub:

https://github.com/unicode-cldr/cldr-json#cldr-json

Więcej informacji na temat pobierania tutaj:

http://cldr.unicode.org/index/downloads

noderman
źródło
Dzięki za wkład, ale teraz najbardziej interesują mnie liczby. :)
Machado,
Pewnie. Właśnie zredagowałem odpowiedź, aby dołączyć link do narzędzia ankiety, w którym możesz zawęzić wyszukiwanie.
noderman
Próbowałem zmienić na Brazylię, aby sprawdzić różnice, ale wydaje się, że nie umożliwia to wizualizacji: st.unicode.org/cldr-apps/v#/pt_BR/Number_Formatting_Patterns W przeciwnym razie narzędzie wydaje się całkiem dobre.
Machado,
To dlatego, że Brazylia jest językiem głównym. Narzędzie ankietowe jest faktycznie używane do wprowadzania zmian w danych CLDR, więc korzenie wymagają specjalnych kont. Możesz przejść do GitHub i uzyskać wszystkie informacje bezpośrednio: github.com/unicode-cldr/cldr-numbers-modern/tree/master/main W szczególności Brazylia jest tutaj: github.com/unicode-cldr/cldr-numbers-modern/ blob / master / main / pt /…
noderman
0

Cóż, chociaż jestem zadowolony ze wszystkich odpowiedzi tutaj, nie jestem naprawdę zadowolony z każdej z nich osobno, aby oznaczyć jedną jako prawidłową odpowiedź.

Jak do tej pory powinniśmy być świadomi lokalizowania liczb:

Dla ludzi :

  • Tysiące separatorów nie zawsze oddzielają się w tysiącach. Zobacz sprawę Indian w pytaniu;
  • Tysiące i dziesiętne postaci różnią się w zależności od kultury. W języku niemieckim tysiące dzieli się na przykład spacjami, podczas gdy w języku angielskim to komendy, aw języku portugalskim kropki;
  • Nie mamy informacji, jeśli istnieje istotna różnica między językami od lewej do prawej i od prawej do lewej;
  • Podaj określony zestaw obsługiwanych lokalizacji i wyjaśnij go użytkownikom;
  • Pozwól użytkownikom zmienić domyślną lokalizację na jedną z obsługiwanych lokalizacji, a oni będą szczęśliwi i wyślą ci ciasta, które będą Ci wdzięczne, ponieważ jesteś hojnym bogiem. :);

Dla komputerów :

  • Pamiętaj, że maszyny nie są łagodne i zawsze powinny otrzymywać to samo formatowanie podczas szeregowania i usuwania serializacji liczby;
  • Trzymaj się jednego formatu dla niego;
  • Użyj minimalnego niezbędnego formatu. Unikaj separacji tysięcy, dziesiętne powinny wystarczyć do serializacji i deserializacji.

Dla programistów :

  • (zgodnie z sugestią @hyde poniżej): Użyj istniejącej biblioteki do lokalizacji;
  • Jeśli możesz, użyj natywnych testerów i określ przypadki testowe lokalizacji / internacjonalizacji, w przeciwnym razie zaufaj bibliotece;
  • Pamiętaj, że lokalizacja to problem najczęściej rozwiązany. Każdy główny język ma bibliotekę, natywną lub zewnętrzną, która może lokalizować liczby, daty i godziny;
Machado
źródło
1
Brakujący element: dla programistów: użyj istniejącej biblioteki do lokalizacji. Jeśli możesz, użyj natywnych testerów i określ przypadki testowe lokalizacji / internacjonalizacji, w przeciwnym razie zaufaj bibliotece.
hyde