]> git.mjollnir.org Git - s9y.git/commitdiff
Simplify and beautify code; allow admin config to override most text options;
authorslothman <slothman>
Mon, 11 Feb 2008 02:12:07 +0000 (02:12 +0000)
committerslothman <slothman>
Mon, 11 Feb 2008 02:12:07 +0000 (02:12 +0000)
graphical rating bars (at last!)

19 files changed:
plugins/serendipity_event_karma/ChangeLog
plugins/serendipity_event_karma/UTF-8/lang_bg.inc.php
plugins/serendipity_event_karma/UTF-8/lang_de.inc.php
plugins/serendipity_event_karma/UTF-8/lang_es.inc.php
plugins/serendipity_event_karma/UTF-8/lang_fr.inc.php
plugins/serendipity_event_karma/UTF-8/lang_ja.inc.php
plugins/serendipity_event_karma/UTF-8/lang_ko.inc.php
plugins/serendipity_event_karma/UTF-8/lang_pl.inc.php
plugins/serendipity_event_karma/UTF-8/lang_pt_PT.inc.php
plugins/serendipity_event_karma/UTF-8/lang_ru.inc.php
plugins/serendipity_event_karma/UTF-8/lang_tn.inc.php
plugins/serendipity_event_karma/UTF-8/lang_zh.inc.php
plugins/serendipity_event_karma/lang_cn.inc.php
plugins/serendipity_event_karma/lang_cs.inc.php
plugins/serendipity_event_karma/lang_cz.inc.php
plugins/serendipity_event_karma/lang_de.inc.php
plugins/serendipity_event_karma/lang_en.inc.php
plugins/serendipity_event_karma/lang_zh.inc.php
plugins/serendipity_event_karma/serendipity_event_karma.php

index 5dcf9145c19555ead1a48396ae47bf7839b2fd47..136462f84be3fcc4392e799bbd88ff16cfd472a5 100644 (file)
@@ -1,5 +1,10 @@
 # $Id: ChangeLog,v 1.27 2007/10/25 13:56:39 brockhaus Exp $\r
 \r
+------------------------------------------------------------------------\r
+Version 2.0 (gregman):\r
+\r
+    * Included new option to change to animated voting based on images.\r
+\r
 ------------------------------------------------------------------------\r
 Version 1.4 (brockhaus):\r
 \r
index c961067e2f5469803cc726641a34f98bf267a7e9..4fa826161aabb182f06cfda2f0042bc7c88b2363 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH', 'Дава възможност посетителите да оценяват качеството на вашите статии');
 @define('PLUGIN_KARMA_VOTETEXT', 'Карма за тази статия: ');
 @define('PLUGIN_KARMA_RATE', 'Оецнете тази статия: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Много добра!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Добра');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Много добра!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Добра');
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Неутрална');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Безинтересна');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Лоша');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Безинтересна');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Лоша');
 @define('PLUGIN_KARMA_VOTED', 'Вашата оценка "%s" беше записана.');
 @define('PLUGIN_KARMA_INVALID', 'Вашето гласуване е невалидно.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Вашата оецнка вече е записана.');
@@ -48,6 +48,3 @@
 @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'точки');
 
 @define('PLUGIN_KARMA_STARRATING', 'Разрешаване на индивидуална оценка на тази статия?');
-
-@define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS', 'Следене на визитите на регистрираните посетители?');
-@define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS_BLAHBLAH', 'При избор \'Да\', посещенията на регистрираните посетители (потребители) ще бъдат броени.');
index 24674278864b661fa1b541d77ceb805c0cc1fe48..2559499572760f11bfa5297804817c4df226fa71 100644 (file)
@@ -1,26 +1,31 @@
 <?php # $Id$
 
-        @define('PLUGIN_KARMA_VERSION', '1.3');
+        @define('PLUGIN_KARMA_VERSION', '2.0');
         @define('PLUGIN_KARMA_NAME', 'Karma');
         @define('PLUGIN_KARMA_BLAHBLAH', 'Abstimmung über die Einträge');
         @define('PLUGIN_KARMA_VOTETEXT', 'Karma dieses Eintrags: ');
+        @define('PLUGIN_KARMA_VOTETEXT_IMAGE', 'aktuelle Bewertung:');
         @define('PLUGIN_KARMA_RATE', 'Eintrag bewerten: %s');
-        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Sehr gut!');
-        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Gut');
-        @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutral');
-        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Uninteressant');
-        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Übel');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Sehr gut');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Gut');
+        @define('PLUGIN_KARMA_VOTEPOINT_3', 'Ok');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Uninteressant');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Schlecht');
         @define('PLUGIN_KARMA_VOTED', 'Punktzahl "%s" gespeichert.');
+        @define('PLUGIN_KARMA_VOTED_IMAGE', 'Bewertung gespeichert.');
+        @define('PLUGIN_KARMA_VOTES', '%3$s Stimme(n)');
         @define('PLUGIN_KARMA_INVALID', 'Bewertung ungültig oder manipuliert!');
         @define('PLUGIN_KARMA_ALREADYVOTED', 'Bewertung bereits gespeichert.');
         @define('PLUGIN_KARMA_NOCOOKIE', 'Der Browser muss Cookies unterstützen um eine Abstimmung zu ermöglichen.');
-        @define('PLUGIN_KARMA_CLOSED', 'Stimm ab für Artikel, die jünger als %s Tage sind!');
+        @define('PLUGIN_KARMA_CLOSED', 'Abstimmungszeitraum abgelaufen.');
         @define('PLUGIN_KARMA_ENTRYTIME', 'Abstimmungszeitraum nach Veröffentlichung eines Artikels');
         @define('PLUGIN_KARMA_VOTINGTIME', 'Abstimmungszeitraum');
         @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'Wie lang (in Minuten) kann nach der Veröffentlichung eines Artikels ein uneingeschränkter Abstimmungszeitraum durchgeführt werden? Standard sind 1440 Minuten (ein Tag).');
         @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Wartezeit (in Minuten), die nach einer Stimmabgabe vergehen muss bevor eine nächste Stimme angenommen wird. Diese Einschränkung gilt erst nach Überschreitung des obigen uneingeschränkten Abstimmungszeitraumes. Standard: 5 Minuten.');
         @define('PLUGIN_KARMA_TIMEOUT', 'Wahlschutz: Ein anderer Besucher hat gerade abgestimmt. Bitte %s Minuten warten.');
         @define('PLUGIN_KARMA_CURRENT', 'Derzeitiges Karma: %2$s, %3$s Stimme(n)');
+        @define('PLUGIN_KARMA_CURRENT_IMAGE', 'aktuelle Bewertung:');
+        @define('PLUGIN_KARMA_CURRENT_IMAGE_ALT', 'aktuelle Bewertung: %2$1.2f von 5');
         @define('PLUGIN_KARMA_EXTENDEDONLY', 'Nur erweiterte Artikel');
         @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Karmavoting nur im erweiterten Artikel einblenden');
         @define('PLUGIN_KARMA_MAXKARMA', 'Maximaler Abstimmungszeitraum');
@@ -44,3 +49,6 @@
 
         @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS', 'Aufrufstatistik auch für eingeloggte Benutzer?');
         @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS_BLAHBLAH', 'Wenn diese Option eingeschaltet ist, dann werden auch die Besuche von eingeloggten Benutzern protokolliert.');
+        
+        @define('PLUGIN_KARMA_BASEIMAGE', 'Animation');
+        @define('PLUGIN_KARMA_BASEIMAGE_DESC', 'Wähle eine Bilddatei aus (z.B. diamonds.png), um die Punkteskala grafisch darzustellen. Wähle \'' . PLUGIN_KARMA_STATISTICS_POINTS_NO . '\' für textbasiertes Voting. Sämtliche notwendigen Grafikdateien findest Du im Image-Verzeichnis.');
index dbde7c385acf9c8b22ceb0698d96cc0285dc6bd7..0d8ab8eaf129f83c14837fa58d02296108a76cc1 100644 (file)
@@ -9,11 +9,11 @@
 @define('PLUGIN_KARMA_BLAHBLAH', 'Permite a los visitantes calificar la calidad de tus entradas');
 @define('PLUGIN_KARMA_VOTETEXT', 'Karma de este artículo: ');
 @define('PLUGIN_KARMA_RATE', 'Califica este artículo: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', '¡Muy bueno!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Bueno');
+@define('PLUGIN_KARMA_VOTEPOINT_5', '¡Muy bueno!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Bueno');
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Regular');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'No es interesante');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Malo');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'No es interesante');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Malo');
 @define('PLUGIN_KARMA_VOTED', 'Tu calificación de "%s" ha sido guardada.');
 @define('PLUGIN_KARMA_INVALID', 'Tu voto fue inválido.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Tu calificación ya habia sido almacenada.');
index 71bf2a262cde57c90b9d5ce1af846b0f8343f02b..471dba708c21f57f48c704831441c53c0035be28 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH', 'Donne à vos visiteurs la possibilité de noter vos billets');
 @define('PLUGIN_KARMA_VOTETEXT', 'Karma de cet article: ');
 @define('PLUGIN_KARMA_RATE', 'Noter cet article: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Excellent!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Bon');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Excellent!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Bon');
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutre');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Pas intéressant');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Mauvais');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Pas intéressant');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Mauvais');
 @define('PLUGIN_KARMA_VOTED', 'Votre notation "%s" a été enregistrée.');
 @define('PLUGIN_KARMA_INVALID', 'Votre notation est invalide.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Votre notation a déjà été enregistrée.');
index 7764a155aafa58f64ee109f6159d64845f21ab51..d36ad108386fe956c48ca79a287b13a17723417c 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH', '訪問者にあなたのエントリの品質を評価させます。');
 @define('PLUGIN_KARMA_VOTETEXT', 'この記事の評価: ');
 @define('PLUGIN_KARMA_RATE', 'この記事の評価: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'とても素晴らしい!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', '素晴らしい');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'とても素晴らしい!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', '素晴らしい');
 @define('PLUGIN_KARMA_VOTEPOINT_3', '普通');
-@define('PLUGIN_KARMA_VOTEPOINT_4', '面白くない');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'よくない');
+@define('PLUGIN_KARMA_VOTEPOINT_2', '面白くない');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'よくない');
 @define('PLUGIN_KARMA_VOTED', 'あなたの評価 "%s" は保管されました。');
 @define('PLUGIN_KARMA_INVALID', 'あなたの投票は無効でした。');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'あなたは既に評価が保管されていました。');
index 39fe6d8e9702b80168020d9e67e01267af3f491d..d0264abd2ace2f161d458f60aa61750a0dc3289e 100644 (file)
@@ -7,11 +7,11 @@
         @define('PLUGIN_KARMA_BLAHBLAH', '작성된 글에 대해 방문자가 평가를 매길 수 있게 함');
         @define('PLUGIN_KARMA_VOTETEXT', '이 글에 대한 카르마 점수: ');
         @define('PLUGIN_KARMA_RATE', '이 글을 평가한다면: %s');
-        @define('PLUGIN_KARMA_VOTEPOINT_1', '매우 좋음');
-        @define('PLUGIN_KARMA_VOTEPOINT_2', '좋음');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', '매우 좋음');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', '좋음');
         @define('PLUGIN_KARMA_VOTEPOINT_3', '평범함');
-        @define('PLUGIN_KARMA_VOTEPOINT_4', '흥미 없음');
-        @define('PLUGIN_KARMA_VOTEPOINT_5', '나쁨');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', '흥미 없음');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', '나쁨');
         @define('PLUGIN_KARMA_VOTED', '평가 등급이 "%s"으로 매겨졌습니다.');
         @define('PLUGIN_KARMA_INVALID', '유효한 투표가 이루어지지 않았습니다.');
         @define('PLUGIN_KARMA_ALREADYVOTED', '이미 평가가 매겨졌습니다.');
index 6ce80d37acec483b4ea2c04d8cff40475e16e7f9..d95996de57fbe6e3f9b8d0d156da758b4194a681 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH', 'Niechaj odwiedzający Twoją stronę ocenią jakość Twoich wpisów');
 @define('PLUGIN_KARMA_VOTETEXT', 'Karma dla tego artykułu: ');
 @define('PLUGIN_KARMA_RATE', 'Oceń ten wpis: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Bardzo dobry!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Dobry');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Bardzo dobry!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Dobry');
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutralny');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Nie interesujący');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Zły');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Nie interesujący');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Zły');
 @define('PLUGIN_KARMA_VOTED', 'Twoja ocena "%s" została zachowana.');
 @define('PLUGIN_KARMA_INVALID', 'Twoje ocenianie nie przebiegło prawidłowo.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Twoja ocena została już zachowana.');
index 85b8d21c7d5b51c7c6994831fb1312b9399bbf58..7fb8b3db543b3ddf987ae2ecd75ec413a4480a4f 100644 (file)
@@ -9,11 +9,11 @@
 @define('PLUGIN_KARMA_BLAHBLAH', 'Permite aos visitantes classificar a qualidade das suas entradas');
 @define('PLUGIN_KARMA_VOTETEXT', 'Karma deste artigo: ');
 @define('PLUGIN_KARMA_RATE', 'Classifica este artigo: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Muito bom!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Bom');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Muito bom!');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Bom');
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Regular');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Sem interesse');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Mau');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Sem interesse');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Mau');
 @define('PLUGIN_KARMA_VOTED', 'A sua classificação de "%s" foi guardada.');
 @define('PLUGIN_KARMA_INVALID', 'Voto inválido.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'A sua classificação já tinha sido guardada.');
index 6ee102625f4312d9d6b3774befc726cf3ee906e6..d2de4b50b1d9738099081147c38b380e2cb4e665 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH', 'Позволяет посетителям оценивать ваши записи');\r
 @define('PLUGIN_KARMA_VOTETEXT', 'Карма этой статьи: ');\r
 @define('PLUGIN_KARMA_RATE', 'Оцените эту статью: %s');\r
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Очень хорошо!');\r
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Хорошо');\r
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Очень хорошо!');\r
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Хорошо');\r
 @define('PLUGIN_KARMA_VOTEPOINT_3', 'Нормально');\r
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Не интересно');\r
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Ужасно');\r
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Не интересно');\r
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Ужасно');\r
 @define('PLUGIN_KARMA_VOTED', 'Выбранная вами оценка "%s" сохранена.');\r
 @define('PLUGIN_KARMA_INVALID', 'Ваш голос не учтен из-за ошибки системы голосования. Да здравствует демократия!');\r
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Ваш голос уже был учтен.');\r
index 2bf1e5cc91cb0bd70d9d3840e4f2f2f17bf2e738..0aeaab00e5457d13adff837c805d53d9eb7853b8 100644 (file)
         @define('PLUGIN_KARMA_BLAHBLAH', '允許訪客評價文章');\r
         @define('PLUGIN_KARMA_VOTETEXT', '評價值: ');\r
         @define('PLUGIN_KARMA_RATE', '評價值: %s');\r
-        @define('PLUGIN_KARMA_VOTEPOINT_1', '很好!');\r
-        @define('PLUGIN_KARMA_VOTEPOINT_2', '好');\r
+        @define('PLUGIN_KARMA_VOTEPOINT_5', '很好!');\r
+        @define('PLUGIN_KARMA_VOTEPOINT_4', '好');\r
         @define('PLUGIN_KARMA_VOTEPOINT_3', '沒意見');\r
-        @define('PLUGIN_KARMA_VOTEPOINT_4', '沒興趣');\r
-        @define('PLUGIN_KARMA_VOTEPOINT_5', '不好');\r
+        @define('PLUGIN_KARMA_VOTEPOINT_2', '沒興趣');\r
+        @define('PLUGIN_KARMA_VOTEPOINT_1', '不好');\r
         @define('PLUGIN_KARMA_VOTED', '您的評價 "%s" 已送出。');\r
         @define('PLUGIN_KARMA_INVALID', '您的評價錯誤。');\r
         @define('PLUGIN_KARMA_ALREADYVOTED', '您已經提供評價。');\r
index 3a7694f4618273a8b39562973c297034d9593621..fb2bc4a1aa80bcce2e87e829fd6e9ddb17308722 100644 (file)
@@ -1,43 +1,56 @@
-<?php
+<?php # $Id$
+##########################################################################
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity    #
+# Developer Team) All rights reserved.  See LICENSE file for licensing   #
+# details                                                               #
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2006 Aphonex Li <aphonex.li@gmail.com>                             #
+#               http://www.exten.cn                                      #
+##########################################################################
 
-@define('PLUGIN_KARMA_NAME', '文章打分');
-@define('PLUGIN_KARMA_BLAHBLAH', '允许访客通过打分的方式评价你的文章质量');
-@define('PLUGIN_KARMA_VOTETEXT', '对此文章进行打分: ');
-@define('PLUGIN_KARMA_RATE', '对此文章的打分: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', '非常好');
-@define('PLUGIN_KARMA_VOTEPOINT_2', '还不错');
-@define('PLUGIN_KARMA_VOTEPOINT_3', '一般般');
-@define('PLUGIN_KARMA_VOTEPOINT_4', '没兴趣');
-@define('PLUGIN_KARMA_VOTEPOINT_5', '挺糟糕');
-@define('PLUGIN_KARMA_VOTED', '你打的分“ %s ”已被保存。');
-@define('PLUGIN_KARMA_INVALID', '你的打分无效。');
-@define('PLUGIN_KARMA_ALREADYVOTED', '你已经打过分了。');
-@define('PLUGIN_KARMA_NOCOOKIE', '你的浏览器必须支持cookies才能对文章进行打分。');
-@define('PLUGIN_KARMA_CLOSED', '请对 %s 天内更新的文章进行打分');
-@define('PLUGIN_KARMA_ENTRYTIME', '文章发表后允许访客打分的时间');
-@define('PLUGIN_KARMA_VOTINGTIME', '打分的时间间隔');
-@define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', '文章发布多长时间(按分钟计算)以后就允许无限制的打分? 默认: 1440 (一天)');
-@define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', '每次打分后要间隔多长时间(按分钟计算)以后才能进行下次打分?此设置仅对上述设置“文章发表后允许访客打分的时间”所设置的时间到期后的文章有效。默认: 5');
-@define('PLUGIN_KARMA_TIMEOUT', '灌水保护:其它访客刚刚提交了打分,请等待  %s 分钟后再提交你的打分。');
-@define('PLUGIN_KARMA_CURRENT', '当前分数: %2$s 。 %3$s 次打分。');
-@define('PLUGIN_KARMA_EXTENDEDONLY', '仅限于文章的扩展内容');
-@define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', '仅在文章的扩展内容浏览中打分工具');
-@define('PLUGIN_KARMA_MAXKARMA', '允许打分的时限');
-@define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', '只允许对 X 天更新的文章进行打分 (默认:7)');
-@define('PLUGIN_KARMA_LOGGING', '记录打分信息');
-@define('PLUGIN_KARMA_LOGGING_BLAHBLAH', '是否要记录打分信息?');
-@define('PLUGIN_KARMA_ACTIVE', '允许打分');
-@define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', '允许对文章打分吗?');
-@define('PLUGIN_KARMA_VISITS', '是否跟踪记录访问信息?');
-@define('PLUGIN_KARMA_VISITS_BLAHBLAH', '是否把对扩展内容的访问也计算在内并显示出来呢?');
-@define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s 次点击');
-@define('PLUGIN_KARMA_STATISTICS_VISITS_TOP', '访问次数最多的文章');
-@define('PLUGIN_KARMA_STATISTICS_VISITS_BOTTOM', '访问次数最少的文章');
-@define('PLUGIN_KARMA_STATISTICS_VOTES_TOP', '总分最高的文章');
-@define('PLUGIN_KARMA_STATISTICS_VOTES_BOTTOM', '总分最低的文章');
-@define('PLUGIN_KARMA_STATISTICS_POINTS_TOP', '均分最高的文章');
-@define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', '均分最低的文章');
-@define('PLUGIN_KARMA_STATISTICS_VISITS_NO', '访问');
-@define('PLUGIN_KARMA_STATISTICS_VOTES_NO', '次数');
-@define('PLUGIN_KARMA_STATISTICS_POINTS_NO', '分数');
-@define('PLUGIN_KARMA_STARRATING', '对这篇文章使用单独的打分方式吗?');
+        @define('PLUGIN_KARMA_VERSION', '1.3');
+        @define('PLUGIN_KARMA_NAME', '评价');
+        @define('PLUGIN_KARMA_BLAHBLAH', '允许访客评论文章');
+        @define('PLUGIN_KARMA_VOTETEXT', '评价值: ');
+        @define('PLUGIN_KARMA_RATE', '评价值: %s');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', '很好');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', '好');
+        @define('PLUGIN_KARMA_VOTEPOINT_3', '没意见');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', '没意见');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', '不好');
+        @define('PLUGIN_KARMA_VOTED', '你的评价 "%s" 已送出。');
+        @define('PLUGIN_KARMA_INVALID', '你的评价错误。');
+        @define('PLUGIN_KARMA_ALREADYVOTED', '你已经提交评价。');
+        @define('PLUGIN_KARMA_NOCOOKIE', '你的浏览器必须支持 cookies 才能进行评价。');
+        @define('PLUGIN_KARMA_CLOSED', '请评价 %s 天内的文章');
+        @define('PLUGIN_KARMA_ENTRYTIME', '公开文章后可以评价的时间');
+        @define('PLUGIN_KARMA_VOTINGTIME', '评价时间');
+        @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', '公开文章后多久 (分钟) 可允许无限制的评价?预设:1440 (一天)');
+        @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', '要等多久 (分钟) 才能进行下一个评价?必须等输入的时候后才生效。预设:5');
+        @define('PLUGIN_KARMA_TIMEOUT', '灌水保护:其它访客刚提交评价,请稍等 %s 分钟在提交您的评价。');
+        @define('PLUGIN_KARMA_CURRENT', '评价值: %2$s, %3$s 次评价');
+        @define('PLUGIN_KARMA_EXTENDEDONLY', '显示文章的副内容');
+        @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', '只在文章的副内容显示评价');
+        @define('PLUGIN_KARMA_MAXKARMA', '评价天数');
+        @define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', '只允许小于 X 天的文章进行评价 (预设:7)');
+        @define('PLUGIN_KARMA_LOGGING', '记录评价');
+        @define('PLUGIN_KARMA_LOGGING_BLAHBLAH', '要记录评价值吗?');
+        @define('PLUGIN_KARMA_ACTIVE', '允许评价');
+        @define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', '允许文章评价吗?');
+        @define('PLUGIN_KARMA_VISITS', '记录访问次数?');
+        @define('PLUGIN_KARMA_VISITS_BLAHBLAH', '要记录和显示访客浏览副文章的次数吗?');
+        @define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s 次浏览');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_TOP', '浏览最多的文章');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_BOTTOM', '浏览最少的文章');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_TOP', '最多评价值的文章');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_BOTTOM', '最少评价值的文章');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_TOP', '最多评价值的文章');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', '最少评价值的文章');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_NO', '浏览');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', '评价');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', '评价值');
+?>
index 3a7694f4618273a8b39562973c297034d9593621..0e3e1624aa7ba9cac407d60431d54b1140d05822 100644 (file)
@@ -4,11 +4,11 @@
 @define('PLUGIN_KARMA_BLAHBLAH', '允许访客通过打分的方式评价你的文章质量');
 @define('PLUGIN_KARMA_VOTETEXT', '对此文章进行打分: ');
 @define('PLUGIN_KARMA_RATE', '对此文章的打分: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', '非常好');
-@define('PLUGIN_KARMA_VOTEPOINT_2', '还不错');
+@define('PLUGIN_KARMA_VOTEPOINT_5', '非常好');
+@define('PLUGIN_KARMA_VOTEPOINT_4', '还不错');
 @define('PLUGIN_KARMA_VOTEPOINT_3', '一般般');
-@define('PLUGIN_KARMA_VOTEPOINT_4', '没兴趣');
-@define('PLUGIN_KARMA_VOTEPOINT_5', '挺糟糕');
+@define('PLUGIN_KARMA_VOTEPOINT_2', '没兴趣');
+@define('PLUGIN_KARMA_VOTEPOINT_1', '挺糟糕');
 @define('PLUGIN_KARMA_VOTED', '你打的分“ %s ”已被保存。');
 @define('PLUGIN_KARMA_INVALID', '你的打分无效。');
 @define('PLUGIN_KARMA_ALREADYVOTED', '你已经打过分了。');
index 0a63c08593c76c2ace2b514c122651a236b70685..77b7d1a74d1b91331b45a0b2e745f9074b411433 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH',                    'Ètenáøi hodnotí kvalitu Va\9aich pøíspìvkù');
 @define('PLUGIN_KARMA_VOTETEXT',                    'Karma tohoto èlánku: ');
 @define('PLUGIN_KARMA_RATE',                        'Ohodno\9d tento èlánek: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1',                 'Dost dobrý!');
-@define('PLUGIN_KARMA_VOTEPOINT_2',                 'Dobrý');
+@define('PLUGIN_KARMA_VOTEPOINT_5',                 'Dost dobrý!');
+@define('PLUGIN_KARMA_VOTEPOINT_4',                 'Dobrý');
 @define('PLUGIN_KARMA_VOTEPOINT_3',                 'Prùmer');
-@define('PLUGIN_KARMA_VOTEPOINT_4',                 'Nezajímavý');
-@define('PLUGIN_KARMA_VOTEPOINT_5',                 'Mizerný');
+@define('PLUGIN_KARMA_VOTEPOINT_2',                 'Nezajímavý');
+@define('PLUGIN_KARMA_VOTEPOINT_1',                 'Mizerný');
 @define('PLUGIN_KARMA_VOTED',                       'Vy\9ae hodnocení "%s" bylo zaznamenáno.');
 @define('PLUGIN_KARMA_INVALID',                     'Va\9ae hlasování je neplatné.');
 @define('PLUGIN_KARMA_ALREADYVOTED',                'Ji\9e jste hlasoval.');
index cad35266c63d4862bec6a44d7bc7f9692d3a6269..335fb69904a61d588962f408da809a42c3050f03 100644 (file)
 @define('PLUGIN_KARMA_BLAHBLAH',                    'Ètenáøi hodnotí kvalitu Va¹ich pøíspìvkù');
 @define('PLUGIN_KARMA_VOTETEXT',                    'Karma tohoto èlánku: ');
 @define('PLUGIN_KARMA_RATE',                        'Ohodno» tento èlánek: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1',                 'Dost dobrý!');
-@define('PLUGIN_KARMA_VOTEPOINT_2',                 'Dobrý');
+@define('PLUGIN_KARMA_VOTEPOINT_5',                 'Dost dobrý!');
+@define('PLUGIN_KARMA_VOTEPOINT_4',                 'Dobrý');
 @define('PLUGIN_KARMA_VOTEPOINT_3',                 'Prùmer');
-@define('PLUGIN_KARMA_VOTEPOINT_4',                 'Nezajímavý');
-@define('PLUGIN_KARMA_VOTEPOINT_5',                 'Mizerný');
+@define('PLUGIN_KARMA_VOTEPOINT_2',                 'Nezajímavý');
+@define('PLUGIN_KARMA_VOTEPOINT_1',                 'Mizerný');
 @define('PLUGIN_KARMA_VOTED',                       'Vy¹e hodnocení "%s" bylo zaznamenáno.');
 @define('PLUGIN_KARMA_INVALID',                     'Va¹e hlasování je neplatné.');
 @define('PLUGIN_KARMA_ALREADYVOTED',                'Ji¾ jste hlasoval.');
index ace88647d2dd9c8e613c36ec96ea01772ef4e4b2..4f40e0ec344d0ab75959ab07032446c77a15c0e1 100644 (file)
@@ -1,26 +1,31 @@
 <?php # $Id$
 
-        @define('PLUGIN_KARMA_VERSION', '1.3');
+        @define('PLUGIN_KARMA_VERSION', '2.0');
         @define('PLUGIN_KARMA_NAME', 'Karma');
         @define('PLUGIN_KARMA_BLAHBLAH', 'Abstimmung über die Einträge');
         @define('PLUGIN_KARMA_VOTETEXT', 'Karma dieses Eintrags: ');
+        @define('PLUGIN_KARMA_VOTETEXT_IMAGE', 'aktuelle Bewertung:');
         @define('PLUGIN_KARMA_RATE', 'Eintrag bewerten: %s');
-        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Sehr gut!');
-        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Gut');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Sehr gut!');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Gut');
         @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutral');
-        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Uninteressant');
-        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Übel');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Uninteressant');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Übel');
         @define('PLUGIN_KARMA_VOTED', 'Punktzahl "%s" gespeichert.');
+        @define('PLUGIN_KARMA_VOTED_IMAGE', 'Bewertung gespeichert.');
+        @define('PLUGIN_KARMA_VOTES', '%3$s Stimme(n)');
         @define('PLUGIN_KARMA_INVALID', 'Bewertung ungültig oder manipuliert!');
         @define('PLUGIN_KARMA_ALREADYVOTED', 'Bewertung bereits gespeichert.');
         @define('PLUGIN_KARMA_NOCOOKIE', 'Der Browser muss Cookies unterstützen um eine Abstimmung zu ermöglichen.');
-        @define('PLUGIN_KARMA_CLOSED', 'Stimm ab für Artikel, die jünger als %s Tage sind!');
+        @define('PLUGIN_KARMA_CLOSED', 'Abstimmungszeitraum abgelaufen.');
         @define('PLUGIN_KARMA_ENTRYTIME', 'Abstimmungszeitraum nach Veröffentlichung eines Artikels');
         @define('PLUGIN_KARMA_VOTINGTIME', 'Abstimmungszeitraum');
         @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'Wie lang (in Minuten) kann nach der Veröffentlichung eines Artikels ein uneingeschränkter Abstimmungszeitraum durchgeführt werden? Standard sind 1440 Minuten (ein Tag).');
         @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Wartezeit (in Minuten), die nach einer Stimmabgabe vergehen muss bevor eine nächste Stimme angenommen wird. Diese Einschränkung gilt erst nach Überschreitung des obigen uneingeschränkten Abstimmungszeitraumes. Standard: 5 Minuten.');
         @define('PLUGIN_KARMA_TIMEOUT', 'Wahlschutz: Ein anderer Besucher hat gerade abgestimmt. Bitte %s Minuten warten.');
         @define('PLUGIN_KARMA_CURRENT', 'Derzeitiges Karma: %2$s, %3$s Stimme(n)');
+        @define('PLUGIN_KARMA_CURRENT_IMAGE', 'aktuelle Bewertung:');
+        @define('PLUGIN_KARMA_CURRENT_IMAGE_ALT', 'aktuelle Bewertung: %2$1.2f von 5');
         @define('PLUGIN_KARMA_EXTENDEDONLY', 'Nur erweiterte Artikel');
         @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Karmavoting nur im erweiterten Artikel einblenden');
         @define('PLUGIN_KARMA_MAXKARMA', 'Maximaler Abstimmungszeitraum');
@@ -42,6 +47,8 @@
         @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', 'Stimmen');
         @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'Punkte');
 
-
         @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS', 'Aufrufstatistik auch für eingeloggte Benutzer?');
         @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS_BLAHBLAH', 'Wenn diese Option eingeschaltet ist, dann werden auch die Besuche von eingeloggten Benutzern protokolliert.');
+
+        @define('PLUGIN_KARMA_BASEIMAGE', 'Animation');
+        @define('PLUGIN_KARMA_BASEIMAGE_DESC', 'Wähle eine Bilddatei aus (z.B. diamonds.png), um die Punkteskala grafisch darzustellen. Wähle \'' . PLUGIN_KARMA_STATISTICS_POINTS_NO . '\' für textbasiertes Voting. Sämtliche notwendigen Grafikdateien findest Du im Image-Verzeichnis.');
index 6a8a8b922b19cff9b44d39da7067e0cbb0f4bd99..2a5805946f8f2a6fca3985a26c23ab25045c07ce 100644 (file)
@@ -7,33 +7,68 @@
  */
 
 @define('PLUGIN_KARMA_NAME', 'Karma');
-@define('PLUGIN_KARMA_BLAHBLAH', 'Let visitors rate the quality of your entries');
+@define('PLUGIN_KARMA_BLAHBLAH', 'Let visitors rate your entries');
 @define('PLUGIN_KARMA_VOTETEXT', 'Karma for this article: ');
+@define('PLUGIN_KARMA_VOTETEXT_NAME', 'Rating Request Message');
+@define('PLUGIN_KARMA_VOTETEXT_NAME_BLAHBLAH', 'The text to use when displaying a bar for voting.  (Default: \'' . PLUGIN_KARMA_VOTETEXT . '\')');
 @define('PLUGIN_KARMA_RATE', 'Rate this article: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', 'Very good!');
-@define('PLUGIN_KARMA_VOTEPOINT_2', 'Good');
-@define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutral');
-@define('PLUGIN_KARMA_VOTEPOINT_4', 'Not interesting');
-@define('PLUGIN_KARMA_VOTEPOINT_5', 'Bad');
+@define('PLUGIN_KARMA_VOTEPOINT_5', 'Excellent!');
+@define('PLUGIN_KARMA_VOTEPOINT_5_NAME', 'Best Rating Description');
+@define('PLUGIN_KARMA_VOTEPOINT_5_BLAHBLAH', 'The text to use for tooltips when considering the best possible rating. (Default: \'' . PLUGIN_KARMA_VOTEPOINT_5 . '\')');
+@define('PLUGIN_KARMA_VOTEPOINT_4', 'Good');
+@define('PLUGIN_KARMA_VOTEPOINT_4_NAME', 'Good Rating Description');
+@define('PLUGIN_KARMA_VOTEPOINT_4_BLAHBLAH', 'The text to use for tooltips when considering the good rating. (Default: ' . PLUGIN_KARMA_VOTEPOINT_4 . ')');
+@define('PLUGIN_KARMA_VOTEPOINT_3', 'Okay');
+@define('PLUGIN_KARMA_VOTEPOINT_3_NAME', 'Neutral Rating Description');
+@define('PLUGIN_KARMA_VOTEPOINT_3_BLAHBLAH', 'The text to use for tooltips when considering the neutral rating. (Default: ' . PLUGIN_KARMA_VOTEPOINT_3 . ')');
+@define('PLUGIN_KARMA_VOTEPOINT_2', 'Bad');
+@define('PLUGIN_KARMA_VOTEPOINT_2_NAME', 'Poor Rating Description');
+@define('PLUGIN_KARMA_VOTEPOINT_2_BLAHBLAH', 'The text to use for tooltips when considering the poor rating. (Default: ' . PLUGIN_KARMA_VOTEPOINT_2 . ')');
+@define('PLUGIN_KARMA_VOTEPOINT_1', 'Terrible!');
+@define('PLUGIN_KARMA_VOTEPOINT_1_NAME', 'Worst Rating Description');
+@define('PLUGIN_KARMA_VOTEPOINT_1_BLAHBLAH', 'The text to use for tooltips when considering the worst possible rating. (Default: ' . PLUGIN_KARMA_VOTEPOINT_1 . ')');
+@define('PLUGIN_KARMA_VOTETEXT_5', '+2');
+@define('PLUGIN_KARMA_VOTETEXT_5_NAME', 'Best Rating Display');
+@define('PLUGIN_KARMA_VOTETEXT_5_BLAHBLAH', 'The text to display in the text rating bar for the best possible rating. (Default: ' . PLUGIN_KARMA_VOTETEXT_5 . ')');
+@define('PLUGIN_KARMA_VOTETEXT_4', '+1');
+@define('PLUGIN_KARMA_VOTETEXT_4_NAME', 'Good Rating Display');
+@define('PLUGIN_KARMA_VOTETEXT_4_BLAHBLAH', 'The text to display in the text rating bar for the good rating. (Default: ' . PLUGIN_KARMA_VOTETEXT_4 . ')');
+@define('PLUGIN_KARMA_VOTETEXT_3', '0');
+@define('PLUGIN_KARMA_VOTETEXT_3_NAME', 'Neutral Rating Display');
+@define('PLUGIN_KARMA_VOTETEXT_3_BLAHBLAH', 'The text to display in the text rating bar for the neutral rating. (Default: ' . PLUGIN_KARMA_VOTETEXT_3 . ')');
+@define('PLUGIN_KARMA_VOTETEXT_2', '-1');
+@define('PLUGIN_KARMA_VOTETEXT_2_NAME', 'Poor Rating Display');
+@define('PLUGIN_KARMA_VOTETEXT_2_BLAHBLAH', 'The text to display in the text rating bar for the poor rating. (Default: ' . PLUGIN_KARMA_VOTETEXT_2 . ')');
+@define('PLUGIN_KARMA_VOTETEXT_1', '-2');
+@define('PLUGIN_KARMA_VOTETEXT_1_NAME', 'Worst Rating Display');
+@define('PLUGIN_KARMA_VOTETEXT_1_BLAHBLAH', 'The text to display in the text rating bar for the worst possible rating. (Default: ' . PLUGIN_KARMA_VOTETEXT_1 . ')');
 @define('PLUGIN_KARMA_VOTED', 'Your rating "%s" was stored.');
+@define('PLUGIN_KARMA_VOTES', '%3$s Vote(s)');
 @define('PLUGIN_KARMA_INVALID', 'Your voting was invalid.');
 @define('PLUGIN_KARMA_ALREADYVOTED', 'Your rating was already stored.');
 @define('PLUGIN_KARMA_NOCOOKIE', 'Your browser must support cookies to be able to vote.');
 @define('PLUGIN_KARMA_CLOSED', 'Vote for articles fresher than %s days!');
-@define('PLUGIN_KARMA_ENTRYTIME', 'Voting time after publishing');
-@define('PLUGIN_KARMA_VOTINGTIME', 'Voting time');
-@define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'How long (in minutes) after your article has been published an unrestricted voting is allowed? Default: 1440 (one day)');
-@define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Amount of time (in minutes) that needs to be passed from one vote to the other. Is only applied after the time above is expired. Default: 5');
+@define('PLUGIN_KARMA_ENTRYTIME', 'Grace Period');
+@define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'How long (in minutes) after your article has been published will unrestricted voting (no minimum voting interval) be allowed? Default: 1440 (one day)');
+@define('PLUGIN_KARMA_VOTINGTIME', 'Minimum voting interval');
+@define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Amount of time (in minutes) that needs to be passed between votes. Use 0 to allow unrestricted voting forever. (Default: 5)');
 @define('PLUGIN_KARMA_TIMEOUT', 'Flood protection: Another visitor has just recently voted. Please wait %s minutes.');
 @define('PLUGIN_KARMA_CURRENT', 'Current karma: %2$s, %3$s vote(s)');
+@define('PLUGIN_KARMA_CURRENT_NAME', 'Current Rating Message');
+@define('PLUGIN_KARMA_CURRENT_NAME_BLAHBLAH', 'The text to use when displaying the current rating (%2$s is the numerical rating; %3$s is the number of votes) (Default: ' . PLUGIN_KARMA_CURRENT . ')');
 @define('PLUGIN_KARMA_EXTENDEDONLY', 'Only extended article');
-@define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Only show karmavoting on extended article view');
+@define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Only show karmavoting on extended article view?');
 @define('PLUGIN_KARMA_MAXKARMA', 'Karmavoting period');
-@define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', 'Only allow karmavoting until the article is X days old (Default: 7)');
-@define('PLUGIN_KARMA_LOGGING', 'Log votes?');
-@define('PLUGIN_KARMA_LOGGING_BLAHBLAH', 'Should karma votes be logged?');
-@define('PLUGIN_KARMA_ACTIVE', 'Enable karma voting?');
+@define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', 'Forbid voting on articles older than X days; 0 allows voting on all articles. (Default: 7)');
+@define('PLUGIN_KARMA_MIN_DISPLAYABLE_VOTES', 'Minimum Votes to Display');
+@define('PLUGIN_KARMA_MIN_DISPLAYABLE_VOTES_BLAHBLAH', 'Supress current rating and vote count until this number of votes have been cast.  Use 0 to display vote count regardless of how many have been cast.');
+@define('PLUGIN_KARMA_LOGGING', 'Log votes');
+@define('PLUGIN_KARMA_LOGGING_BLAHBLAH', 'Will karma votes be logged?');
+@define('PLUGIN_KARMA_ACTIVE', 'Enable karma voting');
 @define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', 'Is karma voting turned on?');
+//--JAM:@define('PLUGIN_KARMA_ALIGNMENT', 'Voting Bar Alignment');
+//--JAM:@define('PLUGIN_KARMA_ALIGNMENT_BLAHBLAH', 'Alignment of voting bar in the entry footer.  Templates can override this setting with !important (Default: right)');
+//--JAM: @define('PLUGIN_KARMA_ALIGNMENT_DETECT', 'from style');
 @define('PLUGIN_KARMA_VISITS', 'Enable visit tracking?');
 @define('PLUGIN_KARMA_VISITS_BLAHBLAH', 'Should every click to an extended article be counted and displayed?');
 @define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s hits');
 @define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', 'Worst karma-voted articles');
 @define('PLUGIN_KARMA_STATISTICS_VISITS_NO', 'visits');
 @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', 'votes');
-@define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'points');
+@define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'text only');
 
 @define('PLUGIN_KARMA_STARRATING', 'Enable individual rating on this entry?');
 
 @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS', 'Track visits of logged in users?');
 @define('PLUGIN_KARMA_VISITS_LOGGEDIN_USERS_BLAHBLAH', 'If this option is enabled, page visits of users who are logged in are tracked, too.');
+@define('PLUGIN_KARMA_MIN_DISPLAYABLE_VISITS', 'Minimum Visits to Display');
+@define('PLUGIN_KARMA_MIN_DISPLAYABLE_VISITS_BLAHBLAH', 'Supress visit display until this number of visits have been recorded.  Use 0 to display visit count regardless of how many visits have been recorded.');
+@define('PLUGIN_KARMA_WORDRATING', 'Display Ratings as Text Words?');
+@define('PLUGIN_KARMA_WORDRATING_BLAHBLAH', 'Display ratings as text words or as numbers? (Default: no; use numerical ratings)');
+@define('PLUGIN_KARMA_IMAGE_WITH_MESSAGE', 'Display Rating Message?');
+@define('PLUGIN_KARMA_IMAGE_WITH_MESSAGE_BLAHBLAH', 'Include a textual rating request or status before graphic bars? (No effect on text bars) (Default: yes)');
+@define('PLUGIN_KARMA_IMAGE_WITH_CURR', 'Display Current Rating Text?');
+@define('PLUGIN_KARMA_IMAGE_WITH_CURR_BLAHBLAH', 'Include textual current rating information after graphic bars?  (No effect on text bars) (Default: yes)');
+@define('PLUGIN_KARMA_IMAGE_WITH_VISITS', 'Display Visits Text?');
+@define('PLUGIN_KARMA_IMAGE_WITH_VISITS_BLAHBLAH', 'Include textual visit count after graphic bars?  (No effect on text bars) (Default: yes)');
+@define('PLUGIN_KARMA_PREVIEW_BG', 'Background for preview table, below');
+@define('PLUGIN_KARMA_PREVIEW_BG_BLAHBLAH', 'Any CSS value is acceptable; it will be used as the \'background\' attribute for the preview table on the admin page ONLY.  No effect on actual rating bars.');
+@define('PLUGIN_KARMA_IMAGE', 'Voting Bar Type');
+@define('PLUGIN_KARMA_IMAGE_DESC', 'Choose image file (e.g. diamonds.png) for image based voting. Choose \'' . PLUGIN_KARMA_STATISTICS_POINTS_NO . '\' for text based voting.');
+@define('PLUGIN_KARMA_NO_IMAGES', 'There were no images in the plugin img/ directory!');
+@define('PLUGIN_KARMA_IMAGE_RATING', '%1.2f of 5');
+@define('PLUGIN_KARMA_IMAGE_INT_RATING', '%d of 5');
+@define('PLUGIN_KARMA_IMAGE_NONE_RATING', 'none');
+@define('PLUGIN_KARMA_TAB_OPTIONS', 'Options');
+@define('PLUGIN_KARMA_TAB_APPEARANCE', 'Appearance');
+@define('PLUGIN_KARMA_TAB_TEXT', 'Text');
index 3a7694f4618273a8b39562973c297034d9593621..0e3e1624aa7ba9cac407d60431d54b1140d05822 100644 (file)
@@ -4,11 +4,11 @@
 @define('PLUGIN_KARMA_BLAHBLAH', '允许访客通过打分的方式评价你的文章质量');
 @define('PLUGIN_KARMA_VOTETEXT', '对此文章进行打分: ');
 @define('PLUGIN_KARMA_RATE', '对此文章的打分: %s');
-@define('PLUGIN_KARMA_VOTEPOINT_1', '非常好');
-@define('PLUGIN_KARMA_VOTEPOINT_2', '还不错');
+@define('PLUGIN_KARMA_VOTEPOINT_5', '非常好');
+@define('PLUGIN_KARMA_VOTEPOINT_4', '还不错');
 @define('PLUGIN_KARMA_VOTEPOINT_3', '一般般');
-@define('PLUGIN_KARMA_VOTEPOINT_4', '没兴趣');
-@define('PLUGIN_KARMA_VOTEPOINT_5', '挺糟糕');
+@define('PLUGIN_KARMA_VOTEPOINT_2', '没兴趣');
+@define('PLUGIN_KARMA_VOTEPOINT_1', '挺糟糕');
 @define('PLUGIN_KARMA_VOTED', '你打的分“ %s ”已被保存。');
 @define('PLUGIN_KARMA_INVALID', '你的打分无效。');
 @define('PLUGIN_KARMA_ALREADYVOTED', '你已经打过分了。');
index 791294b81507714893c13acb6e55cf985bb94398..52f49c1ca998d04e42081c41011723404f4bc49f 100644 (file)
@@ -13,16 +13,39 @@ if (file_exists($probelang)) {
 
 include dirname(__FILE__) . '/lang_en.inc.php';
 
-@define('PLUGIN_KARMA_VERSION', '1.4');
+@define('PLUGIN_KARMA_VERSION', '2.0');
 
 class serendipity_event_karma extends serendipity_event
 {
+    /** @var string Status of current voting action */
     var $karmaVote    = '';
+    /** @var int ID of entry to vote on */
     var $karmaId      = '';
+    /** @var int Minutes until voting will be enabled, if a timeout is in effect */
     var $karmaTimeOut = '';
+    /** @var int Points for this entry: current vote until voting is recorded,
+     *  total points after voting is recorded 
+     */
     var $karmaVoting  = '';
+
+    /** @var string The name of the image to be used in graphic rating bars */
+    var $image_name = 'stars-def-yellow-green-md.png';
+    /** @var int The width of the rating bar image */
+    var $image_width = '';
+    /** @var int The height of the rating bar image */
+    var $image_height = '';
+
+    /** @var string The HTML to be used in backend preview */
+    var $select_html = '';
+    /** @var string The CSS to be added for backend preview */
+    var $select_css = '';
+
+    /** @var string Title if included as sidebar content */
     var $title        = PLUGIN_KARMA_NAME;
 
+    /* The max width/height ratio of a single-segment image */
+    var $max_segment_ratio = 1.0;
+
     function introspect(&$propbag)
     {
         global $serendipity;
@@ -30,21 +53,104 @@ class serendipity_event_karma extends serendipity_event
         $propbag->add('name',          PLUGIN_KARMA_NAME);
         $propbag->add('description',   PLUGIN_KARMA_BLAHBLAH);
         $propbag->add('stackable',     false);
-        $propbag->add('author',        'Garvin Hicking','Grischa Brockhaus');
-        $propbag->add('version',       '1.9');
+        $propbag->add('author',        'Garvin Hicking, Grischa Brockhaus, Gregor Völtz, Judebert');
+        $propbag->add('version',       '2.0');
         $propbag->add('requirements',  array(
             'serendipity' => '0.8',
             'smarty'      => '2.6.7',
             'php'         => '4.1.0'
         ));
-        $propbag->add('event_hooks',   array('frontend_configure' => true, 'entry_display' => true, 'css' => true, 'event_additional_statistics' => true));
+        $propbag->add('event_hooks',   array(
+            'frontend_configure'          => true, 
+            'entry_display'               => true, 
+            'css'                         => true, 
+            'backend_header'              => true, 
+            'event_additional_statistics' => true
+            ));
         $propbag->add('groups', array('STATISTICS'));
-        $propbag->add('configuration', array('karma_active', 'visits_active', 'track_visits_of_loggedin_users', 'exits_active', 'max_entrytime', 'max_votetime', 'extended_only', 'max_karmatime', 'logging'));
+        $propbag->add('configuration', array(
+            // Functionality options
+            'options_tab',
+            'karma_active', 
+            'extended_only', 
+            'max_karmatime', 
+            'max_votetime', 
+            'max_entrytime', 
+            'min_disp_votes',
+            'visits_active', 
+            'track_visits_of_loggedin_users', 
+            'min_disp_visits',
+            'exits_active', 
+            'logging', 
+            // Appearance options
+            'appearance_tab',
+            //--JAM:'alignment',
+            'rate_with_words',
+            'textual_msg',
+            'textual_current',
+            'textual_visits',
+            'preview_bg',
+            'base_image',
+            // Text/Language optins
+            'text_tab',
+            'rate_msg',
+            'curr_msg',
+            'rate_best',
+            'rate_good',
+            'rate_okay',
+            'rate_poor',
+            'rate_vile',
+            'text_best',
+            'text_good',
+            'text_okay',
+            'text_poor',
+            'text_vile',
+            // Close divs
+            'end_tabs',
+            ));
     }
 
     function introspect_config_item($name, &$propbag)
     {
         switch($name) {
+            // Top of tab bar
+            case 'options_tab':
+                $propbag->add('type', 'content');
+                $propbag->add('default', '
+<span class="serendipity_karmaVoting_tabbar">
+<a class="serendipity_karmaVoting_optionstab_link" href="#karmaVoting_options">' . PLUGIN_KARMA_TAB_OPTIONS . '</a> | 
+<a class="serendipity_karmaVoting_appearancetab_link" href="#karmaVoting_appearance">' . PLUGIN_KARMA_TAB_APPEARANCE . '</a> |
+<a class="serendipity_karmaVoting_texttab_link" href="#karmaVoting_text">' . PLUGIN_KARMA_TAB_TEXT . '</a>
+</span>
+<div class="serendipity_karmaVoting_optionstab" style="text-align: center;"><a name="karmaVoting_options"></a>
+<span style="font-size: 10pt; font-weight: bold;">' . PLUGIN_KARMA_TAB_OPTIONS . '<hr style="width: 80%" />
+');
+                break;
+            case 'appearance_tab':
+                $propbag->add('type', 'content');
+                $propbag->add('default', '
+    <input class="serendipityPrettyButton input_button" type="submit" value="Save" name="SAVECONF" />
+</div>
+<div class="serendipity_karmaVoting_appearancetab" style="text-align: center;"><a name="karmaVoting_appearance"></a>
+<span style="font-size: 10pt; font-weight: bold;">' . PLUGIN_KARMA_TAB_APPEARANCE . '<hr style="width: 80%" />
+');
+                break;
+            case 'text_tab':
+                $propbag->add('type', 'content');
+                $propbag->add('default', '
+    <input class="serendipityPrettyButton input_button" type="submit" value="Save" name="SAVECONF" />
+</div>
+<div class="serendipity_karmaVoting_texttab" style="text-align: center;"><a name="karmaVoting_text"></a> 
+<span style="font-size: 10pt; font-weight: bold;">' . PLUGIN_KARMA_TAB_TEXT . '<hr style="width: 80%" />
+');
+                break;
+            case 'end_tabs':
+                $propbag->add('type', 'content');
+                $propbag->add('default', '
+</div>
+');
+                break;
+            // Oldest entry age still valid for unrestricted voting
             case 'max_entrytime':
                 $propbag->add('type', 'string');
                 $propbag->add('name', PLUGIN_KARMA_ENTRYTIME);
@@ -52,6 +158,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 1440);
                 break;
 
+            // Min time between votes
             case 'max_votetime':
                 $propbag->add('type', 'string');
                 $propbag->add('name', PLUGIN_KARMA_VOTINGTIME);
@@ -59,6 +166,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 5);
                 break;
 
+            // Oldest entry age still valid for karma voting (normal, restricted voting)
             case 'max_karmatime':
                 $propbag->add('type', 'string');
                 $propbag->add('name', PLUGIN_KARMA_MAXKARMA);
@@ -66,6 +174,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 7);
                 break;
 
+            // Is karma voting allowed?
             case 'karma_active':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', PLUGIN_KARMA_ACTIVE);
@@ -73,6 +182,15 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'true');
                 break;
 
+            // Min votes to display
+            case 'min_disp_votes':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_MIN_DISPLAYABLE_VOTES);
+                $propbag->add('description', PLUGIN_KARMA_MIN_DISPLAYABLE_VOTES_BLAHBLAH);
+                $propbag->add('default', '0');
+                break;
+                
+            // Is extended article visit tracking allowed?
             case 'visits_active':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', PLUGIN_KARMA_VISITS);
@@ -80,6 +198,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'true');
                 break;
 
+            // Keep or ignore visits for logged in users (like admins/authors)?
             case 'track_visits_of_loggedin_users':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', PLUGIN_KARMA_VISITS_LOGGEDIN_USERS);
@@ -87,6 +206,15 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'true');
                 break;
 
+            // Min visits to display
+            case 'min_disp_visits':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_MIN_DISPLAYABLE_VISITS);
+                $propbag->add('description', PLUGIN_KARMA_MIN_DISPLAYABLE_VISITS_BLAHBLAH);
+                $propbag->add('default', '0');
+                break;
+
+            // Are we tracking exits?  
             case 'exits_active':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', SHOWS_TOP_EXIT);
@@ -94,6 +222,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'false');
                 break;
 
+            // Show karma voting on article summary, or only extended page?
             case 'extended_only':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', PLUGIN_KARMA_EXTENDEDONLY);
@@ -101,6 +230,7 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'false');
                 break;
 
+            // Log karma votes?
             case 'logging':
                 $propbag->add('type', 'boolean');
                 $propbag->add('name', PLUGIN_KARMA_LOGGING);
@@ -108,16 +238,144 @@ class serendipity_event_karma extends serendipity_event
                 $propbag->add('default', 'false');
                 break;
 
+            /*--JAM:
+            // Alignment to use for rating bars
+            case 'alignment':
+                $select = array(
+                            //--JAM: 'detect' => PLUGIN_KARMA_ALIGNMENT_DETECT,
+                            'left' => LEFT,
+                            'center' => CENTER,
+                            'right' => RIGHT);
+                $propbag->add('type', 'select');
+                $propbag->add('name', PLUGIN_KARMA_ALIGNMENT);
+                $propbag->add('description', PLUGIN_KARMA_ALIGNMENT_BLAHBLAH);
+                $propbag->add('select_values', $select);
+                $propbag->add('default', 'right');
+                break;
+             */
+            // Use words for ratings?
+            case 'rate_with_words':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_WORDRATING);
+                $propbag->add('description', PLUGIN_KARMA_WORDRATING_BLAHBLAH);
+                $propbag->add('default', 'false');
+                break;
+            case 'textual_msg':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_IMAGE_WITH_MESSAGE);
+                $propbag->add('description', PLUGIN_KARMA_IMAGE_WITH_MESSAGE_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+            case 'textual_current':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_IMAGE_WITH_CURR);
+                $propbag->add('description', PLUGIN_KARMA_IMAGE_WITH_CURR_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+            case 'textual_visits':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_IMAGE_WITH_VISITS);
+                $propbag->add('description', PLUGIN_KARMA_IMAGE_WITH_VISITS_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+            // Background of admin preview table
+            case 'preview_bg':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_PREVIEW_BG);
+                $propbag->add('description', PLUGIN_KARMA_PREVIEW_BG_BLAHBLAH);
+                $propbag->add('default', '');
+                break;
+            // Image to use for graphical rating bar
+            case 'base_image':
+                $propbag->add('type', 'content');
+                $propbag->add('default', $this->createRatingSelector());
+                break;
+            case 'rate_msg':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_NAME_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT);
+                break;
+            case 'curr_msg':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_CURRENT_NAME);
+                $propbag->add('description', PLUGIN_KARMA_CURRENT_NAME_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_CURRENT);
+                break;
+            case 'rate_best':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTEPOINT_5_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTEPOINT_5_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTEPOINT_5);
+                break;
+            case 'rate_good':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTEPOINT_4_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTEPOINT_4_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTEPOINT_4);
+                break;
+            case 'rate_okay':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTEPOINT_3_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTEPOINT_3_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTEPOINT_3);
+                break;
+            case 'rate_poor':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTEPOINT_2_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTEPOINT_2_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTEPOINT_2);
+                break;
+            case 'rate_vile':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTEPOINT_1_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTEPOINT_1_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTEPOINT_1);
+                break;
+            case 'text_best':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_5_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_5_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT_5);
+                break;
+            case 'text_good':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_4_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_4_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT_4);
+                break;
+            case 'text_okay':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_3_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_3_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT_3);
+                break;
+            case 'text_poor':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_2_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_2_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT_2);
+                break;
+            case 'text_vile':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTETEXT_1_NAME);
+                $propbag->add('description', PLUGIN_KARMA_VOTETEXT_1_BLAHBLAH);
+                $propbag->add('default', PLUGIN_KARMA_VOTETEXT_1);
+                break;
+
             default:
                     return false;
         }
         return true;
     }
 
+    /**
+     * Updates database schema when upgrading from older versions.
+     */
     function checkScheme() {
         global $serendipity;
 
-        $version = $this->get_config('version', '0.9');
+        $version = $this->get_config('version', '0.9'); 
 
         if ($version == '1.1') {
             $q   = "ALTER TABLE {$serendipity['dbPrefix']}karma ADD visits INT(11) default 0";
@@ -166,11 +424,24 @@ class serendipity_event_karma extends serendipity_event
         return true;
     }
 
+    /**
+     * Unused; would create sidebar content. 
+     */
     function generate_content(&$title)
     {
         $title       = $this->title;
     }
 
+    /**
+     * Creates an array of entries and their exit counts.
+     *
+     * @param array entries The entries to get exit counts for
+     * @param boolean get optional Whether to return the array (otherwise
+     *   does all the calculations, but returns only true) default:false
+     *
+     * @return Boolean true when $get is false; otherwise the array of
+     *   entries with their exit counts.
+     */
     function prepareExits($entries, $get = false) {
         static $exits = null;
         global $serendipity;
@@ -220,65 +491,83 @@ class serendipity_event_karma extends serendipity_event
 
     function event_hook($event, &$bag, &$eventData, $addData = null) {
         global $serendipity;
+        
 
         $hooks = &$bag->get('event_hooks');
 
         if (isset($hooks[$event])) {
+
+            // Moved from above: only get image data if we're actually going to do something
+            $this->set_valid_image_data();
+            // Get dimensions of image, only if not text-only
+            if ($this->image_name) {
+                // Is this a single-image bar, or a single segment?
+                $ratio = $this->image_width / $this->image_height;
+                if ($ratio < $max_segment_ratio) {
+                    // This is probably a single segment. Square segments
+                    // will have a ratio of 0.3; long, flat segments won't
+                    // get up to 1.0 unless they're 3 times as wide as they
+                    // are tall; full-bar images with square segments will
+                    // be 1.666; and full-bar images with tall, narrow
+                    // segments will be greater than 1.0 unless they're 
+                    // nearly twice as high as they are wide.
+                    $this->image_width = $this->image_width * 5;
+                }
+            }
+
             switch($event) {
+                // Early hook, before any page is displayed
                 case 'frontend_configure':
+                    
+                    // Make sure the karmaVote cookie is set, even if empty <a name="#1" />
                     if (!isset($serendipity['COOKIE']['karmaVote'])) {
                         serendipity_setCookie('karmaVote', serialize(array()));
                     }
 
-                    if (isset($serendipity['GET']['id'])) {
-                        $entryid = (int)serendipity_db_escape_string($serendipity['GET']['id']);
-                    } elseif (preg_match(PAT_COMMENTSUB, $_SERVER['REQUEST_URI'], $matches)) {
-                        $entryid = (int)$matches[1];
-                    } else {
-                        $entryid = false;
-                    }
-
-                    if ($entryid && empty($serendipity['GET']['adminAction'])) {
-                        $track_clicks  = serendipity_db_bool($this->get_config('visits_active', true)) && $this->track_clicks_allowed_by_user();
-                        if ($track_clicks) {
-                            $sql = serendipity_db_query('UPDATE ' . $serendipity['dbPrefix'] . 'karma SET visits = visits + 1 WHERE entryid = ' . $entryid, true);
-                            if (serendipity_db_affected_rows() < 1) {
-                                serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}karma (entryid, points, votes, lastvote, visits) VALUES ('$entryid', 0, 0, 0, 1)");
-                            }
-                        }
-                    }
-
+                    // If user didn't vote, we're done.
                     if (!isset($serendipity['GET']['karmaId']) || !isset($serendipity['GET']['karmaVote'])) {
                         return;
                     }
 
+                    // Get URL vote data
                     $this->karmaId     = (int)$serendipity['GET']['karmaId'];
                     $this->karmaVoting = (int)$serendipity['GET']['karmaVote'];
 
-                    if (!isset($serendipity['COOKIE']['karmaVote'])) {
+                    // karmaVote cookie was just set (see name="#1"); this boils down to 
+                    // "if check cookie isn't 1, there's no real cookie".
+                    // The check cookie gets set when a rater is displayed,
+                    // so you've got no business voting if you haven't even
+                    // seen the rater yet.
+                    if (!isset($serendipity['COOKIE']['karmaVote']) OR $serendipity['COOKIE']['check'] != '1') {
                         $this->karmaVote = 'nocookie';
                         return;
                     }
 
+                    // Everything is ready.  Get the cookie vote data.
                     $karma   = unserialize($serendipity['COOKIE']['karmaVote']);
 
+                    // Stop on invalid votes (cookie invalid, or URL data incorrect)
                     if (!is_array($karma) || !is_numeric($this->karmaVoting) || !is_numeric($this->karmaId) || $this->karmaVoting > 2 || $this->karmaVoting < -2) {
                         $this->karmaVote = 'invalid1';
                         return;
                     }
 
+                    // Stop if the cookie says we already voted
                     if (!empty($karma[$this->karmaId])) {
                         $this->karmaVote = 'alreadyvoted';
                         return ;
                     }
 
+                    // We don't want googlebots hitting the karma-voting
                     if (stristr($_SERVER['HTTP_USER_AGENT'], 'google')) {
-                        // We don't want googlebots hitting the karma-voting
                         $this->karmaVote = 'invalid1';
                         return ;
                     }
 
                     // Voting takes place here.
+                    // 
+                    // Get voting data from the database (keeps all entries,
+                    // even if no karma match)
                     $q = 'SELECT *
                             FROM ' . $serendipity['dbPrefix'] . 'entries AS e
                  LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'karma   AS k
@@ -286,6 +575,9 @@ class serendipity_event_karma extends serendipity_event
                            WHERE e.id = ' . serendipity_db_escape_string($this->karmaId) . ' LIMIT 1';
                     $row = serendipity_db_query($q, true);
 
+                    // If there's no entry with this ID, we're done
+                    //
+                    // --TODO: Modify the plugin to allow arbitrary voting with generated IDs
                     if (!isset($row) || !is_array($row)) {
                         $this->karmaVote = 'invalid2';
                         return;
@@ -297,12 +589,20 @@ class serendipity_event_karma extends serendipity_event
                         $max_entrytime = $this->get_config('max_entrytime', 1440) * 60;
                         $max_votetime  = $this->get_config('max_votetime', 5)     * 60;
                         $max_karmatime = $this->get_config('max_karmatime', 7)    * 24 * 60 * 60;
+                        // Allow infinite voting when 0 or negative
+                        if ($max_karmatime <= 0) {
+                            $max_karmatime = $now;
+                        }
 
+                        // If the entry's timestamp is too old for voting,
+                        // we're done.
                         if ($row['timestamp'] < ($now - $max_karmatime)) {
                             $this->karmaVote = 'timeout2';
                             return;
                         }
 
+                        // If the entry is in the grace period, or votes
+                        // aren't too close together, record the vote.
                         if (($row['timestamp'] > ($now - $max_entrytime)) || ($row['lastvote'] + $max_votetime < $now) || $row['lastvote'] == 0) {
                             // Update votes
                             $q = sprintf(
@@ -319,25 +619,29 @@ class serendipity_event_karma extends serendipity_event
 
                             serendipity_db_query($q);
                         } else {
+                            // Entry was too recently voted upon.  Figure out 
+                            // how long until voting will be allowed (in minutes).
                             $this->karmaVote    = 'timeout';
-                            $this->karmaTimeOut = abs(round(($now - ($row['lastvote'] + $max_votetime)) / 60, 1));
+                            $this->karmaTimeOut = abs(ceil(($now - ($row['lastvote'] + $max_votetime)) / 60));
                             return;
                         }
                     } else {
-                        // No Votes. Just insert it.
+                        // No row. Use INSERT instead of UPDATE.
                         $q = sprintf(
                           "INSERT INTO {$serendipity['dbPrefix']}karma
-                                       (entryid, points, votes, lastvote)
-                                VALUES (%s,      %s,     %s,    %s)",
+                                       (entryid, points, votes, lastvote, visits)
+                                VALUES (%s,      %s,     %s,    %s,       %s)",
                           $this->karmaId,
                           $this->karmaVoting,
                           1,
-                          $now
+                          $now,
+                          0
                         );
 
                         $sql = serendipity_db_query($q);
                     }
 
+                    // Log the vote
                     if (serendipity_db_bool($this->get_config('logging', false))) {
                         $q = sprintf(
                           "INSERT INTO {$serendipity['dbPrefix']}karmalog
@@ -355,6 +659,7 @@ class serendipity_event_karma extends serendipity_event
                         }
                     }
 
+                    // Set the cookie that we already voted for this entry
                     $karma[$this->karmaId] = $this->karmaVoting;
                     $this->karmaVote       = 'voted';
                     serendipity_setCookie('karmaVote', serialize($karma));
@@ -362,21 +667,127 @@ class serendipity_event_karma extends serendipity_event
                     return true;
                     break;
 
+                // CSS generation hooks
+                case 'backend_header':
+                    // Generate the CSS for the graphical rating bar selector
+                    // 
+                    // The CSS appears to be generated in a completely 
+                    // different instance of Serendipity, as if index.php gets
+                    // called separately for the CSS.
+                    //
+                    // Note that the css_backend hook adds properties to the 
+                    // serendipity_admin.css, but that file is *always* 
+                    // cached.  We use backend_header and add the CSS to the
+                    // HEAD styles to make it dynamic.
+                    
+                    // Get the CSS, set $this->image_name so we'll output the
+                    // standard graphical CSS prologue if any images are found.
+                    $this->createRatingSelector();
+
+                    print ("<style type='text/css'>\n");
+
+                    $align = 'center';
+                    $bg = $this->get_config('preview_bg', false);
+                    if (!empty($bg)) {
+                        if ((strpos($bg, ';') !== false) || (strpos($bg, ',') !== false)) {
+                            $bg = 'red';
+                        }
+                        print("
+.serendipity_karamVote_selectorTable {
+    background: $bg;
+}
+");
+                    }
+                    print("
+.serendipityAdminContent .serendipity_karmaVoting_links {
+    margin: 5px;
+}
+");
                 case 'css':
-                    if (strpos($eventData, '.serendipity_karmaVoting')) {
-                        // class exists in CSS, so a user has customized it and we don't need default
-                        return true;
+                    // Some CSS notes:
+                    // 
+                    // .serendipity_karmaVoting is the class for the karma wrapper/container,
+                    //      including the text explanations, messages, and rating bar.
+                    //      (currently a div)
+                    // .serendipity_karmaVoting a specifies the links for the text-mode
+                    //      rating bar
+                    // .serendipity_karmaError is the class for any text indicating an
+                    //      error condition
+                    // .serendipity_karmaSuccess is the class for any text indicating
+                    //      successful operation
+                    // .serendipity_karmaVoting_links is the container for the graphical
+                    //      rating bar (currently an ol)
+                    // .serendipity_karmaVoting_links a indicates the various voting links in
+                    //      the graphical rating bar
+                    // .serendipity_karmaVoting_current-rating is the class for the current
+                    //      rating in the graphical rating bar
+                    //  a.serendipity_karmaVoting_link1, _link2, etc are the classes applied 
+                    //      to the individual voting links
+
+                    // Note that there are two possible template types: early
+                    // templates that only handle the text rating bars, and 
+                    // newer templates that understand the graphical raters.
+                    // We check for both types and act appropriately.
+                    /*--JAM: Let's just skip this whole hassle
+                    if (!$align) {
+                        $align = $this->get_config('alignment', 'detect');
                     }
-?>
+                    if ($align == 'detect') {
+                    */
+                    $align = $this->get_config('alignment', 'center');
+                        // Try to let the template take care of it
+                        if ($this->image_name == '0') {
+                            // Text-only rating bar is used
+                            if (strpos($eventData, '.serendipity_karmaVoting')) {
+                                // Template is handling all our CSS
+                                return true;
+                            }
+                        }/* --JAM: else {
+                            // Graphical rating bar is used
+                            if (strpos($eventData, '.serendipity_karmaVoting_images')) {
+                                // Template is handling all our CSS
+                                return true;
+                            }
+                            // Check for old text-only templates
+                            $pos = strpos($eventData, '.serendipity_karmaVoting');
+                            while ($pos && ($align == 'detect')) {
+                                // Find text-align: in the current block
+                                $endpos = strpos($eventData, '}', $pos);
+                                if (!$endpos) {
+                                    // Broken CSS
+                                    break;
+                                }
+                                $alignpos = strpos($eventData, 'text-align:', $pos);
+                                // Can't check for comments, or I would.  Hope
+                                // the first is the correct one.
+                                if ($alignpos && $alignpos < $endpos) {
+                                    $start = $alignpos + 11;
+                                    $alignend = strpos($eventData, ';', $alignpos);
+                                    if ($alignend)
+                                    {
+                                        // All valid.  Pull out the alignment.
+                                        $len = $alignend - $start;
+                                        $align = trim(substr($eventData, $start, $len));
+                                    }
+                                }
+                                $pos = strpos($eventData, '.serendipity_karmaVoting', $endpos);
+                            }
+                            // I should have a valid alignment or 'detect' in $align now. 
+                        }
+                    }
+                    // If we couldn't detect the alignment, guess 'right'
+                    if ($align == 'detect') {
+                        $align = 'right';
+                    }
+                    --JAM: END COMMENT BLOCK */
 
+                    // Since errors might be printed at any time, always
+                    // output the text-mode CSS
+                    print <<<EOS
 .serendipity_karmaVoting {
-    margin-left: auto;
-    margin-right: 0px;
-    text-align: right;
+    text-align: $align;
     font-size: 7pt;
-    display: block;
-    margin-top: 5px;
-    margin-bottom: 0px;
+    margin: 0px;
 }
 
 .serendipity_karmaVoting a {
@@ -391,14 +802,111 @@ class serendipity_event_karma extends serendipity_event
 .serendipity_karmaError {
     color: #FF8000;
 }
-
 .serendipity_karmaSuccess {
     color: green;
 }
-<?php
+EOS;
+                    // Only output the image CSS if it's needed
+                    if ($this->image_name != '0') {
+                        $img = $serendipity['baseURL'] . "plugins/serendipity_event_karma/img/" . $this->image_name; 
+                        $h = $this->image_height / 3;
+                        $w = $this->image_width;
+                        switch ($align) {
+                            case 'left':
+                                $margin = '0px auto 0px 0px';
+                                break;
+                            case 'center':
+                                $margin = '0px auto';
+                                break;
+                            case 'right':
+                            default:
+                                $margin = '0px 0px 0px auto';
+                                break;
+
+                        }
+                        // The CSS here is lifted largely from 
+                        // http://komodomedia.com/blog/index.php/2007/01/20/css-star-rating-redux/
+                        //
+                        // Note, however that margin has been changed for
+                        // multiple cases and all unitless measurements have 
+                        // been specified in pixels.  Additionally, measures 
+                        // have been taken to align the text.
+                        print <<<END_IMG_CSS
+
+.serendipity_karmaVoting_links,
+.serendipity_karmaVoting_links a:hover,
+.serendipity_karmaVoting_current-rating {
+    background: url($img) left;
+    font-size: 0;
+}
+.serendipity_karmaVoting_links {
+    position: relative;
+    width: {$w}px;
+    height: {$h}px;
+    overflow: hidden;
+    list-style: none;
+    margin: $margin;
+    padding: 0px;
+    background-position: left top;     
+    text-align: center;
+}
+.serendipity_karmaVoting_links li {
+   display: inline; 
+}
+.serendipity_karmaVoting_links a ,
+.serendipity_karmaVoting_current-rating {
+    position:absolute;
+    top: 0px;
+    left: 0px;
+    text-indent: -9000em;
+    height: {$h}px;
+    line-height: {$h}px;
+    outline: none;
+    overflow: hidden;
+    border: none;
+}
+.serendipity_karmaVoting_links a:hover {
+    background-position: left bottom;
+}
+.serendipity_karmaVoting_links a.serendipity_karmaVoting_link1 {
+    width: 20%;
+    z-index: 6;
+}
+.serendipity_karmaVoting_links a.serendipity_karmaVoting_link2 {
+    width: 40%;
+    z-index: 5;
+}
+.serendipity_karmaVoting_links a.serendipity_karmaVoting_link3 {
+    width: 60%;
+    z-index: 4;
+}
+.serendipity_karmaVoting_links a.serendipity_karmaVoting_link4 {
+    width: 80%;
+    z-index: 3;
+}
+.serendipity_karmaVoting_links a.serendipity_karmaVoting_link5 {
+  width: 100%;
+    z-index: 2;
+}
+.serendipity_karmaVoting_links .serendipity_karmaVoting_current-rating {
+    z-index: 1;
+    background-position: left center;
+}
+
+END_IMG_CSS;
+                        // Add selector images CSS, if necessary
+                        if (!empty($this->select_css)) {
+                            print($this->select_css);
+                        }
+                    } // End if image bar defined
+
+                    if ($event == 'backend_header') {
+                        print("\n</style>\n");
+                    }
                     return true;
                     break;
 
+                //--TODO: Comment the functionality of this event hook.
                 case 'event_additional_statistics':
                     $sql = array();
                     $sql['visits_top']    = array('visits', 'DESC');
@@ -441,43 +949,80 @@ class serendipity_event_karma extends serendipity_event
                     return true;
                     break;
 
+                // Add voting information to entries
                 case 'entry_display':
+                    // Update database if necessary 
                     if ($this->get_config('version') != PLUGIN_KARMA_VERSION) {
                         $this->checkScheme();
                     }
+                    
+                    // Find the ID of this entry
+                    if (isset($serendipity['GET']['id'])) {
+                        $entryid = (int)serendipity_db_escape_string($serendipity['GET']['id']);
+                    } elseif (preg_match(PAT_COMMENTSUB, $_SERVER['REQUEST_URI'], $matches)) {
+                        $entryid = (int)$matches[1];
+                    } else {
+                        $entryid = false;
+                    }
 
-                    // Check whether the cache plugin is used. If so, we need to append our karma-voting output
-                    // to the cached version, since that one is used instead of the 'extended' key later on.
-                    $extended_key = &$this->getFieldReference('add_footer', $eventData);
+                    // If we're actually reading the entry, not voting or editing it...
+                    if ($entryid && empty($serendipity['GET']['adminAction']) && !$serendipity['GET']['karmaVote']) {
+                        // Update the number of visits
+                        // Are we supposed to track visits?
+                        $track_clicks  = serendipity_db_bool($this->get_config('visits_active', true)) && $this->track_clicks_allowed_by_user();
+                        if ($track_clicks) {
+                            $sql = serendipity_db_query(
+                                "UPDATE {$serendipity['dbPrefix']}karma 
+                                    SET visits = visits + 1 
+                                  WHERE entryid = $entryid", 
+                                  true);
+                            if (serendipity_db_affected_rows() < 1) {
+                                serendipity_db_query(
+                                        "INSERT INTO {$serendipity['dbPrefix']}karma (entryid, points, votes, lastvote, visits) 
+                                              VALUES ('$entryid', 0, 0, 0, 1)"
+                                        );
+                            }
+                        }
+                    }
+                    
+                    // Set a cookie to look for later, verifying that cookies are enabled
+                    serendipity_setCookie('check', '1');
 
                     switch($this->karmaVote) {
                         case 'nocookie':
                             // Users with no cookies won't be able to vote.
                             $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_NOCOOKIE . '</div>';
+                            // Continue until output
 
                         case 'timeout2':
                             if (!isset($msg)) {
                                 $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_CLOSED . '</div>';
                             }
+                            // Continue until output
 
                         case 'timeout':
                             if (!isset($msg)) {
                                 $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . sprintf(PLUGIN_KARMA_TIMEOUT, $this->karmaTimeOut) . '</div>';
                             }
+                            // Continue until output
 
                         case 'alreadyvoted':
                             if (!isset($msg)) {
                                 $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_ALREADYVOTED . '</div>';
                             }
+                            // Continue until output
 
                         case 'invalid1':
                         case 'invalid2':
                         case 'invalid':
+                            // Set message
                             if (!isset($msg)) {
                                 $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_INVALID . '</div>';
                             }
+                            // Continue until output
 
                             /* OUTPUT MESSAGE */
+                            //--TODO: Shouldn't this work with the cache plugin, too?
                             if ($addData['extended']) {
                                 $eventData[0]['exflag'] = 1;
                                 $eventData[0]['add_footer'] .= $msg;
@@ -494,130 +1039,179 @@ class serendipity_event_karma extends serendipity_event
 
                         case 'voted':
                         default:
+                            // If there's no data, there's no need to go on
+                            if (!is_array($eventData)) return;
+
+                            // Find out what the admin wants
                             $track_clicks  = serendipity_db_bool($this->get_config('visits_active', true));
                             $track_karma   = serendipity_db_bool($this->get_config('karma_active', true));
                             $track_exits   = serendipity_db_bool($this->get_config('exits_active', true));
-                            $karma_active  = $track_karma;
-
-                            if (!is_array($eventData)) return;
 
+                            // Get the limits
+                            $now           = time();
                             $karmatime     = $this->get_config('max_karmatime', 7);
                             $max_karmatime = $karmatime    * 24 * 60 * 60;
-                            $now           = time();
+                            // Accept infinite voting
+                            if ($max_karmatime <= 0) {
+                                $max_karmatime = $now;
+                            }
 
+                            //--TODO: Ensure that this works with the Custom Permalinks plugin
+                            // (We've seen trouble; it votes correctly, but redirects to the front page)
                             $url = serendipity_currentURL() . '&amp;';
+                            //$uri = $_SERVER['REQUEST_URI'];
 
+                            // Get the cookie data (past votes, etc)
                             $karma = (isset($serendipity['COOKIE']['karmaVote']) ? unserialize($serendipity['COOKIE']['karmaVote']) : array());
-
-                            $link_1 = '<a class="serendipity_karmaVoting_link1" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=2&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_1) . '">++</a>';
-                            $link_2 = '<a class="serendipity_karmaVoting_link2" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=1&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_2) . '">+</a>';
-                            $link_3 = '<a class="serendipity_karmaVoting_link3" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=0&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_3) . '">0</a>';
-                            $link_4 = '<a class="serendipity_karmaVoting_link4" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=-1&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_4) . '">-</a>';
-                            $link_5 = '<a class="serendipity_karmaVoting_link5" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=-2&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_5) . '">--</a>';
-
-                            if ($addData['extended'] && $eventData[0]['timestamp'] < ($now - $max_karmatime)) {
-                                $karma_active = false;
-                            }
-
-                            $karma_voting = '<div class="serendipity_karmaVoting"><br /><a id="karma_vote%1$s"></a>'
-                                  . ($karma_active ? '<span class="serendipity_karmaVoting_text">' . PLUGIN_KARMA_VOTETEXT . '</span> <span class="serendipity_karmaVoting_links">' . $link_1 . ' | ' . $link_2 . ' | ' . $link_3 . ' | ' . $link_4 . ' | ' . $link_5 . '</span><br />'
-                                  . '<span class="serendipity_karmaVoting_current">' . PLUGIN_KARMA_CURRENT . '</span>' : '') . ($track_clicks ? '<span class="serendipity_karmaVoting_visits">' . PLUGIN_KARMA_VISITSCOUNT . '</span>': '') . '</div>';
-
-                            $karma_current = '<div class="serendipity_karmaVoting"><br /><a id="karma_vote%1$s"></a>'
-                                . ($karma_active ? '<div class="serendipity_karmaSuccess">' . PLUGIN_KARMA_VOTED . '</div>'
-                                  . '<span class="serendipity_karmaVoting_current">' . PLUGIN_KARMA_CURRENT . '</span>' : '') . ($track_clicks ? '<span class="serendipity_karmaVoting_visits">' . PLUGIN_KARMA_VISITSCOUNT . '</span>': '') . '</div>';
-
-                            $karma_timeout = '<div class="serendipity_karmaVoting"><br /><a id="karma_vote%1$s"></a>'
-                                . ($track_karma ? '<div>' . sprintf(PLUGIN_KARMA_CLOSED, $karmatime) . '</div>'
-                                  . '<span class="serendipity_karmaVoting_current">' . PLUGIN_KARMA_CURRENT . '</span>' : '') . ($track_clicks ? '<span class="serendipity_karmaVoting_visits">' . PLUGIN_KARMA_VISITSCOUNT . '</span>': '') . '</div>';
-
+                            // Get all required entry IDs, making keys match keys in eventData
+                            $entries = array();
                             if ($addData['extended'] || $addData['preview']) {
-                                $entryid = (int)serendipity_db_escape_string($eventData[0]['id']);
-                                $q = 'SELECT SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
-                                        FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
-                                       WHERE k.entryid = ' . $entryid . ' GROUP BY k.entryid LIMIT 1';
-                                $row = serendipity_db_query($q, true);
-
-                                if (empty($row['votes'])) {
-                                    $row['votes'] = 0;
-                                }
-
-                                if (empty($row['points'])) {
-                                    $row['points'] = 0;
-                                }
-
-                                if (empty($row['visits'])) {
-                                    $row['visits'] = 0;
+                                // We're in extended or preview mode, we only need the current ID
+                                $eventData[0]['exflag'] = 1;
+                                $entries[0] = (int)($eventData[0]['id']);
+                            } elseif (!serendipity_db_bool($this->get_config('extended_only', false))) {
+                                // We're in overview mode, and we want rating bars for all the entry IDs
+                                foreach(array_keys($eventData) as $key) {
+                                    $entries[$key] = (int)$eventData[$key]['id'];
                                 }
+                            }
 
-                                if ($track_exits) {
-                                    $extended_key .= $this->getExits($entryid);
+                            // Fetch votes for all entry IDs. Store them in an array for later usage.
+                            $q = 'SELECT k.entryid, SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
+                                    FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
+                                   WHERE k.entryid IN (' . implode(', ', $entries) . ') GROUP BY k.entryid';
+
+                            $sql = serendipity_db_query($q);
+
+                            $rows = array();
+                            if ($sql && is_array($sql)) {
+                                foreach($sql AS $row) {
+                                    $rows[$row['entryid']] = array(
+                                            'votes' => $row['votes'], 
+                                            'points' => $row['points'], 
+                                            'visits' => $row['visits']
+                                            );
                                 }
+                            }
 
-                                $eventData[0]['exflag'] = 1;
-                                if (isset($karma[$entryid])) {
-                                    $extended_key .= sprintf($karma_current, $karma[$entryid], $row['points'], $row['votes'], $row['visits'], $url);
-                                } elseif ($eventData[0]['timestamp'] < ($now - $max_karmatime)) {
-                                    $extended_key .= sprintf($karma_timeout, $entryid, $row['points'], $row['votes'], $row['visits'], $url);
-                                } else {
-                                    $extended_key .= sprintf($karma_voting, $entryid, $row['points'], $row['votes'], $row['visits'], $url);
+                            $this->prepareExits($entries);
+
+                            // Add karma block to the footer of each entry
+                            // 
+                            // The entries array was populated, above, so its keys match the eventData array,
+                            // and overview entries are skipped if "extended only" is enabled
+                            foreach (array_keys($entries) as $i) {
+                                // Get the statistics
+                                $entryid = $eventData[$i]['id'];
+                                $votes   = (!empty($rows[$entryid]['votes']) ? $rows[$entryid]['votes'] : 0);
+                                $points  = (!empty($rows[$entryid]['points']) ? $rows[$entryid]['points'] : 0);
+                                $visits  = (!empty($rows[$entryid]['visits']) ? $rows[$entryid]['visits'] : 0);
+                                $enough_votes = $track_karma && ($votes >= $this->get_config('min_disp_votes', 0));
+                                $enough_visits = $track_clicks && ($visits >= $this->get_config('min_disp_visits', 0));
+                                $textual_msg = true;
+                                $textual_current = true;
+                                $textual_visits = true;
+                                if ($this->image_name != '0') {
+                                    $textual_msg = $this->get_config('textual_msg', 'true');
+                                    $textual_current = $this->get_config('textual_current', 'true');
+                                    $textual_visits = $this->get_config('textual_visits', 'true');
                                 }
-                            } elseif (!serendipity_db_bool($this->get_config('extended_only', false))) {
-                                $elements = count($eventData);
 
-                                // Get all existing entry IDs
-                                $entries  = array();
-                                for ($i = 0; $i < $elements; $i++) {
-                                    $entries[] = (int)$eventData[$i]['id'];
+                                // Where's the footer?  Normally it would be 
+                                // in addData['extended']; but if the cache
+                                // plugin is used, it's elsewhere.  This
+                                // method retrieves it either way.
+                                $footer = &$this->getFieldReference('add_footer', $eventData[$i]);
+                                /*--JAM: Probably time to delete this
+                                // Create a footer if one doesn't already exist
+                                if (!isset($eventData[$i]['add_footer'])) {
+                                $eventData[$i]['add_footer'] = '';
                                 }
+                                 */
 
-                                // Fetch votes for all entry IDs. Store them in an array for later usage.
-                                $q = 'SELECT k.entryid, SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
-                                        FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
-                                       WHERE k.entryid IN (' . implode(', ', $entries) . ') GROUP BY k.entryid';
-
-                                $sql = serendipity_db_query($q);
-
-                                $rows = array();
-                                if ($sql && is_array($sql)) {
-                                    foreach($sql AS $idx => $row) {
-                                        $rows[$row['entryid']] = array('votes' => $row['votes'], 'points' => $row['points'], 'visits' => $row['visits']);
-                                    }
+                                if ($track_exits) {
+                                    $footer .= $this->getExits($entryid, true);
                                 }
 
-                                $this->prepareExits($entries);
-
-                                // Walk entry array and insert karma voting line.
-                                for ($i = 0; $i < $elements; $i++) {
-                                    $entryid = $eventData[$i]['id'];
-                                    $votes   = (!empty($rows[$entryid]['votes']) ? $rows[$entryid]['votes'] : 0);
-                                    $points  = (!empty($rows[$entryid]['points']) ? $rows[$entryid]['points'] : 0);
-                                    $visits  = (!empty($rows[$entryid]['visits']) ? $rows[$entryid]['visits'] : 0);
-
-                                    if (!isset($eventData[$i]['add_footer'])) {
-                                        $eventData[$i]['add_footer'] = '';
-                                    }
-
-                                    if ($track_exits) {
-                                        $eventData[$i]['add_footer'] .= $this->getExits($entryid, true);
-                                    }
-
+                                // Pick the appropriate intro msg and rating bar
+                                // No msg or bar if karma is disabled
+                                if ($track_karma) {
                                     if (isset($karma[$entryid])) {
-                                        $eventData[$i]['add_footer'] .= sprintf($karma_current, $karma[$entryid], $points, $votes, $visits, $url);
+                                        // We already voted for this one
+                                        $msg =
+    '<div class="serendipity_karmaSuccess">' . PLUGIN_KARMA_VOTED . '</div>';
+                                        $myvote = $karma[$entryid];
+                                        if ($this->get_config('rate_with_words', false)) {
+                                            $myvote = $this->wordRating($myvote, 1);
+                                        }
+                                        elseif ($this->image_name != '0') {
+                                            $myvote = $this->imageRating($myvote, 1);
+                                        }
+                                        // Just a current rating bar, if any
+                                        $bar = $this->createRatingBar(null, $points, $votes);
                                     } elseif ($eventData[$i]['timestamp'] < ($now - $max_karmatime)) {
-                                        $eventData[$i]['add_footer'] .= sprintf($karma_timeout, $entryid, $points, $votes, $visits, $url);
+                                        // Too late to vote for this one
+                                        $msg = 
+    '<div class="serendipity_karmaClosed">' . sprintf(PLUGIN_KARMA_CLOSED, $karmatime) . '</div>';
+                                        // Just a current rating bar, if any
+                                        $bar = $this->createRatingBar(null, $points, $votes);
                                     } else {
-                                        $eventData[$i]['add_footer'] .= sprintf($karma_voting, $entryid, $points, $votes, $visits, $url);
+                                        // We can vote for this; make the whole voting block
+                                        $rate_msg = $this->get_config('rate_msg', PLUGIN_KARMA_VOTETEXT);
+                                        $msg = 
+    '<div class="serendipity_karmaVoting_text">' . $rate_msg . '</div>';
+                                        // Full voting bar
+                                        $bar = $this->createRatingBar($entryid, $points, $votes);
                                     }
                                 }
-                            }
-                    }
+                                // Create the karma block
+                                $image_class = '';
+                                if ($this->image_name != '0') {
+                                    $image_class = ' serendipity_karmaVoting_images';
+                                }
+                                $karma_block = 
+"<div class='serendipity_karmaVoting$image_class'><a id='karma_vote$entryid'></a>";
+                                if ($textual_msg) {
+                                    $karma_block .= 
+    $msg;
+                                }
+                                $karma_block .=
+    $bar;
+                                if ($enough_votes && $textual_current) {
+                                    $curr_msg = $this->get_config('curr_msg', PLUGIN_KARMA_CURRENT);
+                                    $karma_block .=
+    '<span class="serendipity_karmaVoting_current">' . $curr_msg . '</span>';
+                                }
+                                if ($enough_visits && $textual_visits) {
+                                    $karma_block .= 
+    '<span class="serendipity_karmaVoting_visits">' . PLUGIN_KARMA_VISITSCOUNT . '</span>';
+                                }
+                                $karma_block .=
+"\n</div>\n";
+                                // Adjust rating points
+                                if ($this->get_config('rate_with_words', false)) {
+                                    $points = $this->wordRating($points, $votes);
+                                }
+                                elseif ($this->image_name != '0') {
+                                    $points = $this->imageRating($points, $votes);
+                                }
+
+                                /*
+                                   print("<h3>--DEBUG: Karma block code:</h3>\n<pre>\n");
+                                   print_r(htmlspecialchars($karma_block));
+                                   print("\n</pre>\n");
+                                 */
+
+                                // Substitute the % stuff and add it to the footer
+                                $footer .= sprintf($karma_block, $myvote, $points, $votes, $visits, $url);
+                            } // foreach key in entries
+                    }// End switch on karma voting status
                     return true;
                     break;
 
                 default:
                     return false;
-            }
+            }// End switch on event hooks
         } else {
             return false;
         }
@@ -632,6 +1226,369 @@ class serendipity_event_karma extends serendipity_event
         }
         return true;
     }
+
+    /**
+     * Creates an HTML snippet with images of all the available rating bars.
+     *
+     * @return string an HTML string including working images of all the rating bars in the img/ directory.
+     */
+    function createRatingSelector() {
+        // Since the inputs are set up with the proper names, the config item
+        // gets saved automatically, with no need for magic
+
+        // Get the filename to be automatically selected
+        $this->set_valid_image_data();
+        $cursel = $this->image_name;
+
+        $this->select_css = '';
+        $this->select_html = '';
+        // We will be wrapped in a <tr><td colspan="2">
+        $this->select_html .= "
+<strong>" . PLUGIN_KARMA_IMAGE . "</strong><br />
+<span style='color: rgb(94, 122, 148); font-size: 8pt;'>&nbsp;".PLUGIN_KARMA_IMAGE_DESC."</span>
+</td>
+<td></td>
+</tr>
+<tr>
+<td colspan='2'>
+<table border='1' class='serendipity_karamVote_selectorTable'>";
+        // Add the 'text-only' selection and its CSS
+        if ($cursel == '0') {
+            $checked = 'checked="checked" ';
+        } else {
+            $checked = '';
+        }
+        $this->image_name = '0';
+        $bar = $this->createRatingBar('', 0, 0, 'textbar');
+        $this->select_html .= "
+<tr id='serendipity_karmaVote_selectorTable_textOnly'>
+<td colspan='3' align='center'><input type='radio' name='serendipity[plugin][base_image]' value='0' $checked/>" . PLUGIN_KARMA_STATISTICS_POINTS_NO . "<br />$bar<br /></td>\n";
+        $this->select_css .= "
+.textbar, .textbar a, .textbar a:hover {
+    font-size: 100%;
+    position: relative;
+    background: none;
+}
+.serendipityAdminContent span.textbar {
+    color: black !important;
+}
+";
+        // Retrieve all the *valid* images from the image directory
+        $files = $this->getImageFiles();
+        // Add an <ol> for each rating bar, and add its CSS overrides 
+        $n = 0;
+        foreach ($files as $fdata) {
+            // Columnize 
+            if (($n % 3) == 0) {
+                // Time to start a new row
+                $this->select_html .= "</tr>\n<tr>\n";
+            }
+
+            // Set the image data
+            $fname = $fdata['fname'];
+            $height = $fdata['height'];
+            $width = $fdata['width'];
+            $ratio = $width / $height;
+            // If this is a single segment, adjust width
+            if ($ratio < $max_segment_ratio) {
+                $width = $width * 5;
+            }
+            $height = $height / 3;
+            // Set up class variables correctly
+            $this->image_name = $fname;
+            $this->image_width = $width;
+            $this->image_height = $height;
+
+            // Create a rating bar of this image
+            //
+            // What would be a good CSS class for this image?
+            $css_class = str_replace(array('.',' '), array('_','_'), $fname);
+            $checked = '';
+            if ($fname == $cursel) {
+                $checked = 'checked="checked" ';
+            }
+            $bar_html = 
+"<td align='center' id='serendipity_karmaVote_select_$css_class'>
+    <input type='radio' name='serendipity[plugin][base_image]' value='$fname' $checked/>
+    <span style='font-size: 8pt;'>$fname</span><br />\n" . 
+                $this->createRatingBar('', -1, 2, $css_class) .
+"</td>\n";
+            $bar_html = sprintf($bar_html, '', '2.5 of 5', '1');
+            $this->select_html .= $bar_html;
+            // Add the necessary CSS to the stylesheet (will be added when css hooks are called)
+            // Sorry to interrupt your regularly scheduled HTML; I need to 
+            // use the $css_class while it's still here.
+            $this->select_css .= "
+/* Overrides for $css_class */
+.$css_class 
+{
+  width: ${width}px;
+  height: ${height}px;
+}
+.$css_class,
+.$css_class a:hover,
+.$css_class .serendipity_karmaVoting_current-rating
+{
+  background-image: url({$serendipity['baseURL']}plugins/serendipity_event_karma/img/${fname});
+}
+.$css_class,
+.$css_class a,
+.$css_class .serendipity_karmaVoting_current-rating
+{
+  line-height: ${height}px;
+  height: ${height}px;
+}
+
+";
+            $n++;
+        } // Go back up for another image
+
+        // Check for nothing displayed
+        if ($n == 0) {
+            // There were no images!
+            $this->select_html .= "</tr>\n<tr><td>" . PLUGIN_KARMA_NO_IMAGES . "</td>";
+        }
+
+        // End the table, with a config-item bottom-border separator
+        $this->select_html .= 
+"</tr>\n</table>
+<tr><td colspan='2' style='border-bottom: 1px solid #000000; vertical-align: top'>&nbsp;<td></tr>\n";
+        // The config item and row are closed by the core code
+
+        return $this->select_html;
+    }
+
+    /**
+     * Retrieves all the images from the img/ directory
+     *
+     * @return array an array with 'fname', 'width', and 'height' entries for
+     *     each valid image file in the img/ directory
+     */
+    function getImageFiles() {
+        $path = dirname(__FILE__) . "/img";
+        $images = array();
+        $folder = opendir($path);
+        while (false !== ($filename = readdir($folder))) {
+            $parts = serendipity_parseFileName($filename);
+            $img_data = serendipity_getimagesize($path . '/' . $filename);
+            if (!isset($img_data['noimage'])) {
+                // Curly braces are just a different syntax of associative array assignment
+                $images{$filename} = array('fname'=>$filename, 'width'=>$img_data[0], 'height'=>$img_data[1]);
+            }
+        }
+        closedir($folder);                               
+        ksort($images);
+        return $images;
+    }
+
+    /**
+     * Creates the HTML snippet for the currently defined rating bar, with 
+     * appropriate links (and current rating indication for graphical bars).
+     * Automatically detects from $this->image_name whether to create text
+     * links or a graphical bar.
+     *
+     * @param string id optional The ID of the bar we're creating; an empty
+     *     id ('' or 0) creates a bar with dummy links; null creates a bar with 
+     *     no voting links at all (shows only current configuration).
+     * @param int karma optional The current total karma (default: 0 points)
+     * @param int votes optional The total number of votes (default: 0 votes))
+     * @param string extra_class optional Any additional CSS classes to be added to the bar container
+     */
+    function createRatingBar($id = null, $karma = 0, $votes = 0, $extra_class = '') {
+        // Are there enough votes to display the current rating?
+        $enough_votes = ($votes >= $this->get_config('min_disp_votes', 0));
+        // Do I need to create links?
+        if ($id !== null) {
+            // Create the rating tooltips and texts
+            $vilestr = $this->get_config('rate_vile', PLUGIN_KARMA_VOTEPOINT_1);
+            $poorstr = $this->get_config('rate_poor', PLUGIN_KARMA_VOTEPOINT_2);
+            $okaystr = $this->get_config('rate_okay', PLUGIN_KARMA_VOTEPOINT_3);
+            $goodstr = $this->get_config('rate_good', PLUGIN_KARMA_VOTEPOINT_4);
+            $beststr = $this->get_config('rate_best', PLUGIN_KARMA_VOTEPOINT_5);
+            $vile = sprintf(PLUGIN_KARMA_RATE, $vilestr);
+            $poor = sprintf(PLUGIN_KARMA_RATE, $poorstr);
+            $okay = sprintf(PLUGIN_KARMA_RATE, $okaystr);
+            $good = sprintf(PLUGIN_KARMA_RATE, $goodstr);
+            $best = sprintf(PLUGIN_KARMA_RATE, $beststr);
+            $vilestr = $this->get_config('text_vile', PLUGIN_KARMA_VOTETEXT_1);
+            $poorstr = $this->get_config('text_poor', PLUGIN_KARMA_VOTETEXT_2);
+            $okaystr = $this->get_config('text_okay', PLUGIN_KARMA_VOTETEXT_3);
+            $goodstr = $this->get_config('text_good', PLUGIN_KARMA_VOTETEXT_4);
+            $beststr = $this->get_config('text_best', PLUGIN_KARMA_VOTETEXT_5);
+            
+            if (empty($id)) {
+                // Create dummy links
+                $link_1 = 
+'<a class="serendipity_karmaVoting_link1" rel="nofollow" href="#" title="' . $vile . '">' . $vilestr . '</a>';
+                $link_2 = 
+'<a class="serendipity_karmaVoting_link2" rel="nofollow" href="#" title="' . $poor . '">' . $poorstr . '</a>';
+                $link_3 = 
+'<a class="serendipity_karmaVoting_link3" rel="nofollow" href="#" title="' . $okay . '">' . $okaystr . '</a>';
+                $link_4 = 
+'<a class="serendipity_karmaVoting_link4" rel="nofollow" href="#" title="' . $good . '">' . $goodstr . '</a>';
+                $link_5 = 
+'<a class="serendipity_karmaVoting_link5" rel="nofollow" href="#" title="' . $best . '">' . $beststr . '</a>';
+                // There *are* enough votes for a dummy rating bar
+                $enough_votes = true;
+            } else {
+                // Create ordinary links
+                $link_1 = "<a class='serendipity_karmaVoting_link1' rel='nofollow' href='%5\$sserendipity[karmaVote]=-2&amp;serendipity[karmaId]=$id#karma_vote$id' title='$vile'>$vilestr</a>";
+                $link_2 = "<a class='serendipity_karmaVoting_link2' rel='nofollow' href='%5\$sserendipity[karmaVote]=-1&amp;serendipity[karmaId]=$id#karma_vote$id' title='$poor'>$poorstr</a>";
+                $link_3 = "<a class='serendipity_karmaVoting_link3' rel='nofollow' href='%5\$sserendipity[karmaVote]=0&amp;serendipity[karmaId]=$id#karma_vote$id' title='$okay'> $okaystr</a>";
+                $link_4 = "<a class='serendipity_karmaVoting_link4' rel='nofollow' href='%5\$sserendipity[karmaVote]=1&amp;serendipity[karmaId]=$id#karma_vote$id' title='$good'>$goodstr</a>";
+                $link_5 = "<a class='serendipity_karmaVoting_link5' rel='nofollow' href='%5\$sserendipity[karmaVote]=2&amp;serendipity[karmaId]=$id#karma_vote$id' title='$best'>$beststr</a>";
+            }
+        }
+
+        // Normalize the CSS class
+        if (!empty($extra_class)) {
+            $extra_class = " $extra_class";
+        }
+
+        // Create the rating bar
+        if ($this->image_name == '0') {
+            // Text bar
+            //
+            if ($id === null) {
+                // No need for a "current rating" bar, like with graphics
+                $karma_display = '';
+            } else {
+                // Show the links
+                $karma_display = "
+                    <span class='serendipity_karmaVoting_links$extra_class'>$link_1 | $link_2 | $link_3 | $link_4 | $link_5</span><br />";
+            }
+        } else {
+            // Graphic bar
+            //
+
+            // No need to create a bar if there's nothing to display
+            if (($id !== null) || $enough_votes) {
+                // Start the bar
+                $karma_display = "
+<ol class='serendipity_karmaVoting_links$extra_class'>";
+                // Only display the current rating if there are enough votes
+                if ($enough_votes) {
+                    // Figure out the image-based rating and width
+                    $rating = $this->imageRating($karma, $votes);
+                    $cr_width = ($rating * $this->image_width) / 5;
+                    // Get current karma text
+                    $curr_msg = $this->get_config('curr_msg', PLUGIN_KARMA_CURRENT);
+                    $karma_display .= "
+    <li class='serendipity_karmaVoting_current-rating' style='width: ${cr_width}px;' title='$curr_msg'> </li>
+    ";
+                }
+                // Only create voting links if required
+                if ($id !== null) {
+                    $karma_display .= "
+    <li>$link_1</li>
+    <li>$link_2</li>
+    <li>$link_3</li>
+    <li>$link_4</li>
+    <li>$link_5</li>
+    ";
+                }
+                // Close the <ol>
+                $karma_display .= "
+</ol>
+";
+            }
+        }
+        return $karma_display;
+    }
+
+    /**
+     * Sets $this->image_name to the name of a valid image, or to '0' to
+     * indicate text-only rating bars should be used.
+     */
+    function set_valid_image_data() {
+        $base_image = $this->get_config('base_image', false);
+        if ($base_image !== false) {
+            // Definitely configured
+            if ($base_image == '0') {
+                // Configured to text-only
+                $this->image_name = $base_image;
+            } else {
+                $imagesize = serendipity_getimagesize(dirname(__FILE__) . "/img/" . $base_image);
+                if ($imagesize['noimage']) {
+                    // Leave as default
+                } else {
+                    // Set to valid image name
+                    $this->image_name = $base_image;
+                }
+            }
+        }
+        // Is the (possibly default) image valid?
+        if ($this->image_name) {
+            $imagesize = serendipity_getimagesize(dirname(__FILE__) . "/img/" . $this->image_name);
+            if ($imagesize['noimage']) {
+                // No valid image; use text-only
+                $this->image_name = '0';
+            } else {
+                // Valid graphical image; set the dimensions, too
+                $this->image_width = $imagesize[0];
+                $this->image_height = $imagesize[1];
+            }
+        }
+    }
+
+    /**
+     * Compute the equivalent graphical points rating for a karma rating.
+     *
+     * @param int points The total karma points
+     * @param int votes The total number of votes
+     * 
+     * @return string A string indicating the number of points "of 5", 
+     *     or PLUGIN_KARMA_IMAGE_NONE_RATING if no votes have been recorded.
+     */
+    function imageRating($points, $votes) {
+        if ($votes == 0) {
+            $rating = PLUGIN_KARMA_IMAGE_NONE_RATING;
+        } else {
+            // Find average karma (-2 to +2)
+            $rating = ((float)$points) / ((float)$votes);
+            // Remap into [1,5]
+            $rating = $rating + 3;
+            // Put it into the language-specific string format
+            if ($rating == (int)$rating) {
+                $rating = sprintf(PLUGIN_KARMA_IMAGE_INT_RATING, $rating);
+            } else {
+                $rating = sprintf(PLUGIN_KARMA_IMAGE_RATING, $rating);
+            }
+        }
+        return $rating;
+    }
+
+    /* Compute the equivalent word rating for a karma rating.
+     * 
+     * @param mixed points The total karma points
+     * @param mixed votes The total number of votes
+     *
+     * @return string A word corresponding to the article rating, 
+     *     or PLUGIN_KARMA_IMAGE_NONE_RATING if no votes have been recorded.
+     */
+    function wordRating($points, $votes) {
+        if ($votes == 0) {
+            $rating = PLUGIN_KARMA_IMAGE_NONE_RATING;
+        } else {
+            // Find average karma (-2 to +2)
+            $rating = ((float)$points) / ((float)$votes);
+            // Put it into the language-specific string format, rounding up
+            // I'm mapping invalid cases (rating > 5 and rating < -2) to the extremes
+            $rating = (int)($rating + 0.5);
+            if ($rating <= -2) {
+                $rating = PLUGIN_KARMA_VOTEPOINT_1;
+            } elseif ($rating <= -1) {
+                $rating = PLUGIN_KARMA_VOTEPOINT_2;
+            } elseif ($rating <= 0) {
+                $rating = PLUGIN_KARMA_VOTEPOINT_3;
+            } elseif ($rating <= 1) {
+                $rating = PLUGIN_KARMA_VOTEPOINT_4;
+            } else {
+                $rating = PLUGIN_KARMA_VOTEPOINT_5;
+            }
+        }
+        return $rating;
+    }
 }
 
-/* vim: set sts=4 ts=4 expandtab : */
+/* vim: set sts=4 ts=4 sw=4 expandtab : */