您的当前位置:首页SAPUI5 (21) - 如何实现多语言

SAPUI5 (21) - 如何实现多语言

2024-12-14 来源:哗拓教育

在 SAPUI5 中,通过两种方法来实现多语言,一是 SAPUI5 提供 Resource Model,Resource Model 读取资源包 (Resource Bundle) 并与 View 中的控件绑定。第二种方法是使用 jQuery.sap.resources 相关的 API 读取资源包。两种方法都需要资源包文件并且在配置中设置。

先介绍两个知识点:语言代码和资源包文件。

语言代码

OpenUI5 对语言使用字符串标识,遵循 BCP-47 标准。比如 en 表示英语,en-US 表示美国英语。zh-Hans 表示中文简体,zh-Hant 表示中文繁体。

SAP ABAP 使用的是另外一套专门的编码,比如 ZH 表示中文简体,ZF 表示中文繁体。OpenUI5 能识别 ABAP 的编码并转换成 BCP-47 编码。

OpenUI5 对页面的显示,有一个 当前语言( Current Language ) 的概念,按照当前语言,读取相应的资源包文件,按当前语言显示。那么,当前语言如何确定呢?OpenUI5 按照如下顺序顺序(从高到低),如果都没有找到,最后读取通用设置(比如 i18n.properties)。

  1. URL中的 locale 参数(即在 url 后面加上 ?sap-ui-language=xx )
  2. 应用程序代码的 locale 设置,比如:
sap.ui.getCore().getConfiguration().applySettings({
    language: 'de',
    calendarType: sap.ui.core.CalendarType.Gregorian,
    formatSettings: {
        legacyDateFormat: '1',
        legacyTimeFormat: '1',
        legacyNumberFormat: '1'
    }
});
  1. Android 平台的用户代理字符串设置
  2. 浏览器的一般语言设置,可以用 window.navigator.language 查看
  3. 浏览器中用户语言配置。这个与浏览器相关,比如 IE 通过 window.navigator.userLanguage 查看。
  4. 浏览器语言配置。这个业余浏览器相关,比如 IE 通过 window.navigator.browserLanguage 查看
  5. OpenUI5中硬编码,默认为 en

资源包文件

资源包文件就是 Java 的属性文件( Properties 文件)。文件中包含与语言相关的文本。资源包文件的特征:

  1. 文件的扩展名总是 .properties
  2. 文件名包括固定部分和语言相关部分。比如在 OpenUI5 中,大家习惯将 Resource Bundle 的文件名叫做 i18n(来源于 internationalization 这个单词,取首位两个字母,中间字母数为18)。那么 i18n.properties 是默认的文件(如果没有其他文件,就用这个文件作为默认设置),i18n_zh_CN.properties 是中文简体的资源文件,依此类推。
  3. 资源包文件为扁平结构,不能嵌套。每一行要么是 key-value pair ,要么是 # 开头的注释。也可以可以空行。key-value pair 没有引号。后面有资源包文件的例子。
  4. 如果 Properties 文件的文本为 Unicode 字符,文件使用16进制的编码来存储,而不是明文。这样对开发人员来说,友好性较差。

Resource Model 及数据绑定

我们继续对前面显示供应商 Master-detail 的程序进行重构,增加程序多语言的功能。Eclipse 的项目文件结构如下:

使用 Resource Model 绑定数据需要三步:

  1. 添加资源包文件,将不同的语言放在不同的资源包文件中。本示例给出两个资源包文件:
  • i18n.properties(默认)
  • i18n_zh_CN.properties。(中文简体)

i18n.properties 文件的内容:

#-------------------------------------
# In master page
#-------------------------------------
# master page title
masterTitle=Supplier Overview

# Count of supplier
supplierCount=Supplier count
id=ID
name=Supplier Name

#-------------------------------------
# In detail page
#-------------------------------------

# detail page title
detailTitle=Supplier detail

i18n_zh_CN.properties:

#-------------------------------------
# In master page
#-------------------------------------
# master page title: Supplier Overview
masterTitle=\u4F9B\u5E94\u5546\u6982\u89C8

# Count of supplier
supplierCount=\u4F9B\u5E94\u5546\u6570\u91CF
id=ID
name=\u4F9B\u5E94\u5546\u540D\u79F0

#-------------------------------------
# In detail page
#-------------------------------------

# detail page title: Supplier Detail
detailTitle=\u4F9B\u5E94\u5546\u660E\u7EC6
  1. 在 Component.js 文件中,创建 Resource model 的实例 。Component.js 的完整代码如下:
sap.ui.define([
        "sap/ui/core/UIComponent",
        "sap/ui/model/json/JSONModel",
        "sap/ui/model/resource/ResourceModel"
    ], 
        
    function(UIComponent, JSONModel, ResourceModel){
        return  { 
            // meta-data
            metadata: {
                "rootView": "webapp.view.App",
                "config": {
                    "serviceUrl": "service/data.json",
                    "i18nBundle": "webapp.i18n.i18n"
                }
            },
            
            // initialization
            init: function(){               
                UIComponent.prototype.init.apply(this, arguments);
                
                var mConfig = this.getMetadata().getConfig();
                
                // resource bundle
                var oResourceModel = new ResourceModel({
                    bundleName: mConfig.i18nBundle
                });
                this.setModel(oResourceModel, "i18n");              

                // application data
                var oModel = new JSONModel(mConfig.serviceUrl);
                this.setModel(oModel);
            },
            
            createContent: function() {                 
                // root view
                var oRootView = UIComponent.prototype.createContent.apply(this, arguments);
                oApp = oRootView.byId("app");
                
                return oRootView;               
            }
        });
    }
);

和前一篇的代码相比,代码有如下变更:

  • 添加对 sap.ui.model.resource.ResourceModel 的依赖:
sap.ui.define([
        "sap/ui/core/UIComponent",
        "sap/ui/model/json/JSONModel",
        "sap/ui/model/resource/ResourceModel"
    ], ...
  • 在 metadata 配置中,指定 i18n 文件的位置为 app root->webapp->i18n 。最后一个 i18n 表示文件名。文件的扩展名总是 .properties。
metadata: {
    "rootView": "webapp.view.App",
    "config": {
        "serviceUrl": "service/data.json",
        "i18nBundle": "webapp.i18n.i18n"
    }        
  • 实例化 Resource Model
// initialization
init: function(){               
    UIComponent.prototype.init.apply(this, arguments);
    
    var mConfig = this.getMetadata().getConfig();
    
    // resource bundle
    var oResourceModel = new ResourceModel({
        bundleName: mConfig.i18nBundle
    });
    this.setModel(oResourceModel, "i18n");              

    // application data
    var oModel = new JSONModel(mConfig.serviceUrl);
    this.setModel(oModel);
},

读取配置 config->i18nBundle ,然后使用 setModel() 方法,设置 Component 的 Model 为 ResourceModel ,并且将其命名为i18n。

3)在 View 中参照 Resource Model 中定义的 key。以 Master View 为例:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
        controllerName="webapp.controller.Master" 
        
        
    <Page title="{i18n>masterTitle}">
        <content>
            <Table items="{/Suppliers}">
            
                <headerToolbar>
                    <Toolbar>
                        <Label text="{i18n>supplierCount}: {/CountOfSuppliers}" />
                    </Toolbar>
                </headerToolbar>
                
                <columns>
                    <Column>
                        <header><Text text="{i18n>id}" /> </header>
                    </Column>
                    <Column>
                        <header><Text text="{i18n>name}" /> </header>
                    </Column>
                </columns>
                
                <items>
                    <ColumnListItem type="Navigation" press="onListPress">
                        <cells>
                            <ObjectIdentifier text="{ID}" />
                            <ObjectIdentifier text="{Name}" />
                        </cells>
                    </ColumnListItem>
                </items>
                
            </Table>
        </content>
        
        <footer>
            <Toolbar>
                <Button text="language information" press="onBtnPress"/>
            </Toolbar>
        </footer>
    </Page>
    
</core:View>

Master页面标题,之前是硬编码,现在变为:Page title="{i18n>masterTitle}"。其它的控件,属性设置相同。

detail view(Detail.view.xml)

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m"
        controllerName="webapp.controller.Detail" 
        
        
    <Page title="{i18n>detailTitle}" showNavButton="true" navButtonPress="onNavPress">
        <content>
            <ObjectHeader title="{Name}" number="ID: {ID}">
                <ObjectAttribute text="{Address/Street}, {Address/City}"/>
            </ObjectHeader>
        </content>
    </Page>
    
</core:View>

启动程序,界面和上篇相同。但我们可在 url 后面添加?sap-ui-language=XXX,实现语言的切换。比如:?sap-ui-language=en切换为英语:

简体中文 英语

使用 jQuery.sap.resources

如果要在代码中直接使用资源包的文本,OpenUI5 提供了 jQuery.sap.resources 方法。比如我们需要在页面中根据不同的语言,显示不同的提示消息。接下来我们在 Master View 中添加一个按钮( sap.m.Button ),当点击的时候读取资源包文件的 msgCurrLanguage ,然后 alert 这个消息给用户。

  1. 先在 i18n.properties 文件中添加 key-value:
msgCurrLanguage=Current Language is {0}

在 i18n_zh_CN.properties 中添加 msgCurrLanguage 的中文显示:

msgCurrLanguage=\u5F53\u524D\u8BED\u8A00\u662F {0}
  1. 在 Master view 的 Page 中添加 Button
<footer>
    <Toolbar>
        <Button text="{i18n>languageTitle}" press="onLanButtonPress" />
    </Toolbar>
</footer>

Master View 的完整代码:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" 
           xmlns="sap.m"
        controllerName="webapp.controller.Master" 
        
    <Page id="master" title="{i18n>masterTitle}">
        <content>
            <Table class="sapUiResponsiveMargin" width="auto" items="{/Suppliers}">
                
       <!--  Table的细节省略,请参考之前代码--> 
                
            </Table>            
        </content>
        
        <footer>
            <Toolbar>
                <Button text="{i18n>languageTitle}" press="onLanButtonPress" />
            </Toolbar>
        </footer>
    </Page>
</core:View>

3)在 Master controller 中添加 event handler: onLanButtonPress:

onLanButtonPress: function(oEvent){
    // 添加依赖包
    jQuery.sap.require("jquery.sap.resources");
    
    var sLocale = sap.ui.getCore().getConfiguration().getLanguage();
    var oBundle = jQuery.sap.resources({
        url: "i18n/i18n.properties",
        locale: sLocale
    })
    
    var sMessage = oBundle.getText("msgCurrLanguage", [sLocale]);
    alert(oBundle.getText("msgCurrLanguage", [sLocale]));
}

代码说明:

  • sap.ui.getCore().getConfiguration().getLanguage() 获得当前语言。

  • getText() 根据资源包文件的 key,获取与语言相关的 value。

界面效果(Edge 浏览器),当在中文环境中,显示:

中文

当在英文环境中,显示:

英文

源代码

参考

显示全文