【问题标题】:How do I internationalize an OSGi application using Eclipse?如何使用 Eclipse 国际化 OSGi 应用程序?
【发布时间】:2019-09-20 19:41:09
【问题描述】:

我正在尝试使用“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 source

@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 Tutorial ArchiveOSGi enRoute 均不包含任何相关内容。

环境:

PS:我确信这不是一项复杂的任务,只是我没有找到任何有用的(对我而言)有关它的文档。

【问题讨论】:

    标签: java eclipse localization internationalization osgi


    【解决方案1】:

    理论知识

    本地化1

    Bundle 本地化条目共享一个通用的基本名称。为了找到一个潜在的本地化条目,添加一个下划线 ('_' \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/bundleBundle-Localization 清单标头可用于覆盖本地化文件的默认基本名称。这个位置是相对于 bundle 和 bundle 片段的根目录的。

    本地化条目包含本地化信息的键/值条目。捆绑包清单中的所有标头都可以本地化。但是,框架必须始终使用具有框架语义的标头的非本地化版本。

    可以使用以下语法将本地化键指定为包的清单标头的值:

    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.SimpleLoggingComponent中使用MessageProvider组件。

    @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


    参考文献

    完整源代码

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-24
      相关资源
      最近更新 更多