在XML视图中向i18n模型传递参数

7
我们如何在XML视图内向i18n模型传递参数?
没有参数。
<Label text="{i18n>myKey}"/>

这个代码可以工作,但我们如何在表达式中传递参数呢?

到目前为止,我找到的唯一信息是http://scn.sap.com/thread/3586754。我真的希望这不是正确的方法,因为这看起来更像是一个(丑陋的)hack。


1
当前被接受的解决方案使用了已弃用的jQuery函数。有关当前最佳实践,请参见https://dev59.com/irPma4cB1Zd3GeqPlR6o#55587775。 - Boghyon Hoffmann
这个回答解决了你的问题吗?如何在XML视图中使用i18n模型和参数与“formatMessage”模块 - Boghyon Hoffmann
6个回答

13

关键是要像这样使用格式化程序jQuery.sap.formatMessage

<Label text="{parts:['i18n>myKey', 'someModel>/someProperty'], 
                    formatter: 'jQuery.sap.formatMessage'}"/>

这将从模型someModel中取出值为/someProperty的内容,并将其放入i18n资源包的myKey中。

编辑 2020-05-19: jQuery.sap.formatMessage已于UI5版本1.58中弃用,请使用sap/base/strings/formatMessage。有关用法说明,请参见此答案


在“正常”绑定中运行得很好。 :) 在表达式绑定中对我不起作用。 如果能够传递静态参数而不是另一个绑定,比如“someModel>/someBinding”,那就太好了。 - Tim Malich
1
@TimMalich 在UI5 1.61+中,现在可以将静态值传递给格式化程序。请参见https://dev59.com/mpffa4cB1Zd3GeqP4jQQ#53609552。 - Boghyon Hoffmann

4

目前这是不可能的。但是你可以使用这个简单的解决方法,对我有效。

准备工作

首先,在我们的 Component.js 中创建一个通用的 i18n 处理程序。我们还创建了一个 JSONModel,进行简单修改,以便立即返回请求的路径。

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/model/json/JSONModel"
], function(UIComponent, JSONModel) {
    "use strict";

    return UIComponent.extend("your namespace", {
        /**
         * Add a simple "StringReturnModel" to the components' models
         */
        init: function() {
            // [...] your other code in the init method

            // String Return Model
            var stringModel = new JSONModel({});
            stringModel.getProperty = function(sPath) {
                return sPath;
            };
            this.setModel(stringModel, "string");
        },

        /**
         * Reads out a string from our text domain.
         * The model i18n is defined in your manifest.json
         *
         * @param param text parameter
         * @param arr array for parameters
         * @return string
         */
        i18n: function(param, arr) {
            var oBundle = this.getModel("i18n").getResourceBundle();
            return oBundle.getText(param, arr);
        },
    });
});

现在,已经存在一个带有上下文{string>}的模型。要在XML视图中使用i18n函数,我们需要创建一个格式化函数。该函数解析绑定的部分并返回本地化字符串。

sap.ui.define([
], function() {
    "use strict";

    var formatter = {
        /**
         * First argument must be the property key. The other
         * one are the parameters. If there are no parameters, the
         * function returns an empty string.
         * 
         * @return string The localized text
         */
        i18n: function() {
            var args = [].slice.call(arguments);
            if (args.length > 1) {
                var key = args.shift();
                // Get the component and execute the i18n function
                return this.getOwnerComponent().i18n(key, args);
            }
            return "";
        }
    };
    return formatter;
});

使用方法:

与字符串模型一起,您可以使用格式化程序将参数传递给您的i18n:

<Text text="{ parts: ['string>yourProperty', 'string/yourFirstParamter', 'anotherModel/yourSecondParamter'], formatter: '.model.formatter.i18n' }" />

你可以传递任意数量的参数,但是请确保第一个“部分”是属性键。


2
链接中的内容对于复杂格式的情况是正确的。 但是,如果您想要将两个字符串组合在一起,只需编写即可。
<Label text="{i18n>myKey} Whatever"/> 
or
<Label text="{i18n>myKey1} {i18n>myKey2}"/>

2
将可翻译的文本进行拼接并不是一个好主意。在不同的语言中,不同的文本部分的位置可能完全不同。 - user2808624
这种方式对我不起作用:<Text text="5 {i18n>hours}"/>渲染为"5 {i18n>hours}"。 - z00bs
2
@z00bs: 在你的引导脚本(index.html中)中,你需要添加data-sap-ui-xx-bindingSyntax="complex"。 - user2808624

2

create file formatter.js

   sap.ui.define([
        "sap/base/strings/formatMessage"
    ], function (formatMessage) {
        "use strict";

        return {
            formatMessage: formatMessage
        };
    });

View

<headerContent>
            <m:MessageStrip
                text="{
                    parts: [
                        'i18n>systemSettingsLastLoginTitle',
                        'view>/currentUser',
                        'view>/lastLogin'
                    ],
                    formatter: '.formatter.formatMessage'
                }"
                type="Information"
                showIcon="true">
            </m:MessageStrip>
        </headerContent>

控制器

var oBundle = this.getModel("i18n").getResourceBundle();

MessageToast.show(this.formatter.formatMessage(oBundle.getText("systemSettingsLastLoginTitle"), "sInfo1", "sInfo2"));

i18n

systemSettingsLastLoginTitle=You are logged in as: {0}\nLast Login: {1}

1
As ugly as it may seem, the answer given in the link that you mentioned is the way to go. However it may seem complicated(read ugly), so let's break it down..
因此,您可以使用以下内容来传递单个参数,
<Label text="{path: 'someParameter', formatter: '.myOwnFormatter'}"/>
这里,“someParameter”是绑定到整个页面/控件的OData模型属性的绑定,因为在实际情况下,您不会绑定“硬编码”值。但它确实以此结束,因为您会发现没有地方放置您的i18n文本。这在controller.js中得到处理。
在您的控制器中,添加一个与格式化程序名称相同的控制器方法,

myOwnFormatter : function(someParameter) { /* 在此函数中接收'someParameter' */ var i18n = this.i18nModel; /* 你可以在这里访问i18n模型 */ var sCompleteText = someParameter + " " + i18n.getText("myKey") /* 根据需要拼接字符串 */ }

对于传递多个参数,请使用:

<Label text="{parts:[{path : 'parameter1'}, {path :'parameter2'}], formatter : '.myOwnFormatter'}" />

在你的控制器中,接收这些参数:

myOwnFormatter : function(parameter1, parameter2) { } /* 以此类推.. */

完成后,标签的文本将显示带有参数和i18n文本。


0
原则上,它与上述 SCN-Link 中所描述的完全相同。您需要将绑定绑定到资源包的关键字,以及用于进入相应文本参数的值的其他绑定。最后,这些绑定找到的所有值必须以某种方式组合起来,因此您需要指定格式化程序。
可以通过省略绑定数组内部的路径前缀来稍微缩短它。使用 SCN 中的示例,也可以按以下方式工作:
<Text text="{parts: ['i18n>PEC_to',
       'promoprocsteps>RetailPromotionSalesFromDate_E',
       'promoprocsteps>RetailPromotionSalesToDate_E'}], 
        formatter: 'retail.promn.promotioncockpit.utils.Formatter.formatDatesString'}"/>

假设您正在使用{0}、{1}等作为占位符,格式化函数可能如下所示(没有任何错误处理和日期的特殊处理,这在SCN示例中可能是必要的):

formatTextWithParams : function(textWithPlaceholders, any_placeholders /*Just as marker*/) {
    var finalText = textWithPlaceholders;
    for (var i = 1; i < arguments.length; i++) {
        var argument = arguments[i];
        var placeholder = '{' + (i - 1) + '}';
        finalText = finalText.replace(placeholder, arguments[i]);
    }
    return finalText;
},

1
谢谢您的回答,但正如问题所述,我不想要过于复杂的解决方案。如果开发人员最终开始使用这样的“功能”,则需要将其很好地包含在框架中。这是我的观点。 - z00bs
我有点同意。但是我想指出的是,你至少要指定文本和参数之间的绑定关系。这不能被任何框架猜测。因此,“多余”的部分主要是格式化程序的定义。但即使它是ResourceModel的内置函数,你也需要一些特殊的语法来将值传递到模型中。 - user2808624

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接