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

在 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 UIComponent.extend("webapp.Component", {	
			// 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" 
		xmlns:html="http://www.w3.org/1999/xhtml">
		
	<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" 
		xmlns:html="http://www.w3.org/1999/xhtml">
		
	<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" 
		xmlns:html="http://www.w3.org/1999/xhtml">
	<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() 获得当前语言。

  • jQuery.sap.resources(...) 根据指定的 URL 和 Locale,创建一个新的资源包实例(Creates and returns a new instance of jQuery.sap.util.ResourceBundle using the given URL and locale to determine what to load.)。

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

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

中文

当在英文环境中,显示:

英文

源代码

21_zui5_resource_model

参考

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值