String formatting for Dates etc #774

Closed
LodewijkSioen opened this Issue Jul 8, 2016 · 11 comments

Projects

None yet

2 participants

@LodewijkSioen

Given the following:

{
  "en": {
    "translation": {
      "test": "hello, it is now {{date}}"
    }
  }
}

This code will:

i18next.t('test',  { date: new Date()  });

produce hello, it is now Fri Jul 08 2016 16:39:38 GMT+0200 (Romance (standaardtijd)).

However, we would like to format our dates in a more user-friendly way. I've browsed the source, but I could not find a hook to do such a thing. How would I go around doing this?

@jamuhl
Member
jamuhl commented Jul 8, 2016

you will need to pass in already formatted time (using moment.js or equal)....we might use Intl API in future to fill this https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl

@LodewijkSioen

That's what we thought. The Intl API doesn't look like it would solve our requirements, though. We now transform our objects to stringyfied versions before passing them in i18next.

Can I make a suggestion as an alternative to the Intl API? How about this as resource:

"test": "hello, it is now {{date, dd/MM/yyyy}}"

and have an extension point where a function can be plugged in like this (pseudocode):

function(value, formatting){
    if(value instanceof Date){
        return moment(value).format(formatting);
    }
    return value.toString();
}
@jamuhl
Member
jamuhl commented Jul 9, 2016

honestly....let me think....loving it. i always struggled with this problem, as i did not want to include moment.js or numeral.js or even less a own implementation for that. But your suggestion is just perfect...nice formatting but still no need to include something fix to i18next - and devs get enough power to extend to support formatting...

very well.....now i just need the time to add this ;)

@jamuhl
Member
jamuhl commented Jul 10, 2016

so here's the plan:

we create something like post processor plugins with interface looking like:

{
  type: 'formatter',
  name: 'momentFormatter',
  format: function(value, format) {
    /* return manipulated value */
  },
  changeLanguage: function(lng) {
    /* change language on moment, evtl. load the resource file */
  }
}

in interpolator we check if matching to the defined patter https://github.com/i18next/i18next/blob/master/src/Interpolator.js#L43 (like nest function below this one) and call all formatters appended by i18next.use(myFormatter)

@LodewijkSioen

I'm glad that you like my suggestion. To be honest, this method is the way string interpolation with formatting is done in .net and some other languages. In .net we do $"Today is {date:dd/MM/yyyy}"´ and other languages have a similar construct. Most languages use a colon (:`) to separate the formatting, so I've edited my example above.

About your plugin interface: what is the changeLanguage method for? Shouldn't it be an overload for the format(value, format)-function?

@jamuhl
Member
jamuhl commented Jul 11, 2016

changeLanguage is optional -> eg. when using moment you can set language on moment (evtl. one even need to load that language file for moment) - but you are right...we need to pass language on the format function itself too - as one could do that on the outer t function, too.

hm...loading that locales for eg. moment https://github.com/moment/moment/tree/develop/locale or numeral will be the biggest issue i think as that's an async operation in a sync function call....

@jamuhl
Member
jamuhl commented Jul 11, 2016

so we might end in just let devs pass in a function on init like you initial suggested:

function(value, formatting, lng){
    if(value instanceof Date){
        return moment(value).format(formatting);
    }
    return value.toString();
}

So loading correct locales for moment stays in control of the developer integrating i18next to his project - which might be very different from project to project (using webpack, requirejs,...).

Solving this in form of plugins would only make sense if one could publish that for reuse - but basically i think this would only work for simple formatters not needing own locales files.

@LodewijkSioen

I agree that just having a function would give more flexibility then a plugin.

@jamuhl
Member
jamuhl commented Jul 13, 2016

in v3.4.0:

i18next.init({
  interpolation: {
    formatSeparator: ',',
    format: function(value, formatting, lng){
       if(value instanceof Date) return moment(value).format(formatting);
       return value.toString();
    }
  }
});
"test": "hello, it is now {{date, dd/MM/yyyy}}"
i18next.t('test',  { date: new Date()  }); // -> hello, it is now 13/07/2016
@jamuhl jamuhl closed this Jul 13, 2016
@LodewijkSioen

Brilliant! Thanks a lot for this!

@jamuhl
Member
jamuhl commented Jul 14, 2016

thank you for bringing up the topic again and for directing to the solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment