Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate static files automatically #6

Open
juhamust opened this issue Sep 29, 2015 · 8 comments
Open

Generate static files automatically #6

juhamust opened this issue Sep 29, 2015 · 8 comments

Comments

@juhamust
Copy link

As it can be seen from the related discussion (globalizejs/globalize#481 (comment)), the requirement of static formatting rules took me by surprise.

Now the globalization works as expected, but to get there I had to generate following JavaScript code from all the messages. This is something I'd expect Globalize Webpack plugin to do for me.

// jscs:disable
// NOTE: This file is generated. Do not modify.
var Globalize = require('globalize');
var lookupTable = {};
Globalize.locale("en");
lookupTable["en"] = {};
lookupTable["en"]["app.calc.button"] = Globalize.messageFormatter("app.calc.button");
lookupTable["en"]["app.dates.day"] = Globalize.messageFormatter("app.dates.day");
lookupTable["en"]["app.dates.days"] = Globalize.messageFormatter("app.dates.days");
lookupTable["en"]["app.dates.month"] = Globalize.messageFormatter("app.dates.month");
lookupTable["en"]["app.dates.months"] = Globalize.messageFormatter("app.dates.months");
lookupTable["en"]["app.dates.year"] = Globalize.messageFormatter("app.dates.year");
// .... goes on for 2000+ of lines ...
@rxaviers
Copy link
Owner

rxaviers commented Oct 1, 2015

@juhamust

Globalize.locale("en");

You should not set the locale yourself. Let the plugin do it for you automatically.

lookupTable["en"] = {};
lookupTable["en"]["app.calc.button"] = Globalize.messageFormatter("app.calc.button");
...

Can you show me an example how you are using this lookupTable in your code? I am wondering why you don't simply use Globalize inline where you want the messages, for example:

<button>{{Globalize.formatMessage("app.calc.button")}}</button>

@juhamust
Copy link
Author

juhamust commented Oct 6, 2015

@rxaviers Thanks for reaching me about the topic. Hope this will help improving the plugin even further.

I'm developing an Angular based app, where Globalize is doing the localisation: translation + number and currency formatting. In practice, I've created simple filters for formatting and translation (here's the latter):

<div>Here is the translation: {{ value | t }}</div>
var Globalize = require('globalize');
// Static set of messages
var messageTable = require('./message-table');

function translate(value) {
  value = value || '';
  var messageFormatter = messageTable[Globalize.locale()][value];

  if (!messageFormatter) {
    console.warn('Translation missing:', value);
    return value;
  }

  return messageTable[Globalize.locale()][value]();
}

If I'd use Globalize without lookup table, I'd give weird errors like function not found.

// Does not work
function translate(value) {
  return Globalize.messageFormatter(value);
}

Same applies to number/currency formatters - they need to defined statically, right?

works = Globalize.numberFormatter({ maximumFractionDigits: 0 });
doesnot = Globalize.numberFormatter({ minimumFractionDigits: 1, maximumFractionDigits: 1 });

To solve this, I'm generating list of different formatting rules into lookup table and using them from there.

And as for setting locale within lookup table, I'm changing to get outcome from correct language:

var Globalize = require('globalize');
var lookupTable = {};
Globalize.locale("en");
lookupTable["en"] = {};
lookupTable["en"]["app.calc.button"] = Globalize.messageFormatter("app.calc.button");
lookupTable["en"]["app.dates.day"] = Globalize.messageFormatter("app.dates.day");
// ...
Globalize.locale("fi");
lookupTable["fi"] = {};
lookupTable["fi"]["app.calc.button"] = Globalize.messageFormatter("app.calc.button");
lookupTable["fi"]["app.dates.day"] = Globalize.messageFormatter("app.dates.day");
// ...
Globalize.locale("zh");
lookupTable["zh"] = {};
lookupTable["zh"]["app.calc.button"] = Globalize.messageFormatter("app.calc.button");
// etc.

Is there a better way or what is that I'm missing here?

@rxaviers
Copy link
Owner

rxaviers commented Oct 6, 2015

First of all, you have a great goal. Note that I and other people have done something similar for react.js https://github.com/kborchers/react-globalize, which could be useful to you as a reference. Also, see this example https://github.com/rxaviers/yarsk/tree/react-globalize.

Note that Globalize is very flexible. It allows dynamic stuff like your translate(value) example, where it will generate the formatter on the fly. Note it requires appropriate portions of CLDR and messages content to be loaded in advance (so, it can technically generate any formatter or parser on the fly). Also note CLDR is pretty big and on client-side applications it's important that its bundle size be optimized. This is where Globalize runtime modules come into play. They are a great solution for such optimization (reasons described at https://github.com/jquery/globalize/#performance). But, they require you to build your formatters (and parsers) at build time, which means no dynamic formatters on the fly (they need to be pre-built). Although, note it doesn't mean you have to manage that crazy lookup table yourself.

globalize-webpack-plugin makes a lot of the Globalize workflow above transparent for its users. You could re-use this plugin in your Angular library (like react.js integration does reuse it). But, it requires you to understand a little more of its underlings. The best thing I suggest is to take a deep look at the react.js integration I have linked above. That would be a good fist step. I can answer to any further questions.

@juhamust
Copy link
Author

juhamust commented Oct 6, 2015

Thanks for your response - will have to look into react-globalize, whether it clarifies the usage with other libraries.

Feel free to close this issue if you find it no longer valid.

@nkovacs
Copy link

nkovacs commented Jan 4, 2016

This plugin tries to find formatters and messages inside your js code. The main problem with angular is that you want to write the messages and the formatting code into the html templates. The plugin won't find them there, e.g. it can't find this:

<button>{{Globalize.formatMessage("app.calc.button")}}</button>
<span>Balance: {{ Globalize.formatCurrency(62, "USD") }}</span>

That's why you had to create the lookup table.

You'd have to write a plugin to handle angular (like https://github.com/rxaviers/react-globalize-compiler/, I think), but that would be pretty difficult, since you'd have to parse angular templates.

Instead of that I decided to make the lookup table creation simpler, so I wrote a loader that can parse a configuration file with all the parsers and formatters, plus the message files: https://github.com/nkovacs/globalize-config-loader

It takes a configuration file like this and converts it into a compiled globalize module: https://github.com/nkovacs/globalize-config-compiler/blob/master/example/test-config.json

@rxaviers
Copy link
Owner

You'd have to write a plugin to handle angular (like https://github.com/rxaviers/react-globalize-compiler/, I think), but that would be pretty difficult, since you'd have to parse angular templates.

Yeap, that's the solution you should be looking for. How difficult? Maybe you could re-use existing webpack loaders for angular template, and/or do something similar to https://github.com/rxaviers/react-globalize-webpack-plugin and https://github.com/jquery-support/react-globalize.

@rightwork
Copy link

@juhamust, if it helps, check out https://github.com/lp-/globalize-compiler-plus. It generates a file from messages.json that can feed into globalize-compiler, so that all messages, whether referenced in the code or not, can be included.

I also wrote an example (https://github.com/lp-/webpack-riot-uikit-globalize-jsdata-template) using npm scripts and webpack workflow to show how the output from globalize-compiler-plus can feed into the workflow and locales can be retrieved dynamically, as needed, rather than including them all in the bundle. I wrote all this because I found the globalize-webpack example hard to digest, and needed something simpler to reason about (for my feeble little brain).

@juhamust
Copy link
Author

juhamust commented Feb 3, 2016

@lp- thanks, much appreciated. i'm going use the existing setup for this project (as it works), but will definitely consider globalize-compiler-plus in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants