Теоретические знания
Локализация 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
-nl en">
Ссылки
Полный исходный код