Как я могу интернационализировать приложение OSGi, используя Eclipse? - PullRequest
3 голосов
/ 02 мая 2019

Я пытаюсь интернационализировать приложение OSGi , используя "путь OSGi", но у меня не было прогресса.Под OSGi я имею в виду, используя возможности, которые предоставляет фреймворк.Ранее я интернационализировал Java-приложения, но я хотел бы знать, как сделать это как OSGi приложение.

Я создал эту простую демонстрационную версию [GitHub repo] , целью которого является создание пакета, который будет регистрировать сообщение после его активации и другое сообщение после его деактивации.

Структура проекта:

src
   |- org.example.i18n
                     |- SimpleLoggingComponent   // where the actual strings are
                     |- SimpleLogService
                     |- SimpleLogServiceImpl
META-INF
   |- MANIFEST.MF
OSGI-INF
   |- org.example.i18n.SimpleLoggingComponent
   |- org.example.i18n.SimpleLogServiceImpl
build.properties

SimpleLoggingComponent источник

@Component
public class SimpleLoggingComponent {

    private SimpleLogService simpleLogService;

    @Reference
    public void bindLogger(SimpleLogService logService) {
        this.simpleLogService = logService;
    }

    public void unbindLogger(SimpleLogService logService) {
        this.simpleLogService = null;
    }

    @Activate
    public void activate() {
        if (simpleLogService != null) {
            simpleLogService.log("Yee ha, I'm logging!"); // <-- need this message internationalized
        }
    }

    @Deactivate
    public void deactivate() {
        if (simpleLogService != null) {
            simpleLogService.log("Done, I'm finishing logging!"); // <-- need this message internationalized
        }
    }
}

На данный момент строки зафиксированы в коде, и яЯ хотел бы иметь возможность интернационализировать их.Допустим, поддерживаются английский и испанский языки.

Позже я планирую добавить поддержку большего количества языков с помощью Fragment Bundles , поэтому решение должно быть готово к расширению этимзначит.


Я прочитал все это, но я не нашел ничего последовательного, что помогло бы мне.

Кроме того, ни Архив учебников по OSGi Alliance , ни OSGi enRoute ничего не содержат.

Среда:

PS: IЯ уверен, что это не сложная задача, просто я не нашел никакой полезной (для меня) документации об этом.

1 Ответ

1 голос
/ 04 мая 2019

Теоретические знания

Локализация 1

Связанные записи локализации имеют общее базовое имя.Чтобы найти потенциальную запись локализации, добавляется нижнее подчеркивание ('_' \ u005F) плюс несколько суффиксов, разделенных другим подчеркиванием и, наконец, с добавлением суффикса .properties.Суффиксы определены в java.util.Locale.Порядок суффиксов должен быть следующим:

  • язык

  • страна

  • вариант

Например, следующие файлы предоставляют переводы манифеста для английского, голландского (Бельгия и Нидерланды) и шведского языков.

OSGI-INF/l10n/bundle_en.properties
OSGI-INF/l10n/bundle_nl_BE.properties
OSGI-INF/l10n/bundle_nl_NL.properties
OSGI-INF/l10n/bundle_sv.properties

Локализация манифеста 2

Локализованные значения хранятся в ресурсах свойств в комплекте.Базовое имя по умолчанию для файлов свойств локализации пакета - OSGI-INF/l10n/bundle.Заголовок манифеста Bundle-Localization может использоваться для переопределения базового имени по умолчанию для файлов локализации.Это расположение относительно корня пакета и фрагментов пакета.

Запись локализации содержит записи ключа / значения для локализованной информации.Все заголовки в манифесте пакета могут быть локализованы.Однако Framework всегда должен использовать нелокализованные версии заголовков с семантикой Framework.

Ключ локализации можно указать в качестве значения заголовка манифеста пакета, используя следующий синтаксис:

header-value ::= '%'text
text ::= < any value which is both a valid manifest headervalue
   and a valid property key name >

Например, рассмотрим следующие записи манифеста пакета:

Bundle-Name: %acme bundle
Bundle-Vendor: %acme corporation
Bundle-Description: %acme description
Bundle-Activator: com.acme.bundle.Activator
Acme-Defined-Header: %acme special header

Пользовательские заголовки также могут быть локализованы.Пробелы в ключах локализации явно разрешены.

Записи манифеста предыдущего примера могут быть локализованы с помощью следующих записей в записи локализации манифеста OSGI-INF/l10n/bundle.properties.

# bundle.properties
acme\ bundle=The ACME Bundle
acme\ corporation=The ACME Corporation
acme\ description=The ACME Bundle provides all of the ACME\ services
acme\ special\ header=user-defined Acme Data

На практике

1. Сначала давайте создадим файлы комплекта, которые будут содержать пары ключ / значение.В этом случае один для английского языка (bundle.properties), который будет по умолчанию, и один для испанского языка (bundle_es.properties)

...
OSGI-INF
   |- l10n
        |- bundle.properties
        |- bunlde_es.properties
   |- ...

..., который будет содержать наши ранее жестко закодированные строковые значения.

#bundle.properties
startMessage = Yeah ha, I'm logging!
endMessage = Done, I'm finishing logging!

#bundle_es.properties
startMessage = Si, Estoy registrando logs!
endMessage = Terminado, He concluido de registrar logs!

2. Теперь давайте создадим служебный компонент, который поможет нам получить значения, связанные с каждым ключом в соответствии с локалью.

src
   ...
   |- org.example.i18n.messages
                              |- MessageProvider
                              |- MessagesProviderImpl
   ...

Существует два файла: интерфейс и фактическая реализация, которая содержит логику для получения пар ключ / значение.

public interface MessageProvider {
    String get(String key);
}

@Component
public class MessagesProviderImpl implements MessageProvider {
    private BundleLocalization bundleLocalization;
    private LocaleProvider localeProvider;
    private ResourceBundle resourceBundle;

    @Reference
    public void bindBundleLocalization(BundleLocalization bundleLocalization) {
        this.bundleLocalization = bundleLocalization;
    }

    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
    public void bindLocaleProvider(LocaleProvider localeProvider) {
        this.localeProvider = localeProvider;
        setResourceBundle()
    }

    /*unbind methods omitted*/

    @Activate
    public void activate() {
        setResourceBundle();
    }

    @Override
    public String get(String key) {
        return resourceBundle.getString(key);
    }

    private String getLocale() {
        return localeProvider != null ? localeProvider.getLocale().toString() : Locale.getDefault().toString();
    }

    private void setResourceBundle() {
        resourceBundle = bundleLocalization.getLocalization(FrameworkUtil.getBundle(getClass()), getLocale());
    }
}

3. Использование компонента MessageProviderв SimpleLoggingComponent.

@Component
public class SimpleLoggingComponent {

    /*previously code omitted for brevity*/

    private MessageProvider messages;

    @Reference
    public void bindMessageProvider(MessageProvider messageProvider) {
        messages = messageProvider;
    }

    /*unbind methods omitted*/

    @Activate
    public void activate() {
        simpleLogService.log(messages.get("startMessage")); // <- use now the key: startMessage
    }

    @Deactivate
    public void deactivate() {
        simpleLogService.log(messages.get("endMessage")); // <- use now the key: endMessage
    }
}

Запуск приложения с пользовательским языком

На вкладке Аргументы используйте для этого параметр времени выполнения -nl, например, -nl en

image-nl en">


Ссылки

Полный исходный код

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...