Pregunta

Mi proyecto incluye varios plugins y cada plug-in incluye el archivo de plugin.properties con cerca de 20 traducciones. El archivo MANIFEST.MF define el nombre de los archivos de propiedades donde se almacenan las cadenas de plugins externos.

Bundle-Localization: plugin

El nombre del plugin i defino como

%plugin.name

Eclipse buscará el "% plugin.name" en el archivo plugin.properties en tiempo de ejecución.

¿Qué clase de lectura a la entrada MANIFIEST.MF Bundle-localización y momento en el que es la cadena con el sufijo iniciando '%' se busca en el archivo "plugin.properties"?

Quiero encontrar y parchear estas clases de esa manera, que por primera vez se puede ver en algunos otros directorios / archivos para el identificador "plugin.name%". Con estos nuevos mecanismo puedo añadir fragmentos de mi producto y sobrescribir las líneas individuales en un archivo "plugin.properties" sin cambiar el plugin originales. Con estos mecanismos que podría crear un proceso de construcción para múltiples clientes simplemente añadiendo diferentes fragmentos. Los fragmentos que incluyen los nombres de los clientes y cadena especial que desea cambiar.

Quiero hacerlo de esa manera, ya que el mecanismo fragmento sólo se suman a los archivos originales el plugin. Cuando el archivo "plugin.properties" es existente en el complemento, los archivos de fragmentos "plugin.properties" se ignoran.

ACTUALIZACIÓN 1:

El método

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

devuelve el ResourceBundle del archivo de propiedades para la cadena de localización dada. Cuando alguien nows cómo puedo ahora buscará primero en el fragmento para obtener la ruta del recurso publicarlo.

ACTUALIZACIÓN 2:

El método en ManifestLocalization clase

    private URL findInResolved(String filePath, AbstractBundle bundleHost) {

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

busque por el archivo de propiedades y la memoria caché ella. Las traducciones se pueden obtener de que el archivo almacenado en caché. El problema es que el archivo completo se almacena en caché y no traducciones individuales.

Una solución sería la de leer primero el archivo de fragmento, de leer el archivo de paquete. Cuando ambos archivos son existentes agruparlos en un solo archivo y escribir las propiedades del nuevo archivo en el disco. La URL de las nuevas propiedades presentar declaraciones, por lo que el nuevo archivo propetries puede caché.

¿Fue útil?

Solución

A pesar de que me dio la información incorrecta ... tenía exactamente el mismo problema. El plugin no se activa dos veces y no puedo llegar a los fragmentos clave Bundle-localización.

Quiero que todos mis traducciones de idiomas en los plugin.properties (Sé que esto está mal visto pero es mucho más fácil de manejar un único archivo).

I (media) resolvió el problema utilizando

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

y simplemente llamar a mis fragmento de nombre de archivo de localización 'fragment.properties'.

Esto no es particularmente elegante, pero funciona.

Por cierto, para obtener archivos desde el fragmento que necesita el getResource, parece que los archivos de fragmentos están en la ruta de clase o sólo se buscan cuando se utiliza getResource.

Si alguien tiene un mejor enfoque, por favor, corríjanme.

Todo lo mejor,

Marcos.

Otros consejos

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

Cambiar el nombre de sus plugin.properties fragmento a otra cosa, por ejemplo. fragment.properties

en su fragmento de manifestar cambiar el Bundle-Localización: Plugin a Bundle-Localización: fragmento

Tu lector se activa dos veces, la primera vez que utiliza los plugin.properties, el segundo utilizando los fragment.properties.

activación Plugin es manejado por el OSGi tiempo de ejecución Equinox. Sin embargo, me gustaría desalentar fuertemente tratando de parchear los archivos allí para crear un comportamiento específico. La forma sugerida de Marcos parece un enfoque mucho más cuerdo a su problema.

Una forma es conectar un oyente paquete, y escuchar para instalaciones de paquetes (y quizás también mirar a los paquetes ya instalados) y para cada paquete de generar / proporcionar - e instalar - un fragmento con los archivos de propiedades deseadas. Si esto se hace antes de la aplicación se inicia, esto debería tener efecto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top