2009-03-23 28 views
7

Dự án của tôi bao gồm nhiều plugin và mọi plugin đều bao gồm tệp plugin.properties có gần 20 bản dịch. Tệp MANIFEST.MF xác định tên của các tệp thuộc tính nơi các chuỗi plugin bên ngoài được lưu trữ.cơ chế plugin.properties trong nhật thực RCP

Bundle-Localization: plugin 

Tên của các plugin tôi xác định như

%plugin.name 

Eclipse sẽ tìm kiếm "% plugin.name" trong tập tin plugin.properties khi chạy.

Lớp nào đọc mục nhập MANIFEST.MF Bundle-Localization và tại điểm nào là chuỗi có hậu tố bắt đầu '%' được tìm kiếm trong tệp "plugin.properties"?

Tôi muốn tìm và vá các lớp này theo cách đó, trước tiên tôi có thể xem xét một số thư mục/tệp khác cho số nhận dạng "% plugin.name". Với những cơ chế mới này, tôi có thể thêm các mảnh vào sản phẩm của mình và ghi đè lên các dòng đơn trong tệp "plugin.properties" mà không thay đổi plugin gốc. Với những cơ chế này tôi có thể tạo một quy trình xây dựng cho nhiều khách hàng chỉ bằng cách thêm các đoạn khác nhau. Các mảnh bao gồm tên khách hàng và chuỗi đặc biệt mà họ muốn thay đổi.

Tôi muốn thực hiện theo cách đó, vì cơ chế phân đoạn chỉ thêm tệp vào plugin gốc. Khi tệp "plugin.properties" tồn tại trong plugin, các tệp "plugin.properties" mảnh bị bỏ qua.

UPDATE 1:

Phương pháp

class ManifestLocalization{ 
... 
protected ResourceBundle getResourceBundle(String localeString) { 
} 
... 
} 

trả về ResourceBundle các thuộc tính tập tin cho chuỗi locale nhất định. Khi ai đó nows làm thế nào bây giờ tôi có thể đầu tiên nhìn vào mảnh để có được đường dẫn tài nguyên xin vui lòng gửi nó.

UPDATE 2:

Các phương thức trong lớp ManifestLocalization

private URL findInResolved(String filePath, AbstractBundle bundleHost) { 

     URL result = findInBundle(filePath, bundleHost); 
     if (result != null) 
      return result; 
     return findInFragments(filePath, bundleHost); 
    } 

Mấu tìm kiếm cho các thuộc tính tập tin và bộ nhớ cache nó. Các bản dịch có thể nhận được từ tệp được lưu trong bộ nhớ cache. Vấn đề là, tệp hoàn chỉnh được lưu trữ và không phải là bản dịch đơn lẻ.

Giải pháp trước hết là đọc tệp mảnh, thay vì đọc tệp bó. Khi cả hai tệp hiện có hợp nhất chúng thành một tệp và ghi tệp thuộc tính mới vào đĩa. URL của tệp thuộc tính mới sẽ trả về, do đó tệp propetries mới có thể được lưu trong bộ nhớ cache.

Trả lời

3

Mặc dù tôi đã nhận được thông tin sai ... Tôi đã có chính xác cùng một vấn đề. Plugin không được kích hoạt hai lần và tôi không thể nhận được các khóa Bundle-Localization.

Tôi muốn tất cả bản dịch ngôn ngữ của mình trong plugin.properties (Tôi biết điều này được tán thành nhưng dễ quản lý một tệp đơn giản hơn nhiều).

I (nửa) giải quyết vấn đề bằng cách sử dụng

public void populate(Bundle bundle) { 
    String localisation = (String) bundle.getHeaders().get("Bundle-Localization"); 
    Locale locale = Locale.getDefault(); 

    populate(bundle.getEntry(getFileName(localisation))); 
    populate(bundle.getEntry(getFileName(localisation, locale.getLanguage()))); 
    populate(bundle.getEntry(getFileName(localisation, locale.getLanguage(), locale.getCountry()))); 
    populate(bundle.getResource(getFileName("fragment"))); 
    populate(bundle.getResource(getFileName("fragment", locale.getLanguage()))); 
    populate(bundle.getResource(getFileName("fragment", locale.getLanguage(), locale.getCountry()))); 
} 

và chỉ cần gọi tên file nội địa hóa mảnh của tôi 'fragment.properties'.

Điều này không đặc biệt thanh lịch, nhưng nó hoạt động.

Bằng cách này, để lấy tệp từ đoạn bạn cần getResource, có vẻ như tệp mảnh nằm trên đường dẫn lớp hoặc chỉ được tìm kiếm khi sử dụng getResource.

Nếu ai đó có cách tiếp cận tốt hơn, vui lòng sửa tôi.

Tất cả tốt nhất,

Đánh dấu.

+0

Nơi tôi có thể tìm thấy phương pháp phổ biến? Hay tôi phải viết nó? –

+0

Bạn có thể vui lòng đưa thêm thông tin vào câu trả lời của bạn. Cảm ơn bạn! –

0

Thay đổi tên của plugin plugin.properties thành ví dụ khác. fragment.properties

trong đoạn của bạn Manifest thay đổi Bundle-Localization: Plugin để Bundle-Localization: mảnh

plugin của bạn sẽ được kích hoạt hai lần, lần đầu tiên sử dụng plugin.properties, thứ hai sử dụng fragment.properties.

+0

Nhưng tôi không thể sử dụng cùng một khóa cho một giá trị khác. Chỉ có phím plugin mới tìm và trả lại. Khi phím tìm kiếm được tìm thấy trong các plugin fragmet là không bao giờ mở –

0

Kích hoạt plugin được xử lý bởi thời gian chạy OSGi Equinox. Tuy nhiên tôi sẽ mạnh mẽ không khuyến khích cố gắng để vá bất kỳ tập tin đó để tạo ra hành vi cụ thể. Cách đề nghị từ Mark có vẻ là một cách tiếp cận lành mạnh hơn nhiều cho vấn đề của bạn.

+0

Bạn có nghĩa là cách gợi ý từ Mark Miller hoặc những gì Mark? :) – Peteter

1
/** 
* The Hacked NLS (National Language Support) system. 
* <p> 
* Singleton. 
* 
* @author mima 
*/ 
public final class HackedNLS { 
    private static final HackedNLS instance = new HackedNLS(); 

    private final Map<String, String> translations; 

    private final Set<String> knownMissing; 

    /** 
    * Create the NLS singleton. 
    */ 
    private HackedNLS() { 
     translations = new HashMap<String, String>(); 
     knownMissing = new HashSet<String>(); 
    } 

    /** 
    * Populates the NLS key/value pairs for the current locale. 
    * <p> 
    * Plugin localization files may have any name as long as it is declared in the Manifest under 
    * the Bundle-Localization key. 
    * <p> 
    * Fragments <b>MUST</b> define their localization using the base name 'fragment'. 
    * This is due to the fact that I have no access to the Bundle-Localization key for the 
    * fragment. 
    * This may change. 
    * 
    * @param bundle The bundle to use for population. 
    */ 
    public void populate(Bundle bundle) { 
     String baseName = (String) bundle.getHeaders().get("Bundle-Localization"); 

     populate(getLocalizedEntry(baseName, bundle)); 
     populate(getLocalizedEntry("fragment", bundle)); 
    } 

    private URL getLocalizedEntry(String baseName, Bundle bundle) { 
     Locale locale = Locale.getDefault(); 
     URL entry = bundle.getEntry(getFileName(baseName, locale.getLanguage(), locale.getCountry())); 
     if (entry == null) { 
      entry = bundle.getResource(getFileName(baseName, locale.getLanguage(), locale.getCountry())); 
     } 
     if (entry == null) { 
      entry = bundle.getEntry(getFileName(baseName, locale.getLanguage())); 
     } 
     if (entry == null) { 
      entry = bundle.getResource(getFileName(baseName, locale.getLanguage())); 
     } 
     if (entry == null) { 
      entry = bundle.getEntry(getFileName(baseName)); 
     } 
     if (entry == null) { 
      entry = bundle.getResource(getFileName(baseName)); 
     } 
     return entry; 
    } 

    private String getFileName(String baseName, String...arguments) { 
     String name = baseName; 
     for (int index = 0; index < arguments.length; index++) { 
      name += "_" + arguments[index]; 
     } 
     return name + ".properties"; 
    } 

    private void populate(URL resourceUrl) { 
     if (resourceUrl != null) { 
      Properties props = new Properties(); 
      InputStream stream = null; 
      try { 
       stream = resourceUrl.openStream(); 
       props.load(stream); 
      } catch (IOException e) { 
       warn("Could not open the resource file " + resourceUrl, e); 
      } finally { 
       try { 
        stream.close(); 
       } catch (IOException e) { 
        warn("Could not close stream for resource file " + resourceUrl, e); 
       } 
      } 
      for (Object key : props.keySet()) { 
       translations.put((String) key, (String) props.get(key)); 
      } 
     } 
    } 

    /** 
    * @param key The key to translate. 
    * @param arguments Array of arguments to format into the translated text. May be empty. 
    * @return The formatted translated string. 
    */ 
    public String getTranslated(String key, Object...arguments) { 
     String translation = translations.get(key); 
     if (translation != null) { 
      if (arguments != null) { 
       translation = MessageFormat.format(translation, arguments); 
      } 
     } else { 
      translation = "!! " + key; 
      if (!knownMissing.contains(key)) { 
       warn("Could not find any translation text for " + key, null); 
       knownMissing.add(key); 
      } 
     } 
     return translation; 
    } 

    private void warn(String string, Throwable cause) { 
     Status status; 
     if (cause == null) { 
      status = new Status(
        IStatus.ERROR, 
        MiddlewareActivator.PLUGIN_ID, 
        string); 
     } else { 
      status = new Status(
       IStatus.ERROR, 
       MiddlewareActivator.PLUGIN_ID, 
       string, 
       cause); 
     } 
     MiddlewareActivator.getDefault().getLog().log(status); 

    } 

    /** 
    * @return The NLS instance. 
    */ 
    public static HackedNLS getInstance() { 
     return instance; 
    } 

    /** 
    * @param key The key to translate. 
    * @param arguments Array of arguments to format into the translated text. May be empty. 
    * @return The formatted translated string. 
    */ 
    public static String getText(String key, Object...arguments) { 
     return getInstance().getTranslated(key, arguments); 
    } 
} 
+0

Các gói getLocalizedEntry bundle.getResource và bundle.getEntry được yêu cầu vì các tệp trên classpath (các tệp được tìm thấy trong đoạn) cần getResource trong khi các tệp trong root plugin (bản địa hóa plugin) yêu cầu getEntry. Một lần nữa, nếu có ai có câu trả lời hay hơn, vui lòng cho chúng tôi biết vì tôi cũng sẽ quan tâm. –

+0

Tôi không rõ cách sử dụng lớp học mà bạn đã cung cấp. Nó có thể được sử dụng để dịch ví dụ một tên phối cảnh khai báo trong một tập tin plugin.xml, theo một cách khác hơn là tìm kiếm trong file bundle.properties? – Peteter

0

Một cách là để đính kèm một bó người nghe, và lắng nghe cho việc cài đặt các gói (và có lẽ cũng nhìn vào bó đã được cài đặt) và đối với mỗi bó tạo/cung cấp - và cài đặt - một mảnh với các tập tin bất động sản truy nã . Nếu điều này được thực hiện trước khi ứng dụng khởi động, điều này sẽ có hiệu lực.

Các vấn đề liên quan