Question

Mon projet comprend plusieurs plugins et chaque plug-in inclut le fichier plugin.properties avec près de 20 traductions. Le fichier MANIFEST.MF définit le nom des fichiers de propriétés où les chaînes de plug-ins externes sont stockés.

Bundle-Localization: plugin

Le nom du plug-in i comme définis

%plugin.name

Eclipse cherchera le "% plugin.name" dans le fichier plugin.properties lors de l'exécution.

Quelle classe lu l'entrée MANIFEST.MF Bundle-localisation et à quel point est la chaîne avec le démarrage suffixe « % » est recherché dans le fichier « plugin.properties »?

Je veux trouver et patcher ces classes de cette façon, que je peux d'abord regarder dans d'autres répertoires / fichiers pour l'identificateur « % de plugin.name ». Avec ces nouveaux mécanismes que je peux ajouter des fragments à mon produit et écraser simples lignes dans un fichier « plugin.properties » sans changer le plug-in d'origine. Avec ces mécanismes que je pourrais créer un processus de construction pour plusieurs clients tout en ajoutant différents fragments. Les fragments dont les noms des clients et chaîne spéciale qu'ils veulent changer.

Je veux le faire de cette façon, parce que le mécanisme de fragment ajouter uniquement les fichiers du plug-in d'origine. Lorsque le fichier « plugin.properties » est en vigueur dans le plug-in, le fragment « fichiers de plugin.properties » sont ignorés.

UPDATE 1:

La méthode

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

renvoie le ResourceBundle des fichier de propriétés pour la chaîne locale donnée. Quand quelqu'un nows comment je peux maintenant regarder d'abord dans le fragment pour obtenir le chemin de la ressource s'il vous plaît l'afficher.

UPDATE 2:

La méthode dans la classe ManifestLocalization

    private URL findInResolved(String filePath, AbstractBundle bundleHost) {

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

Recherches pour le fichier de propriétés et mettre en cache. Les traductions peuvent obtenir que à partir du fichier mis en cache. Le problème est que le dossier complet est mis en mémoire cache et non simples traductions.

Une solution serait d'abord lire le fichier de fragments, de lire le fichier de regroupement. Lorsque les deux fichiers sont existants les fusionner en un seul fichier et d'écrire les nouvelles propriétés fichier sur le disque. L'URL du nouveau fichier de propriétés des rendements, de sorte que le nouveau fichier propetries peut en cache.

Était-ce utile?

La solution

Bien que je suis la mauvaise information ... J'ai eu exactement le même problème. Le plug-in n'est pas activé deux fois et je ne peux pas obtenir des fragments clé Bundle-localisation.

Je veux que tous mes traductions linguistiques dans les plugin.properties (je sais que cela est mal vu, mais il est beaucoup plus facile de gérer un seul fichier).

I (demi) résolu le problème en utilisant

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

et simplement appeler mon nom de fichier de localisation fragment fragment.properties '.

Ce n'est pas particulièrement élégant, mais il fonctionne.

Par ailleurs, pour obtenir des fichiers à partir du fragment dont vous avez besoin du getResource, il semble que les fichiers fragments sont sur le chemin de classe, ou ne sont recherchées lors de l'utilisation getResource.

Si quelqu'un a une meilleure approche, s'il vous plaît me corriger.

Cordialement,

Mark.

Autres conseils

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

Changer le nom de votre fragment plugin.properties à autre chose par exemple. fragment.properties

dans votre fragment était manifesté changer la Bundle-localisation: plug-in à Bundle-localisation: fragment

Votre plugin sera activé deux fois, la première fois à l'aide des plugin.properties, le second en utilisant les fragment.properties.

activation de plug-in est assurée par le moteur d'exécution OSGi Equinox. Cependant, je déconseillons fortement d'essayer de colmater les fichiers là pour créer des comportements spécifiques. La façon suggérée par Mark semble une approche beaucoup plus sain d'esprit à votre problème.

Une façon est d'attacher un écouteur de paquet, et écouter les installations de faisceaux (et peut-être aussi regarder des paquets déjà installés) et pour chaque paquet générer / fournir - et installer - un fragment avec les fichiers de propriétés recherchées. Si cela se fait avant l'application démarre, cela devrait avoir un effet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top