MediaWiki:Gadget-Stockphoto.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search

Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload

/*
 * StockPhoto - shows download and attribution buttons
 *
 * Dependencies: mediawiki.util, mediawiki.user, mediawiki.RegExp, jquery.ui.dialog
 *
 * @rev 2018-04-16
 * @source https://commons.wikimedia.org/wiki/MediaWiki:Gadget-Stockphoto.js
 *
 * Copyright 2010-09/10 by Magnus Manske
 * Copyright 2011-2018 Timo Tijhof
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/* eslint-env browser */
/* global $, mw */
(function () {
'use strict';

var stockPhoto;

if (
  // Already loaded
  window.stockPhoto
  // Unsupported skin
  || !(mw.config.get('skin') === 'vector' || mw.config.get('skin') === 'monobook')
  // Not a file page
  || mw.config.get('wgCanonicalNamespace') !== 'File'
  // Not regular view
  || mw.config.get('wgAction') !== 'view'
) {
  // Do not load in these cases
  return;
}

/**
 * @param {string} opt.pageName
 * @param {string} opt.originalUrl
 * @param {jQuery} opt.info Keys '$src', '$aut'
 * @param {jQuery} opt.license For credit line, keys '$aut', '$attr', '$credit'
 * @param {jQuery} opt.$creator
 * @param {jQuery} opt.$licenses
 */
function File(opt) {
  var re, file = this;

  // Strip namespace prefix and file suffix.
  // Use spaces for underscore.
  file.title = opt.pageName.replace(/^[^:]+:|\.[^.]+$/g, '').replace(/_+/g, ' ');

  file.url = opt.originalUrl;

  file.backlink = 'https://commons.wikimedia.org/wiki/' + mw.util.wikiUrlencode(opt.pageName);

  re = new RegExp('\\.(?:' + stockPhoto.audio_only.map(mw.RegExp.escape).join('|') + ')$', 'i');
  file.audio = re.test(opt.pageName);

  this.fromCommons = false;
  this.gfdlNote = false;
  this.attrRequired = true;
  this.computeMetadata(opt.info, opt.license, opt.$creator, opt.$licenses);
}

// Set #author, #attribution, #attributionHtml and #licenses
File.prototype.computeMetadata = function (info, license, $creator, $licenses) {
  var attribution, attributionHtml, licenses, attrIsCredit, from,
    file = this,
    author = info.$aut.text().trim(),
    source = info.$src.text().trim();

  // Clean up 'author'
  if (info.$aut.find('.boilerplate').length) {
    author = '';
  }
  if (author.match(/^[Uu]nknown$/)) {
    author = '';
  }
  author = author.replace(/\s*\(talk\)$/i, '');
  if (author.indexOf('Original uploader was') !== -1) {
    author = author.replace(/\s*Original uploader was\s*/g, '');
    this.fromCommons = true;
  }
  if (author.substr(0, 3) === '[▼]') {
    author = author.substr(3); // ▼ (Black Down-Pointing Triangle)
    author = author.split('Description')[0].trim();
  }

  // Clean up 'source'
  if (info.$src.find('.boilerplate').length) {
    source = '';
  }
  if (author && info.$src.find('.int-own-work').length) {
    // Remove "own work" notice
    source = '';
    this.fromCommons = true;
  }
  if (author && source.length > 50) {
    // Only use source in attribution if source is short
    source = '';
  }

  // Decide author
  if (author && source) {
    this.author = author + ' (' + source + ')';
  } else if (author) {
    this.author = author;
  } else if (source) {
    this.author = source;
  } else {
    this.author = '';
  }

  // Decide attribution
  if (license.$credit.length) {
    attribution = license.$credit.text();
    attributionHtml = license.$credit.html();
    attrIsCredit = true;
  } else if (license.$attr.length) {
    attribution = license.$attr.text();
    attributionHtml = license.$attr.html();
  } else if (license.$aut.length) {
    attribution = license.$aut.text();
    attributionHtml = license.$aut.html();
  } else if ($creator.length) {
    attribution = $creator.text();
  } else if (author && this.author) {
    // Default attribution: prepend author/source with "By"
    attribution = stockPhoto.i18n.by_u + ' ' + this.author;
  } else {
    // If no author/source, or only source
    attribution = stockPhoto.i18n.see_page_for_author;
  }
  this.attribution = attribution;
  this.attributionHtml = attributionHtml || attribution;

  // Parse licenses
  licenses = [];
  $licenses.each(function () {
    var $tpl = $(this);
    var cL = {
      link: $tpl.find('.licensetpl_link').text(),
      short: $tpl.find('.licensetpl_short').text(),
      long: $tpl.find('.licensetpl_long').text(),
      attr: $tpl.find('.licensetpl_attr').text(),
      aut: $tpl.find('.licensetpl_aut').text(),
      link_req: $tpl.find('.licensetpl_link_req').text(),
      attr_req: $tpl.find('.licensetpl_attr_req').text()
    };
    if (cL.short) {
      licenses.push(cL);
    }
  });
  this.licenses = licenses.map(function (v) {
    var txt;
    if (v.attr_req === 'false') {
      file.attrRequired = false;
    }
    if (v.short.indexOf('GFDL') !== -1) {
      file.gfdlNote = true;
    }
    if (v.link_req === 'true' && v.link) {
      txt = v.short + ' (' + v.link + ')';
    } else {
      txt = v.short;
    }
    if (v.link) {
      return {
        html: '<a href="' + v.link + '">' + v.short + '</a>',
        txt: txt
      };
    } else {
      return { html: txt, txt: txt };
    }
  });

  // Decide credit
  if (attrIsCredit) {
    this.credit = this.attribution;
    this.creditHtml = this.attributionHtml;
  } else {
    from = this.fromCommons ? stockPhoto.i18n.from_wikimedia_commons : stockPhoto.i18n.via_wikimedia_commons;
    this.credit = this.attribution + this.getLicense() + ', ' + from;
    this.creditHtml = this.attributionHtml + this.getLicense(true) +
      ', <a href="' + mw.html.escape(this.backlink) + '">' + from + '</a>';
  }
};

File.prototype.getLicense = function (useHtml) {
  var l1, l2,
  licenses = this.licenses.map(function (l) {
    return useHtml ? l.html : l.txt;
  });
  if (!licenses.length) {
    return ' [' + stockPhoto.i18n.see_page_for_license + ']';
  }
  if (licenses.length >= 2) {
    l2 = licenses.pop();
    l1 = licenses.pop();
    licenses.push(l1 + ' ' + stockPhoto.i18n.or + ' ' + l2);
  }
  return ' [' + licenses.join(', ') + ']';
};

stockPhoto = {
  ui_icon_download: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Gnome-document-save.svg/50px-Gnome-document-save.svg.png',
  ui_icon_web: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c0/Gnome-emblem-web.svg/50px-Gnome-emblem-web.svg.png',
  ui_icon_wiki: 'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/Tango_style_Wikipedia_Icon.svg/50px-Tango_style_Wikipedia_Icon.svg.png',
  ui_icon_email: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/Gnome-mail-send.svg/50px-Gnome-mail-send.svg.png',
  ui_icon_help: 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Dialog-information_on.svg/50px-Dialog-information_on.svg.png',
  ui_icon_remove: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Emblem-unreadable.svg/20px-Emblem-unreadable.svg.png',
  information_template_hints: ['fileinfotpl_desc', 'fileinfotpl_src'],
  audio_only: ['midi', 'ogg', 'flac'],
  horizontal_ui: ['midi', 'ogg', 'flac', 'pdf', 'djvu'],
  ogg_icon: '/w/resources/assets/file-type-icons/fileicon-ogg.png',

  init: function () {
    var $enable, $orgItems, has_information, img_width, img_height, xoff, yoff, horizontal, html, $base, re;
    // Original filetoc items
    $orgItems = $('#filetoc').find('a[href="#file"], a[href="#filehistory"], a[href="#filelinks"], a[href="#metadata"], a[href="#globalusage"]').parent();
    if ($.cookie('StockPhotoDisabled')) {
      $enable = $('<li>')
      .append($('<a href="#"></a>').text(stockPhoto.i18n.reuse))
      .click(function (e){
        e.preventDefault();
        $(this).remove();
        $.cookie('StockPhotoDisabled', null, {
          path: '/'
        });
        stockPhoto.init();
      });
      $('#filetoc').append($enable);
      $orgItems = $orgItems.add($enable);
      return;
    }
    if (!$('#file').length) {
      return;
    }

    has_information = false;
    stockPhoto.information_template_hints.forEach(function (v) {
      if ($('#' + v).length) {
        has_information = true;
      }
    });
    // No {{Information}}
    if (!has_information) {
      return;
    }

    // Has one or more problemtags
    // Changed to also include renames and normal deletes
    if (document.querySelector('.nuke')) {
      return;
    }

    img_width = $('.multipageimage, #file img').eq(0).width();
    img_height = $('#file img').height();
    xoff = img_width + 40;
    yoff = $('#file').position().top + 5;

    stockPhoto.small_horizontal_layout = (
      // Small for logged-in
      !mw.user.isAnon()
      // Small for narrow media
      || (img_height < 300)
    );

    re = new RegExp('\\.(?:' + stockPhoto.horizontal_ui.map(mw.RegExp.escape).join('|') + ')$', 'i');

    horizontal = (
      // Anything small
      stockPhoto.small_horizontal_layout
      || re.test(mw.config.get('wgTitle'))
      // Window width
      || (document.documentElement.clientWidth < 1030)
    );

    // Initialize values
    stockPhoto.share_this(-1);
    html = '<div class="';
    html += (horizontal ? 'stockphoto-layout-horizontal' : 'stockphoto-layout-vertical');
    html += (stockPhoto.small_horizontal_layout ? ' stockphoto-layout-horizontal-small' : '');
    html += '"';
    if (!horizontal) {
      if (document.querySelector('body.rtl')) {
        html += ' style="right: ' + xoff + 'px; top:' + yoff + 'px;"';
      } else {
        html += ' style="left: ' + xoff + 'px; top:' + yoff + 'px;"';
      }
    }
    html += '></div>';

    $base = $(html).append(
      stockPhoto.add_button_row(stockPhoto.ui_icon_download, stockPhoto.call_download, stockPhoto.i18n.download, stockPhoto.i18n.all_sizes),
      stockPhoto.add_button_row(stockPhoto.ui_icon_web, stockPhoto.call_web, stockPhoto.i18n.use_this_file_web_short, stockPhoto.i18n.on_a_website),
      stockPhoto.add_button_row(stockPhoto.ui_icon_wiki, stockPhoto.call_wiki, stockPhoto.i18n.use_this_file_wiki_short, stockPhoto.i18n.on_a_wiki),
      stockPhoto.add_button_row(stockPhoto.ui_icon_email,
        'mailto:?subject=' + encodeURIComponent(stockPhoto.file.title) + '&body=' +
          encodeURIComponent(stockPhoto.file.backlink + '\n\n' + stockPhoto.file.credit),
        stockPhoto.i18n.email_link_short, stockPhoto.i18n.to_this_file),
      stockPhoto.add_button_row(stockPhoto.ui_icon_help,
        mw.util.getUrl('Special:MyLanguage/Commons:Reusing_content_outside_Wikimedia'),
        stockPhoto.i18n.information, stockPhoto.i18n.about_reusing),
      $('<span class="stockphoto_buttonrow"><a title="' + stockPhoto.i18n.remove_icons + '" class="stockphoto_buttonrow_icon"><img src="' + stockPhoto.ui_icon_remove + '"></a></span>')
        .click(function () {
          $.cookie('StockPhotoDisabled', true, {
            expires: 60, // days
            path: '/'
          });
          $base.remove();
          $orgItems.show();
        })
    );
    if (stockPhoto.small_horizontal_layout) {
      $orgItems.hide();
      $('#filetoc').append($base);
    } else {
      $('#filetoc').after($base);
    }
  },

  add_button_row: function (icon_url, fn, txt, html) {
    var ret,
      size = 50;
    if (stockPhoto.small_horizontal_layout) {
      size = 20;
      // HiDPI "Retina" icon
      icon_url = icon_url.replace('/50px-', window.devicePixelRatio > 1.0 ? '/40px-' : '/20px-');
    }

    ret = document.createElement(typeof fn === 'string' ? 'a' : 'span');
    ret.className = 'stockphoto_buttonrow';
    ret.title = txt + ' ' + html;
    if (typeof fn === 'string') {
      ret.href = fn;
    } else {
      ret.role = 'button';
      ret.tabIndex = 0;
      ret.onclick = fn;
    }
    ret.innerHTML = '<span class="stockphoto_buttonrow_icon"><img width="' + size + '" height="' + size + '" src="' + icon_url + '"></span>' +
      '<span class="stockphoto_buttonrow_text"><a>' + txt + '</a><small>' + html + '</small></span>';
    return ret;
  },

  stockphoto_get_thumbnail_url: function (width) {
    var thumb_url, alt_title, last;
    if (stockPhoto.file.audio) {
      return stockPhoto.ogg_icon;
    }
    alt_title = mw.config.get('wgCanonicalNamespace') + ':' + mw.config.get('wgTitle');
    $('#file img').each(function () {
      var i = this.alt;
      if (i && i !== alt_title) {
        return;
      }
      thumb_url = this.src.split('/');
    });
    // Special case of mwEmbed rewrite
    if (!thumb_url && $('#mwe_ogg_player_1').length) {
      return $('#mwe_ogg_player_1').find('img').attr('src');
    }
    if (!thumb_url || !thumb_url.length)
      return;

    last = thumb_url.pop().replace(/^\d+px-/, width + 'px-');
    thumb_url.push(last);
    thumb_url = thumb_url.join('/');
    return thumb_url;
  },

  is_audio_video_asset: function (url) {
    var ext = url.substr(-3);
    return (ext === 'ogv' || ext === 'ogg' || ext === 'oga' || ext === 'ebm');
  },

  /**
   * @param e {jQuery.Event} [optional]
   */
  make_html_textarea: function (e) {
    var width, type, height, thumb_url, t;

    if(e) {
      e.preventDefault();
    }

    width = $('#stockphoto_html_select').val();
    type = $('input[name="stockphoto_code_type"]:checked').val();

    // Iframe share for mwEmbed player
    if (stockPhoto.is_audio_video_asset(stockPhoto.file.backlink) && type === 'html') {
      // Get the ratio (from html or from mwEmbed player)
      height = $('#mwe_ogg_player_1').width()
        ? width * $('#mwe_ogg_player_1').height() / $('#mwe_ogg_player_1').width()
        : width * $('#file img,#file video').height() / $('#file img,#file video').width();

      if (height === 0) {
        // For audio that has zero height
        height = 20;
      }
      $('#stockphoto_html').text('<iframe src="' + stockPhoto.file.backlink +
        '?embedplayer=yes" width="' + width + '" height="'+ height + '" frameborder="0" ></iframe>');
      return;
    }

    thumb_url = stockPhoto.stockphoto_get_thumbnail_url(width);

    if (type === 'html') {
      t = '<a title="' + mw.html.escape(stockPhoto.file.credit) +
        '" href="' + stockPhoto.file.backlink + '"><img width="' + width + '" alt="' +
        mw.html.escape(stockPhoto.file.title) + '" src="' + thumb_url + '"></a>';
    } else if (type === 'bbcode') {
      t = '[url=' + stockPhoto.file.backlink + '][img]' +
        thumb_url + '[/img][/url]\n[url=' + stockPhoto.file.backlink + ']' +
        stockPhoto.file.title + '[/url]' + stockPhoto.file.getLicense() + ', ' +
        stockPhoto.i18n.by + ' ' + stockPhoto.file.author + ', ' +
        stockPhoto.i18n.from_wikimedia_commons;
    }
    $('#stockphoto_html').text(t);
  },

  // Event 'change' on input#stockphoto_attribution_html
  refresh_attribution: function () {
    $('#stockphoto_attribution').val(stockPhoto.file[this.checked ? 'creditHtml' : 'credit']);
  },

  createDialogRow: function (label, prefill, id, append) {
    var idtext = id ? ('id="' + id + '"') : '';
    return '<div class="stockphoto_dialog_row"><b>' + label + ':</b><br><input type="text" readonly ' + idtext + ' onClick="select()" value="' + prefill + '">' + (append || '') + '</div>';
  },

  share_this: function (ui_mode) {
    var widths, html, dtitle, dl_links, best_fit,
      pixelStr, widthSearchMatch, imageWidth, power, i;

    stockPhoto.file = new File({
      pageName: mw.config.get('wgPageName'),
      originalUrl: $('div.fullMedia a').prop('href') || '',
      info: {
        $src: $('#fileinfotpl_src + td'),
        $aut: $('#fileinfotpl_aut + td')
      },
      $creator: $('#creator'),
      license: {
        $aut: $('.licensetpl_aut').eq(0),
        $attr: $('.licensetpl_attr').eq(0),
        $credit: $('#fileinfotpl_credit + td')
      },
      $licenses: $('.licensetpl')
    });

    // Grab width in pixel from DOM, and trim it down
    // This does not yet work for SVGs or videos
    widths = [];
    try {
      pixelStr = $('.fileInfo').contents().get(0).data;
      widthSearchMatch = /([0-9 ,.\u00a0]+)\s*×/.exec(pixelStr);
      imageWidth = parseInt(widthSearchMatch[1].replace(/[ ,.\u00a0]/g, ''), 10);
      if (isNaN(imageWidth)) {
        throw new Error('Cannot parse');
      }

      // Calculate to which power of two we should go
      power = Math.floor(Math.log(imageWidth) / Math.log(2));

      // Push 6 width to array
      for (i = 0; i < 5; i++) {
        widths.push(Math.pow(2, power-i));
      }
      widths = widths.reverse();

    } catch (e) {
      widths = [75, 100, 120, 240, 500, 640, 800, 1024];
    }
    if (ui_mode === -1) {
      return;
    }

    html = '';
    html += stockPhoto.createDialogRow(stockPhoto.i18n.page_url, mw.html.escape(stockPhoto.file.backlink));
    html += stockPhoto.createDialogRow(stockPhoto.i18n.file_url, mw.html.escape(stockPhoto.file.url));
    html += stockPhoto.createDialogRow(stockPhoto.i18n.attribution, mw.html.escape(stockPhoto.file.credit),
      'stockphoto_attribution',
      '<input id="stockphoto_attribution_html" type="checkbox"><label for="stockphoto_attribution_html">' + stockPhoto.i18n.html + '</label>'
    );
    if (stockPhoto.file.gfdlNote) {
      html += '<span class="stockphoto_note">' + stockPhoto.i18n.gfdl_warning + '</span>';
    }
    if (!stockPhoto.file.attrRequired) {
      html += '<br><span class="stockphoto_note">' + stockPhoto.i18n.no_attr + '</span>';
    }

    switch (ui_mode) {
    case 1:

      dtitle = stockPhoto.i18n.download_this_file;
      if (stockPhoto.file.url) {
        html += '<div><b>' + stockPhoto.i18n.download_image_file + ':</b><br>';
        dl_links = [];
        widths.forEach(function (v) {
          if (stockPhoto.file.audio) {
            return;
          }
          dl_links.push('<a href="' + stockPhoto.stockphoto_get_thumbnail_url(v) + '" download>' + v + 'px</a>');
        });
        dl_links.push('<a href="' + stockPhoto.file.url + '" download>' + stockPhoto.i18n.full_resolution + '</a>');
        if (dl_links.length) {
          html += dl_links.join(' | ');
        } else {
          html += '<i>' + stockPhoto.i18n.not_available + '</i>';
        }
        html += '</div>';
      }

      break;

    case 2:
      dtitle = stockPhoto.i18n.use_this_file_web;
      html += '<div class="stockphoto_dialog_row"><div style="float: right;">';
      html += '<input type="radio" name="stockphoto_code_type" value="html" id="stockphoto_code_type_html" onchange="stockPhoto.make_html_textarea();" checked><label for="stockphoto_code_type_html">' + stockPhoto.i18n.html + '</label> ';
      html += '<input type="radio" name="stockphoto_code_type" value="bbcode" id="stockphoto_code_type_bbcode" onchange="stockPhoto.make_html_textarea();"><label for="stockphoto_code_type_bbcode">' + stockPhoto.i18n.bbcode + '</label> ';

      html += '<select id="stockphoto_html_select" onchange="stockPhoto.make_html_textarea();">';
      best_fit = 75;
      if (stockPhoto.file.audio) {
        best_fit = 120;
        html += '<option value="120">120' + stockPhoto.i18n.px_wide_icon + '</option>';
      } else {
        widths.forEach(function (v) {
          if (v <= $('#file img').width()) {
            best_fit = v;
          }
          html += '<option value="' + v + '">' + v + stockPhoto.i18n.px_wide + '</option>';
        });
      }
      html += '</select></div>';
      html += '<b>' + stockPhoto.i18n.html + '/' + stockPhoto.i18n.bbcode + ':</b><textarea onclick="select()" id="stockphoto_html" readonly>';
      html += '</textarea></div>';

      break;

    case 3:
      dtitle = stockPhoto.i18n.use_this_file_wiki;

      html = stockPhoto.createDialogRow(stockPhoto.i18n.thumbnail, mw.html.escape('[[File:' + mw.config.get('wgTitle') + '|thumb|' + stockPhoto.file.title + ']]'));
      html += stockPhoto.createDialogRow(stockPhoto.i18n.image, mw.html.escape('[[File:' + mw.config.get('wgTitle') + '|' + stockPhoto.file.title + ']]'));

      break;
    }

    $('<div style="display: none;"></div>').html(html).dialog({
      modal: true,
      width: 610,
      height: 'auto',
      title: dtitle,
      close: function () {
        $(this).remove();
      }
    });
    $('#stockphoto_html_select').val(best_fit);

    stockPhoto.make_html_textarea();
    $('#stockphoto_attribution_html').on('change', stockPhoto.refresh_attribution);
  },

  call_download: function () {
    stockPhoto.share_this(1);
  },

  call_web: function () {
    stockPhoto.share_this(2);
  },

  call_wiki: function () {
    stockPhoto.share_this(3);
  },

  i18n: {
    // Download:
    // - Button label
    download: 'Download',
    // - Button caption
    all_sizes: 'all sizes',
    // - Dialog title
    download_this_file: 'Download this file',

    // Use web:
    // - Button label
    use_this_file_web_short: 'Use this file',
    // - Button caption
    on_a_website: 'on the web',
    // - Dialog title
    use_this_file_web: 'Use this file on the web',

    // Use wiki:
    // - Button label
    use_this_file_wiki_short: 'Use this file',
    // - Button caption
    on_a_wiki: 'on a wiki',
    // - Dialog title
    use_this_file_wiki: 'Use this file on a wiki',
    thumbnail: 'Thumbnail',
    image: 'Image',

    // Email:
    // - Button label
    email_link_short: 'Email a link',
    // - Button caption
    to_this_file: 'to this file',

    // Reuse:
    // - Button label
    information: 'Information',
    // - Button caption
    about_reusing: 'about reusing',

    // Disable (button caption)
    remove_icons: 'Remove these icons',
    // Enable (button label)
    reuse: 'Reuse this file',

    from_wikimedia_commons: 'from Wikimedia Commons',
    via_wikimedia_commons: 'via Wikimedia Commons',
    by: 'by',
    by_u: 'By',
    see_page_for_author: 'See page for author',
    see_page_for_license: 'see page for license',
    page_url: 'Page URL',
    file_url: 'File URL',
    attribution: 'Attribution',
    no_attr: 'Attribution not legally required',
    or: 'or',
    gfdl_warning: 'Using this file might require attaching a full copy of the <a href="//en.wikipedia.org/wiki/GNU_Free_Documentation_License">GFDL</a>',
    download_image_file: 'Download image file',
    full_resolution: 'Full resolution',
    not_available: 'not available',
    share_this_file: 'Share this file',
    html: 'HTML',
    bbcode: 'BBCode',
    px_wide_icon: 'px wide (icon)',
    px_wide: 'px wide'
  }
};

/* Export */
window.stockPhoto = stockPhoto;

if (mw.config.get('wgUserLanguage') === 'en') {
  $(stockPhoto.init);
} else {
  $.ajax({
    url: mw.config.get('wgScript') + '?title=' + mw.util.wikiUrlencode('MediaWiki:Gadget-Stockphoto.js/' + mw.config.get('wgUserLanguage')) + '&action=raw&ctype=text/javascript',
    dataType: 'script',
    // @performance Browsers do HTTP 304 cache for script, but not XHR.
    // Use 'crossDomain' to trigger <script> instead of XHR.
    crossDomain: true,
    cache: true
  }).then(stockPhoto.init);
}

// i18n on subpages [[MediaWiki:stockPhoto.js/langcode]]:
// stockPhoto.i18n = { ... }
}());