globalizejs / globalize

A JavaScript library for internationalization and localization that leverages the official Unicode CLDR JSON data
https://globalizejs.com
MIT License
4.8k stars 603 forks source link

Should I be able to load messages for language and territory like 'en-US' #852

Open astewart opened 5 years ago

astewart commented 5 years ago

Shouldn't I be able to load en-US. If not, then what is the proper way to load this data.

var Globalize = require("globalize");
var cldr = require("cldr-data");

Globalize.load(cldr.all());
Globalize.loadMessages({
  "en-US": { "common.legal.esrb.blood": "Blood" }
});
Globalize("en-US").formatMessage("common.legal.esrb.blood");

This gives the error: Error: E_MISSING_MESSAGE_BUNDLE: Missing message bundle for locale `en-US`.

rxaviers commented 5 years ago

Yes, you should be able to. Please, which globalize and cldrjs versions are you using?

rxaviers commented 5 years ago

Oh! I see the issue. I believe that if you load it using "en" it should work:

Globalize.loadMessages({
  "en": { "common.legal.esrb.blood": "Blood" }
});

Ideally, globalize should normalize that for you. Anyway, the quickest explanation is that it expects you to pass valid bundles. In order to get them, you can use the code below:

let en = new Globalize("en");
let { bundle } = en.cldr.attributes;
kolman commented 3 years ago

Also, behaves differently for en territories (en-US, en-GB) and others. When I load any cldr data from de and then define messages for de-DE, it won't be able to find it. Consider this test:

    Globalize.load(require('../cldr-data/supplemental/likelySubtags.json'))
    Globalize.load(require('../cldr-data/supplemental/plurals.json'));
    Globalize.load(require('../cldr-data/main/en/numbers.json'));
    Globalize.load(require('../cldr-data/main/de/numbers.json')); // comment this line and it will pass

    Globalize.loadMessages({
      root: {},
      'en-GB': {
        'app.message': 'Localized message'
      },
      'de-DE': { 
        'app.message': 'Lokalisierte Nachricht' 
      }
    });

    // works as expected
    const en = new Globalize('en-GB').messageFormatter('app.message')();
    expect(en).toEqual('Localized message');

    // throws E_MISSING_MESSAGE: Missing required message content `app.message`.
    const de = new Globalize('de-DE').messageFormatter('app.message')();
    expect(de).toEqual('Lokalisierte Nachricht');
kolman commented 3 years ago

And another interesting test case:

    Globalize.load(require('../cldr-data/supplemental/likelySubtags.json'));
    Globalize.load(require('../cldr-data/supplemental/plurals.json'));
    Globalize.loadMessages({
      'de': { 'app.message': 'Not this one!' },
      'de-DE': { 'app.message': 'Lokalisierte Nachricht' }
    });

    const de = new Globalize('de-DE').messageFormatter('app.message')();
    expect(de).toEqual('Lokalisierte Nachricht');
    // error:
    // Expected: "Lokalisierte Nachricht"
    // Received: "Not this one!"

This is with the latest versions (globalize@1.6.0, cldrjs@0.5.5).

kolman commented 3 years ago

All these test cases work with cldrjs@0.5.0 but fail with cldrjs@^0.5.1. I'm pretty sure it's caused by this https://github.com/rxaviers/cldrjs/issues/67 The {bundle} attribute (used in message.js) now points to de instead of de-DE. The problem is that when I replace this line:

// message.js:76
    message = cldr.get( [ "globalize-messages/{bundle}" ].concat( path ) );

with this line:

    message = cldr.get( [ "globalize-messages/{bundle}-{territory}" ].concat( path ) );

it will break the other test cases.