2011-09-09 11 views
27

Przeglądałem cały StackOverflow w wielu pytaniach na temat pisania słów w języku Java, a żadna z nich nie wydaje się być najmniej zainteresowana internacjonalizacją i tak na prawdę żadna nie wydaje się do pracy w kontekście międzynarodowym. Oto moje pytanie.Poprawne pisanie tytułu w języku Java w wersji Unicode

Mam ciąg w Javie, który reprezentuje słowo - wszystkie znaki isLetter(), bez spacji. Chcę, aby pierwszy znak wielkimi literami, a reszta - małymi literami. Mam przydomek mojego słowa.

Łatwo wywołać .substring (1) .toLowerCase (Locale) dla ostatniej części mojego łańcucha. Nie mam pojęcia, jak uzyskać prawidłowy pierwszy znak.

Pierwszy problem, jaki mam, dotyczy języka niderlandzkiego, gdzie "ij" oznacza dwuznak i powinno być pisane razem. Mogłem to zrobić osobiście, ponieważ wiem o tym; teraz mogą istnieć inne języki z tego rodzaju rzeczami, o których nie wiem, i jestem pewien, że Unicode powie mi, jeśli dobrze zapytam. Ale nie wiem, jak zapytać.

Nawet jeśli powyższy problem został rozwiązany, nadal utknąłem bez odpowiedniego sposobu obsługi języka angielskiego, tureckiego i greckiego, ponieważ Character obsługuje titlecase, ale nie ma locale, a String obsługuje locale, ale nie titlecase.

Jeśli wziąłem punkt kodowy i przekazałem go do Character.toTitleCase(), to się nie powiedzie, ponieważ nie ma sposobu na przekazanie ustawień narodowych tej metody. Jeśli więc system jest ustawiony w języku angielskim, ale słowo to jest tureckie, a pierwszy znak tego słowa to "i", zamiast "İ" otrzymam "ja", a to jest złe. Teraz, jeśli wezmę podłańcuch i użyję .toUpperCase (locale), to się nie powiedzie, ponieważ jest w górnej, a nie w tytule. Więc jeśli słowo jest po grecku, nadal otrzymam niewłaściwą postać.

Jeśli ktoś ma przydatne wskazówki, chętnie bym je usłyszał.

+0

'ToTitleCase()' nie potrzebuje ustawień narodowych, ponieważ jest niezależne od ustawień narodowych. --- Jeśli chcesz, aby dwa znaki 'ij' były dwuznakowe, powinieneś przekonwertować je na znak Unicode digraph' ij' (['LATIN SMALL LIGATURE IJ' (U + 0133)] (http: // www. fileformat.info/info/unicode/char/0133/index.htm)). – Andreas

Odpowiedz

6

Podobnie jak ty, nie mogłem znaleźć odpowiedniej metody w rdzeniu Java API.

Jednak wydaje się, że istnieje locale-sensitive string-title-case method (UCharacter#toTitleCase) in the ICU library.


Patrząc na źródło odpowiednich metod OIT (UCharacter#toTitleCase i UCaseProps#toUpperOrTitle), nie wydaje się być wiele ustawień narodowych szczególne przypadki dla tytułowej obudowy, więc może być w stanie uciec z następujące:

  1. Znajdź pierwszą literę w ciągu znaków.
  2. Jeśli ma on inną, niż w przypadku dużej litery, formę, użyj tego.
  3. W przeciwnym razie, należy wykonać dużą literę na tym pierwszym znaku i kombinację znaków.
  4. Wykonaj zależną od ustawień regionalnych małą literę na pozostałej części łańcucha.
  5. Jeśli regionem jest język niderlandzki, a pierwszym znakiem cased jest "I", a po nim "j", wielka litera "j".
4

Jedyny dwuznakowy dwuznak, w którym obie litery są pisane wielką literą jednocześnie i że prawdopodobnie napotkasz w prawdziwym programie życia, to holenderski IJ. Po prostu obsłuż go, jeśli lokalizacja jest holenderska. W najgorszym scenariuszu będzie 1-2 przypadków, które będziesz musiał dodać później, nie jest tak, że codziennie spotykasz się z nowym digraftem wielkimi literami, więc nie warto skupiać się na generalizacji tutaj.

Uwaga, ogólnie rzecz biorąc, nie można używać konwersji znaków do postaci, aby uzyskać tytuł lub wielkie litery dla dowolnego języka. Niektóre małe litery tłumaczą na więcej niż jedną wielką literę. Więc musisz użyć String w ogólnym przypadku.

Ale nie ma żadnego problemu z ustawieniami regionalnymi tytułu. Prawdopodobnie istnieje małe nieporozumienie dotyczące sposobu działania metody TitleCase(). Spowoduje to przekształcenie w tytułową literę dowolną postać, w tym taką, która jest już w dużym formacie.

Na przykład rozważ znak dž. Jest to górna forma sprawa jest DŽ i forma tytuł sprawa jest Dž:

System.out.println(Character.toUpperCase('\u01C4')); 
DŽ 

i

System.out.println(Character.toTitleCase('\u01C4')); 
Dž 

jednak dodaje także dać tytuł przypadek

System.out.println(Character.toTitleCase(Character.toUpperCase('\u01C4'))); 
Dž 

Tak , jeśli konwertujesz z ustawieniem narodowym na wielkie litery przed nazwą tytułu, otrzymasz poprawny punkt kodowy i nie ma żadnego probl em używać tytułowy przypadek na wynik, w tym turecki, itp .:

System.out.println(Character.toTitleCase("dž".toUpperCase().charAt(0))); 
System.out.println(Character.toTitleCase("i".toUpperCase(Locale.forLanguageTag("tr")).charAt(0))); 
Dž 
İ 

Uwaga, tylko przy użyciu tytułowy przypadek pojedynczego charakteru, jeśli istnieje różnica od jego górnej przypadku nie jest poprawna w przypadku leków generycznych .

Podsumowując:

  • Uchwyt holenderski digraf (lub inne digrafy jeśli je spotkać, bardzo wątpię, że w najgorszym będzie 1-2 przypadki na całe życie programu).
  • Konwertuj wymagane znaki jako Ciąg przy użyciu ustawień narodowych i doUpperCase()
  • Konwertuj wszystkie znaki wyniku ToUpperCase, używając znaku doTitleCase.

Uwaga, nadal istnieją pewne przypadki kapitalizacji, które są świadome kontekstu, jak irlandzki, angielski ff przedrostek nazwy, itp, które wymagają więcej niż tylko przetwarzanie Charakter/string, ale wątpię, trzeba obsługiwać je za tytuł generowanie w programie.