Index: common/db/tags.php
===================================================================
--- common/db/tags.php	(revision 1084)
+++ common/db/tags.php	(working copy)
@@ -2,6 +2,7 @@
 
 require_once(IA_ROOT_DIR."common/db/db.php");
 require_once(IA_ROOT_DIR."common/common.php");
+require_once(IA_ROOT_DIR."common/cache.php");
 
 // Get list of all tag names, filtered by type and parent
 function tag_get_all($types = null, $parent = null) {
@@ -182,13 +183,25 @@
 }
 
 // Count the number of objects containing all tags from a list of tag ids
-function tag_count_objects($obj, $tag_ids) {
+function tag_count_objects($obj, $tag_ids, $no_cache=false) {
     log_assert(is_taggable($obj));
     log_assert(is_array($tag_ids));
+    // Cache object count for single tags.
+    if (!$no_cache && count($tag_ids) == 1) {
+        $result = mem_cache_get("$obj-count-with-tag:".$tag_ids[0]);
+        if ($result !== false) {
+            return $result;
+        }
+    }
     $query = sprintf("SELECT COUNT(*) as `cnt` FROM ia_%s WHERE %s", db_escape($obj),
                      tag_build_where($obj, $tag_ids));
     $result = db_fetch($query);
-    return $result['cnt'];
+    $result = $result['cnt'];
+    if (count($tag_ids) == 1) {
+        mem_cache_set("$obj-count-with-tag:".$tag_ids[0], $result,
+            IA_MEM_CACHE_TAGS_EXPIRATION);
+    }
+    return $result;
 }
 
 // Clear all tags, filtered by type
Index: config.php.sample
===================================================================
--- config.php.sample	(revision 1084)
+++ config.php.sample	(working copy)
@@ -128,6 +128,9 @@
 // Task TTL. Smaller because of evaluator.
 define("IA_MEM_CACHE_TASK_EXPIRATION", 10);
 
+// TTL for tag caches.
+define("IA_MEM_CACHE_TAGS_EXPIRATION", 600);
+
 // Logging options. Anything else in normal operation is a bug.
 // Filling error_log on a production machine sucks.
 
Index: scripts/migrate-authors-to-task-tags
===================================================================
--- scripts/migrate-authors-to-task-tags	(revision 1084)
+++ scripts/migrate-authors-to-task-tags	(working copy)
@@ -8,7 +8,7 @@
 
 $tasks = task_get_all();
 $author_tags = array();
-foreach($tasks as $task) {
+foreach($tasks as &$task) {
     // Special cases to make my life easier.
     if ($task["author"] == "") {
         $task["author"] = "Necunoscut";
Index: www/controllers/task_tags.php
===================================================================
--- www/controllers/task_tags.php	(revision 1084)
+++ www/controllers/task_tags.php	(working copy)
@@ -16,10 +16,16 @@
         }
     }
 
+    $authors = tag_get_all(array("author"));
+    foreach ($authors as &$author) {
+        $author["task_count"] = tag_count_objects("task", array($author["id"]));
+    }
+
     // Create view.
     $view = array();
     $view['title'] = "Tag-uri probleme";
     $view['categories'] = $categories;
+    $view['authors'] = $authors;
     execute_view_die("views/task_tags.php", $view);
 }
 
@@ -72,13 +78,13 @@
     }
 
     // Do not delete tags if they have been added to tasks.
-    if ($tag["type"] == "algorithm") {
-        $task_count = tag_count_objects("task", array($tag_id));
-    } else if ($tag["type"] == "method") {
+    if ($tag["type"] != "method") {
+        $task_count = tag_count_objects("task", array($tag_id), true);
+    } else {
         $task_count = 0;
         $sub_tags = tag_get_all(array("algorithm"), $tag_id);
         foreach ($sub_tags as $sub_tag) {
-            $task_count += tag_count_objects("task", array($sub_tag["id"]));
+            $task_count += tag_count_objects("task", array($sub_tag["id"]), true);
         }
     }
     if ($task_count != 0) {
@@ -115,6 +121,10 @@
     }
 
     $tag["name"] = $new_name;
+    if (tag_get_id($tag)) {
+        flash_error("Tagul deja exista.");
+        redirect(url_task_tags());
+    }
     tag_update_by_id($tag_id, $tag);
     flash("Tag-ul a fost redenumit.");
     redirect(url_task_tags());
Index: www/static/js/inline_form.js
===================================================================
--- www/static/js/inline_form.js	(revision 1084)
+++ www/static/js/inline_form.js	(working copy)
@@ -10,7 +10,7 @@
         if (formElement.style.display == "none") {
             // Display inline form and replace toggleElement with "Anuleaza"
             formElement.style.display = "inline";
-            toggleElement.innerHTML = "Anuleaza";
+            toggleElement.innerHTML = "Anulează";
             // Hide original content if specified
             if (typeof(originalElement) != "undefined") {
                 originalElement.style.display = "none";
Index: www/views/task_tags.php
===================================================================
--- www/views/task_tags.php	(revision 1084)
+++ www/views/task_tags.php	(working copy)
@@ -8,25 +8,25 @@
 function format_tag_name($row) {
     $tag = inline_post_form(url_task_tags_rename(),
         array(
-            "type" => "algorithm",
             "old_name" => $row["name"],
+            "type" => $row["type"],
             "parent" => $row["parent"]
         ),
-        $row["name"], "Redenumeste");
+        $row["name"], "Redenumește");
     $tag .= ' <a class="algorithm_tag" href="#">' . html_escape($row["name"]) . '</a>';
     return $tag;
 }
 
 // Returns a delete tag link and a toggle rename form link
 function format_operations($row) {
-    $delete = format_post_link(url_task_tags_delete(), "Sterge",
+    $delete = format_post_link(url_task_tags_delete(), "Șterge",
         array(
+            "name" => $row["name"],
             "type" => $row["type"],
-            "name" => $row["name"],
             "parent" => $row["parent"]
         )
     );
-    $rename = '<a href="#" class="toggle_rename">Redenumeste</a>';
+    $rename = '<a href="#" class="toggle_rename">Redenumește</a>';
     return sprintf("[%s] [%s]", $delete, $rename);
 }
 
@@ -49,12 +49,12 @@
         'css_class' => 'tag-name',
     ),
     array(
-        'title' => 'Numar probleme',
+        'title' => 'Număr probleme',
         'key' => 'task_count',
         'css_class' => 'tag-task-count',
     ),
     array(
-        'title' => 'Operatii',
+        'title' => 'Operații',
         'rowform' => 'format_operations',
         'css_class' => 'tag-operations',
     ),
@@ -64,8 +64,8 @@
 
 <h1>Editare taguri algoritmi</h1>
 <div id="add_category" class="task-tag-actions">
-[<a href="#">Adauga categorie noua</a><?php
-    echo inline_post_form(url_task_tags_add(), array("type" => "method"), "", "Adauga");
+[<a href="#">Adaugă categorie nouă</a><?php
+    echo inline_post_form(url_task_tags_add(), array("type" => "method"), "", "Adaugă");
 ?>]
 </div>
 <?php
@@ -73,17 +73,17 @@
 ?>
     <h2><?php echo html_escape($category["name"]); ?></h2>
     <ul class="task-tag-actions">
-        <li class="algorithm_tag_add">[<a class="toggle_add" href="#">Adauga tag nou</a><?php
+        <li class="algorithm_tag_add">[<a class="toggle_add" href="#">Adaugă tag nou</a><?php
             echo inline_post_form(url_task_tags_add(),
                 array("type" => "algorithm", "parent" => $category["id"]),
-                "", "Adauga");
+                "", "Adaugă");
         ?>]</li>
-        <li class="delete_method">[<?php echo format_post_link(url_task_tags_delete(), "Sterge categorie",
+        <li class="delete_method">[<?php echo format_post_link(url_task_tags_delete(), "Șterge categorie",
             array("type" => "method", "name" => $category["name"])); ?>]</li>
-        <li class="rename_method">[<a class="toggle_rename" href="#">Redenumeste categorie</a><?php
+        <li class="rename_method">[<a class="toggle_rename" href="#">Redenumește categorie</a><?php
             echo inline_post_form(url_task_tags_rename(),
                 array("type" => "method", "old_name" => $category["name"]),
-                $category["name"], "Redenumeste");
+                $category["name"], "Redenumește");
         ?>]</li>
     </ul>
     <?php
@@ -93,6 +93,16 @@
 <?php
 }
 ?>
+<h1>Editare taguri autori</h1>
+<div id="add_author" class="task-tag-actions">[<a class="toggle_add" href="#">Adaugă tag nou</a><?php
+    echo inline_post_form(url_task_tags_add(),
+        array("type" => "author"),
+        "", "Adaugă");
+?>]</div>
+<?php
+echo format_table($authors, $column_infos,
+    array('css_class' => 'category fill-screen tag-table'));
+?>
 <script type="text/javascript" src="<?= html_escape(url_static('js/inline_form.js')) ?>"></script>
 <script type="text/javascript">
 /* <![CDATA[ */
@@ -101,6 +111,11 @@
     bindToggleLinkToForm($$("#add_category > a")[0], $$("#add_category > form")[0]);
 });
 
+// Bind add author link to form
+addLoadEvent(function() {
+    bindToggleLinkToForm($$("#add_author > a")[0], $$("#add_author > form")[0]);
+});
+
 // Bind add algorithm links to forms.
 var addForms = $$(".algorithm_tag_add form");
 var addLinks = $$(".algorithm_tag_add a.toggle_add");
