r44017 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r44016‎ | r44017 | r44018 >
Date:16:45, 28 November 2008
Author:skizzerz
Status:deferred
Tags:
Comment:
* committing new extension AmazonPlus
Modified paths:
  • /trunk/extensions/AmazonPlus (added) (history)
  • /trunk/extensions/AmazonPlus/AmazonPlus.i18n.php (added) (history)
  • /trunk/extensions/AmazonPlus/AmazonPlus.js (added) (history)
  • /trunk/extensions/AmazonPlus/AmazonPlus.php (added) (history)

Diff [purge]

Index: trunk/extensions/AmazonPlus/AmazonPlus.php
@@ -0,0 +1,433 @@
 2+<?php
 3+
 4+/**
 5+ * AmazonPlus extension for MediaWiki -- a highly customizable extension to display Amazon information
 6+ * Documentation is available at http://www.mediawiki.org/wiki/Extension:AmazonPlus
 7+ *
 8+ * Copyright (c) 2008 Ryan Schmidt (Skizzerz)
 9+ *
 10+ * This program is free software; you can redistribute it and/or modify
 11+ * it under the terms of the GNU General Public License as published by
 12+ * the Free Software Foundation; either version 2 of the License, or
 13+ * (at your option) any later version.
 14+ *
 15+ * This program is distributed in the hope that it will be useful,
 16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 18+ * GNU General Public License for more details.
 19+ *
 20+ * You should have received a copy of the GNU General Public License along
 21+ * with this program; if not, write to the Free Software Foundation, Inc.,
 22+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 23+ * http://www.gnu.org/copyleft/gpl.html
 24+ */
 25+
 26+# make sure that everything that needs to be set/loaded is that way
 27+$err = '';
 28+if(!ini_get('allow_url_fopen')) {
 29+ # we need allow_url_fopen to be on in order for the file_get_contents() call to work on the amazon url
 30+ if(ini_set('allow_url_fopen', 1) === false) {
 31+ $err .= "\n<li>allow_url_fopen must be enabled in php.ini</li>";
 32+ }
 33+}
 34+if(!extension_loaded('simplexml')) {
 35+ # we need the simplexml extension loaded to parse the xml string
 36+ $err .= "\n<li>The SimpleXML extension for PHP must be loaded</li>";
 37+}
 38+# if there were errors found, die with the messages
 39+if($err) {
 40+ $html = '<html><head><title>Error</title></head><body>
 41+ The following errors were discovered with the AmazonPlus extension for MediaWiki:
 42+ <ul>' . $err . '</ul></body></html>';
 43+ echo $html;
 44+ die(1);
 45+}
 46+
 47+$wgExtensionCredits['other'][] = array(
 48+ 'name' => 'AmazonPlus',
 49+ 'description' => 'A highly customizable extension to display Amazon information',
 50+ 'descriptionmsg' => 'amazonplus-desc',
 51+ 'version' => '0.1',
 52+ 'url' => 'http://www.mediawiki.org/wiki/Extension:AmazonPlus',
 53+ 'author' => 'Ryan Schmidt',
 54+);
 55+
 56+$wgExtensionMessagesFiles['AmazonPlus'] = dirname(__FILE__) . '/AmazonPlus.i18n.php';
 57+
 58+if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
 59+ $wgHooks['ParserFirstCallInit'][] = 'efAmazonPlusSetup';
 60+} else {
 61+ $wgExtensionFunctions[] = 'efAmazonPlusSetup';
 62+}
 63+
 64+$wgHooks['BeforePageDisplay'][] = 'efAmazonPlusJavascript';
 65+
 66+$wgAmazonPlusAWS = ''; #Amazon AWS Id. Required
 67+$wgAmazonPlusAssociates = array(); #Amazon Associates IDs, per locale.Example: array( 'us' => 'myamazonid', 'fr' => 'myfrenchid' ); Required
 68+$wgAmazonPlusDefaultSearch = 'Books'; #Default search type, can be Books, DVDs, etc.
 69+$wgAmazonPlusDecimal = '.'; #What to seperate the decimals with in currency. e.g. 15.43 or 12,72
 70+
 71+#defines
 72+define('AMAZONPLUS_ALL', 0);
 73+define('AMAZONPLUS_AMAZON', 1);
 74+define('AMAZONPLUS_NEW', 2);
 75+define('AMAZONPLUS_USED', 3);
 76+
 77+# Set up the tag extension
 78+function efAmazonPlusSetup() {
 79+ global $wgParser;
 80+ $wgParser->setHook( 'amazon', 'efAmazonPlusRender' );
 81+ wfLoadExtensionMessages('AmazonPlus');
 82+ return true;
 83+}
 84+
 85+# Set up the javascript
 86+function efAmazonPlusJavascript(&$out, $sk) {
 87+ global $wgScriptPath;
 88+ $src = $wgScriptPath . '/extensions/AmazonPlus/AmazonPlus.js';
 89+ $out->addScript('<script type="text/javascript" src="'.$src.'"></script>');
 90+ return true;
 91+}
 92+
 93+# Render the tag extension
 94+function efAmazonPlusRender($input, $args, $parser) {
 95+ $title = $parser->getTitle();
 96+ #If we can, disable the time limit so queries don't time out
 97+ @set_time_limit(0);
 98+
 99+ #Parse out template parameters only before getting setting up the class so {{{1}}} and the like work
 100+ $input = $parser->replaceVariables($input, false, true);
 101+
 102+ $am = new AmazonPlus($title, $args, $input);
 103+ if(!$am instanceOf AmazonPlus) {
 104+ return wfMsg($am);
 105+ }
 106+ wfSuppressWarnings();
 107+ $s = $am->doRequest();
 108+ if($s === false) {
 109+ return wfMsg('amazonplus-nores');
 110+ } elseif($s !== true) {
 111+ return wfMsg($s);
 112+ }
 113+
 114+ $ret = $am->getResult();
 115+ $temp = $parser->mOptions->setAllowExternalImages(true);
 116+ $ret = $parser->recursiveTagParse($ret);
 117+ $ret = str_replace('%' . $am->getToken() . '%', $am->priceSelect(), $ret);
 118+ $parser->mOptions->setAllowExternalImages($temp);
 119+ wfRestoreWarnings();
 120+ return $ret;
 121+}
 122+
 123+# Class for holding/parsing information from the Amazon REST interface
 124+class AmazonPlus {
 125+ var $locale, $request, $response, $xml, $input, $error, $valid, $token, $title;
 126+
 127+ function __construct($title, $args, $input) {
 128+ global $wgAmazonPlusAWS, $wgAmazonPlusAssociates;
 129+ $this->valid = array('us', 'gb', 'ca', 'de', 'fr', 'jp');
 130+ $this->currencies = array();
 131+ $this->token = rand();
 132+ if(isset($args['locale'])) {
 133+ $this->locale = ($this->validLocale($args['locale'])) ? $args['locale'] : 'us';
 134+ } else {
 135+ $this->locale = 'us';
 136+ }
 137+ $id = (isset($args['id'])) ? $args['id'] : $this->getId($title, $args);
 138+ if(!$id) {
 139+ return 'amazonplus-noidres';
 140+ }
 141+ $this->title = $title;
 142+ $this->input = $input;
 143+ $this->request = array(
 144+ 'Service' => 'AWSECommerceService',
 145+ 'AssociateTag' => $wgAmazonPlusAssociates[$this->locale],
 146+ 'AWSAccessKeyId' => $wgAmazonPlusAWS,
 147+ 'Operation' => 'ItemLookup',
 148+ 'Version' => '2008-08-19',
 149+ 'ItemId' => $id,
 150+ 'ResponseGroup' => 'Large',
 151+ );
 152+ }
 153+
 154+ function validLocale($loc) {
 155+ global $wgAmazonPlusAssociates;
 156+ return (in_array($loc, $this->valid) && array_key_exists($loc, $wgAmazonPlusAssociates));
 157+ }
 158+
 159+ function setValue($key, $value) { $this->request[$key] = $value; }
 160+ function getValue($key) { return $this->request[$key]; }
 161+ function getToken() { return $this->token; }
 162+ function getLocale() { return $this->locale; }
 163+
 164+ function getId($title, $args) {
 165+ global $wgAmazonPlusAWS, $wgAmazonPlusAssociates, $wgAmazonPlusDefaultSearch;
 166+ $kw = (isset($args['keywords'])) ? $args['keywords'] : $title->getText();
 167+ $si = (isset($args['search'])) ? $args['search'] : $wgAmazonPlusDefaultSearch;
 168+ $this->request = array(
 169+ 'Service' => 'AWSECommerceService',
 170+ 'Operation' => 'ItemSearch',
 171+ 'ResponseGroup' => 'ItemIds',
 172+ 'Version' => '2008-08-19',
 173+ 'Keywords' => $kw,
 174+ 'AWSAccessKeyId'=> $wgAmazonPlusAWS,
 175+ 'SearchIndex' => $si,
 176+ 'AssociateTag' => $wgAmazonPlusAssociates[$this->locale],
 177+ );
 178+ $this->doRequest();
 179+ if(!$this->xml->Items->TotalResults) {
 180+ return false;
 181+ }
 182+ return $this->xml->Items->Item[0]->ASIN;
 183+ }
 184+
 185+ function doRequest() {
 186+ $tld = $this->localeString();
 187+ $str = "http://ecs.amazonaws.{$tld}/onca/xml";
 188+ $i = false;
 189+ foreach($this->request as $key => $value) {
 190+ if($i) {
 191+ $str .= '&';
 192+ } else {
 193+ $str .= '?';
 194+ $i = true;
 195+ }
 196+ $str .= wfUrlencode($key) . '=' . wfUrlencode($value);
 197+ }
 198+
 199+ $this->response = file_get_contents($str);
 200+ if($this->response === false) {
 201+ return 'amazonplus-fgcerr';
 202+ }
 203+
 204+ $this->xml = simplexml_load_string($this->response);
 205+ if($this->xml === false) {
 206+ return 'amazonplus-slserr';
 207+ }
 208+
 209+ if($this->xml->Items->TotalResults == '0') {
 210+ return false;
 211+ }
 212+ return true;
 213+ }
 214+
 215+ function getResult() {
 216+ $item = $this->xml->Items->Item;
 217+ $imageset = $item->ImageSets->ImageSet;
 218+ $attr = $item->ItemAttributes;
 219+ $editorials = $item->EditorialReviews->EditorialReview;
 220+ $reviews = $item->CustomerReviews;
 221+ $links = array();
 222+ foreach($item->ItemLinks->ItemLink as $link) {
 223+ $links[str_replace(' ', '', $link->Description)] = $link->URL;
 224+ }
 225+ $replace = array(
 226+ /* IMAGES */
 227+ 'largeimage' => $imageset->LargeImage->URL,
 228+ 'mediumimage' => $imageset->MediumImage->URL,
 229+ 'smallimage' => $imageset->SmallImage->URL,
 230+ 'tinyimage' => $imageset->TinyImage->URL,
 231+ 'swatchimage' => $imageset->SwatchImage->URL,
 232+ 'thumbnail' => $imageset->ThumbnailImage->URL,
 233+ /* REVIEWS AND RATINGS */
 234+ 'review' => $editorials->Content,
 235+ 'reviewlink' => $links['AllCustomerReviews'],
 236+ 'source' => $editorials->Source,
 237+ 'rating' => $reviews->AverageRating,
 238+ 'stars' => $this->starsImage($reviews->AverageRating),
 239+ 'total' => $reviews->TotalReviews,
 240+ /* PRICES */
 241+ 'price' => $this->formatPrice($item, AMAZONPLUS_ALL),
 242+ 'price-amazon' => $this->formatPrice($item, AMAZONPLUS_AMAZON),
 243+ 'price-new' => $this->formatPrice($item, AMAZONPLUS_NEW),
 244+ 'price-used' => $this->formatPrice($item, AMAZONPLUS_USED),
 245+ 'price-us' => $this->getPrice('us', $item->ASIN, AMAZONPLUS_ALL),
 246+ 'price-gb' => $this->getPrice('gb', $item->ASIN, AMAZONPLUS_ALL),
 247+ 'price-ca' => $this->getPrice('ca', $item->ASIN, AMAZONPLUS_ALL),
 248+ 'price-de' => $this->getPrice('de', $item->ASIN, AMAZONPLUS_ALL),
 249+ 'price-jp' => $this->getPrice('jp', $item->ASIN, AMAZONPLUS_ALL),
 250+ 'price-fr' => $this->getPrice('fr', $item->ASIN, AMAZONPLUS_ALL),
 251+ 'price-us-amazon' => $this->getPrice('us', $item->ASIN, AMAZONPLUS_AMAZON),
 252+ 'price-gb-amazon' => $this->getPrice('gb', $item->ASIN, AMAZONPLUS_AMAZON),
 253+ 'price-ca-amazon' => $this->getPrice('ca', $item->ASIN, AMAZONPLUS_AMAZON),
 254+ 'price-de-amazon' => $this->getPrice('de', $item->ASIN, AMAZONPLUS_AMAZON),
 255+ 'price-jp-amazon' => $this->getPrice('jp', $item->ASIN, AMAZONPLUS_AMAZON),
 256+ 'price-fr-amazon' => $this->getPrice('fr', $item->ASIN, AMAZONPLUS_AMAZON),
 257+ 'price-us-new' => $this->getPrice('us', $item->ASIN, AMAZONPLUS_NEW),
 258+ 'price-gb-new' => $this->getPrice('gb', $item->ASIN, AMAZONPLUS_NEW),
 259+ 'price-ca-new' => $this->getPrice('ca', $item->ASIN, AMAZONPLUS_NEW),
 260+ 'price-de-new' => $this->getPrice('de', $item->ASIN, AMAZONPLUS_NEW),
 261+ 'price-jp-new' => $this->getPrice('jp', $item->ASIN, AMAZONPLUS_NEW),
 262+ 'price-fr-new' => $this->getPrice('fr', $item->ASIN, AMAZONPLUS_NEW),
 263+ 'price-us-used' => $this->getPrice('us', $item->ASIN, AMAZONPLUS_USED),
 264+ 'price-gb-used' => $this->getPrice('gb', $item->ASIN, AMAZONPLUS_USED),
 265+ 'price-ca-used' => $this->getPrice('ca', $item->ASIN, AMAZONPLUS_USED),
 266+ 'price-de-used' => $this->getPrice('de', $item->ASIN, AMAZONPLUS_USED),
 267+ 'price-jp-used' => $this->getPrice('jp', $item->ASIN, AMAZONPLUS_USED),
 268+ 'price-fr-used' => $this->getPrice('fr', $item->ASIN, AMAZONPLUS_USED),
 269+ 'compare' => '%' . $this->token . '%',
 270+ 'offers' => $links['AllOffers'],
 271+ /* DETAILS */
 272+ 'url' => $item->DetailPageURL,
 273+ 'author' => $attr->Author,
 274+ 'actor' => $attr->Actor,
 275+ 'title' => $attr->Title,
 276+ 'binding' => $attr->Binding,
 277+ 'pages' => $attr->NumberOfPages,
 278+ 'edition' => $attr->Edition,
 279+ 'releaseyear' => $this->parseDate($attr->ReleaseDate, 0),
 280+ 'releasemonth' => $this->parseDate($attr->ReleaseDate, 1),
 281+ 'releaseday' => $this->parseDate($attr->ReleaseDate, 2),
 282+ 'publishedyear' => $this->parseDate($attr->PublicationDate, 0),
 283+ 'publishedmonth' => $this->parseDate($attr->PublicationDate, 1),
 284+ 'publishedday' => $this->parseDate($attr->PublicationDate, 2),
 285+ 'detailslink' => $links['Technical Details'],
 286+ /* IDENTIFICATION */
 287+ 'isbn' => $attr->ISBN,
 288+ 'asin' => $item->ASIN,
 289+ 'ean' => $item->EAN,
 290+ /* PURCHASING URLS */
 291+ 'buy' => $item->DetailPageURL,
 292+ 'buy-us' => $this->getUrl('us', $item->ASIN),
 293+ 'buy-gb' => $this->getUrl('gb', $item->ASIN),
 294+ 'buy-ca' => $this->getUrl('ca', $item->ASIN),
 295+ 'buy-de' => $this->getUrl('de', $item->ASIN),
 296+ 'buy-jp' => $this->getUrl('jp', $item->ASIN),
 297+ 'buy-fr' => $this->getUrl('fr', $item->ASIN),
 298+ );
 299+
 300+ foreach($replace as $find => $rep) {
 301+ $this->input = str_replace('%'.$find.'%', $rep, $this->input);
 302+ }
 303+ return $this->input;
 304+ }
 305+
 306+ function starsImage($rating) {
 307+ $rating = str_replace('.', '-', $rating);
 308+ return 'http://g-ecx.images-amazon.com/images/G/01/x-locale/common/customer-reviews/ratings/stars-'.$rating.'._V25749327_.gif';
 309+ }
 310+
 311+ function parseDate($date, $segment) {
 312+ $pieces = explode('-', $date);
 313+ return $pieces[$segment];
 314+ }
 315+
 316+ function getPrice($loc, $asin, $type) {
 317+ #if it isn't in the input, then don't do the query to save time
 318+ switch($type) {
 319+ case AMAZONPLUS_ALL:
 320+ $app = '';
 321+ break;
 322+ case AMAZONPLUS_AMAZON:
 323+ $app = '-amazon';
 324+ break;
 325+ case AMAZONPLUS_NEW:
 326+ $app = '-new';
 327+ break;
 328+ case AMAZONPLUS_USED:
 329+ $app = '-used';
 330+ break;
 331+ }
 332+ if(strpos($this->input, "%price-{$loc}{$app}%") === false)
 333+ return '';
 334+ #do we already have this info?
 335+ if($loc == $this->locale)
 336+ return $this->formatPrice($this->xml->Items->Item, $type);
 337+ $ap = new AmazonPlus($this->title, array('locale' => $loc, 'id' => $asin), "%price{$app}%");
 338+ #if we can't get the right locale, stop early
 339+ if($ap->getLocale() != $loc)
 340+ return ''; #Perhaps this should be an error message?
 341+ $ap->doRequest();
 342+ return $ap->getResult();
 343+ }
 344+
 345+ function getUrl($loc, $asin) {
 346+ #if it isn't in the input, then don't do the query to save time
 347+ if(strpos($this->input, "%buy-{$loc}%") === false)
 348+ return '';
 349+ #do we already have this info?
 350+ if($loc == $this->locale)
 351+ return $this->xml->Items->Item->DetailPageURL;
 352+ $ap = new AmazonPlus($this->title, array('locale' => $loc, 'id' => $asin), '%buy%');
 353+ #if we can't get the right locale, stop early
 354+ if($ap->getLocale() != $loc)
 355+ return ''; #Perhaps this should be an error message?
 356+ $ap->doRequest();
 357+ return $ap->getResult();
 358+ }
 359+
 360+ function priceSelect() {
 361+ $html = '<select onchange="javascript:convertPrices();">
 362+<option id="cp-none" value="cp-none">' . wfMsgHtml('amazonplus-cp-none') . '</option>
 363+<option id="cp-usd" value="cp-usd">' . wfMsgHtml('amazonplus-cp-usd') . '</option>
 364+<option id="cp-cad" value="cp-cad">' . wfMsgHtml('amazonplus-cp-cad') . '</option>
 365+<option id="cp-gbp" value="cp-gbp">' . wfMsgHtml('amazonplus-cp-gbp') . '</option>
 366+<option id="cp-eur" value="cp-eur">' . wfMsgHtml('amazonplus-cp-eur') . '</option>
 367+<option id="cp-jpy" value="cp-jpy">' . wfMsgHtml('amazonplus-cp-jpy') . '</option>
 368+</select>';
 369+ return $html;
 370+ }
 371+
 372+ function formatPrice($offer, $type) {
 373+ global $wgAmazonPlusDecimal;
 374+ if($offer->Offers->TotalOffers != '0' && ($type == AMAZONPLUS_ALL || $type == AMAZONPLUS_AMAZON)) {
 375+ $amount = $offer->Offers->Offer->OfferListing->Price->Amount;
 376+ $code = $offer->Offers->Offer->OfferListing->Price->CurrencyCode;
 377+ $extra[] = 'amazonplus-amazon';
 378+ $err = false;
 379+ } elseif($offer->OfferSummary->TotalNew != '0' && ($type == AMAZONPLUS_ALL || $type == AMAZONPLUS_NEW)) {
 380+ $amount = $offer->OfferSummary->LowestNewPrice->Amount;
 381+ $code = $offer->OfferSummary->LowestNewPrice->CurrencyCode;
 382+ $extra[] = 'amazonplus-new';
 383+ $err = false;
 384+ } elseif($offer->TotalUsed != '0' && ($type == AMAZONPLUS_ALL || $type == AMAZONPLUS_USED)) {
 385+ $amount = $offer->OfferSummary->LowestUsedPrice->Amount;
 386+ $code = $offer->OfferSummary->LowestUsedPrice->CurrencyCode;
 387+ $extra[] = 'amazonplus-used';
 388+ $err = false;
 389+ } else {
 390+ $err = 'amazonplus-none';
 391+ }
 392+ if($err) {
 393+ return wfMsg($err);
 394+ }
 395+ foreach($offer->ItemAttributes->Languages as $lang) {
 396+ if($lang->Type != 'Published') continue;
 397+ $extra[] = 'amazonplus-' . strtolower($lang->Name);
 398+ break;
 399+ }
 400+ $app = '';
 401+ $params = '';
 402+ $i = 0;
 403+ foreach($extra as $val) {
 404+ $msg = wfMsg($val);
 405+ if($msg == '') continue;
 406+ if($i++ != 0) $params .= wfMsg('amazonplus-status-sep');
 407+ $params .= $msg;
 408+ }
 409+ if($params) $app = ' '.wfMsg('amazonplus-status', $params);
 410+ $begin = substr($amount, 0, strlen($amount)-2);
 411+ $end = substr($amount, -2);
 412+ switch($this->locale) {
 413+ case 'us': $sign = '&#36;'; break;
 414+ case 'ca': $sign = '&#36;'; break;
 415+ case 'de': $sign = '&euro;'; break;
 416+ case 'fr': $sign = '&euro;'; break;
 417+ case 'jp': $sign = '&yen;'; break;
 418+ case 'gb': $sign = '&pound;'; break;
 419+ }
 420+ return wfMsg('amazonplus-currency', array($begin . $wgAmazonPlusDecimal . $end, $code, $sign, $app));
 421+ }
 422+
 423+ function localeString() {
 424+ switch($this->locale) {
 425+ case 'us': return 'com';
 426+ case 'gb': return 'co.uk';
 427+ case 'ca': return 'ca';
 428+ case 'jp': return 'jp';
 429+ case 'fr': return 'fr';
 430+ case 'de': return 'de';
 431+ }
 432+ return 'com';
 433+ }
 434+}
\ No newline at end of file
Property changes on: trunk/extensions/AmazonPlus/AmazonPlus.php
___________________________________________________________________
Added: svn:eol-style
1435 + native
Index: trunk/extensions/AmazonPlus/AmazonPlus.js
@@ -0,0 +1,3 @@
 2+function convertPrices() {
 3+ return;
 4+}
\ No newline at end of file
Property changes on: trunk/extensions/AmazonPlus/AmazonPlus.js
___________________________________________________________________
Added: svn:eol-style
15 + native
Index: trunk/extensions/AmazonPlus/AmazonPlus.i18n.php
@@ -0,0 +1,28 @@
 2+<?php
 3+
 4+$messages = array();
 5+
 6+$messages['en'] = array(
 7+ 'amazonplus-desc' => 'A highly customizable extension to display Amazon information',
 8+ 'amazonplus-nores' => '<span class="error">Error: No results found!</span>',
 9+ 'amazonplus-noidres' => '<span class="error">Error: Could not find a product ID!</span>',
 10+ 'amazonplus-fgcerr' => '<span class="error">Error: Could not retrieve data from Amazon!</span>',
 11+ 'amazonplus-slserr' => '<span class="error">Error: Could not parse data from Amazon!</span>',
 12+ 'amazonplus-used' => 'used',
 13+ 'amazonplus-german' => 'german',
 14+ 'amazonplus-french' => 'french',
 15+ 'amazonplus-japanese' => 'japanese',
 16+ 'amazonplus-english' => '',
 17+ 'amazonplus-amazon' => 'amazon price',
 18+ 'amazonplus-new' => 'new',
 19+ 'amazonplus-status' => '($1)',
 20+ 'amazonplus-status-sep' => ', ',
 21+ 'amazonplus-none' => 'No copies of this item are up for sale.',
 22+ 'amazonplus-currency' => '$3$1 $2$4',
 23+ 'amazonplus-cp-none' => 'None',
 24+ 'amazonplus-cp-usd' => 'USD',
 25+ 'amazonplus-cp-cad' => 'CAD',
 26+ 'amazonplus-cp-gbp' => 'GBP',
 27+ 'amazonplus-cp-eur' => 'EUR',
 28+ 'amazonplus-cp-jpy' => 'JPY',
 29+);
\ No newline at end of file
Property changes on: trunk/extensions/AmazonPlus/AmazonPlus.i18n.php
___________________________________________________________________
Added: svn:eol-style
130 + native

Status & tagging log