tor-browser

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

fluent-utils.mjs (4197B)


      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 import { DOMLocalization } from "@fluent/dom";
      6 import { FluentBundle, FluentResource } from "@fluent/bundle";
      7 import { addons } from "@storybook/addons";
      8 import { PSEUDO_STRATEGY_TRANSFORMS } from "./l10n-pseudo.mjs";
      9 import {
     10  FLUENT_SET_STRINGS,
     11  UPDATE_STRATEGY_EVENT,
     12  STRATEGY_DEFAULT,
     13  PSEUDO_STRATEGIES,
     14 } from "./addon-fluent/constants.mjs";
     15 
     16 let loadedResources = new Map();
     17 let currentStrategy;
     18 let storybookBundle = new FluentBundle("en-US", {
     19  transform(str) {
     20    if (currentStrategy in PSEUDO_STRATEGY_TRANSFORMS) {
     21      return PSEUDO_STRATEGY_TRANSFORMS[currentStrategy](str);
     22    }
     23    return str;
     24  },
     25 });
     26 
     27 // Listen for update events from addon-fluent.
     28 const channel = addons.getChannel();
     29 channel.on(UPDATE_STRATEGY_EVENT, updatePseudoStrategy);
     30 channel.on(FLUENT_SET_STRINGS, ftlContents => {
     31  let resource = new FluentResource(ftlContents);
     32  for (let message of resource.body) {
     33    let existingMessage = storybookBundle.getMessage(message.id);
     34    existingMessage.value = message.value;
     35    existingMessage.attributes = message.attributes;
     36  }
     37  document.l10n.translateRoots();
     38 });
     39 
     40 /**
     41 * Updates "currentStrategy" when the selected pseudo localization strategy
     42 * changes, which in turn changes the transform used by the Fluent bundle.
     43 *
     44 * @param {string} strategy
     45 *  Pseudo localization strategy. Can be "default", "accented", or "bidi".
     46 */
     47 function updatePseudoStrategy(strategy = STRATEGY_DEFAULT) {
     48  if (strategy !== currentStrategy && PSEUDO_STRATEGIES.includes(strategy)) {
     49    currentStrategy = strategy;
     50    document.l10n.translateRoots();
     51  }
     52 }
     53 
     54 export function connectFluent() {
     55  document.l10n = new DOMLocalization([], generateBundles);
     56  document.l10n.connectRoot(document.documentElement);
     57  document.l10n.translateRoots();
     58 }
     59 
     60 function* generateBundles() {
     61  yield* [storybookBundle];
     62 }
     63 
     64 export async function insertFTLIfNeeded(fileName) {
     65  if (loadedResources.has(fileName)) {
     66    return;
     67  }
     68 
     69  // This should be browser, locales-preview or toolkit.
     70  let [root, ...rest] = fileName.split("/");
     71  let ftlContents;
     72 
     73  // TODO(mstriemer): These seem like they could be combined but I don't want
     74  // to fight with webpack anymore.
     75  if (root == "toolkit") {
     76    // eslint-disable-next-line no-unsanitized/method
     77    let imported = await import(
     78      /* webpackInclude: /.*[\/\\].*\.ftl$/ */
     79      `toolkit/locales/en-US/${fileName}`
     80    );
     81    ftlContents = imported.default;
     82  } else if (root == "browser") {
     83    // eslint-disable-next-line no-unsanitized/method
     84    let imported = await import(
     85      /* webpackInclude: /.*[\/\\].*\.ftl$/ */
     86      `browser/locales/en-US/${fileName}`
     87    );
     88    ftlContents = imported.default;
     89  } else if (root == "locales-preview") {
     90    // eslint-disable-next-line no-unsanitized/method
     91    let imported = await import(
     92      /* webpackInclude: /\.ftl$/ */
     93      `browser/locales-preview/${rest}`
     94    );
     95    ftlContents = imported.default;
     96  } else if (root == "branding") {
     97    // eslint-disable-next-line no-unsanitized/method
     98    let imported = await import(
     99      /* webpackInclude: /\.ftl$/ */
    100      `browser/branding/nightly/locales/en-US/${rest}`
    101    );
    102    ftlContents = imported.default;
    103  } else if (root == "preview") {
    104    // eslint-disable-next-line no-unsanitized/method
    105    let imported = await import(
    106      /* webpackInclude: /\.ftl$/ */
    107      `toolkit/components/satchel/megalist/content/${rest}`
    108    );
    109    ftlContents = imported.default;
    110  }
    111 
    112  if (loadedResources.has(fileName)) {
    113    // Seems possible we've attempted to load this twice before the first call
    114    // resolves, so once the first load is complete we can abandon the others.
    115    return;
    116  }
    117 
    118  provideFluent(ftlContents, fileName);
    119 }
    120 
    121 export function provideFluent(ftlContents, fileName) {
    122  let ftlResource = new FluentResource(ftlContents);
    123  storybookBundle.addResource(ftlResource);
    124  if (fileName) {
    125    loadedResources.set(fileName, ftlResource);
    126  }
    127  document.l10n.translateRoots();
    128  return ftlResource;
    129 }