2014-09-11 10 views
5

Próbuję dodać zasób ResourceBundle dla mojego języka dla formantów JavaFx, ale nie robię tego.Lokalizowanie kontrolek JavaFx

Próbowałem dodać control_fi_FI.properties do ścieżki klasy .. i miałem nadzieję, że zadziała, ale nie.

Tak więc przyjrzałem się klasie ControlResources JavaFx, która jest odpowiedzialna za lokalizację kontrolek i zauważyłem, że podstawową nazwą pakietu jest "com \ sun \ javafx \ scene \ control \ skin \ resources \ controls".

Jak mogę dodać mój plik właściwości do tego pakietu? Uważam za dziwne, że praktycznie nie ma nigdzie informacji, jak to zrobić?

+0

Korzystanie z 'ResourceBundle' określona przez właściwości pliku w ścieżce klasy powinno działać. Czy możesz pokazać, jak pobierasz wartości z twojego pakietu? –

+0

Myślę, że źle zrozumiałeś mój problem. Moja własna lokalizacja działa już z ResourceBundle, po prostu próbuję zlokalizować wbudowane ciągi kontrolne. Na przykład ProgressIndicator ma to "zrobione" -string, który jest wyświetlany, gdy kontrola jest w 100%. Po prostu skopiowałem plik controls.properties z jre i przetłumaczyłem go sam, dodając go do ścieżki klas. – user2499946

+0

Ach, tak: źle mnie zrozumiałem. Dzięki za wytłumaczenie. –

Odpowiedz

4

Mogę uruchomić to tylko za pomocą całkiem masywnego hacka, który nie jest nawet przenośny. Może jednak da ci wystarczająco dużo pracy, aby stworzyć realistyczne rozwiązanie. (To działa pod Java 8.)

stworzyłem paczkę com.sun.javafx.scene.control.skin.resources, a utworzony plik controls_fi_FI.properties w nim z jednej linii

ProgressIndicator.doneString=Valmis 

I stworzył aplikację testową z następujących czynności:

import java.util.Locale; 
import java.util.ResourceBundle; 

import javafx.application.Application; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.control.ProgressIndicator; 
import javafx.scene.layout.BorderPane; 


public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
      System.out.println(ResourceBundle.getBundle("com/sun/javafx/scene/control/skin/resources/controls").getString("ProgressIndicator.doneString")); 

      BorderPane root = new BorderPane(); 
      ProgressIndicator progressIndicator = new ProgressIndicator(1); 
      root.setCenter(progressIndicator); 
      Scene scene = new Scene(root,400,400); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     Locale.setDefault(new Locale("fi", "FI")); 
     launch(args); 
    } 
} 

Uruchomienie tej aplikacji na wiele sposobów nie działa zgodnie z oczekiwaniami: podczas gdy System.out.println(...) daje prawidłowy wynik, tekst wyświetlany na wskaźniku postępu jest nieprawidłowy.

Jednakże, jeśli pakiet com/sun/javafx/control/skin/resources/controls_fi_FI.properties w pliku jar i przenieść ten plik jar do podkatalogu mojej instalacji JDK jre/lib/ext (tj. W tym samym miejscu jak jfxrt.jar), działa jako wymagane (przynajmniej w moim prostego testu; jak już powiedziałem, nie twierdzę, że jest to jakieś solidne rozwiązanie).

Wydaje się, że ładowanie klasy ControlsResources jest ładowane przez moduł ładujący klasy rozszerzenia i dlatego używa tego samego programu ładującego klasy, aby załadować pakiet zasobów.

Dzięki lepszej znajomości ładowarki klasy niż mam, może być w stanie kształtować to w rozsądnym rozwiązaniem ...

+0

Tak naprawdę próbowałem utworzyć ten pakiet w folderze projektu, i umieścić w nim pakiet, i zauważyłem, że nie działa. Jednak naprawdę nie myślałem o umieszczeniu go w folderze zewnętrznym. To jest dla mnie dobry hack, ponieważ faktycznie dołączam JRE do mojej aplikacji, więc nie mam problemu z dodawaniem rzeczy do ext. Jednak nadal powstrzymam się (na razie) od zaakceptowania twojego rozwiązania, ponieważ ja również uważam, że może być lepsze rozwiązanie. Dziękuję Ci! – user2499946

-2

to tylko, że staram się zlokalizować wbudowane w ciągi kontrolne.

JavaFX jest projekt Open Source hostowane na: http://openjdk.java.net/projects/openjfx/

Proponuję zgłosić problem na stronie: https://javafx-jira.kenai.com

oraz ewentualnie dostarczyć poprawkę.

+1

Ewentualnie OP powinien określić, czy rzeczywiście jest uszkodzony w pierwszej kolejności. tj. czy istnieje sposób na osiągnięcie tego, o czym OP nie jest świadomy. stąd post. – simpleuser

-1

Stworzyłem prosty "Hello, world!" przykład pokazujący gotowy do uruchomienia projekt JavaFX z obsługą wielu języków jest dla tych, którzy potrzebują bardziej egzotycznego języka (be-BY, ru-RU itp.)

Oto jak rozwiązać ten problem, że pracuje dla mnie

Messages.java

/** 
* The class with all messages of this application. 
*/ 
public abstract class Messages { 

    private static ResourceBundle BUNDLE; 

    private static final String FIELD_NAME = "lookup"; 
    private static final String BUNDLE_NAME = "messages/messages"; 
    private static final String CONTROLS_BUNDLE_NAME = "com/sun/javafx/scene/control/skin/resources/controls"; 

    public static final String MAIN_APP_TITLE; 

    public static final String DIALOG_HEADER; 
    public static final String MAIN_CONTROLLER_CONTENT_TEXT; 
    public static final String MAIN_CONTROLLER_HELLO_TEXT; 
    public static final String MAIN_CONTROLLER_GOODBYE_TEXT; 

    static { 
     final Locale locale = Locale.getDefault(); 
     final ClassLoader classLoader = ControlResources.class.getClassLoader(); 

     final ResourceBundle controlBundle = getBundle(CONTROLS_BUNDLE_NAME, 
       locale, classLoader, PropertyLoader.getInstance()); 

     final ResourceBundle overrideBundle = getBundle(CONTROLS_BUNDLE_NAME, 
       PropertyLoader.getInstance()); 

     final Map override = getUnsafeFieldValue(overrideBundle, FIELD_NAME); 
     final Map original = getUnsafeFieldValue(controlBundle, FIELD_NAME); 

     //noinspection ConstantConditions,ConstantConditions,unchecked 
     original.putAll(override); 

     BUNDLE = getBundle(BUNDLE_NAME, PropertyLoader.getInstance()); 

     MAIN_APP_TITLE = BUNDLE.getString("MainApp.title"); 

     DIALOG_HEADER = BUNDLE.getString("Dialog.information.header"); 
     MAIN_CONTROLLER_CONTENT_TEXT = BUNDLE.getString("MainController.contentText"); 
     MAIN_CONTROLLER_HELLO_TEXT = BUNDLE.getString("MainController.helloText"); 
     MAIN_CONTROLLER_GOODBYE_TEXT = BUNDLE.getString("MainController.goodbyeText"); 
    } 

    public static ResourceBundle GetBundle() { 
     return BUNDLE; 
    } 
} 

aw PropertyLoader.java

public class PropertyLoader extends ResourceBundle.Control { 

    private static final String PROPERTIES_RESOURCE_NAME = "properties"; 

    private static final PropertyLoader INSTANCE = new PropertyLoader(); 

    public static PropertyLoader getInstance() { 
     return INSTANCE; 
    } 

    @Override 
    public ResourceBundle newBundle(final String baseName, final Locale locale, final String format, 
            final ClassLoader loader, final boolean reload) 
      throws IllegalAccessException, InstantiationException, IOException { 

     final String bundleName = toBundleName(baseName, locale); 
     final String resourceName = toResourceName(bundleName, PROPERTIES_RESOURCE_NAME); 

     ResourceBundle bundle = null; 
     InputStream stream = null; 

     if (reload) { 

      final URL url = loader.getResource(resourceName); 

      if (url != null) { 
       final URLConnection connection = url.openConnection(); 
       if (connection != null) { 
        connection.setUseCaches(false); 
        stream = connection.getInputStream(); 
       } 
      } 

     } else { 
      stream = loader.getResourceAsStream(resourceName); 
     } 

     if (stream != null) { 
      try { 
       bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8)); 
      } finally { 
       stream.close(); 
      } 
     } 

     return bundle; 
    } 
} 

Więcej opisałem here lub na GitHub

Oto demonstracja w języku białoruskim: enter image description here

0

I odwrócone wiązki załadunek i wpadł brudnego roztworu w przypadku oddanie słoik do jre/lib/ext nie jest opcją. Domyślny algorytm wymaga, aby plik pakunku był kodowany w ISO-8859-1 i nie zapewnia żadnych środków do określenia kodowania. Moje rozwiązanie również rozwiązuje problem z kodowaniem.

Następująca metoda ładuje zasoby za pomocą programu ładującego klasy i umieszcza wynikowy pakunek w pamięci podręcznej pakietów za pomocą rozszerzenia classloader (który jest używany w środowisku wykonawczym przez klasy javafx do przeszukiwania pakietów).

import com.sun.javafx.scene.control.skin.resources.ControlResources; 
import java.util.Locale; 
import java.util.PropertyResourceBundle; 
import java.util.ResourceBundle; 
// rest of the imports is ommitted 

private void putResourceBundleInCache(String baseName, Charset cs) throws ReflectiveOperationException, IOException { 
    Locale currentLocale = Locale.getDefault(); 
    ResourceBundle.Control control = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_DEFAULT); 
    String resourceName = control.toResourceName(control.toBundleName(baseName, currentLocale), "properties"); 
    ResourceBundle bundle; 
    try (Reader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resourceName), cs)) { 
     bundle = new PropertyResourceBundle(reader); 
    } 
    Class<?> cacheKeyClass = Class.forName("java.util.ResourceBundle$CacheKey"); 
    Constructor<?> cacheKeyClassConstructor = cacheKeyClass.getDeclaredConstructor(String.class, Locale.class, ClassLoader.class); 
    cacheKeyClassConstructor.setAccessible(true); 
    Object cacheKey = cacheKeyClassConstructor.newInstance(baseName, currentLocale, ControlResources.class.getClassLoader()); 
    Method putBundleInCache = ResourceBundle.class.getDeclaredMethod("putBundleInCache", cacheKeyClass, ResourceBundle.class, ResourceBundle.Control.class); 
    putBundleInCache.setAccessible(true); 
    putBundleInCache.invoke(null, cacheKey, bundle, control); 
} 

nazywam go od tak:

public void start(Stage primaryStage) throws Exception { 
    putResourceBundleInCache("com/sun/javafx/scene/control/skin/resources/controls", StandardCharsets.UTF_8); 
    // mian logic here 
} 
Powiązane problemy