문제

내 프로젝트에는 여러 플러그인이 포함되어 있으며 모든 플러그인에는 플러그인이 포함되어 있습니다. manifest.mf 파일 외부 플러그인 문자열이 저장된 속성 파일의 이름을 정의합니다.

Bundle-Localization: plugin

내가 정의하는 플러그인의 이름

%plugin.name

Eclipse는 런타임에 Plugin.Properties 파일에서 "%plugin.name"을 검색합니다.

어떤 클래스가 매니페스트를 읽었는지 MF 번들 로컬 화 항목을 읽고 시작 '%'접미사가 "플러그인 .properties"파일에서 검색되는 문자열은 어느 시점입니까?

이 클래스를 찾아 패치하고 싶습니다. 먼저 "%plugin.name"식별자에 대한 다른 디렉토리/파일을 살펴볼 수 있습니다. 이 새로운 메커니즘을 사용하면 제품에 조각을 추가하고 원래 플러그인을 변경하지 않고 "플러그인 .properties"파일로 단일 라인을 덮어 쓸 수 있습니다. 이러한 메커니즘을 사용하여 다른 조각을 추가하여 여러 고객을위한 빌드 프로세스를 만들 수 있습니다. 고객 이름과 변경하려는 특수 문자열을 포함한 조각.

조각 메커니즘은 원래 플러그인에 파일 만 추가하기 때문에 그렇게하고 싶습니다. 플러그인에 "plugin.properties"파일이 존재하는 경우 조각 "플러그인 .properties"파일이 무시됩니다.

UPDATE 1:

방법

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

주어진 로케일 문자열에 대한 속성 파일의 ResourceBundle을 반환합니다. 누군가가 이제 내가 어떻게 먼저 조각을 조사하여 자원 경로를 얻을 수있는 방법을 게시 할 수있는 방법을 게시하십시오.

UPDATE 2:

클래스 증상의 방법

    private URL findInResolved(String filePath, AbstractBundle bundleHost) {

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

속성 파일을 검색하고 캐시합니다. 번역은 캐시 된 파일에서 얻을 수 있습니다. 문제는 전체 파일이 캐시되고 단일 번역이 아니라는 것입니다.

솔루션은 먼저 번들 파일을 읽는 것보다 Fragment 파일을 읽는 것입니다. 두 파일이 모두 존재하면 하나의 파일로 병합되어 새 속성 파일을 디스크에 씁니다. 새 속성 파일의 URL이 반환되므로 새 Proptries 파일이 캐시 될 수 있습니다.

도움이 되었습니까?

해결책

정보가 잘못되었지만 ... 정확히 같은 문제가있었습니다. 플러그인은 두 번 활성화되지 않았으며 Fragments 번들 로컬 화 키에 도달 할 수 없습니다.

플러그인의 모든 언어 번역을 원합니다.

나는 (절반)을 사용하여 문제를 해결했습니다

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

내 조각 현지화 파일 이름을 'Fragment.Properties'로 호출하십시오.

이것은 특히 우아하지는 않지만 작동합니다.

그건 그렇고, 조각에서 파일을 가져 오려면 getResource가 필요합니다. 조각 파일이 클래스 경로에 있거나 getResource를 사용할 때만 검색되는 것 같습니다.

누군가가 더 나은 접근 방식을 가지고 있다면 저를 수정하십시오.

모두 제일 좋다,

표시.

다른 팁

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

조각 플러그인의 이름을 다른 것으로 변경하십시오. Fragment.properties

파편 매니페스트에서 번들로 국소화 : 플러그인으로 플러그인을 번들로 국소화 : 파편

플러그인 .properties를 사용하여 처음으로 플러그인이 두 번 활성화되고 두 번째는 Fragment.Properties를 사용합니다.

플러그인 활성화는 OSGI 런타임 Equinox에 의해 처리됩니다. 그러나 특정 동작을 만들기 위해 파일을 패치하려고 시도하지 않을 것입니다. Mark의 제안 된 방법은 문제에 대한 훨씬 더 세심한 접근 방식으로 보입니다.

한 가지 방법은 번들 리스너를 부착하고 번들 설치 (그리고 이미 설치된 번들을 살펴 보는 것)와 각 번들에 대해 원하는 속성 파일이있는 조각을 생성하고 설치하는 것입니다. 응용 프로그램이 시작되기 전에이 작업이 완료되면 효과가 있어야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top