Pracuję nad internacjonalizacją wprowadzonych przez użytkownika danych w dość dużym kliencie/serwerze (aplikacja HTTP (Hessian) służy do komunikacji), która jest przechowywana w bazie danych. Użytkownicy mogą wybrać język, który chcą zobaczyć, oraz domyślny język używany w przypadku braku tłumaczenia w żądanym języku.Czy można używać ThreadLocal do przechowywania wymaganych ustawień regionalnych?
Obecnie klasa dane mogą wyglądać następująco:
class MyDataClass {
private Long id;
private String someText;
/* getters and setters */
}
Po internacjonalizacji może to wyglądać tak:
class MyDataClass {
private Long id;
private Set<LocalizedStrings> localizedStrings;
/* getters and setters */
}
class LocalizedStrings {
private Locale locale;
private String someText;
/* getters and setters */
}
Oczywiście może to być interesujące, aby utworzyć getter powierzać MyDataClass który trwa dbałość o uzyskanie tekstu w odpowiednim języku:
public String getSomeText(Locale locale) {
for(LocalizedString localized : localizedStrings) {
if (localized.getLocale().equals(locale)) {
return localized.getSomeText();
}
}
}
W moim zespole były jednak pewne obawy dotyczące konieczności przekazywania ustawień regionalnych przez cały czas, dopóki nie dotrą do klasy danych. Ponieważ wszystkie te rzeczy dzieje się na serwerze, a każde żądanie do serwera jest obsługiwany w dedykowanym wątku, niektórzy sugerują, aby zapisać żądane ustawienia regionalne w ThreadLocal obiektu i stworzenie wstecznie kompatybilny getter no-argument:
public String getSomeText() {
return getSomeText(myThreadLocalLocale.get());
}
Wątek ThreadLocal musi być zmienną globalną (statyczną gdzieś) lub musi być wstrzyknięty do MyDataClass przy każdym tworzeniu pojedynczej instancji (używamy sprężyny, abyśmy mogli ją wprowadzić, jeśli sprawimy, że nasze klasy danych będą zarządzane w sposób wiosenny (co jest niewłaściwe dla mnie)).
Używanie właściwości ThreadLocal dla lokalizacji jest dla mnie złe. Mogę niejasno twierdzić, że nie podoba mi się niewidzialna magia w geterze i zależność od zmiennej globalnej (w klasie danych!). Jednak posiadanie "złego przeczucia" nie jest dobrym sposobem na dyskusję z moimi kolegami na ten temat. Aby pomóc muszę odpowiedź z jednego z następujących powodów:
- Powiedz mi, że moje uczucie do bani, a rozwiązanie jest idealne dla powodów X, Y i Z.
- dać mi kilka dobrych zacytowania argumentów można użyć do spierać się z moimi kolegami i mówić mi, jak to zrobić lepiej (po prostu zawsze przekazywać lokalizację lub jakikolwiek inny pomysł?)
Dlaczego używasz zestawu dla 'localizedStrings', a nie mapy? –
Czy rozważałeś użycie Spring [LocaleContextHolder] (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/context/i18n/LocaleContextHolder.html). Jego źródła mają własny sposób przechowywania bieżących ustawień narodowych (przechowywanych przez DispatcherServlet) dla wątku. – sbk
Jeśli zasięg zmiennej lokalizacyjnej jest pojedynczym wątkiem, wydaje się, że jest to rozwiązanie inteligentne (i proste). Jeśli wybierasz się na wiele wątków, to oczywiście wymaga to czegoś więcej. Jeśli twój interfejs API zawiera informacje o lokalizacji w każdym żądaniu, jest to całkowicie poprawne rozwiązanie. Pocałuj, to najlepszy argument, jaki możesz zrobić. –