1 locale.inc _locale_parse_js_file($filepath)

Parses a JavaScript file, extracts strings wrapped in Backdrop.t() and Backdrop.formatPlural() and inserts them into the database.

File

core/includes/locale.inc, line 601
Administration functions for locale.module.

Code

function _locale_parse_js_file($filepath) {
  // The file path might contain a query string, so make sure we only use the
  // actual file.
  $parsed_url = backdrop_parse_url($filepath);
  $filepath = $parsed_url['path'];
  // Load the JavaScript file.
  $file = file_get_contents($filepath);

  // Match all calls to Backdrop.t() in an array.
  // Note: \s also matches newlines with the 's' modifier.
  preg_match_all('~
    [^\w]Backdrop\s*\.\s*t\s*                     # match "Backdrop.t" with whitespace
    \(\s*                                         # match "(" argument list start
    (' . LOCALE_JS_STRING . ')\s*                 # capture string argument
    (?:,\s*' . LOCALE_JS_OBJECT . '\s*            # optionally capture str args
      (?:,\s*' . LOCALE_JS_OBJECT_CONTEXT . '\s*) # optionally capture context
    ?)?                                           # close optional args
    [,\)]                                         # match ")" or "," to finish
    ~sx', $file, $t_matches);

  // Match all Backdrop.formatPlural() calls in another array.
  preg_match_all('~
    [^\w]Backdrop\s*\.\s*formatPlural\s* # match "Backdrop.formatPlural" with whitespace
    \(                                   # match "(" argument list start
    \s*.+?\s*,\s*                        # match count argument
    (' . LOCALE_JS_STRING . ')\s*,\s*    # match singular string argument
    (                             # capture plural string argument
      (?:                         # non-capturing group to repeat string pieces
        (?:
          \'(?:\\\\\'|[^\'])*\'   # match single-quoted string with any character except unescaped single-quote
          |
          "(?:\\\\"|[^"])*"       # match double-quoted string with any character except unescaped double-quote
        )
        (?:\s*\+\s*)?             # match "+" with possible whitespace, for str concat
      )+                          # match multiple because we supports concatenating strs
    )\s*                          # end capturing of plural string argument
    (?:,\s*' . LOCALE_JS_OBJECT . '\s*          # optionally capture string args
      (?:,\s*' . LOCALE_JS_OBJECT_CONTEXT . '\s*)?  # optionally capture context
    )?
    [,\)]
    ~sx', $file, $plural_matches);

  $matches = array();

  // Add strings from Backdrop.t().
  foreach ($t_matches[1] as $key => $string) {
    $matches[] = array(
      'string' => $string,
      'context' => $t_matches[2][$key],
    );
  }

  // Add string from Backdrop.formatPlural().
  foreach ($plural_matches[1] as $key => $string) {
    $matches[] = array(
      'string' => $string,
      'context' => $plural_matches[3][$key],
    );

    // If there is also a plural version of this string, add it to the strings array.
    if (isset($plural_matches[2][$key])) {
      $matches[] = array(
        'string' => $plural_matches[2][$key],
        'context' => $plural_matches[3][$key],
      );
    }
  }

  // Loop through all matches and process them.
  foreach ($matches as $key => $match) {

    // Remove the quotes and string concatenations from the string and context.
    $string = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($match['string'], 1, -1)));
    $context = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($match['context'], 1, -1)));

    $source = db_query("SELECT lid, location FROM {locales_source} WHERE source = :source AND context = :context", array(':source' => $string, ':context' => $context))->fetchObject();
    if ($source) {
      // We already have this source string and now have to add the location
      // to the location column, if this file is not yet present in there.
      $locations = preg_split('~\s*;\s*~', $source->location);

      if (!in_array($filepath, $locations)) {
        $locations[] = $filepath;
        $locations = implode('; ', $locations);

        // Save the new locations string to the database.
        db_update('locales_source')
          ->fields(array(
            'location' => $locations,
          ))
          ->condition('lid', $source->lid)
          ->execute();
      }
    }
    else {
      // We don't have the source string yet, thus we insert it into the database.
      db_insert('locales_source')
        ->fields(array(
          'location' => $filepath,
          'source' => $string,
          'context' => $context,
        ))
        ->execute();
    }
  }
}