【问题标题】:MessageFormat in javascript (parameters in localized UI strings)javascript 中的 MessageFormat(本地化 UI 字符串中的参数)
【发布时间】:2010-11-24 02:46:29
【问题描述】:

在javascript中处理本地化字符串中的参数的好方法是什么? 我使用与 java 的 MessageFormat 类中相同的格式,例如:

There are {0} apples in basket ID {1}.

其中{0} 将替换为第一个参数,{1} 将替换为第二个参数。

这是我想在 JS 中使用的调用(即我想实现origStr):

var str = replaceParams(origStr, [5, 'AAA']);

我猜最好的策略是使用正则表达式。如果是这样,请提供一个好的正则表达式。但我愿意听取任何其他选择。

【问题讨论】:

  • 可见 JS 有多不成熟 :(

标签: javascript regex internationalization


【解决方案1】:
String.prototype.format = function() {
    var args = arguments;

    return this.replace(/\{(\d+)\}/g, function() {
        return args[arguments[1]];
    });
};

// Returns '2 + -1 = 1'.
'{0} + {1} = {2}'.format(2, -1, 1);

或满足您的要求:

function replaceParams(string, replacements) {
    return string.replace(/\{(\d+)\}/g, function() {
        return replacements[arguments[1]];
    });

    // Or, if prototype code above...
    String.format.apply(string, replacements);
}

您可以添加花哨的 i18n 功能,例如 ordinal-i-fying(不管它叫什么):

// Not well tested.

i18n.en.filters = {
    ordinal: function(n) {
        // FIXME Doesn't handle all cases.
        switch(('' + n).substr(-1)) {
            case '1':
                return '' + n + 'st';
            case '2':
                return '' + n + 'nd';
            case '3':
                return '' + n + 'rd';
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            case '0':
                return '' + n + 'th';
            default:
                return n; // Just in case...
        }

    },
    plural: function(n, singular, plural) {
        if(n == 1) {
            return singular;
        } else {
            return plural;
        }
    }
};

i18n.current = i18n.en;

String.prototype.format = function() {
    var args = arguments;

    return this.replace(/\{((\d+)((\|\w+(:\w+)*)*))\}/g, function() {
        var arg = args[arguments[2]],
            filters = arguments[3].split('|'),
            i, curFilter, curFilterArgs, curFilterFunc;

        for(i = 0; i < filters.length; ++i) {
            curFilterArgs = filters[i].split(':');
            curFilter = curFilterArgs.shift();
            curFilterFunc = i18n.current.filters[curFilter];

            if(typeof curFilterFunc === 'function') {
                arg = curFilterFunc.apply(null, [ arg ].concat(curFilterArgs));
            }
        }

        return arg;
    });
};

'You have {0} {0|plural:cow:cows} but I have {1} {1|plural:cow:cows}.'.format(2,1);
'My horse came in {0|ordinal} place while yours came in {1|ordinal}.'.format(42,1);

【讨论】:

    【解决方案2】:

    看起来我只晚了大约 3 年,但万一有人仍然需要一个真正的独立 MessageFormat 库用于 JS:

    https://github.com/SlexAxton/messageformat.js

    你去吧!编译为 JS - 所以速度非常快,并且支持 SelectFormatPluralFormat

    注意:这是 ICU MessageFormat,与您的语言中可能内置的内容略有不同(阅读:更好)。

    【讨论】:

    • 得说,这与我的预期有些不同。我们在 Java 中使用 ICU MessageFormat,它看起来更像 {0,plural, zero{no results} one{1 result} other{{0} results}}。而这个看起来像 {RES, 复数, =0{no results} one{1 result} other{# results} } - 除了表面上使用相同的 CLDR 关键字来表示 one/other/etc。对我来说,这似乎是一种完全不同的格式。
    • MessageFormat.js 和 MessageFormat.java 只是碰巧共享名称。语法完全不同。
    • 它们是相同的格式,实际上大部分是相互兼容的。 @Trejkaz 提到的两个示例仅在使用的关键字方面有所不同。 =0 是文字值,其中 zero 是关键字(不适用于 en-US)。
    • “不适用”,但据我们所知完全可以正常工作,并且在谈论“无事”时有助于区分信息。
    【解决方案3】:

    @strager 的回答对我来说并没有真正起作用,但经过一些调整,我得到了它正是我想要的(这与 @Omesh 的目标非常相似)。

    String.prototype.format = function() {
        var args = arguments;
    
        return this.replace(/\{(\d+)\}/g, function(a) {
            return args[0][parseInt(a.match(/(\d+)/g))];
        });
    };
    

    注意args数组的索引值不同。

    应该像@strager 建议的那样调用它:

    'I like {0} and {1} but not {2}'.format('apples', 'oranges', 'kiwi');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 2023-03-17
      • 2010-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多