-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
feat: Add placeholder function for translation/localization/i18n to Leaflet #9092
Comments
I also think it is time to add a translation function in Leaflet. Like @yohanboniface predicted in #1232 only a few plugins are translated. We can help to change this with only a few bytes. But instead of implementing a placeholder, I would implement the logic for the translation too. Pretty similar to Leaflet.i18n, only with a few changes:
But we should not provide any translation files. This should be in a different repo like you suggested. |
Hi @Falke-Design, Thanks for the response. Interesting thoughts. A few points:
History including #1232 suggests concern to keep core Leaflet small and simpler. Also, when a Leaflet map is just one component in a site based on e.g. WordPress or Vue.js, the implementor probably wants localization handled by that system, not by Leaflet on its own. We need to get a consensus on this.
Libraries patterned after GNU Gettext tend to use And, for the string "Zoom out", do I care that it's for core Leaflet, or another plugin? Surely, I just care that it's a good translation?
The function name We should probably look at what others are doing in this space: Thanks Nick |
A few thoughts:
|
In my eyes we should go away of thinking translation and accesibillity is opt-in. I think many things can be a plugin but translation and accesibillity should be always available and then it should be in the core. Doesn't matter if Leaflet is only showing the position of a company or is used for a whole application. This few bytes are worth it. (329 bytes) But if we provide it as external plugin, then it should be possible for the plugins to use
That is true but there would be maybe some problems when the same text has multiple translations. We can prevent this when it is possible to add a preferred translation-set
Fine by me. A solution could be that we make it possible to pass a function for the translation and then it can be determined by the data which text should be returned. On the other hand, the user can do this internally in his code with some |
I am also a proponent of implementing localization in Leaflet itself, this has been a request many times before and can be a valuable addition for both us and especially authors of plugins to standardize. So let's talk implementation. Using the 'gettext' style of passing in the English source has my preference for a couple of reasons. Firstly, it is instantly clear what the text is supposed to be, no need for additional lookups. Secondly, if the text changes, so does the 'key', forcing translations to be updated. It also means we can simply use the string as-is for Leaflet without localization. The function that does the translation should be short and to the point. I also am not a proponent of using yet another single special character function (such as Perhaps we could use the letter Taking @nfreear's original example, I would imagine something like this for a high-level API: import { t } from "leaflet";
const options = {
zoomInTitle: t("Zoom in"),
zoomOutTitle: t("Zoom out"),
}; I also agree with the idea to provide interpolation based on the existing import { t } from "leaflet";
// => "Hello, Jane Doe."
const message = t("Hello, {firstName} {lastName}.", {
firstName: "Jane",
lastName: "Doe",
}); So let's agree on this first, so we can move on to the API design of the part that is responsible for providing the the localizations to Leaflet itself. And the mechanism which Leaflet will use to detect the locale, or allow it to be set externally. @Leaflet/core @Leaflet/leaflet-maintainers can we bikeshed the above and agree on this part of the API? |
But on the down side this has the problem (especially for plugins) that the same key is used in different projects and can be translated different. Which translation will win and be displayed?
That is true and a big benefit.
I personally don't like this single characters. It is a function so let us use a name which can be directly understand by everyone for example
I have two solutions for this:
|
Yeah, that is always a concern. But I haven't really ran into this issue in practice. Personally, I think the benefit of having the source there, without mapping values, outweighs this.
I agree with all of this. Shall we settle on As for the name-spacing for translations, I would have to go with option 1. Perhaps we could use a Symbol as a first argument to the translate function? import { translate } from "leaflet";
const PLUGIN_NAMESPACE = Symbol("pluginName");
const message = translate(PLUGIN_NAMESPACE, "Hello, World"); Perhaps a simple string would suffice, but it would force a single and unique value. Alternatively to option 2, we could provide a function that is a 'factory' for name-spaced translation functions. For example: import { createTranslateFn } from "leaflet";
const PLUGIN_NAMESPACE = Symbol("pluginName");
const translate = createTranslateFn(PLUGIN_NAMESPACE);
const message = translate("Hello, World"); This would ensure all translations are still name-spaced, without sacrificing too much convenience for plugin authors, specifically having to repeat the namespace for every translation. |
Checklist
Motivation
Currently, core Leaflet and Leaflet plugins are not translated from English. This is not a big problem for visual users, as most controls like the "Zoom in" button rely on icons. However, for non-visual and low vision users, for example those relying on screen readers it is a significant barrier, when maps are implemented on non-English websites (accessibility).
You may argue that implementors should set the
zoomInTitle
option for the control. However, that is not exposed through the main map options, making it fiddly and inconsistent.And, there are a number of accessibility-related open bugs and pull requests that add new text strings to Leaflet. For example:
aria-label = "Layers"
leaflet-container
a programmatically determinable element #7193 –aria-roledescription="map"
/aria-label="map"
Suggested solution
I propose adding a placeholder or "dummy" for a translation function to core Leaflet. This would be a very small "pass-through" function that simply returns the string that is input as the first parameter.
That is, as an arrow function or non-arrow function:
Or, in a form that handles a second
data
parameter:This placeholder would be called wherever needed in core Leaflet - Control.Zoom.js:
And, it can be adopted by third-party plugins @brunob/leaflet.fullscreen - ...js:
Re-implement
Finally, anyone wishing to implement a map on a Non-English website would use a third-party internationalization plugin, for example, Leaflet.i18n, which re-implements the
L._()
function.Benefits of this approach:
A standardized, consistent, documented function is available to translate EVERY string in Leaflet for core and third-party plugins.
A lightweight approach. No need to implement all the internationalization functionality within Leaflet. No need to add language packs to core Leaflet. Instead, rely on an external plugin and language packs/locale files as needed.
Steps
L._()
function in core Leaflet,L._()
function throughout Leaflet,L._()
function.L._()
function in the API docs,L._()
function in the Plugin Guide,L._()
function, for example a fullscreen plugin.This proposal is inspired by @yohanboniface's "Leaflet.i18n" plugin, PR #1232, and GNU Gettext.
I welcome feedback on this proposal!
Thanks.
Alternatives considered
The Leaflet.a11y plugin is a short-term, non-optimal alternative. The solution above is much better long-term solution.
See the open PR: #9087, to list "Leaflet.a11y" in the plugin list!
The text was updated successfully, but these errors were encountered: