为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 Eclipse 国际化 OSGi 应用程序?

如何使用 Eclipse 国际化 OSGi 应用程序?

皈依舞 2022-11-02 16:50:39
我正在尝试使用“OSGi 方式”将 OSGi 应用程序国际化,但我没有取得进展。通过OSGi 的方式,我的意思是,使用框架为其提供的功能。我之前已经将 Java 应用程序国际化,但我想知道如何将其作为OSGi应用程序来实现。我创建了这个简单的演示[GitHub repo],它旨在创建一个捆绑包,一旦它被激活就会记录一条消息,一旦它被停用就会记录另一条消息。项目结构:src   |- org.example.i18n                     |- SimpleLoggingComponent   // where the actual strings are                     |- SimpleLogService                     |- SimpleLogServiceImplMETA-INF   |- MANIFEST.MFOSGI-INF   |- org.example.i18n.SimpleLoggingComponent   |- org.example.i18n.SimpleLogServiceImplbuild.propertiesSimpleLoggingComponent源码@Componentpublic 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添加对更多语言的支持,因此该解决方案应该可以通过这种方式进行扩展。
查看完整描述

1 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

理论知识

本地化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清单标头可用于覆盖本地化文件的默认基本名称。此位置相对于捆绑包和捆绑包片段的根。

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

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


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

    }

}

使用自定义语言启动应用程序

在 Arguments 选项卡上-nl,为此目的使用 runtime 参数,例如-nl en

//img1.sycdn.imooc.com//63622f990001b4fd11880280.jpg

查看完整回答
反对 回复 2022-11-02
  • 1 回答
  • 0 关注
  • 174 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号