tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

l10n-pseudo.mjs (4281B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 // Stolen from https://github.com/firefox-devtools/profiler/blob/52a7531662a08d96dc8bd03d25adcdb4c9653b92/src/utils/l10n-pseudo.js
      6 // Which was stolen from https://hg.mozilla.org/mozilla-central/file/a1f74e8c8fb72390d22054d6b00c28b1a32f6c43/intl/l10n/L10nRegistry.jsm#l425
      7 
      8 /**
      9 * Pseudolocalizations
     10 *
     11 * PSEUDO_STRATEGIES is a dict of strategies to be used to modify a
     12 * context in order to create pseudolocalizations.  These can be used by
     13 * developers to test the localizability of their code without having to
     14 * actually speak a foreign language.
     15 *
     16 * Currently, the following pseudolocales are supported:
     17 *
     18 *   accented - Ȧȧƈƈḗḗƞŧḗḗḓ Ḗḗƞɠŀīīşħ
     19 *
     20 *     In Accented English all Latin letters are replaced by accented
     21 *     Unicode counterparts which don't impair the readability of the content.
     22 *     This allows developers to quickly test if any given string is being
     23 *     correctly displayed in its 'translated' form.  Additionally, simple
     24 *     heuristics are used to make certain words longer to better simulate the
     25 *     experience of international users.
     26 *
     27 *   bidi - ɥsıʅƃuƎ ıpıԐ
     28 *
     29 *     Bidi English is a fake RTL locale.  All words are surrounded by
     30 *     Unicode formatting marks forcing the RTL directionality of characters.
     31 *     In addition, to make the reversed text easier to read, individual
     32 *     letters are flipped.
     33 *
     34 *     Note: The name above is hardcoded to be RTL in case code editors have
     35 *     trouble with the RLO and PDF Unicode marks.  In reality, it should be
     36 *     surrounded by those marks as well.
     37 *
     38 * See https://bugzil.la/1450781 for more information.
     39 *
     40 * In this implementation we use code points instead of inline unicode characters
     41 * because the encoding of JSM files mangles them otherwise.
     42 */
     43 
     44 const ACCENTED_MAP = {
     45  // ȦƁƇḒḖƑƓĦĪĴĶĿḾȠǾƤɊŘŞŦŬṼẆẊẎẐ
     46  // prettier-ignore
     47  "caps": [550, 385, 391, 7698, 7702, 401, 403, 294, 298, 308, 310, 319, 7742, 544, 510, 420, 586, 344, 350, 358, 364, 7804, 7814, 7818, 7822, 7824],
     48  // ȧƀƈḓḗƒɠħīĵķŀḿƞǿƥɋřşŧŭṽẇẋẏẑ
     49  // prettier-ignore
     50  "small": [551, 384, 392, 7699, 7703, 402, 608, 295, 299, 309, 311, 320, 7743, 414, 511, 421, 587, 345, 351, 359, 365, 7805, 7815, 7819, 7823, 7825],
     51 };
     52 
     53 const FLIPPED_MAP = {
     54  // ∀ԐↃᗡƎℲ⅁HIſӼ⅂WNOԀÒᴚS⊥∩ɅMX⅄Z
     55  // prettier-ignore
     56  "caps": [8704, 1296, 8579, 5601, 398, 8498, 8513, 72, 73, 383, 1276, 8514, 87, 78, 79, 1280, 210, 7450, 83, 8869, 8745, 581, 77, 88, 8516, 90],
     57  // ɐqɔpǝɟƃɥıɾʞʅɯuodbɹsʇnʌʍxʎz
     58  // prettier-ignore
     59  "small": [592, 113, 596, 112, 477, 607, 387, 613, 305, 638, 670, 645, 623, 117, 111, 100, 98, 633, 115, 647, 110, 652, 653, 120, 654, 122],
     60 };
     61 
     62 function transformString(
     63  map = FLIPPED_MAP,
     64  elongate = false,
     65  prefix = "",
     66  postfix = "",
     67  msg
     68 ) {
     69  // Exclude access-keys and other single-char messages
     70  if (msg.length === 1) {
     71    return msg;
     72  }
     73  // XML entities (‪) and XML tags.
     74  const reExcluded = /(&[#\w]+;|<\s*.+?\s*>)/;
     75 
     76  const parts = msg.split(reExcluded);
     77  const modified = parts.map(part => {
     78    if (reExcluded.test(part)) {
     79      return part;
     80    }
     81    return (
     82      prefix +
     83      part.replace(/[a-z]/gi, ch => {
     84        const cc = ch.charCodeAt(0);
     85        if (cc >= 97 && cc <= 122) {
     86          const newChar = String.fromCodePoint(map.small[cc - 97]);
     87          // duplicate "a", "e", "o" and "u" to emulate ~30% longer text
     88          if (
     89            elongate &&
     90            (cc === 97 || cc === 101 || cc === 111 || cc === 117)
     91          ) {
     92            return newChar + newChar;
     93          }
     94          return newChar;
     95        }
     96        if (cc >= 65 && cc <= 90) {
     97          return String.fromCodePoint(map.caps[cc - 65]);
     98        }
     99        return ch;
    100      }) +
    101      postfix
    102    );
    103  });
    104  return modified.join("");
    105 }
    106 
    107 export const PSEUDO_STRATEGY_TRANSFORMS = {
    108  accented: transformString.bind(null, ACCENTED_MAP, true, "", ""),
    109  bidi: transformString.bind(null, FLIPPED_MAP, false, "\u202e", "\u202c"),
    110 };