Leaflet icon indicating copy to clipboard operation
Leaflet copied to clipboard

Add i18n helpers in core (v2)

Open simon04 opened this issue 4 months ago β€’ 9 comments

Resurrecting #9281. Fixes #9092.

simon04 avatar Aug 17 '25 07:08 simon04

@yohanboniface as the maintainer of leaflet-i18n I'd appreciate your input on this feature.

jonkoops avatar Sep 15 '25 15:09 jonkoops

Thank you @simon04 and @jonkoops for all your work on this. Very much appreciated!

I've found a bug - on line 42 of I18n.js, the data parameter should be passed into the Util.template(string) call, when the locale is not set.

Expected JavaScript:

static translate(string, data = {}) {
  if (this.#locale === null) {
    return Util.template(string, data);
  }
  ...
}

Apart from that, I can't find any other problems.

I'm testing the I18n class in this demo page.

(FYI, I'm the maintainer of the Leaflet.translate plugin, which uses @yohanboniface's leaflet-i18n plugin.)

nfreear avatar Sep 20 '25 15:09 nfreear

I've found a bug - on line 42 of I18n.js, the data parameter should be passed into the Util.template(string) call, when the locale is not set.

Thanks for spotting this. Fixed now.

simon04 avatar Sep 20 '25 18:09 simon04

Great stuff. Thanks @simon04 for responding.

I've found some more places where I believe I18n.translate() could and should be used:

  1. src/layer/Popup.js - Line 107:

    closeButtonLabel: 'Close popup',
    

    I'm not sure that the closeButtonLabel option is actually needed now that translation is an option.

  2. src/control/Control.Layers.js - Line 227:

    link.title = 'Layers';
    
  3. src/control/Control.Scale.js - Lines 97 - 113:

    label = meters < 1000 ? `${meters} m` : `${meters / 1000} km`;  // Line 97.
    
    this._updateScale(this._iScale, `${miles} mi`, miles / maxMiles);  // Line 109.
    
    this._updateScale(this._iScale, `${feet} ft`, feet / maxFeet);  // Line 113.
    

Regarding number 3., though an abbreviation like "km" is widely known, for example in China, there is an alternative using Chinese characters. And, the abbreviation "mi" for miles would not be known.

I hope this all helps.

Nick

PS. Sorry I'm not in a position to formally "sign off" on this PR!

nfreear avatar Sep 21 '25 20:09 nfreear

Regarding src/layer/tile/TileLayer.js - Line 105, options.attribution =… - from a security (XSS) standpoint, the translation strings should not contain HTML markup.

I suggest that this would be better written as:

options.attribution = I18n.translate('Β© {link}OpenStreetMap{endlink} contributors', {
    link: '<a href="http://www.openstreetmap.org/copyright">',
    endlink: '</a>',
});

(Finished for the evening!)

nfreear avatar Sep 21 '25 21:09 nfreear

+1 on the HTML suggestion, we need to find a way to handle interpolation properly.

jonkoops avatar Sep 22 '25 13:09 jonkoops

@nfreear, thanks for listing additional places in the code. Regarding "OpenStreetMap contributors", I found it easier to mark "OpenStreetMap contributors" for translation and wrap it in the <a> outside of the translation system.

simon04 avatar Sep 23 '25 18:09 simon04

Yes let's handle "OpenStreetMap contributors" separately. In my eyes there is no translation needed

Falke-Design avatar Sep 23 '25 18:09 Falke-Design

I consider this pull request to be on the critical path for several 2.0-related things:

  • Plugin developers, who while they update their plugins for 2.0, wish to also use I18n.translate(),
  • Accessibility: various open issues including #9119, #9116(PR), #7822, and so on that involve setting an accessible name/text alternative, may rely on calls to I18n.translate().

FYI, @simon04, @jonkoops, @yohanboniface and @Falke-Design

nfreear avatar Oct 04 '25 09:10 nfreear