airbnb / polyglot.js

Give your JavaScript the ability to speak many languages.
http://airbnb.github.io/polyglot.js
BSD 2-Clause "Simplified" License
3.71k stars 208 forks source link

Allow default message to be a function #98

Closed tkvw closed 6 years ago

tkvw commented 6 years ago

It would be nice to allow the default message to be a function, so I can use:

t('very_specific_error',{
  _: (t)=> t('more_generic_error',{
    _:(t)=> t('error')
 }
}

First of all, this allows lazy initialization of default messages. Secondly it allows me to use default messages from a side effect which passes the message down to a ui component with knowledge of the locale and polyglot instance

ljharb commented 6 years ago
t('very_specific_error',{
  _: {
    toString() {
      return t('more_generic_error', {
        _: 'error',
      };
    }),
  },
});

?

tkvw commented 6 years ago

I realize the example is probably not the best one I could have picked, consider this:

Promise.reject({
    message: 'very_specific_error',
    messageArgs: {
        _: (t)=> t('more_generic_error',{
             _:(t)=> t('error')
        }
    }
})

The side effect does not have access to t, but rejects with an error message descriptor which is interpreted by polyglot. Now I need to make a middleware for this.

ljharb commented 6 years ago

I’m not sure what the benefit of the function is there tho - polyglot would still invoke the function immediately, so you’d not be effectively deferring any execution.

tkvw commented 6 years ago

I solved this by using the onMissingKey function.

    const polyglot = new Polyglot({
        locale,
        phrases,
        onMissingKey: function(key, options) {
            if (typeof options['__'] === 'function') {
                return options['__'](this.t);
            } else {
                this.warn('Missing translation for key: "' + key + '"');
                return key;
            }
        },
    });
    polyglot.onMissingKey = polyglot.onMissingKey.bind(polyglot);
    polyglot.t = polyglot.t.bind(polyglot);

Thanks for your help!