electricitymaps / electricitymaps-contrib

A real-time visualisation of the CO2 emissions of electricity consumption
https://app.electricitymaps.com
GNU Affero General Public License v3.0
3.52k stars 936 forks source link

[RFC] Translate country names with `Intl.DisplayNames()` instead of translation files. #4093

Closed VIKTORVAV99 closed 2 weeks ago

VIKTORVAV99 commented 2 years ago

Translate country names with Intl.DisplayNames() instead of translation files.

Right now we use translation files for each language to get the names of countries. I propose we switch to using the built-in Intl object together with it's function DisplayNames. In usage it would look like this:

// document.documentElement.lang is 'en' 
const localizedRegionName = new Intl.DisplayNames(document.documentElement.lang, { type: 'region' }).of(/* ISO 3166-1 alpha-2, example: */ 'DK');
console.log(localizedRegionName);
// logs: "Denmark"

This would give the local name for the region by using the html document lang we already set when users change the language.

This change would also allow us to reduce the size of the translation files by removing country names (not subzone names).

The current translation files look like this:

{
// ...  
    "zoneShortName": {
// ...
      "AS": {
          "zoneName": "American Samoa"
      },
      "AT": {
          "zoneName": "Austria"
      },
      "AUS-NSW": {
          "countryName": "Australia",
          "zoneName": "New South Wales"
      },
      "AUS-NT": {
          "countryName": "Australia",
          "zoneName": "Northern Territory"
      },
// ...
   }
}

With my proposed change we could modify them to look like this:

{
// ...
   "zoneShortName": {
// ...
       /* 
        * Removed!
        * "AS": {
        *     "zoneName": "American Samoa"
        * },
        * "AT": {
        *     "zoneName": "Austria"
        * },
        */
        "AUS-NSW": {
            "countryCode": "AU",
            "zoneName": "New South Wales"
        },
        "AUS-NT": {
            "countryCode": "AU",
            "zoneName": "Northern Territory"
        },
// ...
    }
}  

Since a large portion of the language files are just translated names for zones and a lot of zones are just countries this could bring some considerable size reductions to the language files as well as improve maintainability.

The country code could also be moved to zones.json to remove duplication in the translation files or removed all together if we change all zone codes to follow the same structure, ISO 3166-1 alpha-2 and subzone specifier with a - delimiter. Most if not all regions except the Australian subzones already use this format.

Please let me know what you think so I can start working on it if we want to move forward!

jarek commented 2 years ago

This is pretty interesting. I didn't know this was a thing. Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames#browser_compatibility it's supported by recent versions of everything but IE. Do you have an idea of market share of the browser versions that support it (e.g. Chrome >= 81)? And for browsers that support the API, do they also support all the country names... in all the languages?

VIKTORVAV99 commented 2 years ago

This is pretty interesting. I didn't know this was a thing. Per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames#browser_compatibility it's supported by recent versions of everything but IE. Do you have an idea of market share of the browser versions that support it (e.g. Chrome >= 81)? And for browsers that support the API, do they also support all the country names... in all the languages?

As far as I know they it support all countries with a ISO 3166-1 alpha-2 and all languages we currently support plus regional variants (if no regional variant is found it falls back to the "main" language) and more (This might be the entire list.). So it would support all countries (except Northern Cyprus as it's not a recognized country by anyone except Turkey and don't have a ISO 3166-1 alpha-2 code, this is perhaps a different discussion to be had?).

By looking at caniuse data (press the usage relative button) the vast majority is supported, but there are some old versions still in use that don't support it (ios might be a problem) , it would perhaps be best to cross-check this with browser visitor statistics from the website itself but I think it would be relatively safe to implement.

Edit: Also worth noting is that if a language is not supported it falls back to best fit and if it can't find one it falls back to the preferred language by the browser (usually the device language) if I understood the documentation right.

VIKTORVAV99 commented 2 years ago

@madsnedergaard you might be interested in this. 🙂

madsnedergaard commented 2 years ago

I think this is awesome! The zone names cannot be changes (as we also use them for the API), but we can definitely find a solution that removes most of these from translations :) It would still be nice to keep a "connection" between a zoneName/countryCode and the actual country somewhere in the code, but maybe that should live as a key in zones.json?

VIKTORVAV99 commented 2 years ago

I was planning on using something like this to use both of them together:

const translationFile = await import('language-file');
const countryName = 
  translationFile?.zoneShortName?.[/* ISO 3166-1 alpha-2 */]?.zoneName ??
  new Intl.DisplayNames(document.documentElement.lang, { type: 'region' }).of(/* ISO 3166-1 alpha-2 */);
Will probably need some slight modification as not all regions use the ISO 3166-1 alpha-2 as a identifier.

That way it will be like a "reverse fallback" that gives priority to the translation files as long as they contain the zoneKey for the region in question. Would it be possible to use something similar in the API backend?

But yes the country code could live in zones.json, it could possibly even replace the flag property as it appear they could all be [ISO 3166-1 alpha-2].png with some other modifications.

Some slightly of topic questions but somewhat important to end implementation:

VIKTORVAV99 commented 2 weeks ago

Closing this as we would only ever be able to translate the countries.