Подтвердить что ты не робот

MessageFormat в javascript (параметры в локализованных строках пользовательского интерфейса)

Что такое хороший способ обработки параметров в локализованных строках в javascript? Я использую тот же формат, что и в java MessageFormat, например:

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

Где {0} будет заменено первым параметром, а {1} - вторым.

Это вызов, который я хочу использовать в JS (т.е. я хочу реализовать origStr):

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

Я предполагаю, что лучшей стратегией будет использование регулярного выражения. Если да, пожалуйста, предложите хорошее регулярное выражение. Но я открыт для прослушивания любых других вариантов.

4b9b3361

Ответ 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, такие как ординал-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 - так что она может быть очень быстрой и поддерживает SelectFormat и PluralFormat.

Примечание. Это ICU MessageFormat, который немного отличается (читайте: лучше), чем материал, который может быть встроен в ваш язык.

Ответ 3

Вы можете использовать L10ns. Он использует ICU MessageFormat.

There are {apples} apples in basket ID {baskedId}.

Вы также можете определить его с помощью PluralFormat. Чтобы получить форму множественного числа прямо для Apple.

There are {apples, plural, one{# apple} other{# apples}} apples in basket ID {baskedId}.

В приведенном выше утверждении CLDR определяет множественную форму one и other. Более подробную информацию можно найти в их документации.

Ответ 4

Ответ @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');