Domanda

Il mio progetto include più plugin e tutti i plugin include il file plugin.properties con vicino a 20 traduzioni. Il file MANIFEST.MF definisce il nome del file di proprietà in cui sono memorizzati i fili di plugin esterni.

Bundle-Localization: plugin

Il nome del plugin definisco come

%plugin.name

Eclipse cercherà la "% plugin.name" nel file plugin.properties in fase di esecuzione.

Quale classe di leggere la voce di MANIFEST.MF Bundle-localizzazione e in quale punto è la stringa con il suffisso di partenza '%' viene ricercato nel file "plugin.properties"?

Voglio trovare e correggere questi classe in quel modo, che io possa prima esaminare alcune altre directory / file per l'identificatore "% plugin.name". Con questi nuovi meccanismi posso aggiungere frammenti al mio prodotto e sovrascrivere singole linee in un file "plugin.properties" senza cambiare il plugin originale. Con questi meccanismi ho potuto creare un processo di compilazione per più clienti solo con l'aggiunta di frammenti diversi. I frammenti compresi i nomi dei clienti e stringa speciale vogliono cambiare.

Io voglio farlo in quel modo, perché il meccanismo frammento solo aggiungere i file al plugin originale. Quando il file "plugin.properties" è esistente nel plugin, i file frammento "plugin.properties" vengono ignorati.

UPDATE 1:

Il metodo

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

restituisce il ResourceBundle delle proprietà del file per il data stringa locale. Quando qualcuno nows come posso ora prima esaminare il frammento per ottenere il percorso risorsa si prega di postare.

UPDATE 2:

Il metodo della classe ManifestLocalization

    private URL findInResolved(String filePath, AbstractBundle bundleHost) {

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

ricerche per le proprietà del file e la cache di esso. Le traduzioni possono che ottenere dal file memorizzato nella cache. Il problema è che il file completo viene memorizzato nella cache e non traduzioni singoli.

Una soluzione potrebbe essere quella di leggere prima il file frammento, di leggere il file bundle. Quando entrambi i file sono già esistenti unirli in un unico file e scrivere il nuovo file delle proprietà per il disco. L'URL della nuova proprietà presentare le dichiarazioni, in modo che il nuovo file propetries può cache.

È stato utile?

Soluzione

Anche se ho avuto informazioni sbagliate ... Ho avuto esattamente lo stesso problema. Il plugin non viene attivato due volte e non riesco a raggiungere i frammenti chiave Bundle-localizzazione.

Voglio che tutte le mie traduzioni delle lingue nella plugin.properties (so che questo è visto di buon occhio, ma è molto più facile da gestire un singolo file).

I (meta) risolto il problema utilizzando

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())));
}

e semplicemente chiamare i miei frammento di nomi file di localizzazione 'fragment.properties'.

Questo non è particolarmente elegante, ma funziona.

Tra l'altro, per ottenere i file dal frammento è necessario il getResource, sembra che i file frammento si trovano sul classpath, o vengono cercati solo quando si utilizza getResource.

Se qualcuno ha un approccio migliore, per favore correggetemi.

Tutto il meglio,

Marco.

Altri suggerimenti

/**
 * 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);
    }
}

Cambiare il nome dei tuoi plugin.properties frammento di qualcosa d'altro esempio. fragment.properties

nel frammento manifestare cambiare la Bundle-localizzazione: plug-in per Bundle-localizzazione: frammento

Il plugin verrà attivato due volte, la prima volta con i plugin.properties, la seconda con i fragment.properties.

attivazione plugin è gestita dal OSGi runtime Equinox. Tuttavia vorrei scoraggiare fortemente cercando di rattoppare i file lì per creare un comportamento specifico. Il modo suggerito da Mark sembra un approccio molto più sano al vostro problema.

Un modo è quello di collegare un ascoltatore fascio, e ascoltare per le installazioni di pacchetti (e forse anche guardare fasci già installati) e per ogni pacco generare / fornire - ed installare - un frammento con i file di proprietà desiderati. Se questo è fatto prima che l'applicazione si avvia, questo dovrebbe avere effetto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top