bitjson / gulp-l10n

A gulp plugin for localizing html.
https://www.npmjs.com/package/gulp-l10n
MIT License
14 stars 7 forks source link

How do I ignore an element from localization? #23

Open jonimake opened 8 years ago

jonimake commented 8 years ago

I have a language menu dropdown where the placeholder/current language is a two letter language code. In the dropdown menu elements the same kind of language codes are used. The placeholder/current language is handled by using localizations, so on on native language the dropdown value shows AA, on language BB it shows BB and so on. The list then shows languages AA, BB and CC.

My problem is that I only want to localize the current value and not the contents of the dropdown menu:

<div class="selectedlang">FI</div>       <--- I want to localize this "FI"
<ul>
  <li>FI</li>              <--- I don't want to localize this "FI"
  <li>EN</li>
  <li>SV</li>
</ul>

Is it possible to force the mapper to ignore the list item contents or should I just find another way to handle my case?

bitjson commented 8 years ago

Hey @jonimake – thanks for opening the issue.

Currently, it will only replace exact matches that occur in places from which a string might have been extracted (between > and <, two "s, and two 's). The goal is to keep localization extremely simple by de-emphasizing context. The downside of course is the lack of context makes certain cases a bit more complex.

We could consider making it possible to disable localization within defined blocks (like a canceler for the localization task), but there's nothing like that available right now.

You might want to consider either:

  1. choosing a slightly different string for the other location (which won't be localized if it's not an exact match), or
  2. converting the text in that location to the equivalent HTML character codes – in your example:
<div class="selectedlang">FI</div>
<ul>
  <li translate="no">&#70;&#73;</li>
  <li>EN</li>
  <li>SV</li>
</ul>

Does that help?

basile-laderchi commented 7 years ago

I tried using the "cancel-s18n", "s18n-exclude" and "translate=no" and none had an impact on the result. Shouldn't at least the "translate=no" be respected?

bitjson commented 7 years ago

@basile-laderchi does the snippet above work for your use case? The localization task does not parse HTML, so those options should only work to customize string extraction. The snippet above should work, because the strings FI, EN, and SV should be extracted and localized, while the string &#70;&#73; will not be extracted. Since it has no localization, the localization task will ignore it.

The ideal solution is to choose unique strings for unique functions (a good idea UX-wise too), but if you absolutely need one to be localized, and the other to not, HTML character codes are a simple option. (Also much simpler than any sort of metadata system we could engineer to solve this in a "prettier" way.)

basile-laderchi commented 7 years ago

@bitjson the above solution would be a workaround, but shouldn't the "translate=no" be observed in the localization process also?

bitjson commented 7 years ago

@basile-laderchi – that would require a pretty fundamental architecture switch for s18n. Currently, the localization process itself does no parsing and no processing, it's a very fast find/replace. Adding a parsing step would waste a lot of processing time, and generally make the library much harder to grok.

By not attempting to differentiate between the exact same string in multiple locations, this library is simplified significantly (and processing is much faster). I would argue that using the same string to mean two different things is always "a bad idea" from a design perspective. Doing so usually means your interface/UI language needs clarification. (I should probably explain this reasoning in a readme.)

I think your example is a language switcher? If so, it's likely that something like the following would solve your issue more effectively:

<div class="selectedlang">Suomi</div>
<ul translate=no>
  <li>FI</li>
  <li>EN</li>
  <li>SV</li>
</ul>

Or better yet:

<div class="selectedlang" translate=no>Suomi</div>
<ul translate=no>
  <li>Suomi</li>
  <li>English</li>
  <li>Svenska</li>
</ul>

Language names should never really be localized when used in a language-selection context, because native speakers often will not know what the localized name of their own language is in all other languages. (E.g. English speakers are unlikely to recognize 英语 as their own language.)

basile-laderchi commented 7 years ago

I was thinking. Couldn't the string extraction be changed and instead of only extracting the strings, extract also the exact location of the strings found? This way the localization will know exactly where to find a string, if and how to localize it. It would also be faster, wouldn't it?

So according to this example:

<div class="selectedlang" translate="no">Suomi</div>
<ul>
  <li>Suomi</li>
  <li>English</li>
  <li>Svenska</li>
</ul>

it could store something like:

{
  "e75c475b": {
    "text": "Suomi",
    "line": 3,
    "char": 7
  },
  "1685a71e": {
    "text": "English",
    "line": 4,
    "char": 7
  },
  "5b1d59b5": {
    "text": "Svenska",
    "line": 5,
    "char": 7
  }
}